├── .babelrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── __tests__ ├── Sparklines.js ├── compareSvg.js ├── dataToPoints.js ├── fixtures.js ├── graphical-tests.js ├── mean.js ├── median.js └── sampleData.js ├── bootstrap-tests.js ├── build └── index.js ├── demo ├── demo.js ├── index.html └── webpack.config.js ├── index.js ├── package.json ├── src ├── Sparklines.js ├── SparklinesBars.js ├── SparklinesCurve.js ├── SparklinesLine.js ├── SparklinesNormalBand.js ├── SparklinesReferenceLine.js ├── SparklinesSpots.js ├── SparklinesText.js └── dataProcessing │ ├── dataToPoints.js │ ├── index.js │ ├── max.js │ ├── mean.js │ ├── median.js │ ├── midRange.js │ ├── min.js │ ├── stdev.js │ └── variance.js ├── wallaby.conf.js ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "react", 4 | "es2015", 5 | "stage-1" 6 | ], 7 | "plugins": [ 8 | "transform-object-assign" 9 | ], 10 | "sourceMaps": true, 11 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | # build 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | .DS_Store 30 | .idea 31 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | demo 3 | wallaby.conf.js 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_install: npm install -g npm@3 3 | script: travis_retry npm test 4 | node_js: 5 | - '7' 6 | sudo: false 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Boris Yankov 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 | # Beautiful and expressive sparklines component for React 2 | 3 | [![Build Status](https://travis-ci.org/borisyankov/react-sparklines.svg?branch=master)](https://travis-ci.org/borisyankov/react-sparklines) 4 | 5 | Live demos and docs: [borisyankov.github.io/react-sparklines/](http://borisyankov.github.io/react-sparklines/) 6 | 7 | ![](http://borisyankov.github.io/react-sparklines/img/dynamic.gif) 8 | 9 | ## Install 10 | 11 | ``` 12 | npm install react-sparklines --save 13 | ``` 14 | 15 | ## Run demo 16 | 17 | ``` 18 | npm install 19 | npm start 20 | http://localhost:8080 21 | ``` 22 | 23 | 24 | ## Use 25 | 26 | Import the Sparklines components that you need; for example to generate a simple chart: 27 | 28 | ![](http://borisyankov.github.io/react-sparklines/img/basic.png) 29 | 30 | ``` 31 | import React from 'react'; 32 | import { Sparklines } from 'react-sparklines'; 33 | ... 34 | 35 | 36 | ``` 37 | 38 | Sparklines component is a container with the following properties: 39 | 40 | data - the data set used to build the sparkline 41 | 42 | limit - optional, how many data points to display at once 43 | 44 | width, height - dimensions of the generated sparkline in the SVG viewbox. This will be automatically scaled (i.e. responsive) inside the parent container by default. 45 | 46 | svgWidth, svgHeight - If you want absolute dimensions instead of a responsive component set these attributes. 47 | 48 | [preserveAspectRatio](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio) - default: 'none', set this to modify how the sparkline should scale 49 | 50 | margin - optional, offset the chart 51 | 52 | min, max - optional, bound the chart 53 | 54 | 55 | #### Basic Sparkline 56 | 57 | ![](http://borisyankov.github.io/react-sparklines/img/customizable.png) 58 | 59 | ``` 60 | import React from 'react'; 61 | import { Sparklines, SparklinesLine } from 'react-sparklines'; 62 | ... 63 | 64 | 65 | 66 | ``` 67 | 68 | #### Bars 69 | 70 | ![](http://borisyankov.github.io/react-sparklines/img/bars.png) 71 | 72 | 73 | ``` 74 | import React from 'react'; 75 | import { Sparklines, SparklinesBars } from 'react-sparklines'; 76 | ... 77 | 78 | 79 | 80 | ``` 81 | 82 | #### Spots 83 | 84 | ![](http://borisyankov.github.io/react-sparklines/img/spots.png) 85 | 86 | 87 | ``` 88 | import React from 'react'; 89 | import { Sparklines, SparklinesLine, SparklinesSpots } from 'react-sparklines'; 90 | ... 91 | 92 | 93 | 94 | 95 | ``` 96 | 97 | #### Reference Line 98 | 99 | ![](http://borisyankov.github.io/react-sparklines/img/referenceline.png) 100 | 101 | 102 | ``` 103 | import React from 'react'; 104 | import { Sparklines, SparklinesLine, SparklinesReferenceLine } from 'react-sparklines'; 105 | ... 106 | 107 | 108 | 109 | 110 | ``` 111 | 112 | #### Normal Band 113 | 114 | ![](http://borisyankov.github.io/react-sparklines/img/normalband.png) 115 | 116 | 117 | ``` 118 | import React from 'react'; 119 | import { Sparklines, SparklinesLine, SparklinesNormalBand } from 'react-sparklines'; 120 | ... 121 | 122 | 123 | 124 | 125 | ``` 126 | -------------------------------------------------------------------------------- /__tests__/Sparklines.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { shallow } from 'enzyme'; 4 | import { expect } from 'chai'; 5 | import { Sparklines } from '../src/Sparklines'; 6 | 7 | describe('Sparklines', () => { 8 | it('does not throw without any parameters', () => { 9 | expect(() => ).to.not.throw; 10 | }); 11 | 12 | it('renders nothing when passed no data', () => { 13 | const wrapper = shallow(); 14 | expect(wrapper.find('svg')).to.have.length(0); 15 | }); 16 | 17 | it('is rendered as svg', () => { 18 | const wrapper = shallow(); 19 | expect(wrapper.find('svg')).to.have.length(1); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /__tests__/compareSvg.js: -------------------------------------------------------------------------------- 1 | import hiff from 'hiff'; 2 | 3 | function normalizeStyle(style) { 4 | style = (style || '').split(';').map(s => s.trim()); 5 | style.sort(); 6 | return style.join(';'); 7 | } 8 | 9 | function normalizeAttrs(...$ns) { 10 | for (let $n of $ns) { 11 | if ($n.attr('style')) 12 | $n.attr('style', normalizeStyle($n.attr('style'))); 13 | } 14 | } 15 | 16 | function comparatorFn($n1, $n2, childChanges) { 17 | normalizeAttrs($n1, $n2); 18 | return hiff.defaultTagComparisonFn($n1, $n2, childChanges); 19 | } 20 | 21 | export default function compareSvg(svg1, svg2, options = {}) { 22 | return hiff.compare(svg1, svg2, Object.assign({}, options, {tagComparison: comparatorFn})); 23 | } 24 | -------------------------------------------------------------------------------- /__tests__/dataToPoints.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import dataToPoints from '../src/dataProcessing/dataToPoints'; 3 | 4 | describe('dataToPoints', () => { 5 | 6 | it('should return an array', () => { 7 | expect(dataToPoints({ data: [] })).to.be.an('array'); 8 | expect(dataToPoints({ data: [1, 2, 3] })).to.be.an('array'); 9 | expect(dataToPoints({ data: [1, null, undefined] })).to.be.an('array'); 10 | }); 11 | 12 | it('should return only `limit` items', () => { 13 | expect(dataToPoints({ data: [1,2,3,4,5] })).to.have.length(5); 14 | expect(dataToPoints({ data: [1,2,3,4,5], limit: 2 })).to.have.length(2); 15 | expect(dataToPoints({ data: [1,2,3,4,5], limit: 5 })).to.have.length(5); 16 | expect(dataToPoints({ data: [1,2,3,4,5], limit: 10 })).to.have.length(5); 17 | }); 18 | 19 | it('should return proper values for 1 value', () => { 20 | expect(dataToPoints({ data: [1] })).to.eql([ 21 | {x: 0, y: 0.5} 22 | ]) 23 | }); 24 | 25 | it('should return proper values 2+ values', () => { 26 | expect(dataToPoints({ data: [1,1] })).to.eql([ 27 | {x: 0, y: 0.5}, 28 | {x: 1, y: 0.5} 29 | ]) 30 | 31 | expect(dataToPoints({ data: [0,1] })).to.eql([ 32 | {x: 0, y: 1}, 33 | {x: 1, y: 0} 34 | ]) 35 | 36 | expect(dataToPoints({ data: [1,0] })).to.eql([ 37 | {x: 0, y: 0}, 38 | {x: 1, y: 1} 39 | ]) 40 | 41 | expect(dataToPoints({ data: [0,1,2] })).to.eql([ 42 | {x: 0, y: 1}, 43 | {x: 0.5, y: 0.5}, 44 | {x: 1, y: 0} 45 | ]) 46 | }); 47 | 48 | it('should inerpolate values properly', () => { 49 | expect(dataToPoints({data: [0,1,2], width: 10, height: 10 })).to.eql([ 50 | {x: 0, y: 10}, 51 | {x: 5, y: 5}, 52 | {x: 10, y: 0} 53 | ]) 54 | }); 55 | 56 | it('should take min and max into account', () => { 57 | expect(dataToPoints({ data: [1,2,3,4], width: 6, height: 10, max: 2, min: 3 })).to.eql([ 58 | {x: 0, y: -10}, 59 | {x: 2, y: 0}, 60 | {x: 4, y: 10}, 61 | {x: 6, y: 20} 62 | ]) 63 | }); 64 | 65 | it('should return y == height for 0 and null values', () => { 66 | expect(dataToPoints({ data: [0] })).to.eql([ 67 | {x: 0, y: 0.5} 68 | ]) 69 | expect(dataToPoints({ data: [0, null, 0] })).to.eql([ 70 | {x: 0, y: 0.5}, 71 | {x: 0.5, y: 0.5}, 72 | {x: 1, y: 0.5} 73 | ]) 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /__tests__/graphical-tests.js: -------------------------------------------------------------------------------- 1 | import fixtures from './fixtures'; 2 | import { render } from 'enzyme'; 3 | import { expect } from 'chai'; 4 | import compareSvg from './compareSvg'; 5 | 6 | describe.skip('Graphical tests from fixtures.js', function() { 7 | for (let key of Object.keys(fixtures)) { 8 | describe(`${key}`, function() { 9 | it('should render as specified', function() { 10 | const wrapper = render(fixtures[key].jsx); 11 | const result = compareSvg(wrapper.html(), fixtures[key].svg); 12 | const errorMessage = 'SVG output changed:\n' + result.changes.map(change => change.message).join('\n') + '\n'; 13 | expect(result.changes, errorMessage).to.be.empty; 14 | }); 15 | }); 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /__tests__/mean.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import mean from '../src/dataProcessing/mean'; 3 | 4 | describe('mean', () => { 5 | it('should return average of values', () => { 6 | expect(mean([0])).to.eq(0) 7 | expect(mean([0, 1])).to.eq(0.5) 8 | expect(mean([1, 2])).to.eq(3/2) 9 | expect(mean([0, 1, 2])).to.eq(1) 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /__tests__/median.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import median from '../src/dataProcessing/median'; 3 | 4 | describe('median', () => { 5 | it('should return median of values', () => { 6 | expect(median([0])).to.eq(0) 7 | expect(median([0, 1])).to.eq(1) 8 | expect(median([1, 2, 3])).to.eq(2) 9 | expect(median([5, 4, 3, 2, 1])).to.eq(3) 10 | expect(median([2, 4, 1, 3, 5])).to.eq(3) 11 | }); 12 | 13 | it('should calculate median by correctly sorting numbers, not lexicographically', () => { 14 | expect(median([0, 20, 100])).to.eq(20) 15 | expect(median([1, 3, 5, 7, 100, 1000, 10000])).to.eq(7) 16 | }); 17 | 18 | it('should calculate median for real-world data', () => { 19 | const data = [6161.719669666667,4995.179579999999,4040.0326529999998,3776.188567,2969.1544076666664,4701.473427,3128.7432525,3299.3572713333333,4272.681012,3422.561293333333,3462.3769910000005,4303.3568116666665,12118.759180333333,5272.167418666666,3130.953679666666,3830.7221036666665,4253.371313333333,6885.048253666668,4065.784471333334,4051.3181206666673,3312.486034666667,3519.332053333333,3578.4504983333336,3061.1413410000005,82353.92672433333,3166.496492,3962.746236333333,3355.8355669999996,3234.4706403333334,3319.0170516666667,3334.766027666667,7453.3247703333345,3356.1106466666665,7517.256305666666,6227.504952666667,2999.276804666666,3185.139871,2740.3619040000003,3554.696368,3908.206846,3055.0123826666663,3224.6066153333336,3576.984728,4848.392336666667,5388.439963000001,3662.7132256666664,6323.533573333332,3432.6356856666666,6223.385519666666,3137.5223516666665,4890.759132333333,3131.3128269999997,3814.362825333333,3452.1440953333336,2932.7764999999995,2816.087773333333,3989.263918666667,3113.313537,4504.276532333333,3561.8186296666663,3505.547739666667,4404.111484,4417.891140666666,4269.754091666667,3434.4542200000005,5476.430249666667,6312.4283306666675,5366.578057333334,3830.2674359999996,4812.407597333333,3376.3011166666674,3358.902772,6465.302481,3668.810244,2920.755890666667,4098.664499333333,3245.7028793333334,3443.5763826666666,3053.3344556666666,5223.266786,4993.329616000001,4095.5644090000005,3369.0089953333336,4341.683867,3377.744091666667,6399.325108333333,3453.0122806666664,2891.474329333333,4122.205589333334,4019.51985,3977.8773416666663,3615.6507353333336,4873.987182666668,3638.5405246666664,2889.41178]; 20 | expect(median(data)).to.eq(3668.810244) 21 | }) 22 | }); 23 | -------------------------------------------------------------------------------- /__tests__/sampleData.js: -------------------------------------------------------------------------------- 1 | export const sampleData = [ 2 | 0.26789611283279424, 3 | -1.5618808743590797, 4 | -0.46848826820269196, 5 | -0.02429709108986638, 6 | -0.07347501430506465, 7 | 0.938722048681125, 8 | -0.02488170176918398, 9 | 0.014511315562131895, 10 | -1.0920317808493079, 11 | -1.6226651458214956, 12 | 0.6777968350341455, 13 | -1.0989601025670448, 14 | 1.402853678778828, 15 | -1.7923422052616966, 16 | -0.37025235972161835, 17 | -0.10254054014867667, 18 | 0.3709902985604339, 19 | 2.5285657626539253, 20 | -0.18958673659343403, 21 | 0.8578243085059141, 22 | 1.7395812075504404, 23 | 0.9723534409914075, 24 | -0.6799757002898873, 25 | 1.153081489500828, 26 | 1.3851189843556257, 27 | 0.19355625368483506, 28 | 1.262069965103209, 29 | -0.8628137671385424, 30 | -0.6118030618030503, 31 | -0.25257403618789087 32 | ]; 33 | 34 | export const sampleData100 = [ 35 | -0.2809926205121489, 36 | 0.5993223086924007, 37 | 0.5450586119753267, 38 | -0.4794107823559421, 39 | -0.18298272472350668, 40 | 0.3219712568468161, 41 | 2.0566174540438324, 42 | -1.6442809970641576, 43 | 1.971025186834513, 44 | 0.37237930811331116, 45 | -0.4015753275277232, 46 | 1.0601229819271032, 47 | -2.0983317267366988, 48 | 0.26835584955818786, 49 | -0.2899975217753408, 50 | -0.6342464890422705, 51 | -0.10975205424415876, 52 | 0.39583180670735013, 53 | 1.4695948548213784, 54 | -1.2295606440627673, 55 | 1.0056333434310312, 56 | 1.006402733277956, 57 | -1.4092655719724325, 58 | 0.17595701557726026, 59 | -0.19396518917878047, 60 | -1.4314174397644206, 61 | -0.34402041741926476, 62 | 0.6986827111240516, 63 | -0.6157663396302129, 64 | 1.0606864486721386, 65 | 1.3537300165741912, 66 | -0.9521291296713654, 67 | -1.089926042595364, 68 | -0.9723342804049446, 69 | 0.2286317959508994, 70 | 0.2613862542298905, 71 | 0.24840731355644413, 72 | 2.08064561830636, 73 | 0.44534855831763426, 74 | 1.5511436162779393, 75 | -1.5514313805901196, 76 | -0.7497893094776009, 77 | 0.4027674242193654, 78 | -0.38986316786208264, 79 | -1.2167765233154504, 80 | 0.18879490542570268, 81 | -1.5284852088503573, 82 | 0.8789559275619153, 83 | -1.2451506359938267, 84 | -0.7226040247250638, 85 | -0.07157034383583998, 86 | 1.9901707247581082, 87 | 0.22166972734467405, 88 | 0.058080839429433054, 89 | -0.6324465858010533, 90 | -0.8091687560181702, 91 | -1.293296284426419, 92 | 1.8436776591711028, 93 | -0.28314101700652944, 94 | 1.358988312176975, 95 | -0.1152691343859452, 96 | -2.425199332455914, 97 | 0.6696100792204956, 98 | 1.7308347028588733, 99 | -0.9997610678433961, 100 | -0.10106296722138419, 101 | 0.3157348177184432, 102 | -0.34931234065268996, 103 | 0.4662049447935582, 104 | 0.8793589099345607, 105 | 2.069923608446714, 106 | 1.3861543531394107, 107 | -0.2705101572065443, 108 | 0.5980871990258989, 109 | -0.5871146157743545, 110 | -0.9844080263005216, 111 | 0.2972697252124295, 112 | -0.6119868603373193, 113 | -1.8902200290484288, 114 | 0.6996282188319667, 115 | -0.24883654266800448, 116 | -0.1156025389007573, 117 | 1.0370156630612894, 118 | 0.9750054921585302, 119 | -0.635000984672242, 120 | 0.16076716404020402, 121 | 0.1379262931648021, 122 | -0.6838899322825195, 123 | 0.6088591150304701, 124 | -0.3408579041001186, 125 | -0.08790701313160872, 126 | -0.38412257182424137, 127 | -1.3319278452946857, 128 | 0.7154759857504911, 129 | -2.8727571205730915, 130 | -1.3501468729225303, 131 | -0.0865770144109483, 132 | 0.505651174224522, 133 | -2.2111682240498753, 134 | 2.035381345199811 135 | ]; 136 | -------------------------------------------------------------------------------- /bootstrap-tests.js: -------------------------------------------------------------------------------- 1 | // bootstrap-tests.js - A tool for updating the test cases in __tests__/fixtures.js 2 | // 3 | // 1) Reads __tests__/fixtures.js and looks for a "dynamic part", which should be a list of fields 4 | // belonging to that file's default export, enclosed in a pair of markers (see "signal" constants 5 | // below). 6 | // 2) Imports the same fixtures file and (re-)renders each ReactElement to a static SVG string. 7 | // 3) On success, overwrites __tests__/fixtures.js with an updated copy. 8 | // 9 | // Run with babel-node or using "npm run test:bootstrap". 10 | 11 | import path from 'path'; 12 | import { render } from 'enzyme'; 13 | import LineByLineReader from 'line-by-line'; 14 | import reactElementToJsx from 'react-element-to-jsx-string'; 15 | import { writeFileSync } from 'fs'; 16 | import replaceAll from 'replaceall'; 17 | import React from 'react'; 18 | 19 | const fixturesFile = path.resolve(__dirname, './__tests__/fixtures.js'); 20 | const dynamicPartStartSignal = '// AUTO-GENERATED PART STARTS HERE'; 21 | const dynamicPartEndSignal = '// AUTO-GENERATED PART ENDS HERE'; 22 | 23 | const fixtures = require(fixturesFile).default; 24 | 25 | // Handle recurring data constants 26 | import { sampleData, sampleData100 } from './__tests__/data'; 27 | const recognizedDataConstants = { 28 | sampleData, sampleData100 29 | }; 30 | const recognizedDataStrings = {}; 31 | for (let dataKey of Object.keys(recognizedDataConstants)) { 32 | recognizedDataStrings[dataKey] = markupToOneLine(reactElementToJsx(
) 33 | .replace(/[^{]*\{|\}[^}]*/g, '')); 34 | } 35 | 36 | // Output control 37 | let outData = ''; 38 | const write = content => { outData += content + '\n'; } 39 | const save = () => writeFileSync(fixturesFile, outData); 40 | function writeFixtures() { 41 | for (let key of Object.keys(fixtures)) { 42 | const jsx = fixtures[key].jsx; 43 | const wrapper = render(jsx); 44 | let jsxCode = `(${markupToOneLine(reactElementToJsx(jsx))})`; 45 | const htmlCode = JSON.stringify(wrapper.html()); 46 | for (let dataKey of Object.keys(recognizedDataStrings)) { 47 | jsxCode = replaceAll(recognizedDataStrings[dataKey], dataKey, jsxCode); 48 | } 49 | write(`\t${JSON.stringify(key)}: {jsx: ${jsxCode}, svg: ${htmlCode}},`); 50 | } 51 | } 52 | function markupToOneLine(code) { 53 | return code.replace(/\s*[\r\n]\s*/g, ' ').replace(/\s+/g, ' ').replace(/\s*([<>])\s*/g, '$1'); 54 | } 55 | 56 | // Input control 57 | const lr = new LineByLineReader(fixturesFile, {skipEmptyLines: false}); 58 | let inDynamicPart = false, dynamicPartCount = 0, lineCount = 0; 59 | 60 | lr.on('line', line => { 61 | ++lineCount; 62 | if (line === dynamicPartStartSignal) { 63 | if (inDynamicPart) 64 | throw new LineError('Dynamic part opened again'); 65 | ++dynamicPartCount; 66 | if (dynamicPartCount > 1) 67 | throw new LineError('Multiple dynamic parts found'); 68 | inDynamicPart = true; 69 | write(line); 70 | try { 71 | writeFixtures(); 72 | } catch(e) { 73 | throw new LineError(e); 74 | } 75 | } 76 | else if (line === dynamicPartEndSignal) { 77 | if (!inDynamicPart) 78 | throw new LineError('Dynamic part closed again'); 79 | inDynamicPart = false; 80 | write(line); 81 | } 82 | else if (!inDynamicPart) 83 | write(line); 84 | }); 85 | 86 | lr.on('end', () => { 87 | if (inDynamicPart) { 88 | throw new LineError('Dynamic part not closed'); 89 | } 90 | if (!dynamicPartCount) { 91 | throw new LineError('No dynamic part found in file!'); 92 | } 93 | save(); 94 | }); 95 | 96 | lr.on('error', function (err) { 97 | throw new LineError(err); 98 | }); 99 | 100 | class LineError extends Error { 101 | constructor(message) { 102 | super(`${fixturesFile}:${lineCount}: ${message}`); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /build/index.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(require("react")); 4 | else if(typeof define === 'function' && define.amd) 5 | define(["react"], factory); 6 | else if(typeof exports === 'object') 7 | exports["ReactSparklines"] = factory(require("react")); 8 | else 9 | root["ReactSparklines"] = factory(root["React"]); 10 | })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) 20 | /******/ return installedModules[moduleId].exports; 21 | 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ i: moduleId, 25 | /******/ l: false, 26 | /******/ exports: {} 27 | /******/ }; 28 | 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | 32 | /******/ // Flag the module as loaded 33 | /******/ module.l = true; 34 | 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | 39 | 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | 46 | /******/ // identity function for calling harmony imports with the correct context 47 | /******/ __webpack_require__.i = function(value) { return value; }; 48 | 49 | /******/ // define getter function for harmony exports 50 | /******/ __webpack_require__.d = function(exports, name, getter) { 51 | /******/ if(!__webpack_require__.o(exports, name)) { 52 | /******/ Object.defineProperty(exports, name, { 53 | /******/ configurable: false, 54 | /******/ enumerable: true, 55 | /******/ get: getter 56 | /******/ }); 57 | /******/ } 58 | /******/ }; 59 | 60 | /******/ // getDefaultExport function for compatibility with non-harmony modules 61 | /******/ __webpack_require__.n = function(module) { 62 | /******/ var getter = module && module.__esModule ? 63 | /******/ function getDefault() { return module['default']; } : 64 | /******/ function getModuleExports() { return module; }; 65 | /******/ __webpack_require__.d(getter, 'a', getter); 66 | /******/ return getter; 67 | /******/ }; 68 | 69 | /******/ // Object.prototype.hasOwnProperty.call 70 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 71 | 72 | /******/ // __webpack_public_path__ 73 | /******/ __webpack_require__.p = "/"; 74 | 75 | /******/ // Load entry module and return exports 76 | /******/ return __webpack_require__(__webpack_require__.s = 31); 77 | /******/ }) 78 | /************************************************************************/ 79 | /******/ ([ 80 | /* 0 */ 81 | /***/ (function(module, exports, __webpack_require__) { 82 | 83 | /* WEBPACK VAR INJECTION */(function(process) {/** 84 | * Copyright 2013-present, Facebook, Inc. 85 | * All rights reserved. 86 | * 87 | * This source code is licensed under the BSD-style license found in the 88 | * LICENSE file in the root directory of this source tree. An additional grant 89 | * of patent rights can be found in the PATENTS file in the same directory. 90 | */ 91 | 92 | if (process.env.NODE_ENV !== 'production') { 93 | var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' && 94 | Symbol.for && 95 | Symbol.for('react.element')) || 96 | 0xeac7; 97 | 98 | var isValidElement = function(object) { 99 | return typeof object === 'object' && 100 | object !== null && 101 | object.$$typeof === REACT_ELEMENT_TYPE; 102 | }; 103 | 104 | // By explicitly using `prop-types` you are opting into new development behavior. 105 | // http://fb.me/prop-types-in-prod 106 | var throwOnDirectAccess = true; 107 | module.exports = __webpack_require__(28)(isValidElement, throwOnDirectAccess); 108 | } else { 109 | // By explicitly using `prop-types` you are opting into new production behavior. 110 | // http://fb.me/prop-types-in-prod 111 | module.exports = __webpack_require__(27)(); 112 | } 113 | 114 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 115 | 116 | /***/ }), 117 | /* 1 */ 118 | /***/ (function(module, exports) { 119 | 120 | module.exports = __WEBPACK_EXTERNAL_MODULE_1__; 121 | 122 | /***/ }), 123 | /* 2 */ 124 | /***/ (function(module, exports) { 125 | 126 | // shim for using process in browser 127 | var process = module.exports = {}; 128 | 129 | // cached from whatever global is present so that test runners that stub it 130 | // don't break things. But we need to wrap it in a try catch in case it is 131 | // wrapped in strict mode code which doesn't define any globals. It's inside a 132 | // function because try/catches deoptimize in certain engines. 133 | 134 | var cachedSetTimeout; 135 | var cachedClearTimeout; 136 | 137 | function defaultSetTimout() { 138 | throw new Error('setTimeout has not been defined'); 139 | } 140 | function defaultClearTimeout () { 141 | throw new Error('clearTimeout has not been defined'); 142 | } 143 | (function () { 144 | try { 145 | if (typeof setTimeout === 'function') { 146 | cachedSetTimeout = setTimeout; 147 | } else { 148 | cachedSetTimeout = defaultSetTimout; 149 | } 150 | } catch (e) { 151 | cachedSetTimeout = defaultSetTimout; 152 | } 153 | try { 154 | if (typeof clearTimeout === 'function') { 155 | cachedClearTimeout = clearTimeout; 156 | } else { 157 | cachedClearTimeout = defaultClearTimeout; 158 | } 159 | } catch (e) { 160 | cachedClearTimeout = defaultClearTimeout; 161 | } 162 | } ()) 163 | function runTimeout(fun) { 164 | if (cachedSetTimeout === setTimeout) { 165 | //normal enviroments in sane situations 166 | return setTimeout(fun, 0); 167 | } 168 | // if setTimeout wasn't available but was latter defined 169 | if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { 170 | cachedSetTimeout = setTimeout; 171 | return setTimeout(fun, 0); 172 | } 173 | try { 174 | // when when somebody has screwed with setTimeout but no I.E. maddness 175 | return cachedSetTimeout(fun, 0); 176 | } catch(e){ 177 | try { 178 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 179 | return cachedSetTimeout.call(null, fun, 0); 180 | } catch(e){ 181 | // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error 182 | return cachedSetTimeout.call(this, fun, 0); 183 | } 184 | } 185 | 186 | 187 | } 188 | function runClearTimeout(marker) { 189 | if (cachedClearTimeout === clearTimeout) { 190 | //normal enviroments in sane situations 191 | return clearTimeout(marker); 192 | } 193 | // if clearTimeout wasn't available but was latter defined 194 | if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { 195 | cachedClearTimeout = clearTimeout; 196 | return clearTimeout(marker); 197 | } 198 | try { 199 | // when when somebody has screwed with setTimeout but no I.E. maddness 200 | return cachedClearTimeout(marker); 201 | } catch (e){ 202 | try { 203 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 204 | return cachedClearTimeout.call(null, marker); 205 | } catch (e){ 206 | // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. 207 | // Some versions of I.E. have different rules for clearTimeout vs setTimeout 208 | return cachedClearTimeout.call(this, marker); 209 | } 210 | } 211 | 212 | 213 | 214 | } 215 | var queue = []; 216 | var draining = false; 217 | var currentQueue; 218 | var queueIndex = -1; 219 | 220 | function cleanUpNextTick() { 221 | if (!draining || !currentQueue) { 222 | return; 223 | } 224 | draining = false; 225 | if (currentQueue.length) { 226 | queue = currentQueue.concat(queue); 227 | } else { 228 | queueIndex = -1; 229 | } 230 | if (queue.length) { 231 | drainQueue(); 232 | } 233 | } 234 | 235 | function drainQueue() { 236 | if (draining) { 237 | return; 238 | } 239 | var timeout = runTimeout(cleanUpNextTick); 240 | draining = true; 241 | 242 | var len = queue.length; 243 | while(len) { 244 | currentQueue = queue; 245 | queue = []; 246 | while (++queueIndex < len) { 247 | if (currentQueue) { 248 | currentQueue[queueIndex].run(); 249 | } 250 | } 251 | queueIndex = -1; 252 | len = queue.length; 253 | } 254 | currentQueue = null; 255 | draining = false; 256 | runClearTimeout(timeout); 257 | } 258 | 259 | process.nextTick = function (fun) { 260 | var args = new Array(arguments.length - 1); 261 | if (arguments.length > 1) { 262 | for (var i = 1; i < arguments.length; i++) { 263 | args[i - 1] = arguments[i]; 264 | } 265 | } 266 | queue.push(new Item(fun, args)); 267 | if (queue.length === 1 && !draining) { 268 | runTimeout(drainQueue); 269 | } 270 | }; 271 | 272 | // v8 likes predictible objects 273 | function Item(fun, array) { 274 | this.fun = fun; 275 | this.array = array; 276 | } 277 | Item.prototype.run = function () { 278 | this.fun.apply(null, this.array); 279 | }; 280 | process.title = 'browser'; 281 | process.browser = true; 282 | process.env = {}; 283 | process.argv = []; 284 | process.version = ''; // empty string to avoid regexp issues 285 | process.versions = {}; 286 | 287 | function noop() {} 288 | 289 | process.on = noop; 290 | process.addListener = noop; 291 | process.once = noop; 292 | process.off = noop; 293 | process.removeListener = noop; 294 | process.removeAllListeners = noop; 295 | process.emit = noop; 296 | 297 | process.binding = function (name) { 298 | throw new Error('process.binding is not supported'); 299 | }; 300 | 301 | process.cwd = function () { return '/' }; 302 | process.chdir = function (dir) { 303 | throw new Error('process.chdir is not supported'); 304 | }; 305 | process.umask = function() { return 0; }; 306 | 307 | 308 | /***/ }), 309 | /* 3 */ 310 | /***/ (function(module, exports, __webpack_require__) { 311 | 312 | "use strict"; 313 | 314 | 315 | Object.defineProperty(exports, "__esModule", { 316 | value: true 317 | }); 318 | 319 | exports.default = function (data) { 320 | return data.reduce(function (a, b) { 321 | return a + b; 322 | }) / data.length; 323 | }; 324 | 325 | /***/ }), 326 | /* 4 */ 327 | /***/ (function(module, exports, __webpack_require__) { 328 | 329 | "use strict"; 330 | 331 | 332 | Object.defineProperty(exports, "__esModule", { 333 | value: true 334 | }); 335 | 336 | exports.default = function (data) { 337 | return Math.min.apply(Math, data); 338 | }; 339 | 340 | /***/ }), 341 | /* 5 */ 342 | /***/ (function(module, exports, __webpack_require__) { 343 | 344 | "use strict"; 345 | /** 346 | * Copyright 2013-present, Facebook, Inc. 347 | * All rights reserved. 348 | * 349 | * This source code is licensed under the BSD-style license found in the 350 | * LICENSE file in the root directory of this source tree. An additional grant 351 | * of patent rights can be found in the PATENTS file in the same directory. 352 | */ 353 | 354 | 355 | 356 | var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'; 357 | 358 | module.exports = ReactPropTypesSecret; 359 | 360 | 361 | /***/ }), 362 | /* 6 */ 363 | /***/ (function(module, exports, __webpack_require__) { 364 | 365 | "use strict"; 366 | 367 | 368 | /** 369 | * Copyright (c) 2013-present, Facebook, Inc. 370 | * All rights reserved. 371 | * 372 | * This source code is licensed under the BSD-style license found in the 373 | * LICENSE file in the root directory of this source tree. An additional grant 374 | * of patent rights can be found in the PATENTS file in the same directory. 375 | * 376 | * 377 | */ 378 | 379 | function makeEmptyFunction(arg) { 380 | return function () { 381 | return arg; 382 | }; 383 | } 384 | 385 | /** 386 | * This function accepts and discards inputs; it has no side effects. This is 387 | * primarily useful idiomatically for overridable function endpoints which 388 | * always need to be callable, since JS lacks a null-call idiom ala Cocoa. 389 | */ 390 | var emptyFunction = function emptyFunction() {}; 391 | 392 | emptyFunction.thatReturns = makeEmptyFunction; 393 | emptyFunction.thatReturnsFalse = makeEmptyFunction(false); 394 | emptyFunction.thatReturnsTrue = makeEmptyFunction(true); 395 | emptyFunction.thatReturnsNull = makeEmptyFunction(null); 396 | emptyFunction.thatReturnsThis = function () { 397 | return this; 398 | }; 399 | emptyFunction.thatReturnsArgument = function (arg) { 400 | return arg; 401 | }; 402 | 403 | module.exports = emptyFunction; 404 | 405 | /***/ }), 406 | /* 7 */ 407 | /***/ (function(module, exports, __webpack_require__) { 408 | 409 | "use strict"; 410 | /* WEBPACK VAR INJECTION */(function(process) {/** 411 | * Copyright (c) 2013-present, Facebook, Inc. 412 | * All rights reserved. 413 | * 414 | * This source code is licensed under the BSD-style license found in the 415 | * LICENSE file in the root directory of this source tree. An additional grant 416 | * of patent rights can be found in the PATENTS file in the same directory. 417 | * 418 | */ 419 | 420 | 421 | 422 | /** 423 | * Use invariant() to assert state which your program assumes to be true. 424 | * 425 | * Provide sprintf-style format (only %s is supported) and arguments 426 | * to provide information about what broke and what you were 427 | * expecting. 428 | * 429 | * The invariant message will be stripped in production, but the invariant 430 | * will remain to ensure logic does not differ in production. 431 | */ 432 | 433 | var validateFormat = function validateFormat(format) {}; 434 | 435 | if (process.env.NODE_ENV !== 'production') { 436 | validateFormat = function validateFormat(format) { 437 | if (format === undefined) { 438 | throw new Error('invariant requires an error message argument'); 439 | } 440 | }; 441 | } 442 | 443 | function invariant(condition, format, a, b, c, d, e, f) { 444 | validateFormat(format); 445 | 446 | if (!condition) { 447 | var error; 448 | if (format === undefined) { 449 | error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); 450 | } else { 451 | var args = [a, b, c, d, e, f]; 452 | var argIndex = 0; 453 | error = new Error(format.replace(/%s/g, function () { 454 | return args[argIndex++]; 455 | })); 456 | error.name = 'Invariant Violation'; 457 | } 458 | 459 | error.framesToPop = 1; // we don't care about invariant's own frame 460 | throw error; 461 | } 462 | } 463 | 464 | module.exports = invariant; 465 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 466 | 467 | /***/ }), 468 | /* 8 */ 469 | /***/ (function(module, exports, __webpack_require__) { 470 | 471 | "use strict"; 472 | 473 | 474 | Object.defineProperty(exports, "__esModule", { 475 | value: true 476 | }); 477 | 478 | exports.default = function (data) { 479 | return Math.max.apply(Math, data); 480 | }; 481 | 482 | /***/ }), 483 | /* 9 */ 484 | /***/ (function(module, exports, __webpack_require__) { 485 | 486 | "use strict"; 487 | 488 | 489 | Object.defineProperty(exports, "__esModule", { 490 | value: true 491 | }); 492 | 493 | var _mean = __webpack_require__(3); 494 | 495 | var _mean2 = _interopRequireDefault(_mean); 496 | 497 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 498 | 499 | exports.default = function (data) { 500 | var dataMean = (0, _mean2.default)(data); 501 | var sqDiff = data.map(function (n) { 502 | return Math.pow(n - dataMean, 2); 503 | }); 504 | var avgSqDiff = (0, _mean2.default)(sqDiff); 505 | return Math.sqrt(avgSqDiff); 506 | }; 507 | 508 | /***/ }), 509 | /* 10 */ 510 | /***/ (function(module, exports, __webpack_require__) { 511 | 512 | "use strict"; 513 | /* WEBPACK VAR INJECTION */(function(process) {/** 514 | * Copyright 2014-2015, Facebook, Inc. 515 | * All rights reserved. 516 | * 517 | * This source code is licensed under the BSD-style license found in the 518 | * LICENSE file in the root directory of this source tree. An additional grant 519 | * of patent rights can be found in the PATENTS file in the same directory. 520 | * 521 | */ 522 | 523 | 524 | 525 | var emptyFunction = __webpack_require__(6); 526 | 527 | /** 528 | * Similar to invariant but only logs a warning if the condition is not met. 529 | * This can be used to log issues in development environments in critical 530 | * paths. Removing the logging code for production environments will keep the 531 | * same logic and follow the same code paths. 532 | */ 533 | 534 | var warning = emptyFunction; 535 | 536 | if (process.env.NODE_ENV !== 'production') { 537 | (function () { 538 | var printWarning = function printWarning(format) { 539 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 540 | args[_key - 1] = arguments[_key]; 541 | } 542 | 543 | var argIndex = 0; 544 | var message = 'Warning: ' + format.replace(/%s/g, function () { 545 | return args[argIndex++]; 546 | }); 547 | if (typeof console !== 'undefined') { 548 | console.error(message); 549 | } 550 | try { 551 | // --- Welcome to debugging React --- 552 | // This error was thrown as a convenience so that you can use this stack 553 | // to find the callsite that caused this warning to fire. 554 | throw new Error(message); 555 | } catch (x) {} 556 | }; 557 | 558 | warning = function warning(condition, format) { 559 | if (format === undefined) { 560 | throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); 561 | } 562 | 563 | if (format.indexOf('Failed Composite propType: ') === 0) { 564 | return; // Ignore CompositeComponent proptype check. 565 | } 566 | 567 | if (!condition) { 568 | for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { 569 | args[_key2 - 2] = arguments[_key2]; 570 | } 571 | 572 | printWarning.apply(undefined, [format].concat(args)); 573 | } 574 | }; 575 | })(); 576 | } 577 | 578 | module.exports = warning; 579 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 580 | 581 | /***/ }), 582 | /* 11 */ 583 | /***/ (function(module, exports, __webpack_require__) { 584 | 585 | "use strict"; 586 | 587 | 588 | module.exports = __webpack_require__(12); 589 | 590 | /***/ }), 591 | /* 12 */ 592 | /***/ (function(module, exports, __webpack_require__) { 593 | 594 | "use strict"; 595 | 596 | 597 | Object.defineProperty(exports, "__esModule", { 598 | value: true 599 | }); 600 | exports.SparklinesText = exports.SparklinesNormalBand = exports.SparklinesReferenceLine = exports.SparklinesSpots = exports.SparklinesBars = exports.SparklinesCurve = exports.SparklinesLine = exports.Sparklines = undefined; 601 | 602 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 603 | 604 | var _propTypes = __webpack_require__(0); 605 | 606 | var _propTypes2 = _interopRequireDefault(_propTypes); 607 | 608 | var _react = __webpack_require__(1); 609 | 610 | var _react2 = _interopRequireDefault(_react); 611 | 612 | var _SparklinesText = __webpack_require__(19); 613 | 614 | var _SparklinesText2 = _interopRequireDefault(_SparklinesText); 615 | 616 | var _SparklinesLine = __webpack_require__(15); 617 | 618 | var _SparklinesLine2 = _interopRequireDefault(_SparklinesLine); 619 | 620 | var _SparklinesCurve = __webpack_require__(14); 621 | 622 | var _SparklinesCurve2 = _interopRequireDefault(_SparklinesCurve); 623 | 624 | var _SparklinesBars = __webpack_require__(13); 625 | 626 | var _SparklinesBars2 = _interopRequireDefault(_SparklinesBars); 627 | 628 | var _SparklinesSpots = __webpack_require__(18); 629 | 630 | var _SparklinesSpots2 = _interopRequireDefault(_SparklinesSpots); 631 | 632 | var _SparklinesReferenceLine = __webpack_require__(17); 633 | 634 | var _SparklinesReferenceLine2 = _interopRequireDefault(_SparklinesReferenceLine); 635 | 636 | var _SparklinesNormalBand = __webpack_require__(16); 637 | 638 | var _SparklinesNormalBand2 = _interopRequireDefault(_SparklinesNormalBand); 639 | 640 | var _dataToPoints = __webpack_require__(20); 641 | 642 | var _dataToPoints2 = _interopRequireDefault(_dataToPoints); 643 | 644 | var _reactAddonsShallowCompare = __webpack_require__(29); 645 | 646 | var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); 647 | 648 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 649 | 650 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 651 | 652 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 653 | 654 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 655 | 656 | var Sparklines = function (_React$Component) { 657 | _inherits(Sparklines, _React$Component); 658 | 659 | function Sparklines(props) { 660 | _classCallCheck(this, Sparklines); 661 | 662 | return _possibleConstructorReturn(this, (Sparklines.__proto__ || Object.getPrototypeOf(Sparklines)).call(this, props)); 663 | } 664 | 665 | _createClass(Sparklines, [{ 666 | key: 'shouldComponentUpdate', 667 | value: function shouldComponentUpdate(nextProps) { 668 | return (0, _reactAddonsShallowCompare2.default)(this, nextProps); 669 | } 670 | }, { 671 | key: 'render', 672 | value: function render() { 673 | var _props = this.props, 674 | data = _props.data, 675 | limit = _props.limit, 676 | width = _props.width, 677 | height = _props.height, 678 | svgWidth = _props.svgWidth, 679 | svgHeight = _props.svgHeight, 680 | preserveAspectRatio = _props.preserveAspectRatio, 681 | margin = _props.margin, 682 | style = _props.style, 683 | max = _props.max, 684 | min = _props.min; 685 | 686 | 687 | if (data.length === 0) return null; 688 | 689 | var points = (0, _dataToPoints2.default)({ data: data, limit: limit, width: width, height: height, margin: margin, max: max, min: min }); 690 | 691 | var svgOpts = { style: style, viewBox: '0 0 ' + width + ' ' + height, preserveAspectRatio: preserveAspectRatio }; 692 | if (svgWidth > 0) svgOpts.width = svgWidth; 693 | if (svgHeight > 0) svgOpts.height = svgHeight; 694 | 695 | return _react2.default.createElement( 696 | 'svg', 697 | svgOpts, 698 | _react2.default.Children.map(this.props.children, function (child) { 699 | return _react2.default.cloneElement(child, { data: data, points: points, width: width, height: height, margin: margin }); 700 | }) 701 | ); 702 | } 703 | }]); 704 | 705 | return Sparklines; 706 | }(_react2.default.Component); 707 | 708 | Sparklines.propTypes = { 709 | data: _propTypes2.default.array, 710 | limit: _propTypes2.default.number, 711 | width: _propTypes2.default.number, 712 | height: _propTypes2.default.number, 713 | svgWidth: _propTypes2.default.number, 714 | svgHeight: _propTypes2.default.number, 715 | preserveAspectRatio: _propTypes2.default.string, 716 | margin: _propTypes2.default.number, 717 | style: _propTypes2.default.object, 718 | min: _propTypes2.default.number, 719 | max: _propTypes2.default.number, 720 | onMouseMove: _propTypes2.default.func 721 | }; 722 | Sparklines.defaultProps = { 723 | data: [], 724 | width: 240, 725 | height: 60, 726 | //Scale the graphic content of the given element non-uniformly if necessary such that the element's bounding box exactly matches the viewport rectangle. 727 | preserveAspectRatio: 'none', //https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute 728 | margin: 2 729 | }; 730 | exports.Sparklines = Sparklines; 731 | exports.SparklinesLine = _SparklinesLine2.default; 732 | exports.SparklinesCurve = _SparklinesCurve2.default; 733 | exports.SparklinesBars = _SparklinesBars2.default; 734 | exports.SparklinesSpots = _SparklinesSpots2.default; 735 | exports.SparklinesReferenceLine = _SparklinesReferenceLine2.default; 736 | exports.SparklinesNormalBand = _SparklinesNormalBand2.default; 737 | exports.SparklinesText = _SparklinesText2.default; 738 | 739 | /***/ }), 740 | /* 13 */ 741 | /***/ (function(module, exports, __webpack_require__) { 742 | 743 | "use strict"; 744 | 745 | 746 | Object.defineProperty(exports, "__esModule", { 747 | value: true 748 | }); 749 | 750 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 751 | 752 | var _propTypes = __webpack_require__(0); 753 | 754 | var _propTypes2 = _interopRequireDefault(_propTypes); 755 | 756 | var _react = __webpack_require__(1); 757 | 758 | var _react2 = _interopRequireDefault(_react); 759 | 760 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 761 | 762 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 763 | 764 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 765 | 766 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 767 | 768 | var SparklinesBars = function (_React$Component) { 769 | _inherits(SparklinesBars, _React$Component); 770 | 771 | function SparklinesBars() { 772 | _classCallCheck(this, SparklinesBars); 773 | 774 | return _possibleConstructorReturn(this, (SparklinesBars.__proto__ || Object.getPrototypeOf(SparklinesBars)).apply(this, arguments)); 775 | } 776 | 777 | _createClass(SparklinesBars, [{ 778 | key: 'render', 779 | value: function render() { 780 | var _this2 = this; 781 | 782 | var _props = this.props, 783 | points = _props.points, 784 | height = _props.height, 785 | style = _props.style, 786 | barWidth = _props.barWidth, 787 | onMouseMove = _props.onMouseMove; 788 | 789 | var strokeWidth = 1 * (style && style.strokeWidth || 0); 790 | var marginWidth = margin ? 2 * margin : 0; 791 | var width = barWidth || (points && points.length >= 2 ? Math.max(0, points[1].x - points[0].x - strokeWidth - marginWidth) : 0); 792 | 793 | return _react2.default.createElement( 794 | 'g', 795 | { transform: 'scale(1,-1)' }, 796 | points.map(function (p, i) { 797 | return _react2.default.createElement('rect', { 798 | key: i, 799 | x: p.x - (width + strokeWidth) / 2, 800 | y: -height, 801 | width: width, 802 | height: Math.max(0, height - p.y), 803 | style: style, 804 | onMouseMove: onMouseMove.bind(_this2, p) }); 805 | }) 806 | ); 807 | } 808 | }]); 809 | 810 | return SparklinesBars; 811 | }(_react2.default.Component); 812 | 813 | SparklinesBars.propTypes = { 814 | points: _propTypes2.default.arrayOf(_propTypes2.default.object), 815 | height: _propTypes2.default.number, 816 | style: _propTypes2.default.object, 817 | barWidth: _propTypes2.default.number, 818 | margin: _propTypes2.default.number, 819 | onMouseMove: _propTypes2.default.func 820 | }; 821 | SparklinesBars.defaultProps = { 822 | style: { fill: 'slategray' } 823 | }; 824 | exports.default = SparklinesBars; 825 | 826 | /***/ }), 827 | /* 14 */ 828 | /***/ (function(module, exports, __webpack_require__) { 829 | 830 | "use strict"; 831 | 832 | 833 | Object.defineProperty(exports, "__esModule", { 834 | value: true 835 | }); 836 | 837 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 838 | 839 | var _propTypes = __webpack_require__(0); 840 | 841 | var _propTypes2 = _interopRequireDefault(_propTypes); 842 | 843 | var _react = __webpack_require__(1); 844 | 845 | var _react2 = _interopRequireDefault(_react); 846 | 847 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 848 | 849 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 850 | 851 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 852 | 853 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 854 | 855 | var SparklinesCurve = function (_React$Component) { 856 | _inherits(SparklinesCurve, _React$Component); 857 | 858 | function SparklinesCurve() { 859 | _classCallCheck(this, SparklinesCurve); 860 | 861 | return _possibleConstructorReturn(this, (SparklinesCurve.__proto__ || Object.getPrototypeOf(SparklinesCurve)).apply(this, arguments)); 862 | } 863 | 864 | _createClass(SparklinesCurve, [{ 865 | key: 'render', 866 | value: function render() { 867 | var _props = this.props, 868 | points = _props.points, 869 | width = _props.width, 870 | height = _props.height, 871 | margin = _props.margin, 872 | color = _props.color, 873 | style = _props.style, 874 | _props$divisor = _props.divisor, 875 | divisor = _props$divisor === undefined ? 0.25 : _props$divisor; 876 | 877 | var prev = void 0; 878 | var curve = function curve(p) { 879 | var res = void 0; 880 | if (!prev) { 881 | res = [p.x, p.y]; 882 | } else { 883 | var len = (p.x - prev.x) * divisor; 884 | res = ["C", 885 | //x1 886 | prev.x + len, 887 | //y1 888 | prev.y, 889 | //x2, 890 | p.x - len, 891 | //y2, 892 | p.y, 893 | //x, 894 | p.x, 895 | //y 896 | p.y]; 897 | } 898 | prev = p; 899 | return res; 900 | }; 901 | var linePoints = points.map(function (p) { 902 | return curve(p); 903 | }).reduce(function (a, b) { 904 | return a.concat(b); 905 | }); 906 | var closePolyPoints = ["L" + points[points.length - 1].x, height - margin, margin, height - margin, margin, points[0].y]; 907 | var fillPoints = linePoints.concat(closePolyPoints); 908 | 909 | var lineStyle = { 910 | stroke: color || style.stroke || 'slategray', 911 | strokeWidth: style.strokeWidth || '1', 912 | strokeLinejoin: style.strokeLinejoin || 'round', 913 | strokeLinecap: style.strokeLinecap || 'round', 914 | fill: 'none' 915 | }; 916 | var fillStyle = { 917 | stroke: style.stroke || 'none', 918 | strokeWidth: '0', 919 | fillOpacity: style.fillOpacity || '.1', 920 | fill: style.fill || color || 'slategray' 921 | }; 922 | 923 | return _react2.default.createElement( 924 | 'g', 925 | null, 926 | _react2.default.createElement('path', { d: "M" + fillPoints.join(' '), style: fillStyle }), 927 | _react2.default.createElement('path', { d: "M" + linePoints.join(' '), style: lineStyle }) 928 | ); 929 | } 930 | }]); 931 | 932 | return SparklinesCurve; 933 | }(_react2.default.Component); 934 | 935 | SparklinesCurve.propTypes = { 936 | color: _propTypes2.default.string, 937 | style: _propTypes2.default.object 938 | }; 939 | SparklinesCurve.defaultProps = { 940 | style: {} 941 | }; 942 | exports.default = SparklinesCurve; 943 | 944 | /***/ }), 945 | /* 15 */ 946 | /***/ (function(module, exports, __webpack_require__) { 947 | 948 | "use strict"; 949 | 950 | 951 | Object.defineProperty(exports, "__esModule", { 952 | value: true 953 | }); 954 | 955 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 956 | 957 | var _propTypes = __webpack_require__(0); 958 | 959 | var _propTypes2 = _interopRequireDefault(_propTypes); 960 | 961 | var _react = __webpack_require__(1); 962 | 963 | var _react2 = _interopRequireDefault(_react); 964 | 965 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 966 | 967 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 968 | 969 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 970 | 971 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 972 | 973 | var SparklinesLine = function (_React$Component) { 974 | _inherits(SparklinesLine, _React$Component); 975 | 976 | function SparklinesLine() { 977 | _classCallCheck(this, SparklinesLine); 978 | 979 | return _possibleConstructorReturn(this, (SparklinesLine.__proto__ || Object.getPrototypeOf(SparklinesLine)).apply(this, arguments)); 980 | } 981 | 982 | _createClass(SparklinesLine, [{ 983 | key: 'render', 984 | value: function render() { 985 | var _props = this.props, 986 | data = _props.data, 987 | points = _props.points, 988 | width = _props.width, 989 | height = _props.height, 990 | margin = _props.margin, 991 | color = _props.color, 992 | style = _props.style, 993 | onMouseMove = _props.onMouseMove; 994 | 995 | 996 | var linePoints = points.map(function (p) { 997 | return [p.x, p.y]; 998 | }).reduce(function (a, b) { 999 | return a.concat(b); 1000 | }); 1001 | 1002 | var closePolyPoints = [points[points.length - 1].x, height - margin, margin, height - margin, margin, points[0].y]; 1003 | 1004 | var fillPoints = linePoints.concat(closePolyPoints); 1005 | 1006 | var lineStyle = { 1007 | stroke: color || style.stroke || 'slategray', 1008 | strokeWidth: style.strokeWidth || '1', 1009 | strokeLinejoin: style.strokeLinejoin || 'round', 1010 | strokeLinecap: style.strokeLinecap || 'round', 1011 | fill: 'none' 1012 | }; 1013 | var fillStyle = { 1014 | stroke: style.stroke || 'none', 1015 | strokeWidth: '0', 1016 | fillOpacity: style.fillOpacity || '.1', 1017 | fill: style.fill || color || 'slategray', 1018 | pointerEvents: 'auto' 1019 | }; 1020 | 1021 | var tooltips = points.map(function (p, i) { 1022 | return _react2.default.createElement('circle', { 1023 | cx: p.x, 1024 | cy: p.y, 1025 | r: 2, 1026 | style: fillStyle, 1027 | onMouseEnter: function onMouseEnter(e) { 1028 | return onMouseMove('enter', data[i], p); 1029 | }, 1030 | onClick: function onClick(e) { 1031 | return onMouseMove('click', data[i], p); 1032 | } 1033 | }); 1034 | }); 1035 | 1036 | return _react2.default.createElement( 1037 | 'g', 1038 | null, 1039 | tooltips, 1040 | _react2.default.createElement('polyline', { points: fillPoints.join(' '), style: fillStyle }), 1041 | _react2.default.createElement('polyline', { points: linePoints.join(' '), style: lineStyle }) 1042 | ); 1043 | } 1044 | }]); 1045 | 1046 | return SparklinesLine; 1047 | }(_react2.default.Component); 1048 | 1049 | SparklinesLine.propTypes = { 1050 | color: _propTypes2.default.string, 1051 | style: _propTypes2.default.object 1052 | }; 1053 | SparklinesLine.defaultProps = { 1054 | style: {} 1055 | }; 1056 | exports.default = SparklinesLine; 1057 | 1058 | /***/ }), 1059 | /* 16 */ 1060 | /***/ (function(module, exports, __webpack_require__) { 1061 | 1062 | "use strict"; 1063 | 1064 | 1065 | Object.defineProperty(exports, "__esModule", { 1066 | value: true 1067 | }); 1068 | 1069 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1070 | 1071 | var _propTypes = __webpack_require__(0); 1072 | 1073 | var _propTypes2 = _interopRequireDefault(_propTypes); 1074 | 1075 | var _react = __webpack_require__(1); 1076 | 1077 | var _react2 = _interopRequireDefault(_react); 1078 | 1079 | var _mean = __webpack_require__(3); 1080 | 1081 | var _mean2 = _interopRequireDefault(_mean); 1082 | 1083 | var _stdev = __webpack_require__(9); 1084 | 1085 | var _stdev2 = _interopRequireDefault(_stdev); 1086 | 1087 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1088 | 1089 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1090 | 1091 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1092 | 1093 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1094 | 1095 | var SparklinesNormalBand = function (_React$Component) { 1096 | _inherits(SparklinesNormalBand, _React$Component); 1097 | 1098 | function SparklinesNormalBand() { 1099 | _classCallCheck(this, SparklinesNormalBand); 1100 | 1101 | return _possibleConstructorReturn(this, (SparklinesNormalBand.__proto__ || Object.getPrototypeOf(SparklinesNormalBand)).apply(this, arguments)); 1102 | } 1103 | 1104 | _createClass(SparklinesNormalBand, [{ 1105 | key: 'render', 1106 | value: function render() { 1107 | var _props = this.props, 1108 | points = _props.points, 1109 | margin = _props.margin, 1110 | style = _props.style; 1111 | 1112 | 1113 | var ypoints = points.map(function (p) { 1114 | return p.y; 1115 | }); 1116 | var dataMean = (0, _mean2.default)(ypoints); 1117 | var dataStdev = (0, _stdev2.default)(ypoints); 1118 | 1119 | return _react2.default.createElement('rect', { x: points[0].x, y: dataMean - dataStdev + margin, 1120 | width: points[points.length - 1].x - points[0].x, height: _stdev2.default * 2, 1121 | style: style }); 1122 | } 1123 | }]); 1124 | 1125 | return SparklinesNormalBand; 1126 | }(_react2.default.Component); 1127 | 1128 | SparklinesNormalBand.propTypes = { 1129 | style: _propTypes2.default.object 1130 | }; 1131 | SparklinesNormalBand.defaultProps = { 1132 | style: { fill: 'red', fillOpacity: .1 } 1133 | }; 1134 | exports.default = SparklinesNormalBand; 1135 | 1136 | /***/ }), 1137 | /* 17 */ 1138 | /***/ (function(module, exports, __webpack_require__) { 1139 | 1140 | "use strict"; 1141 | 1142 | 1143 | Object.defineProperty(exports, "__esModule", { 1144 | value: true 1145 | }); 1146 | 1147 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1148 | 1149 | var _propTypes = __webpack_require__(0); 1150 | 1151 | var _propTypes2 = _interopRequireDefault(_propTypes); 1152 | 1153 | var _react = __webpack_require__(1); 1154 | 1155 | var _react2 = _interopRequireDefault(_react); 1156 | 1157 | var _dataProcessing = __webpack_require__(21); 1158 | 1159 | var dataProcessing = _interopRequireWildcard(_dataProcessing); 1160 | 1161 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 1162 | 1163 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1164 | 1165 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1166 | 1167 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1168 | 1169 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1170 | 1171 | var SparklinesReferenceLine = function (_React$Component) { 1172 | _inherits(SparklinesReferenceLine, _React$Component); 1173 | 1174 | function SparklinesReferenceLine() { 1175 | _classCallCheck(this, SparklinesReferenceLine); 1176 | 1177 | return _possibleConstructorReturn(this, (SparklinesReferenceLine.__proto__ || Object.getPrototypeOf(SparklinesReferenceLine)).apply(this, arguments)); 1178 | } 1179 | 1180 | _createClass(SparklinesReferenceLine, [{ 1181 | key: 'render', 1182 | value: function render() { 1183 | var _props = this.props, 1184 | points = _props.points, 1185 | margin = _props.margin, 1186 | type = _props.type, 1187 | style = _props.style, 1188 | value = _props.value; 1189 | 1190 | 1191 | var ypoints = points.map(function (p) { 1192 | return p.y; 1193 | }); 1194 | var y = type == 'custom' ? value : dataProcessing[type](ypoints); 1195 | 1196 | return _react2.default.createElement('line', { 1197 | x1: points[0].x, y1: y + margin, 1198 | x2: points[points.length - 1].x, y2: y + margin, 1199 | style: style }); 1200 | } 1201 | }]); 1202 | 1203 | return SparklinesReferenceLine; 1204 | }(_react2.default.Component); 1205 | 1206 | SparklinesReferenceLine.propTypes = { 1207 | type: _propTypes2.default.oneOf(['max', 'min', 'mean', 'avg', 'median', 'custom']), 1208 | value: _propTypes2.default.number, 1209 | style: _propTypes2.default.object 1210 | }; 1211 | SparklinesReferenceLine.defaultProps = { 1212 | type: 'mean', 1213 | style: { stroke: 'red', strokeOpacity: .75, strokeDasharray: '2, 2' } 1214 | }; 1215 | exports.default = SparklinesReferenceLine; 1216 | 1217 | /***/ }), 1218 | /* 18 */ 1219 | /***/ (function(module, exports, __webpack_require__) { 1220 | 1221 | "use strict"; 1222 | 1223 | 1224 | Object.defineProperty(exports, "__esModule", { 1225 | value: true 1226 | }); 1227 | 1228 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1229 | 1230 | var _propTypes = __webpack_require__(0); 1231 | 1232 | var _propTypes2 = _interopRequireDefault(_propTypes); 1233 | 1234 | var _react = __webpack_require__(1); 1235 | 1236 | var _react2 = _interopRequireDefault(_react); 1237 | 1238 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1239 | 1240 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1241 | 1242 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1243 | 1244 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1245 | 1246 | var SparklinesSpots = function (_React$Component) { 1247 | _inherits(SparklinesSpots, _React$Component); 1248 | 1249 | function SparklinesSpots() { 1250 | _classCallCheck(this, SparklinesSpots); 1251 | 1252 | return _possibleConstructorReturn(this, (SparklinesSpots.__proto__ || Object.getPrototypeOf(SparklinesSpots)).apply(this, arguments)); 1253 | } 1254 | 1255 | _createClass(SparklinesSpots, [{ 1256 | key: 'lastDirection', 1257 | value: function lastDirection(points) { 1258 | 1259 | Math.sign = Math.sign || function (x) { 1260 | return x > 0 ? 1 : -1; 1261 | }; 1262 | 1263 | return points.length < 2 ? 0 : Math.sign(points[points.length - 2].y - points[points.length - 1].y); 1264 | } 1265 | }, { 1266 | key: 'render', 1267 | value: function render() { 1268 | var _props = this.props, 1269 | points = _props.points, 1270 | width = _props.width, 1271 | height = _props.height, 1272 | size = _props.size, 1273 | style = _props.style, 1274 | spotColors = _props.spotColors; 1275 | 1276 | 1277 | var startSpot = _react2.default.createElement('circle', { 1278 | cx: points[0].x, 1279 | cy: points[0].y, 1280 | r: size, 1281 | style: style }); 1282 | 1283 | var endSpot = _react2.default.createElement('circle', { 1284 | cx: points[points.length - 1].x, 1285 | cy: points[points.length - 1].y, 1286 | r: size, 1287 | style: style || { fill: spotColors[this.lastDirection(points)] } }); 1288 | 1289 | return _react2.default.createElement( 1290 | 'g', 1291 | null, 1292 | style && startSpot, 1293 | endSpot 1294 | ); 1295 | } 1296 | }]); 1297 | 1298 | return SparklinesSpots; 1299 | }(_react2.default.Component); 1300 | 1301 | SparklinesSpots.propTypes = { 1302 | size: _propTypes2.default.number, 1303 | style: _propTypes2.default.object, 1304 | spotColors: _propTypes2.default.object 1305 | }; 1306 | SparklinesSpots.defaultProps = { 1307 | size: 2, 1308 | spotColors: { 1309 | '-1': 'red', 1310 | '0': 'black', 1311 | '1': 'green' 1312 | } 1313 | }; 1314 | exports.default = SparklinesSpots; 1315 | 1316 | /***/ }), 1317 | /* 19 */ 1318 | /***/ (function(module, exports, __webpack_require__) { 1319 | 1320 | "use strict"; 1321 | 1322 | 1323 | Object.defineProperty(exports, "__esModule", { 1324 | value: true 1325 | }); 1326 | 1327 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1328 | 1329 | var _propTypes = __webpack_require__(0); 1330 | 1331 | var _propTypes2 = _interopRequireDefault(_propTypes); 1332 | 1333 | var _react = __webpack_require__(1); 1334 | 1335 | var _react2 = _interopRequireDefault(_react); 1336 | 1337 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1338 | 1339 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1340 | 1341 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1342 | 1343 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1344 | 1345 | var SparklinesText = function (_React$Component) { 1346 | _inherits(SparklinesText, _React$Component); 1347 | 1348 | function SparklinesText() { 1349 | _classCallCheck(this, SparklinesText); 1350 | 1351 | return _possibleConstructorReturn(this, (SparklinesText.__proto__ || Object.getPrototypeOf(SparklinesText)).apply(this, arguments)); 1352 | } 1353 | 1354 | _createClass(SparklinesText, [{ 1355 | key: 'render', 1356 | value: function render() { 1357 | var _props = this.props, 1358 | point = _props.point, 1359 | text = _props.text, 1360 | fontSize = _props.fontSize, 1361 | fontFamily = _props.fontFamily; 1362 | var x = point.x, 1363 | y = point.y; 1364 | 1365 | return _react2.default.createElement( 1366 | 'g', 1367 | null, 1368 | _react2.default.createElement( 1369 | 'text', 1370 | { x: x, y: y, fontFamily: fontFamily || "Verdana", fontSize: fontSize || 10 }, 1371 | text 1372 | ) 1373 | ); 1374 | } 1375 | }]); 1376 | 1377 | return SparklinesText; 1378 | }(_react2.default.Component); 1379 | 1380 | SparklinesText.propTypes = { 1381 | text: _propTypes2.default.string, 1382 | point: _propTypes2.default.object, 1383 | fontSize: _propTypes2.default.number, 1384 | fontFamily: _propTypes2.default.string 1385 | }; 1386 | SparklinesText.defaultProps = { 1387 | text: '', 1388 | point: { x: 0, y: 0 } 1389 | }; 1390 | exports.default = SparklinesText; 1391 | 1392 | /***/ }), 1393 | /* 20 */ 1394 | /***/ (function(module, exports, __webpack_require__) { 1395 | 1396 | "use strict"; 1397 | 1398 | 1399 | Object.defineProperty(exports, "__esModule", { 1400 | value: true 1401 | }); 1402 | 1403 | var _min = __webpack_require__(4); 1404 | 1405 | var _min2 = _interopRequireDefault(_min); 1406 | 1407 | var _max = __webpack_require__(8); 1408 | 1409 | var _max2 = _interopRequireDefault(_max); 1410 | 1411 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1412 | 1413 | exports.default = function (_ref) { 1414 | var data = _ref.data, 1415 | limit = _ref.limit, 1416 | _ref$width = _ref.width, 1417 | width = _ref$width === undefined ? 1 : _ref$width, 1418 | _ref$height = _ref.height, 1419 | height = _ref$height === undefined ? 1 : _ref$height, 1420 | _ref$margin = _ref.margin, 1421 | margin = _ref$margin === undefined ? 0 : _ref$margin, 1422 | _ref$max = _ref.max, 1423 | max = _ref$max === undefined ? (0, _max2.default)(data) : _ref$max, 1424 | _ref$min = _ref.min, 1425 | min = _ref$min === undefined ? (0, _min2.default)(data) : _ref$min; 1426 | 1427 | 1428 | var len = data.length; 1429 | 1430 | if (limit && limit < len) { 1431 | data = data.slice(len - limit); 1432 | } 1433 | 1434 | var vfactor = (height - margin * 2) / (max - min || 2); 1435 | var hfactor = (width - margin * 2) / ((limit || len) - (len > 1 ? 1 : 0)); 1436 | 1437 | return data.map(function (d, i) { 1438 | return { 1439 | x: i * hfactor + margin, 1440 | y: (max === min ? 1 : max - d) * vfactor + margin 1441 | }; 1442 | }); 1443 | }; 1444 | 1445 | /***/ }), 1446 | /* 21 */ 1447 | /***/ (function(module, exports, __webpack_require__) { 1448 | 1449 | "use strict"; 1450 | 1451 | 1452 | Object.defineProperty(exports, "__esModule", { 1453 | value: true 1454 | }); 1455 | exports.variance = exports.stdev = exports.median = exports.midRange = exports.avg = exports.mean = exports.max = exports.min = undefined; 1456 | 1457 | var _min2 = __webpack_require__(4); 1458 | 1459 | var _min3 = _interopRequireDefault(_min2); 1460 | 1461 | var _mean2 = __webpack_require__(3); 1462 | 1463 | var _mean3 = _interopRequireDefault(_mean2); 1464 | 1465 | var _midRange2 = __webpack_require__(23); 1466 | 1467 | var _midRange3 = _interopRequireDefault(_midRange2); 1468 | 1469 | var _median2 = __webpack_require__(22); 1470 | 1471 | var _median3 = _interopRequireDefault(_median2); 1472 | 1473 | var _stdev2 = __webpack_require__(9); 1474 | 1475 | var _stdev3 = _interopRequireDefault(_stdev2); 1476 | 1477 | var _variance2 = __webpack_require__(24); 1478 | 1479 | var _variance3 = _interopRequireDefault(_variance2); 1480 | 1481 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1482 | 1483 | exports.min = _min3.default; 1484 | exports.max = _min3.default; 1485 | exports.mean = _mean3.default; 1486 | exports.avg = _mean3.default; 1487 | exports.midRange = _midRange3.default; 1488 | exports.median = _median3.default; 1489 | exports.stdev = _stdev3.default; 1490 | exports.variance = _variance3.default; 1491 | 1492 | /***/ }), 1493 | /* 22 */ 1494 | /***/ (function(module, exports, __webpack_require__) { 1495 | 1496 | "use strict"; 1497 | 1498 | 1499 | Object.defineProperty(exports, "__esModule", { 1500 | value: true 1501 | }); 1502 | 1503 | exports.default = function (data) { 1504 | return data.sort(function (a, b) { 1505 | return a - b; 1506 | })[Math.floor(data.length / 2)]; 1507 | }; 1508 | 1509 | /***/ }), 1510 | /* 23 */ 1511 | /***/ (function(module, exports, __webpack_require__) { 1512 | 1513 | "use strict"; 1514 | 1515 | 1516 | Object.defineProperty(exports, "__esModule", { 1517 | value: true 1518 | }); 1519 | 1520 | var _min = __webpack_require__(4); 1521 | 1522 | var _min2 = _interopRequireDefault(_min); 1523 | 1524 | var _max = __webpack_require__(8); 1525 | 1526 | var _max2 = _interopRequireDefault(_max); 1527 | 1528 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1529 | 1530 | exports.default = function (data) { 1531 | return (0, _max2.default)(data) - (0, _min2.default)(data) / 2; 1532 | }; 1533 | 1534 | /***/ }), 1535 | /* 24 */ 1536 | /***/ (function(module, exports, __webpack_require__) { 1537 | 1538 | "use strict"; 1539 | 1540 | 1541 | Object.defineProperty(exports, "__esModule", { 1542 | value: true 1543 | }); 1544 | 1545 | var _mean = __webpack_require__(3); 1546 | 1547 | var _mean2 = _interopRequireDefault(_mean); 1548 | 1549 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1550 | 1551 | exports.default = function (data) { 1552 | var dataMean = (0, _mean2.default)(data); 1553 | var sq = data.map(function (n) { 1554 | return Math.pow(n - dataMean, 2); 1555 | }); 1556 | return (0, _mean2.default)(sq); 1557 | }; 1558 | 1559 | /***/ }), 1560 | /* 25 */ 1561 | /***/ (function(module, exports, __webpack_require__) { 1562 | 1563 | "use strict"; 1564 | /** 1565 | * Copyright (c) 2013-present, Facebook, Inc. 1566 | * All rights reserved. 1567 | * 1568 | * This source code is licensed under the BSD-style license found in the 1569 | * LICENSE file in the root directory of this source tree. An additional grant 1570 | * of patent rights can be found in the PATENTS file in the same directory. 1571 | * 1572 | * @typechecks 1573 | * 1574 | */ 1575 | 1576 | /*eslint-disable no-self-compare */ 1577 | 1578 | 1579 | 1580 | var hasOwnProperty = Object.prototype.hasOwnProperty; 1581 | 1582 | /** 1583 | * inlined Object.is polyfill to avoid requiring consumers ship their own 1584 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 1585 | */ 1586 | function is(x, y) { 1587 | // SameValue algorithm 1588 | if (x === y) { 1589 | // Steps 1-5, 7-10 1590 | // Steps 6.b-6.e: +0 != -0 1591 | // Added the nonzero y check to make Flow happy, but it is redundant 1592 | return x !== 0 || y !== 0 || 1 / x === 1 / y; 1593 | } else { 1594 | // Step 6.a: NaN == NaN 1595 | return x !== x && y !== y; 1596 | } 1597 | } 1598 | 1599 | /** 1600 | * Performs equality by iterating through keys on an object and returning false 1601 | * when any key has values which are not strictly equal between the arguments. 1602 | * Returns true when the values of all keys are strictly equal. 1603 | */ 1604 | function shallowEqual(objA, objB) { 1605 | if (is(objA, objB)) { 1606 | return true; 1607 | } 1608 | 1609 | if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { 1610 | return false; 1611 | } 1612 | 1613 | var keysA = Object.keys(objA); 1614 | var keysB = Object.keys(objB); 1615 | 1616 | if (keysA.length !== keysB.length) { 1617 | return false; 1618 | } 1619 | 1620 | // Test for A's keys different from B. 1621 | for (var i = 0; i < keysA.length; i++) { 1622 | if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { 1623 | return false; 1624 | } 1625 | } 1626 | 1627 | return true; 1628 | } 1629 | 1630 | module.exports = shallowEqual; 1631 | 1632 | /***/ }), 1633 | /* 26 */ 1634 | /***/ (function(module, exports, __webpack_require__) { 1635 | 1636 | "use strict"; 1637 | /* WEBPACK VAR INJECTION */(function(process) {/** 1638 | * Copyright 2013-present, Facebook, Inc. 1639 | * All rights reserved. 1640 | * 1641 | * This source code is licensed under the BSD-style license found in the 1642 | * LICENSE file in the root directory of this source tree. An additional grant 1643 | * of patent rights can be found in the PATENTS file in the same directory. 1644 | */ 1645 | 1646 | 1647 | 1648 | if (process.env.NODE_ENV !== 'production') { 1649 | var invariant = __webpack_require__(7); 1650 | var warning = __webpack_require__(10); 1651 | var ReactPropTypesSecret = __webpack_require__(5); 1652 | var loggedTypeFailures = {}; 1653 | } 1654 | 1655 | /** 1656 | * Assert that the values match with the type specs. 1657 | * Error messages are memorized and will only be shown once. 1658 | * 1659 | * @param {object} typeSpecs Map of name to a ReactPropType 1660 | * @param {object} values Runtime values that need to be type-checked 1661 | * @param {string} location e.g. "prop", "context", "child context" 1662 | * @param {string} componentName Name of the component for error messages. 1663 | * @param {?Function} getStack Returns the component stack. 1664 | * @private 1665 | */ 1666 | function checkPropTypes(typeSpecs, values, location, componentName, getStack) { 1667 | if (process.env.NODE_ENV !== 'production') { 1668 | for (var typeSpecName in typeSpecs) { 1669 | if (typeSpecs.hasOwnProperty(typeSpecName)) { 1670 | var error; 1671 | // Prop type validation may throw. In case they do, we don't want to 1672 | // fail the render phase where it didn't fail before. So we log it. 1673 | // After these have been cleaned up, we'll let them throw. 1674 | try { 1675 | // This is intentionally an invariant that gets caught. It's the same 1676 | // behavior as without this statement except with a better message. 1677 | invariant(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', componentName || 'React class', location, typeSpecName); 1678 | error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret); 1679 | } catch (ex) { 1680 | error = ex; 1681 | } 1682 | warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error); 1683 | if (error instanceof Error && !(error.message in loggedTypeFailures)) { 1684 | // Only monitor this failure once because there tends to be a lot of the 1685 | // same error. 1686 | loggedTypeFailures[error.message] = true; 1687 | 1688 | var stack = getStack ? getStack() : ''; 1689 | 1690 | warning(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : ''); 1691 | } 1692 | } 1693 | } 1694 | } 1695 | } 1696 | 1697 | module.exports = checkPropTypes; 1698 | 1699 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 1700 | 1701 | /***/ }), 1702 | /* 27 */ 1703 | /***/ (function(module, exports, __webpack_require__) { 1704 | 1705 | "use strict"; 1706 | /** 1707 | * Copyright 2013-present, Facebook, Inc. 1708 | * All rights reserved. 1709 | * 1710 | * This source code is licensed under the BSD-style license found in the 1711 | * LICENSE file in the root directory of this source tree. An additional grant 1712 | * of patent rights can be found in the PATENTS file in the same directory. 1713 | */ 1714 | 1715 | 1716 | 1717 | var emptyFunction = __webpack_require__(6); 1718 | var invariant = __webpack_require__(7); 1719 | var ReactPropTypesSecret = __webpack_require__(5); 1720 | 1721 | module.exports = function() { 1722 | function shim(props, propName, componentName, location, propFullName, secret) { 1723 | if (secret === ReactPropTypesSecret) { 1724 | // It is still safe when called from React. 1725 | return; 1726 | } 1727 | invariant( 1728 | false, 1729 | 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 1730 | 'Use PropTypes.checkPropTypes() to call them. ' + 1731 | 'Read more at http://fb.me/use-check-prop-types' 1732 | ); 1733 | }; 1734 | shim.isRequired = shim; 1735 | function getShim() { 1736 | return shim; 1737 | }; 1738 | // Important! 1739 | // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`. 1740 | var ReactPropTypes = { 1741 | array: shim, 1742 | bool: shim, 1743 | func: shim, 1744 | number: shim, 1745 | object: shim, 1746 | string: shim, 1747 | symbol: shim, 1748 | 1749 | any: shim, 1750 | arrayOf: getShim, 1751 | element: shim, 1752 | instanceOf: getShim, 1753 | node: shim, 1754 | objectOf: getShim, 1755 | oneOf: getShim, 1756 | oneOfType: getShim, 1757 | shape: getShim 1758 | }; 1759 | 1760 | ReactPropTypes.checkPropTypes = emptyFunction; 1761 | ReactPropTypes.PropTypes = ReactPropTypes; 1762 | 1763 | return ReactPropTypes; 1764 | }; 1765 | 1766 | 1767 | /***/ }), 1768 | /* 28 */ 1769 | /***/ (function(module, exports, __webpack_require__) { 1770 | 1771 | "use strict"; 1772 | /* WEBPACK VAR INJECTION */(function(process) {/** 1773 | * Copyright 2013-present, Facebook, Inc. 1774 | * All rights reserved. 1775 | * 1776 | * This source code is licensed under the BSD-style license found in the 1777 | * LICENSE file in the root directory of this source tree. An additional grant 1778 | * of patent rights can be found in the PATENTS file in the same directory. 1779 | */ 1780 | 1781 | 1782 | 1783 | var emptyFunction = __webpack_require__(6); 1784 | var invariant = __webpack_require__(7); 1785 | var warning = __webpack_require__(10); 1786 | 1787 | var ReactPropTypesSecret = __webpack_require__(5); 1788 | var checkPropTypes = __webpack_require__(26); 1789 | 1790 | module.exports = function(isValidElement, throwOnDirectAccess) { 1791 | /* global Symbol */ 1792 | var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; 1793 | var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. 1794 | 1795 | /** 1796 | * Returns the iterator method function contained on the iterable object. 1797 | * 1798 | * Be sure to invoke the function with the iterable as context: 1799 | * 1800 | * var iteratorFn = getIteratorFn(myIterable); 1801 | * if (iteratorFn) { 1802 | * var iterator = iteratorFn.call(myIterable); 1803 | * ... 1804 | * } 1805 | * 1806 | * @param {?object} maybeIterable 1807 | * @return {?function} 1808 | */ 1809 | function getIteratorFn(maybeIterable) { 1810 | var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); 1811 | if (typeof iteratorFn === 'function') { 1812 | return iteratorFn; 1813 | } 1814 | } 1815 | 1816 | /** 1817 | * Collection of methods that allow declaration and validation of props that are 1818 | * supplied to React components. Example usage: 1819 | * 1820 | * var Props = require('ReactPropTypes'); 1821 | * var MyArticle = React.createClass({ 1822 | * propTypes: { 1823 | * // An optional string prop named "description". 1824 | * description: Props.string, 1825 | * 1826 | * // A required enum prop named "category". 1827 | * category: Props.oneOf(['News','Photos']).isRequired, 1828 | * 1829 | * // A prop named "dialog" that requires an instance of Dialog. 1830 | * dialog: Props.instanceOf(Dialog).isRequired 1831 | * }, 1832 | * render: function() { ... } 1833 | * }); 1834 | * 1835 | * A more formal specification of how these methods are used: 1836 | * 1837 | * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) 1838 | * decl := ReactPropTypes.{type}(.isRequired)? 1839 | * 1840 | * Each and every declaration produces a function with the same signature. This 1841 | * allows the creation of custom validation functions. For example: 1842 | * 1843 | * var MyLink = React.createClass({ 1844 | * propTypes: { 1845 | * // An optional string or URI prop named "href". 1846 | * href: function(props, propName, componentName) { 1847 | * var propValue = props[propName]; 1848 | * if (propValue != null && typeof propValue !== 'string' && 1849 | * !(propValue instanceof URI)) { 1850 | * return new Error( 1851 | * 'Expected a string or an URI for ' + propName + ' in ' + 1852 | * componentName 1853 | * ); 1854 | * } 1855 | * } 1856 | * }, 1857 | * render: function() {...} 1858 | * }); 1859 | * 1860 | * @internal 1861 | */ 1862 | 1863 | var ANONYMOUS = '<>'; 1864 | 1865 | // Important! 1866 | // Keep this list in sync with production version in `./factoryWithThrowingShims.js`. 1867 | var ReactPropTypes = { 1868 | array: createPrimitiveTypeChecker('array'), 1869 | bool: createPrimitiveTypeChecker('boolean'), 1870 | func: createPrimitiveTypeChecker('function'), 1871 | number: createPrimitiveTypeChecker('number'), 1872 | object: createPrimitiveTypeChecker('object'), 1873 | string: createPrimitiveTypeChecker('string'), 1874 | symbol: createPrimitiveTypeChecker('symbol'), 1875 | 1876 | any: createAnyTypeChecker(), 1877 | arrayOf: createArrayOfTypeChecker, 1878 | element: createElementTypeChecker(), 1879 | instanceOf: createInstanceTypeChecker, 1880 | node: createNodeChecker(), 1881 | objectOf: createObjectOfTypeChecker, 1882 | oneOf: createEnumTypeChecker, 1883 | oneOfType: createUnionTypeChecker, 1884 | shape: createShapeTypeChecker 1885 | }; 1886 | 1887 | /** 1888 | * inlined Object.is polyfill to avoid requiring consumers ship their own 1889 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 1890 | */ 1891 | /*eslint-disable no-self-compare*/ 1892 | function is(x, y) { 1893 | // SameValue algorithm 1894 | if (x === y) { 1895 | // Steps 1-5, 7-10 1896 | // Steps 6.b-6.e: +0 != -0 1897 | return x !== 0 || 1 / x === 1 / y; 1898 | } else { 1899 | // Step 6.a: NaN == NaN 1900 | return x !== x && y !== y; 1901 | } 1902 | } 1903 | /*eslint-enable no-self-compare*/ 1904 | 1905 | /** 1906 | * We use an Error-like object for backward compatibility as people may call 1907 | * PropTypes directly and inspect their output. However, we don't use real 1908 | * Errors anymore. We don't inspect their stack anyway, and creating them 1909 | * is prohibitively expensive if they are created too often, such as what 1910 | * happens in oneOfType() for any type before the one that matched. 1911 | */ 1912 | function PropTypeError(message) { 1913 | this.message = message; 1914 | this.stack = ''; 1915 | } 1916 | // Make `instanceof Error` still work for returned errors. 1917 | PropTypeError.prototype = Error.prototype; 1918 | 1919 | function createChainableTypeChecker(validate) { 1920 | if (process.env.NODE_ENV !== 'production') { 1921 | var manualPropTypeCallCache = {}; 1922 | var manualPropTypeWarningCount = 0; 1923 | } 1924 | function checkType(isRequired, props, propName, componentName, location, propFullName, secret) { 1925 | componentName = componentName || ANONYMOUS; 1926 | propFullName = propFullName || propName; 1927 | 1928 | if (secret !== ReactPropTypesSecret) { 1929 | if (throwOnDirectAccess) { 1930 | // New behavior only for users of `prop-types` package 1931 | invariant( 1932 | false, 1933 | 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' + 1934 | 'Use `PropTypes.checkPropTypes()` to call them. ' + 1935 | 'Read more at http://fb.me/use-check-prop-types' 1936 | ); 1937 | } else if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') { 1938 | // Old behavior for people using React.PropTypes 1939 | var cacheKey = componentName + ':' + propName; 1940 | if ( 1941 | !manualPropTypeCallCache[cacheKey] && 1942 | // Avoid spamming the console because they are often not actionable except for lib authors 1943 | manualPropTypeWarningCount < 3 1944 | ) { 1945 | warning( 1946 | false, 1947 | 'You are manually calling a React.PropTypes validation ' + 1948 | 'function for the `%s` prop on `%s`. This is deprecated ' + 1949 | 'and will throw in the standalone `prop-types` package. ' + 1950 | 'You may be seeing this warning due to a third-party PropTypes ' + 1951 | 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.', 1952 | propFullName, 1953 | componentName 1954 | ); 1955 | manualPropTypeCallCache[cacheKey] = true; 1956 | manualPropTypeWarningCount++; 1957 | } 1958 | } 1959 | } 1960 | if (props[propName] == null) { 1961 | if (isRequired) { 1962 | if (props[propName] === null) { 1963 | return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.')); 1964 | } 1965 | return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.')); 1966 | } 1967 | return null; 1968 | } else { 1969 | return validate(props, propName, componentName, location, propFullName); 1970 | } 1971 | } 1972 | 1973 | var chainedCheckType = checkType.bind(null, false); 1974 | chainedCheckType.isRequired = checkType.bind(null, true); 1975 | 1976 | return chainedCheckType; 1977 | } 1978 | 1979 | function createPrimitiveTypeChecker(expectedType) { 1980 | function validate(props, propName, componentName, location, propFullName, secret) { 1981 | var propValue = props[propName]; 1982 | var propType = getPropType(propValue); 1983 | if (propType !== expectedType) { 1984 | // `propValue` being instance of, say, date/regexp, pass the 'object' 1985 | // check, but we can offer a more precise error message here rather than 1986 | // 'of type `object`'. 1987 | var preciseType = getPreciseType(propValue); 1988 | 1989 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.')); 1990 | } 1991 | return null; 1992 | } 1993 | return createChainableTypeChecker(validate); 1994 | } 1995 | 1996 | function createAnyTypeChecker() { 1997 | return createChainableTypeChecker(emptyFunction.thatReturnsNull); 1998 | } 1999 | 2000 | function createArrayOfTypeChecker(typeChecker) { 2001 | function validate(props, propName, componentName, location, propFullName) { 2002 | if (typeof typeChecker !== 'function') { 2003 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.'); 2004 | } 2005 | var propValue = props[propName]; 2006 | if (!Array.isArray(propValue)) { 2007 | var propType = getPropType(propValue); 2008 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.')); 2009 | } 2010 | for (var i = 0; i < propValue.length; i++) { 2011 | var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret); 2012 | if (error instanceof Error) { 2013 | return error; 2014 | } 2015 | } 2016 | return null; 2017 | } 2018 | return createChainableTypeChecker(validate); 2019 | } 2020 | 2021 | function createElementTypeChecker() { 2022 | function validate(props, propName, componentName, location, propFullName) { 2023 | var propValue = props[propName]; 2024 | if (!isValidElement(propValue)) { 2025 | var propType = getPropType(propValue); 2026 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.')); 2027 | } 2028 | return null; 2029 | } 2030 | return createChainableTypeChecker(validate); 2031 | } 2032 | 2033 | function createInstanceTypeChecker(expectedClass) { 2034 | function validate(props, propName, componentName, location, propFullName) { 2035 | if (!(props[propName] instanceof expectedClass)) { 2036 | var expectedClassName = expectedClass.name || ANONYMOUS; 2037 | var actualClassName = getClassName(props[propName]); 2038 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.')); 2039 | } 2040 | return null; 2041 | } 2042 | return createChainableTypeChecker(validate); 2043 | } 2044 | 2045 | function createEnumTypeChecker(expectedValues) { 2046 | if (!Array.isArray(expectedValues)) { 2047 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.') : void 0; 2048 | return emptyFunction.thatReturnsNull; 2049 | } 2050 | 2051 | function validate(props, propName, componentName, location, propFullName) { 2052 | var propValue = props[propName]; 2053 | for (var i = 0; i < expectedValues.length; i++) { 2054 | if (is(propValue, expectedValues[i])) { 2055 | return null; 2056 | } 2057 | } 2058 | 2059 | var valuesString = JSON.stringify(expectedValues); 2060 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.')); 2061 | } 2062 | return createChainableTypeChecker(validate); 2063 | } 2064 | 2065 | function createObjectOfTypeChecker(typeChecker) { 2066 | function validate(props, propName, componentName, location, propFullName) { 2067 | if (typeof typeChecker !== 'function') { 2068 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.'); 2069 | } 2070 | var propValue = props[propName]; 2071 | var propType = getPropType(propValue); 2072 | if (propType !== 'object') { 2073 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.')); 2074 | } 2075 | for (var key in propValue) { 2076 | if (propValue.hasOwnProperty(key)) { 2077 | var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); 2078 | if (error instanceof Error) { 2079 | return error; 2080 | } 2081 | } 2082 | } 2083 | return null; 2084 | } 2085 | return createChainableTypeChecker(validate); 2086 | } 2087 | 2088 | function createUnionTypeChecker(arrayOfTypeCheckers) { 2089 | if (!Array.isArray(arrayOfTypeCheckers)) { 2090 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.') : void 0; 2091 | return emptyFunction.thatReturnsNull; 2092 | } 2093 | 2094 | for (var i = 0; i < arrayOfTypeCheckers.length; i++) { 2095 | var checker = arrayOfTypeCheckers[i]; 2096 | if (typeof checker !== 'function') { 2097 | warning( 2098 | false, 2099 | 'Invalid argument supplid to oneOfType. Expected an array of check functions, but ' + 2100 | 'received %s at index %s.', 2101 | getPostfixForTypeWarning(checker), 2102 | i 2103 | ); 2104 | return emptyFunction.thatReturnsNull; 2105 | } 2106 | } 2107 | 2108 | function validate(props, propName, componentName, location, propFullName) { 2109 | for (var i = 0; i < arrayOfTypeCheckers.length; i++) { 2110 | var checker = arrayOfTypeCheckers[i]; 2111 | if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) { 2112 | return null; 2113 | } 2114 | } 2115 | 2116 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.')); 2117 | } 2118 | return createChainableTypeChecker(validate); 2119 | } 2120 | 2121 | function createNodeChecker() { 2122 | function validate(props, propName, componentName, location, propFullName) { 2123 | if (!isNode(props[propName])) { 2124 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.')); 2125 | } 2126 | return null; 2127 | } 2128 | return createChainableTypeChecker(validate); 2129 | } 2130 | 2131 | function createShapeTypeChecker(shapeTypes) { 2132 | function validate(props, propName, componentName, location, propFullName) { 2133 | var propValue = props[propName]; 2134 | var propType = getPropType(propValue); 2135 | if (propType !== 'object') { 2136 | return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.')); 2137 | } 2138 | for (var key in shapeTypes) { 2139 | var checker = shapeTypes[key]; 2140 | if (!checker) { 2141 | continue; 2142 | } 2143 | var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret); 2144 | if (error) { 2145 | return error; 2146 | } 2147 | } 2148 | return null; 2149 | } 2150 | return createChainableTypeChecker(validate); 2151 | } 2152 | 2153 | function isNode(propValue) { 2154 | switch (typeof propValue) { 2155 | case 'number': 2156 | case 'string': 2157 | case 'undefined': 2158 | return true; 2159 | case 'boolean': 2160 | return !propValue; 2161 | case 'object': 2162 | if (Array.isArray(propValue)) { 2163 | return propValue.every(isNode); 2164 | } 2165 | if (propValue === null || isValidElement(propValue)) { 2166 | return true; 2167 | } 2168 | 2169 | var iteratorFn = getIteratorFn(propValue); 2170 | if (iteratorFn) { 2171 | var iterator = iteratorFn.call(propValue); 2172 | var step; 2173 | if (iteratorFn !== propValue.entries) { 2174 | while (!(step = iterator.next()).done) { 2175 | if (!isNode(step.value)) { 2176 | return false; 2177 | } 2178 | } 2179 | } else { 2180 | // Iterator will provide entry [k,v] tuples rather than values. 2181 | while (!(step = iterator.next()).done) { 2182 | var entry = step.value; 2183 | if (entry) { 2184 | if (!isNode(entry[1])) { 2185 | return false; 2186 | } 2187 | } 2188 | } 2189 | } 2190 | } else { 2191 | return false; 2192 | } 2193 | 2194 | return true; 2195 | default: 2196 | return false; 2197 | } 2198 | } 2199 | 2200 | function isSymbol(propType, propValue) { 2201 | // Native Symbol. 2202 | if (propType === 'symbol') { 2203 | return true; 2204 | } 2205 | 2206 | // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol' 2207 | if (propValue['@@toStringTag'] === 'Symbol') { 2208 | return true; 2209 | } 2210 | 2211 | // Fallback for non-spec compliant Symbols which are polyfilled. 2212 | if (typeof Symbol === 'function' && propValue instanceof Symbol) { 2213 | return true; 2214 | } 2215 | 2216 | return false; 2217 | } 2218 | 2219 | // Equivalent of `typeof` but with special handling for array and regexp. 2220 | function getPropType(propValue) { 2221 | var propType = typeof propValue; 2222 | if (Array.isArray(propValue)) { 2223 | return 'array'; 2224 | } 2225 | if (propValue instanceof RegExp) { 2226 | // Old webkits (at least until Android 4.0) return 'function' rather than 2227 | // 'object' for typeof a RegExp. We'll normalize this here so that /bla/ 2228 | // passes PropTypes.object. 2229 | return 'object'; 2230 | } 2231 | if (isSymbol(propType, propValue)) { 2232 | return 'symbol'; 2233 | } 2234 | return propType; 2235 | } 2236 | 2237 | // This handles more types than `getPropType`. Only used for error messages. 2238 | // See `createPrimitiveTypeChecker`. 2239 | function getPreciseType(propValue) { 2240 | if (typeof propValue === 'undefined' || propValue === null) { 2241 | return '' + propValue; 2242 | } 2243 | var propType = getPropType(propValue); 2244 | if (propType === 'object') { 2245 | if (propValue instanceof Date) { 2246 | return 'date'; 2247 | } else if (propValue instanceof RegExp) { 2248 | return 'regexp'; 2249 | } 2250 | } 2251 | return propType; 2252 | } 2253 | 2254 | // Returns a string that is postfixed to a warning about an invalid type. 2255 | // For example, "undefined" or "of type array" 2256 | function getPostfixForTypeWarning(value) { 2257 | var type = getPreciseType(value); 2258 | switch (type) { 2259 | case 'array': 2260 | case 'object': 2261 | return 'an ' + type; 2262 | case 'boolean': 2263 | case 'date': 2264 | case 'regexp': 2265 | return 'a ' + type; 2266 | default: 2267 | return type; 2268 | } 2269 | } 2270 | 2271 | // Returns class name of the object, if any. 2272 | function getClassName(propValue) { 2273 | if (!propValue.constructor || !propValue.constructor.name) { 2274 | return ANONYMOUS; 2275 | } 2276 | return propValue.constructor.name; 2277 | } 2278 | 2279 | ReactPropTypes.checkPropTypes = checkPropTypes; 2280 | ReactPropTypes.PropTypes = ReactPropTypes; 2281 | 2282 | return ReactPropTypes; 2283 | }; 2284 | 2285 | /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2))) 2286 | 2287 | /***/ }), 2288 | /* 29 */ 2289 | /***/ (function(module, exports, __webpack_require__) { 2290 | 2291 | module.exports = __webpack_require__(30); 2292 | 2293 | /***/ }), 2294 | /* 30 */ 2295 | /***/ (function(module, exports, __webpack_require__) { 2296 | 2297 | "use strict"; 2298 | /** 2299 | * Copyright 2013-present, Facebook, Inc. 2300 | * All rights reserved. 2301 | * 2302 | * This source code is licensed under the BSD-style license found in the 2303 | * LICENSE file in the root directory of this source tree. An additional grant 2304 | * of patent rights can be found in the PATENTS file in the same directory. 2305 | * 2306 | */ 2307 | 2308 | 2309 | 2310 | var shallowEqual = __webpack_require__(25); 2311 | 2312 | /** 2313 | * Does a shallow comparison for props and state. 2314 | * See ReactComponentWithPureRenderMixin 2315 | * See also https://facebook.github.io/react/docs/shallow-compare.html 2316 | */ 2317 | function shallowCompare(instance, nextProps, nextState) { 2318 | return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState); 2319 | } 2320 | 2321 | module.exports = shallowCompare; 2322 | 2323 | /***/ }), 2324 | /* 31 */ 2325 | /***/ (function(module, exports, __webpack_require__) { 2326 | 2327 | module.exports = __webpack_require__(11); 2328 | 2329 | 2330 | /***/ }) 2331 | /******/ ]); 2332 | }); -------------------------------------------------------------------------------- /demo/demo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Sparklines, SparklinesBars, SparklinesLine, SparklinesCurve, SparklinesNormalBand, SparklinesReferenceLine, SparklinesSpots } from '../src/Sparklines'; 4 | 5 | function boxMullerRandom () { 6 | let phase = false, 7 | x1, x2, w, z; 8 | 9 | return (function() { 10 | 11 | if (phase = !phase) { 12 | do { 13 | x1 = 2.0 * Math.random() - 1.0; 14 | x2 = 2.0 * Math.random() - 1.0; 15 | w = x1 * x1 + x2 * x2; 16 | } while (w >= 1.0); 17 | 18 | w = Math.sqrt((-2.0 * Math.log(w)) / w); 19 | return x1 * w; 20 | } else { 21 | return x2 * w; 22 | } 23 | })(); 24 | } 25 | 26 | function randomData(n = 30) { 27 | return Array.apply(0, Array(n)).map(boxMullerRandom); 28 | } 29 | 30 | const sampleData = randomData(30); 31 | const sampleData100 = randomData(100); 32 | 33 | const Header = () => 34 | 35 | 36 | 37 | 38 | 39 | const Simple = () => 40 | 41 | 42 | 43 | 44 | const SimpleCurve = () => 45 | 46 | 47 | 48 | 49 | const Customizable1 = () => 50 | 51 | 52 | 53 | 54 | const Customizable2 = () => 55 | 56 | 57 | 58 | 59 | const Customizable3 = () => 60 | 61 | 62 | 63 | 64 | const Customizable4 = () => 65 | 66 | 67 | 68 | 69 | const Customizable5 = () => 70 | 71 | 72 | 73 | 74 | const Customizable6 = () => 75 | 76 | 77 | 78 | 79 | const Bounds1 = () => 80 | 81 | 82 | 83 | 84 | const Spots1 = () => 85 | 86 | 87 | 88 | 89 | 90 | const Spots2 = () => 91 | 92 | 93 | 94 | 95 | 96 | const Spots3 = () => 97 | 98 | 99 | 100 | 101 | 102 | const Bars1 = () => 103 | 104 | 105 | 106 | 107 | const Bars2 = () => 108 | 109 | 110 | 111 | 112 | 113 | class Dynamic1 extends Component { 114 | 115 | constructor(props) { 116 | super(props); 117 | this.state = { data: [] }; 118 | setInterval(() => 119 | this.setState({ 120 | data: this.state.data.concat([boxMullerRandom()]) 121 | }), 100); 122 | } 123 | 124 | render() { 125 | return ( 126 | 127 | 128 | 129 | 130 | ); 131 | } 132 | } 133 | 134 | class Dynamic2 extends Component { 135 | 136 | constructor(props) { 137 | super(props); 138 | this.state = { data: [] }; 139 | setInterval(() => 140 | this.setState({ 141 | data: this.state.data.concat([boxMullerRandom()]) 142 | }), 100); 143 | } 144 | 145 | render() { 146 | return ( 147 | 148 | 149 | 150 | 151 | ); 152 | } 153 | } 154 | 155 | 156 | class Dynamic3 extends Component { 157 | 158 | constructor(props) { 159 | super(props); 160 | this.state = { data: [] }; 161 | setInterval(() => 162 | this.setState({ 163 | data: this.state.data.concat([boxMullerRandom()]) 164 | }), 100); 165 | } 166 | 167 | render() { 168 | return ( 169 | 170 | 171 | 172 | ); 173 | } 174 | } 175 | 176 | 177 | class Dynamic4 extends React.Component { 178 | 179 | constructor(props) { 180 | super(props); 181 | this.state = { data: [] }; 182 | setInterval(() => 183 | this.setState({ 184 | data: this.state.data.concat([boxMullerRandom()]) 185 | }), 100); 186 | } 187 | 188 | render() { 189 | return ( 190 | 191 | 192 | 193 | ); 194 | } 195 | } 196 | 197 | const ReferenceLine1 = () => 198 | 199 | 200 | 201 | 202 | 203 | const ReferenceLine2 = () => 204 | 205 | 206 | 207 | 208 | 209 | const ReferenceLine3 = () => 210 | 211 | 212 | 213 | 214 | 215 | const ReferenceLine4 = () => 216 | 217 | 218 | 219 | 220 | 221 | const ReferenceLine5 = () => 222 | 223 | 224 | 225 | 226 | 227 | const ReferenceLine6 = () => 228 | 229 | 230 | 231 | 232 | 233 | const NormalBand1 = () => 234 | 235 | 236 | 237 | 238 | 239 | const NormalBand2 = () => 240 | 241 | 242 | 243 | 244 | 245 | 246 | const RealWorld1 = () => 247 | 248 | 249 | 250 | 251 | const RealWorld2 = () => 252 | 253 | 254 | 255 | 256 | 257 | 258 | const RealWorld3 = () => 259 | 260 | 261 | 262 | 263 | 264 | const RealWorld4 = () => 265 | 266 | 267 | 268 | 269 | const RealWorld5 = () => 270 | 271 | 272 | 273 | 274 | const RealWorld6 = () => 275 | 276 | 277 | 278 | 279 | const RealWorld7 = () => 280 | 281 | 282 | 283 | 284 | const RealWorld8 = () => 285 | 286 | 287 | 288 | 289 | const RealWorld9 = () => 290 | 291 | 292 | 293 | 294 | 295 | const demos = { 296 | 'headersparklines': Header, 297 | 'simple': Simple, 298 | 'simpleCurve': SimpleCurve, 299 | 'customizable1': Customizable1, 300 | 'customizable2': Customizable2, 301 | 'customizable3': Customizable3, 302 | 'customizable4': Customizable4, 303 | 'customizable5': Customizable5, 304 | 'customizable6': Customizable6, 305 | 'spots1': Spots1, 306 | 'spots2': Spots2, 307 | 'spots3': Spots3, 308 | 'bounds1': Bounds1, 309 | 'bars1': Bars1, 310 | 'bars2': Bars2, 311 | 'dynamic1': Dynamic1, 312 | 'dynamic2': Dynamic2, 313 | 'dynamic3': Dynamic3, 314 | 'dynamic4': Dynamic4, 315 | 'referenceline1': ReferenceLine1, 316 | 'referenceline2': ReferenceLine2, 317 | 'referenceline3': ReferenceLine3, 318 | 'referenceline4': ReferenceLine4, 319 | 'referenceline5': ReferenceLine5, 320 | 'referenceline6': ReferenceLine6, 321 | 'normalband1': NormalBand1, 322 | 'normalband2': NormalBand2, 323 | 'realworld1': RealWorld1, 324 | 'realworld2': RealWorld2, 325 | 'realworld3': RealWorld3, 326 | 'realworld4': RealWorld4, 327 | 'realworld5': RealWorld5, 328 | 'realworld6': RealWorld6, 329 | 'realworld7': RealWorld7, 330 | 'realworld8': RealWorld8, 331 | 'realworld9': RealWorld9 332 | }; 333 | 334 | for (let d in demos) { 335 | ReactDOM.render(React.createElement(demos[d]), document.getElementById(d)); 336 | } 337 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 86 | 87 | 88 |
89 |
90 |

React Sparklines

91 |
92 |
93 |
94 |
95 |

96 | Beautiful and expressive sparklines component for React 97 | View on GitHub 98 |

99 |
100 |
101 |

102 | npm install react-sparklines 103 |

104 |
105 |
106 | 107 |

Simple

108 | 109 |
110 |
111 |

112 | <Sparklines data={sampleData}>
113 |     <SparklinesLine />
114 | </Sparklines>
115 |             
116 |
117 | 118 |

Simple Curve

119 | 120 |
121 |
122 |

123 | <Sparklines data={sampleData}>
124 |     <SparklinesCurve />
125 | </Sparklines>
126 |             
127 |
128 | 129 |

Customizable

130 | 131 |
132 |
133 | 134 | 135 | 136 | 137 | 138 | 139 |
140 |

141 | <Sparklines data={sampleData}>
142 |     <SparklinesLine color="#253e56" />
143 | </Sparklines>
144 |             
145 |
146 | 147 |

Spots

148 | 149 |
150 |
151 |

152 | <Sparklines data={sampleData}>
153 |     <SparklinesLine style={{ fill: "none" }} />
154 |     <SparklinesSpots />
155 | </Sparklines>
156 |             
157 |
158 | 159 |
160 |
161 |

162 | <Sparklines data={sampleData}>
163 |     <SparklinesLine color="#56b45d" />
164 |     <SparklinesSpots style={{ fill: "#56b45d" }} />
165 | </Sparklines>
166 |             
167 |
168 | 169 |
170 |
171 |

172 | <Sparklines data={sampleData} margin={6}>
173 |     <SparklinesLine style={{ strokeWidth: 3, stroke: "#336aff", fill: "none" }} />
174 |     <SparklinesSpots size={4}
175 |         style={{ stroke: "#336aff", strokeWidth: 3, fill: "white" }} />
176 | </Sparklines>
177 |             
178 |
179 | 180 |

Bounds

181 | 182 |
183 |
184 |

185 | <Sparklines data={sampleData} max={0.5}>
186 |     <SparklinesLine />
187 | </Sparklines>
188 |             
189 |
190 | 191 |

Bars

192 | 193 |
194 |
195 |

196 | <Sparklines data={sampleData}>
197 |     <SparklinesBars style={{ fill: "#41c3f9" }} />
198 | </Sparklines>
199 |             
200 |
201 | 202 |
203 |
204 |

205 | <Sparklines data={sampleData}>
206 |     <SparklinesBars style={{ stroke: "white", fill: "#41c3f9", fillOpacity: ".25" }} />
207 |     <SparklinesLine style={{ stroke: "#41c3f9", fill: "none" }} />
208 | </Sparklines>
209 |             
210 |
211 | 212 |

Dynamic

213 | 214 |
215 |
216 |

217 | <Sparklines data={this.state.data} limit={20}>
218 |     <SparklinesLine color="#1c8cdc" />
219 |     <SparklinesSpots />
220 | </Sparklines>
221 |             
222 |
223 | 224 |
225 |
226 |

227 | <Sparklines data={this.state.data} limit={20}>
228 |     <SparklinesBars style={{ fill: "#41c3f9", fillOpacity: ".25" }} />
229 |     <SparklinesLine style={{ stroke: "#41c3f9", fill: "none" }} />
230 | </Sparklines>
231 |             
232 |
233 | 234 |
235 |
236 |

237 | <Sparklines data={this.state.data} limit={20}>
238 |     <SparklinesLine style={{ stroke: "none", fill: "#8e44af", fillOpacity: "1" }}/>
239 | </Sparklines>
240 |             
241 |
242 | 243 |
244 |
245 |

246 | <Sparklines data={this.state.data} limit={10} >
247 |     <SparklinesBars color="#0a83d8" />
248 | </Sparklines>
249 |             
250 |
251 | 252 |

Reference Line

253 | 254 |
255 |
256 |

257 | <Sparklines data={sampleData}>
258 |     <SparklinesLine />
259 |     <SparklinesReferenceLine type="max" />
260 | </Sparklines>
261 |             
262 |
263 | 264 |
265 |
266 |

267 | <Sparklines data={sampleData}>
268 |     <SparklinesLine />
269 |     <SparklinesReferenceLine type="min" />
270 | </Sparklines>
271 |             
272 |
273 | 274 |
275 |
276 |

277 | <Sparklines data={sampleData}>
278 |     <SparklinesLine />
279 |     <SparklinesReferenceLine type="mean" />
280 | </Sparklines>
281 |             
282 |
283 | 284 |
285 |
286 |

287 | <Sparklines data={sampleData}>
288 |     <SparklinesLine />
289 |     <SparklinesReferenceLine type="avg" />
290 | </Sparklines>
291 |             
292 |
293 | 294 |
295 |
296 |

297 | <Sparklines data={sampleData}>
298 |     <SparklinesLine />
299 |     <SparklinesReferenceLine type="median" />
300 | </Sparklines>
301 |             
302 |
303 | 304 |
305 |
306 |

307 | <Sparklines data={sampleData}>
308 |     <SparklinesBars style={{ fill: 'slategray', fillOpacity: ".5" }} />
309 |     <SparklinesReferenceLine />
310 | </Sparklines>
311 |             
312 |
313 | 314 |

Normal Band

315 | 316 |
317 |
318 |

319 | <Sparklines data={sampleData}>
320 |     <SparklinesLine style={{ fill: "none" }}/>
321 |     <SparklinesNormalBand />
322 | </Sparklines>
323 |             
324 |
325 | 326 |
327 |
328 |

329 | <Sparklines data={sampleData}>
330 |     <SparklinesLine style={{ fill: "none" }}/>
331 |     <SparklinesNormalBand />
332 |     <SparklinesReferenceLine type="mean" />
333 | </Sparklines>
334 |             
335 |
336 | 337 |

Real world examples

338 | 339 |
340 |
341 |

342 | <Sparklines data={sampleData}>
343 |     <SparklinesLine style={{ strokeWidth: 3, stroke: "#336aff", fill: "none" }} />
344 | </Sparklines>
345 |             
346 |
347 | 348 |
349 |
350 |

351 | <Sparklines data={sampleData100} svgWidth={200}>
352 |     <SparklinesLine style={{ stroke: "#2991c8", fill: "none"}} />
353 |     <SparklinesSpots />
354 |     <SparklinesNormalBand style={{ fill: "#2991c8", fillOpacity: .1 }} />
355 | </Sparklines>
356 |             
357 |
358 | 359 |
360 |
361 |

362 | <Sparklines data={sampleData100}>
363 |     <SparklinesLine style={{ stroke: "black", fill: "none" }} />
364 |     <SparklinesSpots style={{ fill: "orange" }} />
365 | </Sparklines>
366 |             
367 |
368 | 369 |
370 |
371 |

372 | <Sparklines data={sampleData}>
373 |     <SparklinesBars style={{ stroke: "white", strokeWidth: "1", fill: "#40c0f5" }} />
374 | </Sparklines>
375 |             
376 |
377 | 378 |
379 |
380 |

381 | <Sparklines data={sampleData} height={80}>
382 |     <SparklinesLine style={{ stroke: "#8ed53f", strokeWidth: "1", fill: "none" }} />
383 | </Sparklines>
384 |             
385 |
386 | 387 |
388 |
389 |

390 | <Sparklines data={sampleData} height={80}>
391 |     <SparklinesLine style={{ stroke: "#d1192e", strokeWidth: "1", fill: "none" }} />
392 | </Sparklines>
393 |             
394 |
395 | 396 |
397 |
398 |

399 | <Sparklines data={sampleData} height={40}>
400 |     <SparklinesLine style={{ stroke: "#559500", fill: "#8fc638", fillOpacity: "1" }} />
401 | </Sparklines>
402 |             
403 |
404 | 405 |
406 |
407 |

408 | <Sparklines data={sampleData} style={{background: "#272727"}} margin={10} height={40}>
409 |     <SparklinesLine style={{ stroke: "none", fill: "#d2673a", fillOpacity: ".5" }} />
410 | </Sparklines>
411 |             
412 |
413 | 414 |
415 |
416 |

417 | <Sparklines data={sampleData} style={{background: "#00bdcc"}} margin={10} height={40}>
418 |     <SparklinesLine style={{ stroke: "white", fill: "none" }} />
419 |     <SparklinesReferenceLine
420 |         style={{ stroke: 'white', strokeOpacity: .75, strokeDasharray: '2, 2' }} />
421 | </Sparklines>
422 |             
423 |
424 | 425 |
426 | 427 | 428 | 429 | 430 | 431 | 432 | -------------------------------------------------------------------------------- /demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | cache: true, 6 | entry: './demo.js', 7 | output: { 8 | path: __dirname, 9 | publicPath: '/', 10 | filename: 'demo.build.js', 11 | }, 12 | module: { 13 | loaders: [{ 14 | test: /\.jsx?$/, 15 | exclude: /(node_modules)/, 16 | loader: 'babel-loader' 17 | }] 18 | }, 19 | plugins: [] 20 | }; 21 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src/Sparklines.js'); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-sparklines", 3 | "version": "1.7.0", 4 | "description": "Beautiful and expressive Sparklines component for React ", 5 | "main": "build/index.js", 6 | "directories": { 7 | "src": "src/" 8 | }, 9 | "scripts": { 10 | "start": "cd demo && webpack-dev-server --progress", 11 | "test": "mocha --compilers js:babel-core/register __tests__", 12 | "test:watch": "mocha --compilers js:babel-core/register --watch __tests__", 13 | "compile": "webpack", 14 | "prepublish": "npm run compile", 15 | "test:bootstrap": "node -r babel-core/register bootstrap-tests.js" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/borisyankov/react-sparklines.git" 20 | }, 21 | "keywords": [ 22 | "react", 23 | "component", 24 | "react-component", 25 | "charts", 26 | "sparklines", 27 | "visualization", 28 | "jsx" 29 | ], 30 | "author": "Boris Yankov (https://github.com/borisyankov)", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/borisyankov/react-sparklines/issues" 34 | }, 35 | "homepage": "https://github.com/borisyankov/react-sparklines#readme", 36 | "devDependencies": { 37 | "babel": "^6.5.2", 38 | "babel-core": "^6.8.0", 39 | "babel-loader": "7.1.1", 40 | "babel-plugin-transform-object-assign": "^6.8.0", 41 | "babel-preset-es2015": "^6.6.0", 42 | "babel-preset-react": "^6.5.0", 43 | "babel-preset-stage-1": "^6.5.0", 44 | "babel-runtime": "^6.6.1", 45 | "chai": "^4.1.0", 46 | "enzyme": "^2.2.0", 47 | "hiff": "^0.3.0", 48 | "line-by-line": "^0.1.4", 49 | "mocha": "^3.2.0", 50 | "react": "^15.0.2", 51 | "react-addons-test-utils": "^15.0.2", 52 | "react-dom": "^15.0.2", 53 | "react-element-to-jsx-string": "11.0.1", 54 | "replaceall": "^0.1.6", 55 | "webpack": "^3.4.1", 56 | "webpack-dev-server": "^2.2.0" 57 | }, 58 | "peerDependencies": { 59 | "react": "*", 60 | "react-dom": "*" 61 | }, 62 | "dependencies": { 63 | "prop-types": "^15.5.10" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Sparklines.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React, { PureComponent} from 'react'; 3 | import SparklinesText from './SparklinesText'; 4 | import SparklinesLine from './SparklinesLine'; 5 | import SparklinesCurve from './SparklinesCurve'; 6 | import SparklinesBars from './SparklinesBars'; 7 | import SparklinesSpots from './SparklinesSpots'; 8 | import SparklinesReferenceLine from './SparklinesReferenceLine'; 9 | import SparklinesNormalBand from './SparklinesNormalBand'; 10 | import dataToPoints from './dataProcessing/dataToPoints'; 11 | 12 | class Sparklines extends PureComponent { 13 | 14 | static propTypes = { 15 | data: PropTypes.array, 16 | limit: PropTypes.number, 17 | width: PropTypes.number, 18 | height: PropTypes.number, 19 | svgWidth: PropTypes.number, 20 | svgHeight: PropTypes.number, 21 | preserveAspectRatio: PropTypes.string, 22 | margin: PropTypes.number, 23 | style: PropTypes.object, 24 | min: PropTypes.number, 25 | max: PropTypes.number, 26 | onMouseMove: PropTypes.func 27 | }; 28 | 29 | static defaultProps = { 30 | data: [], 31 | width: 240, 32 | height: 60, 33 | //Scale the graphic content of the given element non-uniformly if necessary such that the element's bounding box exactly matches the viewport rectangle. 34 | preserveAspectRatio: 'none', //https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute 35 | margin: 2 36 | }; 37 | 38 | constructor (props) { 39 | super(props); 40 | } 41 | 42 | render() { 43 | const { data, limit, width, height, svgWidth, svgHeight, preserveAspectRatio, margin, style, max, min} = this.props; 44 | 45 | if (data.length === 0) return null; 46 | 47 | const points = dataToPoints({ data, limit, width, height, margin, max, min }); 48 | 49 | const svgOpts = { style: style, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: preserveAspectRatio }; 50 | if (svgWidth > 0) svgOpts.width = svgWidth; 51 | if (svgHeight > 0) svgOpts.height = svgHeight; 52 | 53 | return ( 54 | 55 | { 56 | React.Children.map(this.props.children, function(child) { 57 | return React.cloneElement(child, { data, points, width, height, margin }); 58 | }) 59 | } 60 | 61 | ); 62 | } 63 | } 64 | 65 | export { Sparklines, SparklinesLine, SparklinesCurve, SparklinesBars, SparklinesSpots, SparklinesReferenceLine, SparklinesNormalBand, SparklinesText } 66 | -------------------------------------------------------------------------------- /src/SparklinesBars.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | export default class SparklinesBars extends React.Component { 5 | static propTypes = { 6 | points: PropTypes.arrayOf(PropTypes.object), 7 | height: PropTypes.number, 8 | style: PropTypes.object, 9 | barWidth: PropTypes.number, 10 | margin: PropTypes.number, 11 | onMouseMove: PropTypes.func, 12 | }; 13 | 14 | static defaultProps = { 15 | style: { fill: 'slategray' }, 16 | }; 17 | 18 | render() { 19 | const { points, height, style, barWidth, margin, onMouseMove } = this.props; 20 | const strokeWidth = 1 * ((style && style.strokeWidth) || 0); 21 | const marginWidth = margin ? 2 * margin : 0; 22 | const width = 23 | barWidth || 24 | (points && points.length >= 2 25 | ? Math.max(0, points[1].x - points[0].x - strokeWidth - marginWidth) 26 | : 0); 27 | 28 | return ( 29 | 30 | {points.map((p, i) => 31 | , 40 | )} 41 | 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/SparklinesCurve.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | export default class SparklinesCurve extends React.Component { 5 | 6 | static propTypes = { 7 | color: PropTypes.string, 8 | style: PropTypes.object 9 | }; 10 | 11 | static defaultProps = { 12 | style: {} 13 | }; 14 | 15 | render() { 16 | const { points, width, height, margin, color, style, divisor = 0.25 } = this.props; 17 | let prev; 18 | const curve = (p) => { 19 | let res; 20 | if (!prev) { 21 | res = [p.x, p.y] 22 | } else { 23 | const len = (p.x - prev.x) * divisor; 24 | res = [ "C", 25 | //x1 26 | prev.x + len, 27 | //y1 28 | prev.y, 29 | //x2, 30 | p.x - len, 31 | //y2, 32 | p.y, 33 | //x, 34 | p.x, 35 | //y 36 | p.y 37 | ]; 38 | } 39 | prev = p; 40 | return res; 41 | 42 | } 43 | const linePoints = points 44 | .map((p) => curve(p)) 45 | .reduce((a, b) => a.concat(b)); 46 | const closePolyPoints = [ 47 | "L" + points[points.length - 1].x, height - margin, 48 | margin, height - margin, 49 | margin, points[0].y 50 | ]; 51 | const fillPoints = linePoints.concat(closePolyPoints); 52 | 53 | const lineStyle = { 54 | stroke: color || style.stroke || 'slategray', 55 | strokeWidth: style.strokeWidth || '1', 56 | strokeLinejoin: style.strokeLinejoin || 'round', 57 | strokeLinecap: style.strokeLinecap || 'round', 58 | fill: 'none' 59 | }; 60 | const fillStyle = { 61 | stroke: style.stroke || 'none', 62 | strokeWidth: '0', 63 | fillOpacity: style.fillOpacity || '.1', 64 | fill: style.fill || color || 'slategray' 65 | }; 66 | 67 | return ( 68 | 69 | 70 | 71 | 72 | ) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/SparklinesLine.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | export default class SparklinesLine extends React.Component { 5 | static propTypes = { 6 | color: PropTypes.string, 7 | style: PropTypes.object, 8 | }; 9 | 10 | static defaultProps = { 11 | style: {}, 12 | onMouseMove: () => {}, 13 | }; 14 | 15 | render() { 16 | const { data, points, width, height, margin, color, style, onMouseMove } = this.props; 17 | 18 | const linePoints = points.map(p => [p.x, p.y]).reduce((a, b) => a.concat(b)); 19 | 20 | const closePolyPoints = [ 21 | points[points.length - 1].x, 22 | height - margin, 23 | margin, 24 | height - margin, 25 | margin, 26 | points[0].y, 27 | ]; 28 | 29 | const fillPoints = linePoints.concat(closePolyPoints); 30 | 31 | const lineStyle = { 32 | stroke: color || style.stroke || 'slategray', 33 | strokeWidth: style.strokeWidth || '1', 34 | strokeLinejoin: style.strokeLinejoin || 'round', 35 | strokeLinecap: style.strokeLinecap || 'round', 36 | fill: 'none', 37 | }; 38 | const fillStyle = { 39 | stroke: style.stroke || 'none', 40 | strokeWidth: '0', 41 | fillOpacity: style.fillOpacity || '.1', 42 | fill: style.fill || color || 'slategray', 43 | pointerEvents: 'auto', 44 | }; 45 | 46 | const tooltips = points.map((p, i) => { 47 | return ( 48 | onMouseMove('enter', data[i], p)} 55 | onClick={e => onMouseMove('click', data[i], p)} 56 | /> 57 | ); 58 | }); 59 | 60 | return ( 61 | 62 | {tooltips} 63 | 64 | 65 | 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/SparklinesNormalBand.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import mean from './dataProcessing/mean'; 4 | import stdev from './dataProcessing/stdev'; 5 | 6 | export default class SparklinesNormalBand extends React.Component { 7 | 8 | static propTypes = { 9 | style: PropTypes.object 10 | }; 11 | 12 | static defaultProps = { 13 | style: { fill: 'red', fillOpacity: .1 } 14 | }; 15 | 16 | render() { 17 | 18 | const { points, margin, style } = this.props; 19 | 20 | const ypoints = points.map(p => p.y); 21 | const dataMean = mean(ypoints); 22 | const dataStdev = stdev(ypoints); 23 | 24 | return ( 25 | 28 | ) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/SparklinesReferenceLine.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import * as dataProcessing from './dataProcessing'; 4 | 5 | export default class SparklinesReferenceLine extends React.Component { 6 | 7 | static propTypes = { 8 | type: PropTypes.oneOf(['max', 'min', 'mean', 'avg', 'median', 'custom']), 9 | value: PropTypes.number, 10 | style: PropTypes.object 11 | }; 12 | 13 | static defaultProps = { 14 | type: 'mean', 15 | style: { stroke: 'red', strokeOpacity: .75, strokeDasharray: '2, 2' } 16 | }; 17 | 18 | render() { 19 | 20 | const { points, margin, type, style, value } = this.props; 21 | 22 | const ypoints = points.map(p => p.y); 23 | const y = type == 'custom' ? value : dataProcessing[type](ypoints); 24 | 25 | return ( 26 | 30 | ) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/SparklinesSpots.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | export default class SparklinesSpots extends React.Component { 5 | 6 | static propTypes = { 7 | size: PropTypes.number, 8 | style: PropTypes.object, 9 | spotColors: PropTypes.object 10 | }; 11 | 12 | static defaultProps = { 13 | size: 2, 14 | spotColors: { 15 | '-1': 'red', 16 | '0': 'black', 17 | '1': 'green' 18 | } 19 | }; 20 | 21 | lastDirection(points) { 22 | 23 | Math.sign = Math.sign || function(x) { return x > 0 ? 1 : -1; } 24 | 25 | return points.length < 2 26 | ? 0 27 | : Math.sign(points[points.length - 2].y - points[points.length - 1].y); 28 | } 29 | 30 | render() { 31 | 32 | const { points, width, height, size, style, spotColors } = this.props; 33 | 34 | const startSpot = 39 | 40 | const endSpot = 45 | 46 | return ( 47 | 48 | {style && startSpot} 49 | {endSpot} 50 | 51 | ) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/SparklinesText.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | export default class SparklinesText extends React.Component { 5 | 6 | static propTypes = { 7 | text: PropTypes.string, 8 | point: PropTypes.object, 9 | fontSize: PropTypes.number, 10 | fontFamily: PropTypes.string 11 | }; 12 | 13 | static defaultProps = { 14 | text: '', 15 | point: { x: 0, y: 0 } 16 | }; 17 | 18 | render() { 19 | const { point, text, fontSize, fontFamily } = this.props; 20 | const { x, y } = point; 21 | return ( 22 | 23 | 24 | { text } 25 | 26 | 27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/dataProcessing/dataToPoints.js: -------------------------------------------------------------------------------- 1 | import arrayMin from './min'; 2 | import arrayMax from './max'; 3 | 4 | export default ({ data, limit, width = 1, height = 1, margin = 0, max = arrayMax(data), min = arrayMin(data) }) => { 5 | 6 | const len = data.length; 7 | 8 | if (limit && limit < len) { 9 | data = data.slice(len - limit); 10 | } 11 | 12 | const vfactor = (height - margin * 2) / ((max - min) || 2); 13 | const hfactor = (width - margin * 2) / ((limit || len) - (len > 1 ? 1 : 0)); 14 | 15 | return data.map((d, i) => ({ 16 | x: i * hfactor + margin, 17 | y: (max === min ? 1 : (max - d)) * vfactor + margin 18 | })); 19 | }; 20 | -------------------------------------------------------------------------------- /src/dataProcessing/index.js: -------------------------------------------------------------------------------- 1 | export min from './min'; 2 | export max from './min'; 3 | export mean from './mean'; 4 | export avg from './mean'; 5 | export midRange from './midRange'; 6 | export median from './median'; 7 | export stdev from './stdev'; 8 | export variance from './variance'; 9 | -------------------------------------------------------------------------------- /src/dataProcessing/max.js: -------------------------------------------------------------------------------- 1 | export default data => 2 | Math.max.apply(Math, data); 3 | -------------------------------------------------------------------------------- /src/dataProcessing/mean.js: -------------------------------------------------------------------------------- 1 | export default data => 2 | data.reduce((a, b) => a + b) / data.length; 3 | -------------------------------------------------------------------------------- /src/dataProcessing/median.js: -------------------------------------------------------------------------------- 1 | export default data => 2 | data.sort((a,b) => a - b)[Math.floor(data.length / 2)]; 3 | -------------------------------------------------------------------------------- /src/dataProcessing/midRange.js: -------------------------------------------------------------------------------- 1 | import min from './min'; 2 | import max from './max'; 3 | 4 | export default data => 5 | max(data) - min(data) / 2; 6 | -------------------------------------------------------------------------------- /src/dataProcessing/min.js: -------------------------------------------------------------------------------- 1 | export default data => 2 | Math.min.apply(Math, data); 3 | -------------------------------------------------------------------------------- /src/dataProcessing/stdev.js: -------------------------------------------------------------------------------- 1 | import mean from './mean'; 2 | 3 | export default data => { 4 | const dataMean = mean(data); 5 | const sqDiff = data.map(n => Math.pow(n - dataMean, 2)); 6 | const avgSqDiff = mean(sqDiff); 7 | return Math.sqrt(avgSqDiff); 8 | } 9 | -------------------------------------------------------------------------------- /src/dataProcessing/variance.js: -------------------------------------------------------------------------------- 1 | import mean from './mean' 2 | 3 | export default data => { 4 | const dataMean = mean(data); 5 | const sq = data.map(n => Math.pow(n - dataMean, 2)); 6 | return mean(sq); 7 | } 8 | -------------------------------------------------------------------------------- /wallaby.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function (wallaby) { 2 | return { 3 | files: ['src/*.js'], 4 | 5 | tests: ['__tests__/*.js'], 6 | 7 | env: { 8 | type: 'node', 9 | runner: 'node' 10 | }, 11 | 12 | compilers: { 13 | '**/*.js': wallaby.compilers.babel({ 14 | presets: [ 15 | 'react', 16 | 'es2015', 17 | 'stage-1', 18 | ], 19 | }), 20 | }, 21 | 22 | testFramework: 'mocha' 23 | 24 | }; 25 | }; 26 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: { 6 | index: [ 7 | './index.js' 8 | ] 9 | }, 10 | output: { 11 | path: path.join(__dirname, 'build'), 12 | publicPath: '/', 13 | filename: '[name].js', 14 | library: 'ReactSparklines', 15 | libraryTarget: 'umd' 16 | }, 17 | externals: { 18 | react: { 19 | root: 'React', 20 | commonjs2: 'react', 21 | commonjs: 'react', 22 | amd: 'react' 23 | } 24 | }, 25 | module: { 26 | loaders: [{ 27 | test: /\.jsx?$/, 28 | exclude: /(node_modules)/, 29 | loader: 'babel-loader' 30 | }] 31 | }, 32 | }; 33 | --------------------------------------------------------------------------------