@evergis/charts
Advanced tools
Comparing version 1.0.2 to 1.0.3
@@ -7,12 +7,448 @@ 'use strict'; | ||
var React = _interopDefault(require('react')); | ||
var React = require('react'); | ||
var React__default = _interopDefault(React); | ||
var d3 = require('d3'); | ||
var ReactDOMServer = _interopDefault(require('react-dom/server')); | ||
var styled = require('styled-components'); | ||
var styled__default = _interopDefault(styled); | ||
const Charts = (_ref) => { | ||
function useNode() { | ||
const [node, onSetNode] = React.useState(null); | ||
const ref = React.useCallback(nodeElement => onSetNode(nodeElement), []); | ||
return [ref, node]; | ||
} | ||
function throttle(fn, wait) { | ||
let isCalled = false; | ||
return function () { | ||
if (!isCalled) { | ||
fn(...arguments); | ||
isCalled = true; | ||
setTimeout(function () { | ||
isCalled = false; | ||
}, wait); | ||
} | ||
}; | ||
} | ||
const isNumber = value => { | ||
// First: Check typeof and make sure it returns number | ||
// This code coerces neither booleans nor strings to numbers, | ||
// although it would be possible to do so if desired. | ||
if (typeof value !== 'number') { | ||
return false; | ||
} // Reference for typeof: | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof | ||
// Second: Check for NaN, as NaN is a number to typeof. | ||
// NaN is the only JavaScript value that never equals itself. | ||
if (value !== Number(value)) { | ||
return false; | ||
} // Reference for NaN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN | ||
// Note isNaN() is a broken function, but checking for self-equality works as NaN !== NaN | ||
// Alternatively check for NaN using Number.isNaN(), an ES2015 feature that works how one would expect | ||
// Third: Check for Infinity and -Infinity. | ||
// Realistically we want finite numbers, or there was probably a division by 0 somewhere. | ||
// @ts-ignore | ||
if (value === Infinity || value === !Infinity) { | ||
return false; | ||
} | ||
return true; | ||
}; | ||
const useResize = (width, callback) => { | ||
const wait = 44; | ||
React.useEffect(() => { | ||
callback && !isNumber(width) && window.addEventListener('resize', throttle(callback, wait)); | ||
return () => callback && window.removeEventListener('resize', throttle(callback, wait)); | ||
}, [width, callback]); | ||
}; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _taggedTemplateLiteralLoose(strings, raw) { | ||
if (!raw) { | ||
raw = strings.slice(0); | ||
} | ||
strings.raw = raw; | ||
return strings; | ||
} | ||
const appendSvg = (node, width, height) => { | ||
d3.select(node).select('svg').remove(); | ||
const svg = d3.select(node).append('svg').attr('width', width).attr('height', height); | ||
return svg; | ||
}; | ||
const degByIndex = (index, count) => { | ||
const degs = 360; | ||
const deg = degs / count * index; | ||
return deg; | ||
}; | ||
const getTextAnchor = (index, data) => { | ||
const deg = degByIndex(index, data.length); | ||
const halfAngle = 180; | ||
if ([0, halfAngle].includes(deg)) { | ||
return 'middle'; | ||
} | ||
if (deg < halfAngle) { | ||
return 'start'; | ||
} | ||
return 'end'; | ||
}; | ||
function _templateObject() { | ||
const data = _taggedTemplateLiteralLoose(["\n position: relative;\n width: 100%;\n"]); | ||
_templateObject = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
const Wrapper = /*#__PURE__*/styled__default.div( /*#__PURE__*/_templateObject()); | ||
function _templateObject8() { | ||
const data = _taggedTemplateLiteralLoose(["\n margin-left: 0.25rem;\n font-size: 0.625rem;\n color: rgba(255, 255, 255, 0.54);\n"]); | ||
_templateObject8 = function _templateObject8() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject7() { | ||
const data = _taggedTemplateLiteralLoose(["\n ", "\n"]); | ||
_templateObject7 = function _templateObject7() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject6() { | ||
const data = _taggedTemplateLiteralLoose(["\n display: flex;\n align-items: center;\n padding: 0.125rem 0.25rem;\n border-radius: 0.25rem;\n color: rgb(255, 255, 255);\n background-color: rgb(144, 197, 61);\n margin-left: 0.5rem;\n"]); | ||
_templateObject6 = function _templateObject6() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject5() { | ||
const data = _taggedTemplateLiteralLoose(["\n position: absolute;\n top: 50%;\n right: 0;\n transform: translate(calc(100% + 0.5rem), -50%);\n"]); | ||
_templateObject5 = function _templateObject5() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject4() { | ||
const data = _taggedTemplateLiteralLoose(["\n text-align: center;\n max-width: 7.5rem;\n"]); | ||
_templateObject4 = function _templateObject4() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject3() { | ||
const data = _taggedTemplateLiteralLoose(["\n display: flex;\n align-items: center;\n font-size: 0.75rem;\n"]); | ||
_templateObject3 = function _templateObject3() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject2() { | ||
const data = _taggedTemplateLiteralLoose(["\n position: absolute;\n"]); | ||
_templateObject2 = function _templateObject2() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject$1() { | ||
const data = _taggedTemplateLiteralLoose(["\n .", " {\n path,\n line,\n circle {\n fill: none;\n stroke-width: 1px;\n stroke: #959595;\n stroke-opacity: 0.18;\n }\n }\n .", " {\n font-size: 0.75rem;\n fill-opacity: 0.56;\n }\n .", " {\n fill-opacity: 0.06;\n stroke-width: 2px;\n fill: rgb(144, 197, 61);\n stroke: rgb(144, 197, 61);\n }\n .", " {\n fill: rgb(144, 197, 61);\n }\n"]); | ||
_templateObject$1 = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
const radarChartclassNames = { | ||
radar: 'radar', | ||
radarAxis: 'radarAxis', | ||
radarAxisText: 'radarAxisText', | ||
radarPolygon: 'radarPolygon', | ||
radarLabel: 'radarLabel', | ||
radarLabelName: 'radarLabelName', | ||
radarLabelBadge: 'radarLabelBadge', | ||
radarLabelBadgePrefix: 'radarLabelBadgePrefix', | ||
radarCircle: 'radarCircle' | ||
}; | ||
const SvgWrapper = /*#__PURE__*/styled__default(Wrapper)( /*#__PURE__*/_templateObject$1(), radarChartclassNames.radarAxis, radarChartclassNames.radarAxisText, radarChartclassNames.radarPolygon, radarChartclassNames.radarCircle); | ||
const getTranslate = (_ref) => { | ||
let { | ||
children | ||
anchor, | ||
index, | ||
translateX, | ||
translateY | ||
} = _ref; | ||
return React.createElement("div", null, children || "the snozzberries taste like snozzberries"); | ||
if (index === 0 && anchor === 'middle') { | ||
return "translate(calc(-50% + " + translateX + "px), calc(-100% + " + translateY + "px))"; | ||
} else if (anchor === 'middle') { | ||
return "translate(calc(-50% + " + translateX + "px), calc(" + translateY + "px))"; | ||
} else if (anchor === 'start') { | ||
return "translate(calc(" + translateX + "px), calc(-50% + " + translateY + "px))"; | ||
} else if (anchor === 'end') { | ||
return "translate(calc(-100% + " + translateX + "px), calc(-50% + " + translateY + "px))"; | ||
} | ||
return "translate(" + translateX + "px, " + translateY + "px)"; | ||
}; | ||
exports.Charts = Charts; | ||
const LabelContainer = /*#__PURE__*/styled__default.div.attrs(props => ({ | ||
style: { | ||
transform: getTranslate(props) | ||
} | ||
}))( /*#__PURE__*/_templateObject2()); | ||
const Label = /*#__PURE__*/styled__default.div( /*#__PURE__*/_templateObject3()); | ||
const Name = /*#__PURE__*/styled__default.div( /*#__PURE__*/_templateObject4()); | ||
const middleBadgeStyles = /*#__PURE__*/styled.css( /*#__PURE__*/_templateObject5()); | ||
const DefaultBadge = /*#__PURE__*/styled__default.div( /*#__PURE__*/_templateObject6()); | ||
const MiddleBadge = /*#__PURE__*/styled__default(DefaultBadge)( /*#__PURE__*/_templateObject7(), middleBadgeStyles); | ||
const BadgePrefix = /*#__PURE__*/styled__default.div( /*#__PURE__*/_templateObject8()); | ||
const draw = (node, props) => { | ||
const { | ||
data, | ||
curve, | ||
polar, | ||
formatValue, | ||
badgePrefix, | ||
labelOffset, | ||
circleRadius, | ||
gradient | ||
} = props; | ||
if (node !== null && data.length) { | ||
const defaultBleedLength = 10; | ||
const bleedLength = typeof props.bleedLength === 'number' ? props.bleedLength : defaultBleedLength; | ||
const { | ||
width: nodeWidth | ||
} = node.getBoundingClientRect(); | ||
const width = props.width || nodeWidth; | ||
const defaultHeight = 400; | ||
const height = props.height || defaultHeight; | ||
const minValue = props.minValue || Math.min(0, d3.min(data, i => d3.min(i.map((_ref) => { | ||
let { | ||
value | ||
} = _ref; | ||
return value; | ||
})))); | ||
const maxValue = (props.maxValue || Math.max(0, d3.max(data, i => d3.max(i.map((_ref2) => { | ||
let { | ||
value | ||
} = _ref2; | ||
return value; | ||
}))))) - minValue; | ||
const paddingX = props.paddingX || 0; | ||
const paddingY = props.paddingY || 0; | ||
const radius = Math.min((width - paddingX * 2 - bleedLength * 2) / 2, (height - paddingY * 2 - bleedLength * 2) / 2); | ||
const radiusScale = d3.scaleLinear().range([0, radius]).domain([0, maxValue]); | ||
const defaultLevels = 4; | ||
const levels = props.levels || defaultLevels; | ||
const angleSlice = Math.PI * 2 / data[0].length; | ||
const radarLine = d3.lineRadial().curve(d3.curveLinearClosed) // @ts-ignore | ||
.radius((_ref3) => { | ||
let { | ||
value | ||
} = _ref3; | ||
return radiusScale(value); | ||
}).angle((_, i) => i * angleSlice); | ||
const radarValue = d3.lineRadial().curve(curve || d3.curveLinearClosed) // @ts-ignore | ||
.radius((_ref4) => { | ||
let { | ||
value | ||
} = _ref4; | ||
return radiusScale(value); | ||
}).angle((_, i) => i * angleSlice); | ||
const svg = appendSvg(node, width, height); | ||
const globalCenter = svg.append('g'); | ||
const levelsGrid = d3.range(1, levels + 1).reverse(); | ||
const axisGridY = value => -value * radius / levels; | ||
const getAxisValue = value => maxValue * value / levels; | ||
const gridGlobal = globalCenter.append('g').attr('class', radarChartclassNames.radarAxis).selectAll().data([data[0]]).enter(); | ||
const radarGlobal = globalCenter.append('g').attr('class', radarChartclassNames.radar); | ||
const axis = gridGlobal.selectAll().data(data[0].map((_ref5) => { | ||
let { | ||
name | ||
} = _ref5; | ||
return name; | ||
})).enter(); | ||
let maxGridHeight = 0; | ||
if (polar) { | ||
levelsGrid.forEach(value => { | ||
const path = gridGlobal.append('circle').attr('cx', 0).attr('cy', 0).attr('r', () => radius / levels * value); | ||
const circleNode = path.node(); | ||
const circleHeight = circleNode.getBoundingClientRect().height; | ||
maxGridHeight = Math.max(maxGridHeight, circleHeight); | ||
}); | ||
} else { | ||
levelsGrid.map(getAxisValue).forEach(value => { | ||
const path = gridGlobal.append('path').attr('d', () => // @ts-ignore | ||
radarLine(Array.from({ | ||
length: data[0].length | ||
}, () => ({ | ||
value | ||
})))); | ||
const pathNode = path.node(); | ||
const pathHeight = pathNode.getBoundingClientRect().height; | ||
maxGridHeight = Math.max(maxGridHeight, pathHeight); | ||
}); | ||
} | ||
const radiusByMaxValue = radiusScale(maxValue) + bleedLength; | ||
axis.append('line').attr('x1', 0).attr('y1', 0).attr('x2', (_, i) => radiusByMaxValue * Math.cos(angleSlice * i - Math.PI / 2)).attr('y2', (_, i) => radiusByMaxValue * Math.sin(angleSlice * i - Math.PI / 2)); | ||
data.forEach(d => { | ||
radarGlobal.append('path').attr('class', radarChartclassNames.radarPolygon).attr('d', () => radarValue( // @ts-ignore | ||
d.map(dataItem => _extends({}, dataItem, { | ||
value: dataItem.value - minValue | ||
})))); | ||
}); | ||
globalCenter.selectAll('text').data(levelsGrid).enter().append('text').attr('class', radarChartclassNames.radarAxisText).attr('x', '4').attr('y', axisGridY).attr('dy', 0).attr('dominant-baseline', 'central').text(value => getAxisValue(value) + minValue); | ||
circleRadius && data.forEach(item => { | ||
const circleGlobal = radarGlobal.append('g').attr('class', radarChartclassNames.radarCircle); | ||
item.forEach((_ref6, i) => { | ||
let { | ||
value | ||
} = _ref6; | ||
circleGlobal.append('circle').attr('cx', radiusScale(value) * Math.cos(angleSlice * i - Math.PI / 2)).attr('cy', radiusScale(value * Math.sin(angleSlice * i - Math.PI / 2))).attr('r', circleRadius); | ||
}); | ||
}); | ||
const pxToValue = value => maxValue / radius * value; | ||
const defaultLabelOffset = 8; | ||
const axisX = i => radiusScale(maxValue + pxToValue(bleedLength + (labelOffset || defaultLabelOffset))) * Math.cos(angleSlice * i - Math.PI / 2); | ||
const axisY = i => radiusScale((maxValue + pxToValue(bleedLength + (labelOffset || defaultLabelOffset))) * Math.sin(angleSlice * i - Math.PI / 2)); | ||
const labels = data[0].map((_, i) => ({ | ||
x: Math.ceil(axisX(i)), | ||
y: Math.ceil(axisY(i)) | ||
})); | ||
const heightInner = height - bleedLength - paddingY; | ||
const translateX = width / 2; | ||
const translateY = heightInner / 2 + (heightInner - maxGridHeight) / 2; | ||
globalCenter.attr('transform', "translate(" + translateX + "," + translateY + ")"); | ||
const d3container = d3.select(node); | ||
d3container.selectAll("." + radarChartclassNames.radarLabel).remove(); | ||
labels.forEach((_ref7, index) => { | ||
let { | ||
x, | ||
y | ||
} = _ref7; | ||
const anchor = getTextAnchor(index, data[0]); | ||
const Badge = anchor === 'middle' ? MiddleBadge : DefaultBadge; | ||
const html = ReactDOMServer.renderToString(React__default.createElement(LabelContainer, { | ||
anchor: anchor, | ||
translateX: translateX, | ||
translateY: translateY, | ||
index: index, | ||
style: { | ||
left: x, | ||
top: y | ||
} | ||
}, React__default.createElement(Label, { | ||
className: radarChartclassNames.radarLabel | ||
}, React__default.createElement(Name, { | ||
className: radarChartclassNames.radarLabelName | ||
}, data[0][index].name), data.length === 1 && React__default.createElement(Badge, { | ||
className: radarChartclassNames.radarLabelBadge | ||
}, typeof formatValue === 'function' ? formatValue(data[0][index].value) : data[0][index].value, badgePrefix && React__default.createElement(BadgePrefix, { | ||
className: radarChartclassNames.radarLabelBadgePrefix | ||
}, badgePrefix))))); | ||
d3container.append('div').attr('class', radarChartclassNames.radarLabel).html(html); | ||
}); | ||
if (gradient) { | ||
const html = ReactDOMServer.renderToString(gradient); | ||
svg.append('g').html(html); | ||
} | ||
} | ||
}; | ||
const RadarChart = props => { | ||
const { | ||
className, | ||
style | ||
} = props; | ||
const [ref, node] = useNode(); | ||
React.useEffect(() => { | ||
node && draw(node, props); | ||
}, [node, props]); | ||
const onDraw = () => draw(node, props); | ||
useResize(props.width, onDraw); | ||
return React__default.createElement("div", { | ||
className: className, | ||
style: style | ||
}, React__default.createElement(SvgWrapper, { | ||
ref: ref | ||
})); | ||
}; | ||
RadarChart.defaultProps = { | ||
height: 400, | ||
data: [], | ||
curve: d3.curveLinearClosed | ||
}; | ||
exports.RadarChart = RadarChart; | ||
exports.radarChartclassNames = radarChartclassNames; | ||
//# sourceMappingURL=charts.cjs.development.js.map |
@@ -1,2 +0,2 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=(e=require("react"))&&"object"==typeof e&&"default"in e?e.default:e;exports.Charts=e=>{let{children:r}=e;return t.createElement("div",null,r||"the snozzberries taste like snozzberries")}; | ||
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),a=e(t),r=require("d3"),n=e(require("react-dom/server")),l=require("styled-components"),i=e(l);function c(e,t){let a=!1;return function(){a||(e(...arguments),a=!0,setTimeout((function(){a=!1}),t))}}function s(){return(s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var r in a)Object.prototype.hasOwnProperty.call(a,r)&&(e[r]=a[r])}return e}).apply(this,arguments)}function o(e,t){return t||(t=e.slice(0)),e.raw=t,e}function d(){const e=o(["\n position: relative;\n width: 100%;\n"]);return d=function(){return e},e}function u(){const e=o(["\n margin-left: 0.25rem;\n font-size: 0.625rem;\n color: rgba(255, 255, 255, 0.54);\n"]);return u=function(){return e},e}function p(){const e=o(["\n ","\n"]);return p=function(){return e},e}function f(){const e=o(["\n display: flex;\n align-items: center;\n padding: 0.125rem 0.25rem;\n border-radius: 0.25rem;\n color: rgb(255, 255, 255);\n background-color: rgb(144, 197, 61);\n margin-left: 0.5rem;\n"]);return f=function(){return e},e}function m(){const e=o(["\n position: absolute;\n top: 50%;\n right: 0;\n transform: translate(calc(100% + 0.5rem), -50%);\n"]);return m=function(){return e},e}function h(){const e=o(["\n text-align: center;\n max-width: 7.5rem;\n"]);return h=function(){return e},e}function g(){const e=o(["\n display: flex;\n align-items: center;\n font-size: 0.75rem;\n"]);return g=function(){return e},e}function x(){const e=o(["\n position: absolute;\n"]);return x=function(){return e},e}function v(){const e=o(["\n ."," {\n path,\n line,\n circle {\n fill: none;\n stroke-width: 1px;\n stroke: #959595;\n stroke-opacity: 0.18;\n }\n }\n ."," {\n font-size: 0.75rem;\n fill-opacity: 0.56;\n }\n ."," {\n fill-opacity: 0.06;\n stroke-width: 2px;\n fill: rgb(144, 197, 61);\n stroke: rgb(144, 197, 61);\n }\n ."," {\n fill: rgb(144, 197, 61);\n }\n"]);return v=function(){return e},e}const b={radar:"radar",radarAxis:"radarAxis",radarAxisText:"radarAxisText",radarPolygon:"radarPolygon",radarLabel:"radarLabel",radarLabelName:"radarLabelName",radarLabelBadge:"radarLabelBadge",radarLabelBadgePrefix:"radarLabelBadgePrefix",radarCircle:"radarCircle"},y=i(i.div(d()))(v(),b.radarAxis,b.radarAxisText,b.radarPolygon,b.radarCircle),L=e=>{let{anchor:t,index:a,translateX:r,translateY:n}=e;return 0===a&&"middle"===t?"translate(calc(-50% + "+r+"px), calc(-100% + "+n+"px))":"middle"===t?"translate(calc(-50% + "+r+"px), calc("+n+"px))":"start"===t?"translate(calc("+r+"px), calc(-50% + "+n+"px))":"end"===t?"translate(calc(-100% + "+r+"px), calc(-50% + "+n+"px))":"translate("+r+"px, "+n+"px)"},M=i.div.attrs(e=>({style:{transform:L(e)}}))(x()),P=i.div(g()),E=i.div(h()),w=l.css(m()),A=i.div(f()),C=i(A)(p(),w),N=i.div(u()),B=(e,t)=>{const{data:l,curve:i,polar:c,formatValue:o,badgePrefix:d,labelOffset:u,circleRadius:p,gradient:f}=t;if(null!==e&&l.length){const m=10,h="number"==typeof t.bleedLength?t.bleedLength:m,{width:g}=e.getBoundingClientRect(),x=t.width||g,v=400,y=t.height||v,L=t.minValue||Math.min(0,r.min(l,e=>r.min(e.map(e=>{let{value:t}=e;return t})))),w=(t.maxValue||Math.max(0,r.max(l,e=>r.max(e.map(e=>{let{value:t}=e;return t})))))-L,B=t.paddingY||0,I=Math.min((x-2*(t.paddingX||0)-2*h)/2,(y-2*B-2*h)/2),k=r.scaleLinear().range([0,I]).domain([0,w]),R=4,T=t.levels||R,z=2*Math.PI/l[0].length,O=r.lineRadial().curve(r.curveLinearClosed).radius(e=>{let{value:t}=e;return k(t)}).angle((e,t)=>t*z),j=r.lineRadial().curve(i||r.curveLinearClosed).radius(e=>{let{value:t}=e;return k(t)}).angle((e,t)=>t*z),q=((e,t,a)=>(r.select(e).select("svg").remove(),r.select(e).append("svg").attr("width",t).attr("height",a)))(e,x,y),S=q.append("g"),V=r.range(1,T+1).reverse(),X=e=>-e*I/T,Y=e=>w*e/T,_=S.append("g").attr("class",b.radarAxis).selectAll().data([l[0]]).enter(),D=S.append("g").attr("class",b.radar),F=_.selectAll().data(l[0].map(e=>{let{name:t}=e;return t})).enter();let G=0;c?V.forEach(e=>{const t=_.append("circle").attr("cx",0).attr("cy",0).attr("r",()=>I/T*e).node().getBoundingClientRect().height;G=Math.max(G,t)}):V.map(Y).forEach(e=>{const t=_.append("path").attr("d",()=>O(Array.from({length:l[0].length},()=>({value:e})))).node().getBoundingClientRect().height;G=Math.max(G,t)});const H=k(w)+h;F.append("line").attr("x1",0).attr("y1",0).attr("x2",(e,t)=>H*Math.cos(z*t-Math.PI/2)).attr("y2",(e,t)=>H*Math.sin(z*t-Math.PI/2)),l.forEach(e=>{D.append("path").attr("class",b.radarPolygon).attr("d",()=>j(e.map(e=>s({},e,{value:e.value-L}))))}),S.selectAll("text").data(V).enter().append("text").attr("class",b.radarAxisText).attr("x","4").attr("y",X).attr("dy",0).attr("dominant-baseline","central").text(e=>Y(e)+L),p&&l.forEach(e=>{const t=D.append("g").attr("class",b.radarCircle);e.forEach((e,a)=>{let{value:r}=e;t.append("circle").attr("cx",k(r)*Math.cos(z*a-Math.PI/2)).attr("cy",k(r*Math.sin(z*a-Math.PI/2))).attr("r",p)})});const J=e=>w/I*e,K=8,Q=e=>k(w+J(h+(u||K)))*Math.cos(z*e-Math.PI/2),U=e=>k((w+J(h+(u||K)))*Math.sin(z*e-Math.PI/2)),W=l[0].map((e,t)=>({x:Math.ceil(Q(t)),y:Math.ceil(U(t))})),Z=y-h-B,$=x/2,ee=Z/2+(Z-G)/2;S.attr("transform","translate("+$+","+ee+")");const te=r.select(e);if(te.selectAll("."+b.radarLabel).remove(),W.forEach((e,t)=>{let{x:r,y:i}=e;const c=((e,t)=>{const a=((e,t)=>360/t*e)(e,t.length),r=180;return[0,r].includes(a)?"middle":a<r?"start":"end"})(t,l[0]),s="middle"===c?C:A,u=n.renderToString(a.createElement(M,{anchor:c,translateX:$,translateY:ee,index:t,style:{left:r,top:i}},a.createElement(P,{className:b.radarLabel},a.createElement(E,{className:b.radarLabelName},l[0][t].name),1===l.length&&a.createElement(s,{className:b.radarLabelBadge},"function"==typeof o?o(l[0][t].value):l[0][t].value,d&&a.createElement(N,{className:b.radarLabelBadgePrefix},d)))));te.append("div").attr("class",b.radarLabel).html(u)}),f){const e=n.renderToString(f);q.append("g").html(e)}}},I=e=>{const{className:r,style:n}=e,[l,i]=function(){const[e,a]=t.useState(null);return[t.useCallback(e=>a(e),[]),e]}();return t.useEffect(()=>{i&&B(i,e)},[i,e]),t.useEffect(()=>{var e;return o&&("number"!=typeof(e=s)||e!==Number(e)||Infinity===e||!1===e)&&window.addEventListener("resize",c(o,44)),()=>o&&window.removeEventListener("resize",c(o,44))},[s=e.width,o=()=>B(i,e)]),a.createElement("div",{className:r,style:n},a.createElement(y,{ref:l}));var s,o};I.defaultProps={height:400,data:[],curve:r.curveLinearClosed},exports.RadarChart=I,exports.radarChartclassNames=b; | ||
//# sourceMappingURL=charts.cjs.production.min.js.map |
@@ -1,11 +0,444 @@ | ||
import React from 'react'; | ||
import React, { useState, useCallback, useEffect } from 'react'; | ||
import { select, min, max, scaleLinear, lineRadial, curveLinearClosed, range } from 'd3'; | ||
import ReactDOMServer from 'react-dom/server'; | ||
import styled, { css } from 'styled-components'; | ||
const Charts = (_ref) => { | ||
function useNode() { | ||
const [node, onSetNode] = useState(null); | ||
const ref = useCallback(nodeElement => onSetNode(nodeElement), []); | ||
return [ref, node]; | ||
} | ||
function throttle(fn, wait) { | ||
let isCalled = false; | ||
return function () { | ||
if (!isCalled) { | ||
fn(...arguments); | ||
isCalled = true; | ||
setTimeout(function () { | ||
isCalled = false; | ||
}, wait); | ||
} | ||
}; | ||
} | ||
const isNumber = value => { | ||
// First: Check typeof and make sure it returns number | ||
// This code coerces neither booleans nor strings to numbers, | ||
// although it would be possible to do so if desired. | ||
if (typeof value !== 'number') { | ||
return false; | ||
} // Reference for typeof: | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof | ||
// Second: Check for NaN, as NaN is a number to typeof. | ||
// NaN is the only JavaScript value that never equals itself. | ||
if (value !== Number(value)) { | ||
return false; | ||
} // Reference for NaN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN | ||
// Note isNaN() is a broken function, but checking for self-equality works as NaN !== NaN | ||
// Alternatively check for NaN using Number.isNaN(), an ES2015 feature that works how one would expect | ||
// Third: Check for Infinity and -Infinity. | ||
// Realistically we want finite numbers, or there was probably a division by 0 somewhere. | ||
// @ts-ignore | ||
if (value === Infinity || value === !Infinity) { | ||
return false; | ||
} | ||
return true; | ||
}; | ||
const useResize = (width, callback) => { | ||
const wait = 44; | ||
useEffect(() => { | ||
callback && !isNumber(width) && window.addEventListener('resize', throttle(callback, wait)); | ||
return () => callback && window.removeEventListener('resize', throttle(callback, wait)); | ||
}, [width, callback]); | ||
}; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _taggedTemplateLiteralLoose(strings, raw) { | ||
if (!raw) { | ||
raw = strings.slice(0); | ||
} | ||
strings.raw = raw; | ||
return strings; | ||
} | ||
const appendSvg = (node, width, height) => { | ||
select(node).select('svg').remove(); | ||
const svg = select(node).append('svg').attr('width', width).attr('height', height); | ||
return svg; | ||
}; | ||
const degByIndex = (index, count) => { | ||
const degs = 360; | ||
const deg = degs / count * index; | ||
return deg; | ||
}; | ||
const getTextAnchor = (index, data) => { | ||
const deg = degByIndex(index, data.length); | ||
const halfAngle = 180; | ||
if ([0, halfAngle].includes(deg)) { | ||
return 'middle'; | ||
} | ||
if (deg < halfAngle) { | ||
return 'start'; | ||
} | ||
return 'end'; | ||
}; | ||
function _templateObject() { | ||
const data = _taggedTemplateLiteralLoose(["\n position: relative;\n width: 100%;\n"]); | ||
_templateObject = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
const Wrapper = /*#__PURE__*/styled.div( /*#__PURE__*/_templateObject()); | ||
function _templateObject8() { | ||
const data = _taggedTemplateLiteralLoose(["\n margin-left: 0.25rem;\n font-size: 0.625rem;\n color: rgba(255, 255, 255, 0.54);\n"]); | ||
_templateObject8 = function _templateObject8() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject7() { | ||
const data = _taggedTemplateLiteralLoose(["\n ", "\n"]); | ||
_templateObject7 = function _templateObject7() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject6() { | ||
const data = _taggedTemplateLiteralLoose(["\n display: flex;\n align-items: center;\n padding: 0.125rem 0.25rem;\n border-radius: 0.25rem;\n color: rgb(255, 255, 255);\n background-color: rgb(144, 197, 61);\n margin-left: 0.5rem;\n"]); | ||
_templateObject6 = function _templateObject6() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject5() { | ||
const data = _taggedTemplateLiteralLoose(["\n position: absolute;\n top: 50%;\n right: 0;\n transform: translate(calc(100% + 0.5rem), -50%);\n"]); | ||
_templateObject5 = function _templateObject5() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject4() { | ||
const data = _taggedTemplateLiteralLoose(["\n text-align: center;\n max-width: 7.5rem;\n"]); | ||
_templateObject4 = function _templateObject4() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject3() { | ||
const data = _taggedTemplateLiteralLoose(["\n display: flex;\n align-items: center;\n font-size: 0.75rem;\n"]); | ||
_templateObject3 = function _templateObject3() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject2() { | ||
const data = _taggedTemplateLiteralLoose(["\n position: absolute;\n"]); | ||
_templateObject2 = function _templateObject2() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
function _templateObject$1() { | ||
const data = _taggedTemplateLiteralLoose(["\n .", " {\n path,\n line,\n circle {\n fill: none;\n stroke-width: 1px;\n stroke: #959595;\n stroke-opacity: 0.18;\n }\n }\n .", " {\n font-size: 0.75rem;\n fill-opacity: 0.56;\n }\n .", " {\n fill-opacity: 0.06;\n stroke-width: 2px;\n fill: rgb(144, 197, 61);\n stroke: rgb(144, 197, 61);\n }\n .", " {\n fill: rgb(144, 197, 61);\n }\n"]); | ||
_templateObject$1 = function _templateObject() { | ||
return data; | ||
}; | ||
return data; | ||
} | ||
const radarChartclassNames = { | ||
radar: 'radar', | ||
radarAxis: 'radarAxis', | ||
radarAxisText: 'radarAxisText', | ||
radarPolygon: 'radarPolygon', | ||
radarLabel: 'radarLabel', | ||
radarLabelName: 'radarLabelName', | ||
radarLabelBadge: 'radarLabelBadge', | ||
radarLabelBadgePrefix: 'radarLabelBadgePrefix', | ||
radarCircle: 'radarCircle' | ||
}; | ||
const SvgWrapper = /*#__PURE__*/styled(Wrapper)( /*#__PURE__*/_templateObject$1(), radarChartclassNames.radarAxis, radarChartclassNames.radarAxisText, radarChartclassNames.radarPolygon, radarChartclassNames.radarCircle); | ||
const getTranslate = (_ref) => { | ||
let { | ||
children | ||
anchor, | ||
index, | ||
translateX, | ||
translateY | ||
} = _ref; | ||
return React.createElement("div", null, children || "the snozzberries taste like snozzberries"); | ||
if (index === 0 && anchor === 'middle') { | ||
return "translate(calc(-50% + " + translateX + "px), calc(-100% + " + translateY + "px))"; | ||
} else if (anchor === 'middle') { | ||
return "translate(calc(-50% + " + translateX + "px), calc(" + translateY + "px))"; | ||
} else if (anchor === 'start') { | ||
return "translate(calc(" + translateX + "px), calc(-50% + " + translateY + "px))"; | ||
} else if (anchor === 'end') { | ||
return "translate(calc(-100% + " + translateX + "px), calc(-50% + " + translateY + "px))"; | ||
} | ||
return "translate(" + translateX + "px, " + translateY + "px)"; | ||
}; | ||
export { Charts }; | ||
const LabelContainer = /*#__PURE__*/styled.div.attrs(props => ({ | ||
style: { | ||
transform: getTranslate(props) | ||
} | ||
}))( /*#__PURE__*/_templateObject2()); | ||
const Label = /*#__PURE__*/styled.div( /*#__PURE__*/_templateObject3()); | ||
const Name = /*#__PURE__*/styled.div( /*#__PURE__*/_templateObject4()); | ||
const middleBadgeStyles = /*#__PURE__*/css( /*#__PURE__*/_templateObject5()); | ||
const DefaultBadge = /*#__PURE__*/styled.div( /*#__PURE__*/_templateObject6()); | ||
const MiddleBadge = /*#__PURE__*/styled(DefaultBadge)( /*#__PURE__*/_templateObject7(), middleBadgeStyles); | ||
const BadgePrefix = /*#__PURE__*/styled.div( /*#__PURE__*/_templateObject8()); | ||
const draw = (node, props) => { | ||
const { | ||
data, | ||
curve, | ||
polar, | ||
formatValue, | ||
badgePrefix, | ||
labelOffset, | ||
circleRadius, | ||
gradient | ||
} = props; | ||
if (node !== null && data.length) { | ||
const defaultBleedLength = 10; | ||
const bleedLength = typeof props.bleedLength === 'number' ? props.bleedLength : defaultBleedLength; | ||
const { | ||
width: nodeWidth | ||
} = node.getBoundingClientRect(); | ||
const width = props.width || nodeWidth; | ||
const defaultHeight = 400; | ||
const height = props.height || defaultHeight; | ||
const minValue = props.minValue || Math.min(0, min(data, i => min(i.map((_ref) => { | ||
let { | ||
value | ||
} = _ref; | ||
return value; | ||
})))); | ||
const maxValue = (props.maxValue || Math.max(0, max(data, i => max(i.map((_ref2) => { | ||
let { | ||
value | ||
} = _ref2; | ||
return value; | ||
}))))) - minValue; | ||
const paddingX = props.paddingX || 0; | ||
const paddingY = props.paddingY || 0; | ||
const radius = Math.min((width - paddingX * 2 - bleedLength * 2) / 2, (height - paddingY * 2 - bleedLength * 2) / 2); | ||
const radiusScale = scaleLinear().range([0, radius]).domain([0, maxValue]); | ||
const defaultLevels = 4; | ||
const levels = props.levels || defaultLevels; | ||
const angleSlice = Math.PI * 2 / data[0].length; | ||
const radarLine = lineRadial().curve(curveLinearClosed) // @ts-ignore | ||
.radius((_ref3) => { | ||
let { | ||
value | ||
} = _ref3; | ||
return radiusScale(value); | ||
}).angle((_, i) => i * angleSlice); | ||
const radarValue = lineRadial().curve(curve || curveLinearClosed) // @ts-ignore | ||
.radius((_ref4) => { | ||
let { | ||
value | ||
} = _ref4; | ||
return radiusScale(value); | ||
}).angle((_, i) => i * angleSlice); | ||
const svg = appendSvg(node, width, height); | ||
const globalCenter = svg.append('g'); | ||
const levelsGrid = range(1, levels + 1).reverse(); | ||
const axisGridY = value => -value * radius / levels; | ||
const getAxisValue = value => maxValue * value / levels; | ||
const gridGlobal = globalCenter.append('g').attr('class', radarChartclassNames.radarAxis).selectAll().data([data[0]]).enter(); | ||
const radarGlobal = globalCenter.append('g').attr('class', radarChartclassNames.radar); | ||
const axis = gridGlobal.selectAll().data(data[0].map((_ref5) => { | ||
let { | ||
name | ||
} = _ref5; | ||
return name; | ||
})).enter(); | ||
let maxGridHeight = 0; | ||
if (polar) { | ||
levelsGrid.forEach(value => { | ||
const path = gridGlobal.append('circle').attr('cx', 0).attr('cy', 0).attr('r', () => radius / levels * value); | ||
const circleNode = path.node(); | ||
const circleHeight = circleNode.getBoundingClientRect().height; | ||
maxGridHeight = Math.max(maxGridHeight, circleHeight); | ||
}); | ||
} else { | ||
levelsGrid.map(getAxisValue).forEach(value => { | ||
const path = gridGlobal.append('path').attr('d', () => // @ts-ignore | ||
radarLine(Array.from({ | ||
length: data[0].length | ||
}, () => ({ | ||
value | ||
})))); | ||
const pathNode = path.node(); | ||
const pathHeight = pathNode.getBoundingClientRect().height; | ||
maxGridHeight = Math.max(maxGridHeight, pathHeight); | ||
}); | ||
} | ||
const radiusByMaxValue = radiusScale(maxValue) + bleedLength; | ||
axis.append('line').attr('x1', 0).attr('y1', 0).attr('x2', (_, i) => radiusByMaxValue * Math.cos(angleSlice * i - Math.PI / 2)).attr('y2', (_, i) => radiusByMaxValue * Math.sin(angleSlice * i - Math.PI / 2)); | ||
data.forEach(d => { | ||
radarGlobal.append('path').attr('class', radarChartclassNames.radarPolygon).attr('d', () => radarValue( // @ts-ignore | ||
d.map(dataItem => _extends({}, dataItem, { | ||
value: dataItem.value - minValue | ||
})))); | ||
}); | ||
globalCenter.selectAll('text').data(levelsGrid).enter().append('text').attr('class', radarChartclassNames.radarAxisText).attr('x', '4').attr('y', axisGridY).attr('dy', 0).attr('dominant-baseline', 'central').text(value => getAxisValue(value) + minValue); | ||
circleRadius && data.forEach(item => { | ||
const circleGlobal = radarGlobal.append('g').attr('class', radarChartclassNames.radarCircle); | ||
item.forEach((_ref6, i) => { | ||
let { | ||
value | ||
} = _ref6; | ||
circleGlobal.append('circle').attr('cx', radiusScale(value) * Math.cos(angleSlice * i - Math.PI / 2)).attr('cy', radiusScale(value * Math.sin(angleSlice * i - Math.PI / 2))).attr('r', circleRadius); | ||
}); | ||
}); | ||
const pxToValue = value => maxValue / radius * value; | ||
const defaultLabelOffset = 8; | ||
const axisX = i => radiusScale(maxValue + pxToValue(bleedLength + (labelOffset || defaultLabelOffset))) * Math.cos(angleSlice * i - Math.PI / 2); | ||
const axisY = i => radiusScale((maxValue + pxToValue(bleedLength + (labelOffset || defaultLabelOffset))) * Math.sin(angleSlice * i - Math.PI / 2)); | ||
const labels = data[0].map((_, i) => ({ | ||
x: Math.ceil(axisX(i)), | ||
y: Math.ceil(axisY(i)) | ||
})); | ||
const heightInner = height - bleedLength - paddingY; | ||
const translateX = width / 2; | ||
const translateY = heightInner / 2 + (heightInner - maxGridHeight) / 2; | ||
globalCenter.attr('transform', "translate(" + translateX + "," + translateY + ")"); | ||
const d3container = select(node); | ||
d3container.selectAll("." + radarChartclassNames.radarLabel).remove(); | ||
labels.forEach((_ref7, index) => { | ||
let { | ||
x, | ||
y | ||
} = _ref7; | ||
const anchor = getTextAnchor(index, data[0]); | ||
const Badge = anchor === 'middle' ? MiddleBadge : DefaultBadge; | ||
const html = ReactDOMServer.renderToString(React.createElement(LabelContainer, { | ||
anchor: anchor, | ||
translateX: translateX, | ||
translateY: translateY, | ||
index: index, | ||
style: { | ||
left: x, | ||
top: y | ||
} | ||
}, React.createElement(Label, { | ||
className: radarChartclassNames.radarLabel | ||
}, React.createElement(Name, { | ||
className: radarChartclassNames.radarLabelName | ||
}, data[0][index].name), data.length === 1 && React.createElement(Badge, { | ||
className: radarChartclassNames.radarLabelBadge | ||
}, typeof formatValue === 'function' ? formatValue(data[0][index].value) : data[0][index].value, badgePrefix && React.createElement(BadgePrefix, { | ||
className: radarChartclassNames.radarLabelBadgePrefix | ||
}, badgePrefix))))); | ||
d3container.append('div').attr('class', radarChartclassNames.radarLabel).html(html); | ||
}); | ||
if (gradient) { | ||
const html = ReactDOMServer.renderToString(gradient); | ||
svg.append('g').html(html); | ||
} | ||
} | ||
}; | ||
const RadarChart = props => { | ||
const { | ||
className, | ||
style | ||
} = props; | ||
const [ref, node] = useNode(); | ||
useEffect(() => { | ||
node && draw(node, props); | ||
}, [node, props]); | ||
const onDraw = () => draw(node, props); | ||
useResize(props.width, onDraw); | ||
return React.createElement("div", { | ||
className: className, | ||
style: style | ||
}, React.createElement(SvgWrapper, { | ||
ref: ref | ||
})); | ||
}; | ||
RadarChart.defaultProps = { | ||
height: 400, | ||
data: [], | ||
curve: curveLinearClosed | ||
}; | ||
export { RadarChart, radarChartclassNames }; | ||
//# sourceMappingURL=charts.esm.js.map |
@@ -1,1 +0,2 @@ | ||
export * from './Charts'; | ||
export { RadarChart } from './RadarChart'; | ||
export { radarChartclassNames } from './RadarChart/styled'; |
{ | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"license": "MIT", | ||
@@ -46,4 +46,6 @@ "main": "dist/index.js", | ||
"@storybook/react": "^6.0.26", | ||
"@types/d3": "^5.16.3", | ||
"@types/react": "^16.9.52", | ||
"@types/react-dom": "^16.9.8", | ||
"@types/styled-components": "^5.1.3", | ||
"babel-loader": "^8.1.0", | ||
@@ -53,6 +55,13 @@ "react": "^16.14.0", | ||
"react-dom": "^16.14.0", | ||
"react-is": "^16.13.1", | ||
"ts-loader": "^8.0.5" | ||
}, | ||
"gitHead": "8931f38f6684f15d08455229eb688a0fbb50ef7f" | ||
"resolutions": { | ||
"styled-components": "^5", | ||
"d3": "^6" | ||
}, | ||
"dependencies": { | ||
"d3": "^6.2.0", | ||
"styled-components": "^5.2.0" | ||
}, | ||
"gitHead": "e01a311fdd5e5737d250e8a4b2b9b300715f114d" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
124821
24
863
3
16
2
1
+ Addedd3@^6.2.0
+ Addedstyled-components@^5.2.0
+ Added@ampproject/remapping@2.3.0(transitive)
+ Added@babel/code-frame@7.26.2(transitive)
+ Added@babel/compat-data@7.26.5(transitive)
+ Added@babel/core@7.26.0(transitive)
+ Added@babel/generator@7.26.5(transitive)
+ Added@babel/helper-annotate-as-pure@7.25.9(transitive)
+ Added@babel/helper-compilation-targets@7.26.5(transitive)
+ Added@babel/helper-module-imports@7.25.9(transitive)
+ Added@babel/helper-module-transforms@7.26.0(transitive)
+ Added@babel/helper-plugin-utils@7.26.5(transitive)
+ Added@babel/helper-string-parser@7.25.9(transitive)
+ Added@babel/helper-validator-identifier@7.25.9(transitive)
+ Added@babel/helper-validator-option@7.25.9(transitive)
+ Added@babel/helpers@7.26.0(transitive)
+ Added@babel/parser@7.26.5(transitive)
+ Added@babel/plugin-syntax-jsx@7.25.9(transitive)
+ Added@babel/template@7.25.9(transitive)
+ Added@babel/traverse@7.26.5(transitive)
+ Added@babel/types@7.26.5(transitive)
+ Added@emotion/is-prop-valid@1.3.1(transitive)
+ Added@emotion/memoize@0.9.0(transitive)
+ Added@emotion/stylis@0.8.5(transitive)
+ Added@emotion/unitless@0.7.5(transitive)
+ Added@jridgewell/gen-mapping@0.3.8(transitive)
+ Added@jridgewell/resolve-uri@3.1.2(transitive)
+ Added@jridgewell/set-array@1.2.1(transitive)
+ Added@jridgewell/sourcemap-codec@1.5.0(transitive)
+ Added@jridgewell/trace-mapping@0.3.25(transitive)
+ Addedbabel-plugin-styled-components@2.1.4(transitive)
+ Addedbrowserslist@4.24.4(transitive)
+ Addedcamelize@1.0.1(transitive)
+ Addedcaniuse-lite@1.0.30001692(transitive)
+ Addedcommander@2.20.3(transitive)
+ Addedconvert-source-map@2.0.0(transitive)
+ Addedcss-color-keywords@1.0.0(transitive)
+ Addedcss-to-react-native@3.2.0(transitive)
+ Addedd3@6.7.0(transitive)
+ Addedd3-array@2.12.1(transitive)
+ Addedd3-axis@2.1.0(transitive)
+ Addedd3-brush@2.1.0(transitive)
+ Addedd3-chord@2.0.0(transitive)
+ Addedd3-color@2.0.0(transitive)
+ Addedd3-contour@2.0.0(transitive)
+ Addedd3-delaunay@5.3.0(transitive)
+ Addedd3-dispatch@2.0.0(transitive)
+ Addedd3-drag@2.0.0(transitive)
+ Addedd3-dsv@2.0.0(transitive)
+ Addedd3-ease@2.0.0(transitive)
+ Addedd3-fetch@2.0.0(transitive)
+ Addedd3-force@2.1.1(transitive)
+ Addedd3-format@2.0.0(transitive)
+ Addedd3-geo@2.0.2(transitive)
+ Addedd3-hierarchy@2.0.0(transitive)
+ Addedd3-interpolate@2.0.1(transitive)
+ Addedd3-path@2.0.0(transitive)
+ Addedd3-polygon@2.0.0(transitive)
+ Addedd3-quadtree@2.0.0(transitive)
+ Addedd3-random@2.2.2(transitive)
+ Addedd3-scale@3.3.0(transitive)
+ Addedd3-scale-chromatic@2.0.0(transitive)
+ Addedd3-selection@2.0.0(transitive)
+ Addedd3-shape@2.1.0(transitive)
+ Addedd3-time@2.1.1(transitive)
+ Addedd3-time-format@3.0.0(transitive)
+ Addedd3-timer@2.0.0(transitive)
+ Addedd3-transition@2.0.0(transitive)
+ Addedd3-zoom@2.0.0(transitive)
+ Addeddebug@4.4.0(transitive)
+ Addeddelaunator@4.0.1(transitive)
+ Addedelectron-to-chromium@1.5.80(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addedgensync@1.0.0-beta.2(transitive)
+ Addedglobals@11.12.0(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedhoist-non-react-statics@3.3.2(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedinternmap@1.0.1(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjsesc@3.1.0(transitive)
+ Addedjson5@2.2.3(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedlru-cache@5.1.1(transitive)
+ Addedms@2.1.3(transitive)
+ Addednode-releases@2.0.19(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedpicomatch@2.3.1(transitive)
+ Addedpostcss-value-parser@4.2.0(transitive)
+ Addedreact-dom@19.0.0(transitive)
+ Addedreact-is@16.13.119.0.0(transitive)
+ Addedrw@1.3.3(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedscheduler@0.25.0(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedshallowequal@1.1.0(transitive)
+ Addedstyled-components@5.3.11(transitive)
+ Addedsupports-color@5.5.0(transitive)
+ Addedupdate-browserslist-db@1.1.2(transitive)
+ Addedyallist@3.1.1(transitive)