Update BigNumber design (#5469)

support toggling trend line

experiment using svg to measure size instead of canvas

refactor BigNumber with chart sticked to the bottom

made header line stick to bottom and css adjustment

remove commented code

fix svg text size estimation

remove unused code and round dimensions

handle missing getbbox

remove vx/text from dependency

ensure svg deletion after measurement

add comment to css file.

Add `positive` and `negative` class based on diff.

Add default props.

rename variable

accept container as argument and remove redundant font family

refactor visutils for consistent api

update xy-chart

update xy-chart to alpha1.0

fix pointseries

remove points

update yarn.lock

[4c9c01d7] update xy-chart version

remove unused import
This commit is contained in:
Krist Wongsuphasawat 2018-08-02 10:34:36 -07:00 committed by Chris Williams
parent 906dcd84a9
commit 1b9e5d4174
8 changed files with 651 additions and 284 deletions

View File

@ -45,6 +45,7 @@
"dependencies": {
"@data-ui/event-flow": "^0.0.54",
"@data-ui/sparkline": "^0.0.54",
"@data-ui/xy-chart": "^0.0.61",
"@vx/responsive": "0.0.153",
"babel-register": "^6.24.1",
"bootstrap": "^3.3.6",

View File

@ -1,14 +1,105 @@
export function getTextWidth(text, fontDetails = '12px Roboto') {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
if (context) {
// Won't work outside of a browser context (ie unit tests)
context.font = fontDetails;
return context.measureText(text).width;
}
return 100;
const SVG_NS = 'http://www.w3.org/2000/svg';
function isDefined(x) {
return x !== null && x !== undefined;
}
export default {
getTextWidth,
};
export function getTextDimension({
text,
className,
style,
container = document.body,
}) {
const textNode = document.createElementNS(SVG_NS, 'text');
textNode.textContent = text;
if (isDefined(className)) {
textNode.setAttribute('class', className);
}
if (isDefined(style)) {
['font', 'fontWeight', 'fontStyle', 'fontSize', 'fontFamily']
.filter(field => isDefined(style[field]))
.forEach((field) => {
textNode.style[field] = style[field];
});
}
const svg = document.createElementNS(SVG_NS, 'svg');
svg.style.position = 'absolute'; // so it won't disrupt page layout
svg.style.opacity = 0; // and not visible
svg.appendChild(textNode);
container.appendChild(svg);
let result;
if (textNode.getBBox) {
const bbox = textNode.getBBox();
// round up
result = {
width: Math.ceil(bbox.width),
height: Math.ceil(bbox.height),
};
} else {
// Handle when called from non-browser and do not support getBBox()
result = {
width: 100,
height: 100,
};
}
container.removeChild(svg);
return result;
}
/**
* Shim to support legacy calls
*/
export function getTextWidth(text, font = '12px Roboto') {
return getTextDimension({ text, style: { font } }).width;
}
export function computeMaxFontSize({
text,
idealFontSize,
maxWidth,
maxHeight,
className,
style,
container,
}) {
let size = idealFontSize;
if (!isDefined(idealFontSize)) {
if (isDefined(maxHeight)) {
size = Math.floor(maxHeight);
} else {
throw new Error('You must specify at least one of maxHeight or idealFontSize');
}
}
function computeDimension(fontSize) {
return getTextDimension({
text,
className,
style: { ...style, fontSize },
container,
});
}
let textDimension = computeDimension(size);
// Decrease size until textWidth is less than maxWidth
if (isDefined(maxWidth)) {
while (textDimension.width > maxWidth) {
size -= 2;
textDimension = computeDimension(size);
}
}
// Decrease size until textHeight is less than maxHeight
if (isDefined(maxHeight)) {
while (textDimension.height > maxHeight) {
size -= 2;
textDimension = computeDimension(size);
}
}
return size;
}

View File

@ -0,0 +1,274 @@
import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { XYChart, AreaSeries, CrossHair, LinearGradient } from '@data-ui/xy-chart';
import { brandColor } from '../modules/colors';
import { d3FormatPreset } from '../modules/utils';
import { formatDateVerbose } from '../modules/dates';
import { computeMaxFontSize } from '../modules/visUtils';
import './big_number.css';
const CHART_MARGIN = {
top: 4,
right: 4,
bottom: 4,
left: 4,
};
const PROPORTION = {
HEADER: 0.4,
SUBHEADER: 0.14,
HEADER_WITH_TRENDLINE: 0.3,
SUBHEADER_WITH_TRENDLINE: 0.125,
TRENDLINE: 0.3,
};
function renderTooltipFactory(formatValue) {
return function renderTooltip({ datum }) { // eslint-disable-line
const { x: rawDate, y: rawValue } = datum;
const formattedDate = formatDateVerbose(rawDate);
const value = formatValue(rawValue);
return (
<div style={{ padding: '4px 8px' }}>
{formattedDate}
<br />
<strong>{value}</strong>
</div>
);
};
}
function identity(x) {
return x;
}
const propTypes = {
className: PropTypes.string,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
bigNumber: PropTypes.number.isRequired,
formatBigNumber: PropTypes.func,
subheader: PropTypes.string,
showTrendline: PropTypes.bool,
trendlineData: PropTypes.array,
mainColor: PropTypes.string,
gradientId: PropTypes.string,
renderTooltip: PropTypes.func,
};
const defaultProps = {
className: '',
formatBigNumber: identity,
subheader: '',
showTrendline: false,
trendlineData: null,
mainColor: brandColor,
gradientId: '',
renderTooltip: renderTooltipFactory(identity),
};
class BigNumberVis extends React.Component {
getClassName() {
const { className, showTrendline } = this.props;
const names = `big_number ${className}`;
if (showTrendline) {
return names;
}
return `${names} no_trendline`;
}
createTemporaryContainer() {
const container = document.createElement('div');
container.className = this.getClassName();
container.style.position = 'absolute'; // so it won't disrupt page layout
container.style.opacity = 0; // and not visible
return container;
}
renderHeader(maxHeight) {
const { bigNumber, formatBigNumber, width } = this.props;
const text = formatBigNumber(bigNumber);
const container = this.createTemporaryContainer();
document.body.appendChild(container);
const fontSize = computeMaxFontSize({
text,
maxWidth: width,
maxHeight,
className: 'header_line',
container,
});
document.body.removeChild(container);
return (
<div
className="header_line"
style={{
fontSize,
height: maxHeight,
}}
>
<span>{text}</span>
</div>
);
}
renderSubheader(maxHeight) {
const { subheader, width } = this.props;
let fontSize = 0;
if (subheader) {
const container = this.createTemporaryContainer();
document.body.appendChild(container);
fontSize = computeMaxFontSize({
text: subheader,
maxWidth: width,
maxHeight,
className: 'subheader_line',
container,
});
document.body.removeChild(container);
}
return (
<div
className="subheader_line"
style={{
fontSize,
height: maxHeight,
}}
>
{subheader}
</div>
);
}
renderTrendline(maxHeight) {
const {
width,
trendlineData,
mainColor,
subheader,
renderTooltip,
gradientId,
} = this.props;
return (
<XYChart
ariaLabel={`Big number visualization ${subheader}`}
xScale={{ type: 'timeUtc' }}
yScale={{ type: 'linear' }}
width={width}
height={maxHeight}
margin={CHART_MARGIN}
renderTooltip={renderTooltip}
snapTooltipToDataX
>
<LinearGradient
id={gradientId}
from={mainColor}
to="#fff"
/>
<AreaSeries
data={trendlineData}
fill={`url(#${gradientId})`}
stroke={mainColor}
/>
<CrossHair
stroke={mainColor}
circleFill={mainColor}
circleStroke="#fff"
showHorizontalLine={false}
fullHeight
strokeDasharray="5,2"
/>
</XYChart>
);
}
render() {
const { showTrendline, height } = this.props;
const className = this.getClassName();
if (showTrendline) {
const chartHeight = Math.floor(PROPORTION.TRENDLINE * height);
const allTextHeight = height - chartHeight;
return (
<div className={className}>
<div
className="text_container"
style={{ height: allTextHeight }}
>
{this.renderHeader(Math.ceil(PROPORTION.HEADER_WITH_TRENDLINE * height))}
{this.renderSubheader(Math.ceil(PROPORTION.SUBHEADER_WITH_TRENDLINE * height))}
</div>
{this.renderTrendline(chartHeight)}
</div>
);
}
return (
<div
className={className}
style={{ height }}
>
{this.renderHeader(Math.ceil(PROPORTION.HEADER * height))}
{this.renderSubheader(Math.ceil(PROPORTION.SUBHEADER * height))}
</div>
);
}
}
BigNumberVis.propTypes = propTypes;
BigNumberVis.defaultProps = defaultProps;
function adaptor(slice, payload) {
const { formData, containerId } = slice;
const { data, subheader, compare_suffix: compareSuffix } = payload.data;
const compareLag = Number(payload.data.compare_lag);
const supportTrendline = formData.viz_type === 'big_number';
const showTrendline = supportTrendline && formData.show_trend_line;
const formatValue = d3FormatPreset(formData.y_axis_format);
const bigNumber = supportTrendline ? data[data.length - 1][1] : data[0][0];
let percentChange = 0;
let formattedSubheader = subheader;
if (supportTrendline && compareLag > 0) {
const compareIndex = data.length - (compareLag + 1);
if (compareIndex >= 0) {
const compareValue = data[compareIndex][1];
percentChange = compareValue === 0
? 0 : (bigNumber - compareValue) / Math.abs(compareValue);
const formatPercentChange = d3.format('+.1%');
formattedSubheader = `${formatPercentChange(percentChange)} ${compareSuffix}`;
}
}
const trendlineData = showTrendline ? data.map(([x, y]) => ({ x, y })) : null;
let className = '';
if (percentChange > 0) {
className = 'positive';
} else if (percentChange < 0) {
className = 'negative';
}
ReactDOM.render(
<BigNumberVis
className={className}
width={slice.width()}
height={slice.height()}
bigNumber={bigNumber}
formatBigNumber={formatValue}
subheader={formattedSubheader}
showTrendline={showTrendline}
trendlineData={trendlineData}
mainColor={brandColor}
gradientId={`big_number_${containerId}`}
renderTooltip={renderTooltipFactory(formatValue)}
/>,
document.getElementById(containerId),
);
}
export default adaptor;

View File

@ -1,31 +1,38 @@
.big_number g.axis text,
.big_number_total g.axis text {
font-size: 10px;
font-weight: normal;
color: gray;
fill: gray;
text-anchor: middle;
alignment-baseline: middle;
font-weight: none;
.big_number {
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
}
.big_number text.big,
.big_number_total text.big{
stroke: black;
text-anchor: middle;
fill: black;
.big_number.no_trendline .subheader_line {
padding-bottom: 0.3em;
}
.big_number g.tick line,
.big_number_total g.tick line{
stroke-width: 1px;
stroke: grey;
.big_number .text_container {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
}
.big_number .domain,
.big_number_total .domain{
fill: none;
stroke: black;
stroke-width: 1;
.big_number .header_line {
position: relative;
line-height: 1em;
font-weight: 600;
}
.big_number .header_line span {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
.big_number .subheader_line {
line-height: 1em;
padding-bottom: 0;
font-weight: 200;
}

View File

@ -1,231 +0,0 @@
import d3 from 'd3';
import d3tip from 'd3-tip';
import dompurify from 'dompurify';
import { d3FormatPreset, d3TimeFormatPreset } from '../modules/utils';
import './big_number.css';
import '../../stylesheets/d3tip.css';
function bigNumberVis(slice, payload) {
const div = d3.select(slice.selector);
// Define the percentage bounds that define color from red to green
div.html(''); // reset
const fd = slice.formData;
const json = payload.data;
const f = d3FormatPreset(fd.y_axis_format);
const fp = d3.format('+.1%');
const formatDate = d3TimeFormatPreset('smart_date');
const width = slice.width();
const height = slice.height();
const svg = div.append('svg');
svg.attr('width', width);
svg.attr('height', height);
const data = json.data;
let vCompare;
let v;
if (fd.viz_type === 'big_number') {
v = data[data.length - 1][1];
} else {
v = data[0][0];
}
if (json.compare_lag > 0) {
const pos = data.length - (json.compare_lag + 1);
if (pos >= 0) {
const vAnchor = data[pos][1];
if (vAnchor !== 0) {
vCompare = (v - vAnchor) / Math.abs(vAnchor);
} else {
vCompare = 0;
}
}
}
const dateExt = d3.extent(data, d => d[0]);
const valueExt = d3.extent(data, d => d[1]);
const vMargin = 20;
const hMargin = 10;
const scaleX = d3.time.scale.utc().domain(dateExt).range([hMargin, width - hMargin]);
const scaleY = d3.scale.linear().domain(valueExt).range([height - (vMargin), vMargin]);
const colorRange = [d3.hsl(0, 1, 0.3), d3.hsl(120, 1, 0.3)];
const scaleColor = d3.scale
.linear().domain([-1, 1])
.interpolate(d3.interpolateHsl)
.range(colorRange)
.clamp(true);
const line = d3.svg.line()
.x(function (d) {
return scaleX(d[0]);
})
.y(function (d) {
return scaleY(d[1]);
})
.interpolate('cardinal');
let y = height / 2;
let g = svg.append('g');
// Printing big number
g.append('g').attr('class', 'digits')
.attr('opacity', 1)
.append('text')
.attr('x', width / 2)
.attr('y', y)
.attr('class', 'big')
.attr('alignment-baseline', 'middle')
.attr('id', 'bigNumber')
.style('font-weight', 'bold')
.style('cursor', 'pointer')
.text(f(v))
.style('font-size', d3.min([height, width]) / 3.5)
.style('text-anchor', 'middle')
.attr('fill', 'black');
// Printing big number subheader text
if (json.subheader !== null) {
g.append('text')
.attr('x', width / 2)
.attr('y', (height / 16) * 12)
.text(json.subheader)
.attr('id', 'subheader_text')
.style('font-size', d3.min([height, width]) / 8)
.style('text-anchor', 'middle');
}
if (fd.viz_type === 'big_number') {
// Drawing trend line
if (fd.show_trend_line) {
g.append('path')
.attr('d', function () {
return line(data);
})
.attr('stroke-width', 5)
.attr('opacity', 0.5)
.attr('fill', 'none')
.attr('stroke-linecap', 'round')
.attr('stroke', 'grey');
g = svg.append('g')
.attr('class', 'digits')
.attr('opacity', 1);
if (vCompare !== null) {
y = (height / 8) * 3;
}
}
const c = scaleColor(vCompare);
// Printing compare %
if (vCompare) {
g.append('text')
.attr('x', width / 2)
.attr('y', (height / 16) * 12)
.text(fp(vCompare) + json.compare_suffix)
.style('font-size', d3.min([height, width]) / 8)
.style('text-anchor', 'middle')
.attr('fill', c)
.attr('stroke', c);
}
const gAxis = svg.append('g').attr('class', 'axis').attr('opacity', 0);
g = gAxis.append('g');
const xAxis = d3.svg.axis()
.scale(scaleX)
.orient('bottom')
.ticks(Math.round(2 + (width / 150)))
.tickFormat(formatDate);
g.call(xAxis);
g.attr('transform', 'translate(0,' + (height - vMargin) + ')');
g = gAxis.append('g').attr('transform', 'translate(' + (width - hMargin) + ',0)');
const yAxis = d3.svg.axis()
.scale(scaleY)
.orient('left')
.tickFormat(f)
.tickValues(valueExt);
g.call(yAxis);
g.selectAll('text')
.style('text-anchor', 'end')
.attr('y', '-7')
.attr('x', '-4');
g.selectAll('text')
.style('font-size', '10px');
const renderTooltip = (d) => {
const date = formatDate(d[0]);
const value = dompurify.sanitize(f(d[1]));
return `
<div>
<span style="margin-right: 10px;">${date}: </span>
<strong>${value}</strong>
</div>
`;
};
const tip = d3tip()
.attr('class', 'd3-tip')
.direction('n')
.offset([-5, 0])
.html(renderTooltip);
svg.call(tip);
// Add the scatterplot and trigger the mouse events for the tooltips
svg
.selectAll('dot')
.data(data)
.enter()
.append('circle')
.attr('r', 3)
.attr('stroke-width', 15)
.attr('stroke', 'transparent')
.attr('stroke-location', 'outside')
.attr('cx', d => scaleX(d[0]))
.attr('cy', d => scaleY(d[1]))
.attr('fill-opacity', 0)
.on('mouseover', function (d) {
d3.select(this).attr('fill-opacity', 1);
tip.show(d, this);
})
.on('mouseout', function (d) {
d3.select(this).attr('fill-opacity', 0);
tip.hide(d, this);
});
div.on('mouseover', function () {
const el = d3.select(this);
el.selectAll('path')
.transition()
.duration(500)
.attr('opacity', 1)
.style('stroke-width', '2px');
el.selectAll('g.digits')
.transition()
.duration(500)
.attr('opacity', 0.1);
el.selectAll('g.axis')
.transition()
.duration(500)
.attr('opacity', 1);
})
.on('mouseout', function () {
const el = d3.select(this);
el.select('path')
.transition()
.duration(500)
.attr('opacity', 0.5)
.style('stroke-width', '5px');
el.selectAll('g.digits')
.transition()
.duration(500)
.attr('opacity', 1);
el.selectAll('g.axis')
.transition()
.duration(500)
.attr('opacity', 0);
});
}
}
module.exports = bigNumberVis;

View File

@ -65,9 +65,9 @@ const vizMap = {
[VIZ_TYPES.area]: loadNvd3,
[VIZ_TYPES.bar]: loadNvd3,
[VIZ_TYPES.big_number]: () =>
loadVis(import(/* webpackChunkName: 'big_number' */ './big_number.js')),
loadVis(import(/* webpackChunkName: 'big_number' */ './BigNumber.jsx')),
[VIZ_TYPES.big_number_total]: () =>
loadVis(import(/* webpackChunkName: "big_number" */ './big_number.js')),
loadVis(import(/* webpackChunkName: "big_number" */ './BigNumber.jsx')),
[VIZ_TYPES.box_plot]: loadNvd3,
[VIZ_TYPES.bubble]: loadNvd3,
[VIZ_TYPES.bullet]: loadNvd3,

View File

@ -32,6 +32,13 @@
dependencies:
"@babel/types" "7.0.0-beta.44"
"@babel/helper-module-imports@^7.0.0-beta.49":
version "7.0.0-beta.54"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.54.tgz#c2d8e14ff034225bf431356db77ef467b8d35aac"
dependencies:
"@babel/types" "7.0.0-beta.54"
lodash "^4.17.5"
"@babel/helper-split-export-declaration@7.0.0-beta.44":
version "7.0.0-beta.44"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc"
@ -78,6 +85,14 @@
lodash "^4.2.0"
to-fast-properties "^2.0.0"
"@babel/types@7.0.0-beta.54", "@babel/types@^7.0.0-beta.49":
version "7.0.0-beta.54"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.54.tgz#025ad68492fed542c13f14c579a44c848e531063"
dependencies:
esutils "^2.0.2"
lodash "^4.17.5"
to-fast-properties "^2.0.0"
"@data-ui/event-flow@^0.0.54":
version "0.0.54"
resolved "https://registry.yarnpkg.com/@data-ui/event-flow/-/event-flow-0.0.54.tgz#bb03e1fd2b5634248655b8df9d3c6c38a747e65e"
@ -143,6 +158,19 @@
d3-array "^1.2.1"
prop-types "^15.5.10"
"@data-ui/shared@^0.0.61":
version "0.0.61"
resolved "https://registry.yarnpkg.com/@data-ui/shared/-/shared-0.0.61.tgz#717a1a1f7bd606c0f51573e65b6acdda51a1252b"
dependencies:
"@data-ui/theme" "^0.0.61"
"@vx/event" "^0.0.165"
"@vx/group" "^0.0.165"
"@vx/shape" "^0.0.168"
"@vx/tooltip" "0.0.165"
babel-runtime "^6.26.0"
d3-array "^1.2.1"
prop-types "^15.5.10"
"@data-ui/sparkline@^0.0.54":
version "0.0.54"
resolved "https://registry.yarnpkg.com/@data-ui/sparkline/-/sparkline-0.0.54.tgz#ce3d166d9e0b239a0ba02f3894cb9e8c84171cef"
@ -171,6 +199,37 @@
version "0.0.8"
resolved "https://registry.yarnpkg.com/@data-ui/theme/-/theme-0.0.8.tgz#3116723d04b99f65c7750f81a500e9608b4837c3"
"@data-ui/theme@^0.0.61":
version "0.0.61"
resolved "https://registry.yarnpkg.com/@data-ui/theme/-/theme-0.0.61.tgz#2a792da6c384d08553d1794bdb16ce633bc02cbd"
dependencies:
babel-runtime "^6.26.0"
"@data-ui/xy-chart@^0.0.61":
version "0.0.61"
resolved "https://registry.yarnpkg.com/@data-ui/xy-chart/-/xy-chart-0.0.61.tgz#ee4e47913116a03a7bc4fc0ff1b0d815f80ee736"
dependencies:
"@data-ui/shared" "^0.0.61"
"@data-ui/theme" "^0.0.61"
"@vx/axis" "^0.0.168"
"@vx/curve" "^0.0.165"
"@vx/event" "^0.0.165"
"@vx/glyph" "^0.0.165"
"@vx/gradient" "^0.0.165"
"@vx/grid" "^0.0.169"
"@vx/group" "^0.0.165"
"@vx/pattern" "^0.0.165"
"@vx/point" "^0.0.165"
"@vx/responsive" "^0.0.165"
"@vx/scale" "^0.0.165"
"@vx/shape" "^0.0.165"
"@vx/stats" "^0.0.165"
"@vx/tooltip" "^0.0.165"
"@vx/voronoi" "^0.0.165"
babel-runtime "^6.26.0"
d3-array "^1.2.0"
prop-types "^15.5.10"
"@deck.gl/core@^5.3.1":
version "5.3.1"
resolved "https://registry.yarnpkg.com/@deck.gl/core/-/core-5.3.1.tgz#acfc1e5fefd3b12e9142419b0aeb77c07885626c"
@ -282,6 +341,17 @@
classnames "^2.2.5"
prop-types "15.5.10"
"@vx/axis@^0.0.168":
version "0.0.168"
resolved "https://registry.yarnpkg.com/@vx/axis/-/axis-0.0.168.tgz#fd8c88a2b584b314aaf1ce2023eaebad05304188"
dependencies:
"@vx/group" "0.0.165"
"@vx/point" "0.0.165"
"@vx/shape" "0.0.168"
"@vx/text" "0.0.165"
classnames "^2.2.5"
prop-types "^15.6.0"
"@vx/bounds@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/bounds/-/bounds-0.0.140.tgz#4ede9766aabb41b791a4fbf4c27fcc19ed83f910"
@ -294,6 +364,12 @@
dependencies:
prop-types "^15.5.10"
"@vx/bounds@0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/bounds/-/bounds-0.0.165.tgz#75f107a6deb58223c6878db5053382eff3174567"
dependencies:
prop-types "^15.5.10"
"@vx/clip-path@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/clip-path/-/clip-path-0.0.140.tgz#b2623d004dd5c3c8a6afe8d060de59df51472d94"
@ -310,6 +386,12 @@
dependencies:
d3-shape "^1.0.6"
"@vx/curve@0.0.165", "@vx/curve@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/curve/-/curve-0.0.165.tgz#330d1512dceae0af43dd3eb4c85523132030a3a0"
dependencies:
d3-shape "^1.0.6"
"@vx/event@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/event/-/event-0.0.140.tgz#658ec4de92cd61df40b883296168d4e0824015bf"
@ -322,6 +404,12 @@
dependencies:
"@vx/point" "0.0.143"
"@vx/event@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/event/-/event-0.0.165.tgz#675d89fdfdc08d0c99c36ff1a381ea50fccfba2e"
dependencies:
"@vx/point" "0.0.165"
"@vx/glyph@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/glyph/-/glyph-0.0.140.tgz#f8323f82aee22192b675bef25789bbb7d74691ba"
@ -330,6 +418,14 @@
classnames "^2.2.5"
d3-shape "^1.2.0"
"@vx/glyph@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/glyph/-/glyph-0.0.165.tgz#ba6fe31700dae852c60468e00dd732fa7521d1fc"
dependencies:
"@vx/group" "0.0.165"
classnames "^2.2.5"
d3-shape "^1.2.0"
"@vx/gradient@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/gradient/-/gradient-0.0.140.tgz#56b421016cbae0dcb00190cfffb9e860a28febf4"
@ -337,6 +433,13 @@
classnames "^2.2.5"
prop-types "^15.5.7"
"@vx/gradient@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/gradient/-/gradient-0.0.165.tgz#0cc0fe873e6acded4943fa274f68601ad5a50a38"
dependencies:
classnames "^2.2.5"
prop-types "^15.5.7"
"@vx/grid@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/grid/-/grid-0.0.140.tgz#9dfd3071bc5d90d4b457dd55d7f795699233b230"
@ -346,6 +449,15 @@
"@vx/shape" "0.0.140"
classnames "^2.2.5"
"@vx/grid@^0.0.169":
version "0.0.169"
resolved "https://registry.yarnpkg.com/@vx/grid/-/grid-0.0.169.tgz#241b9edb3894394af2e142a1280a05f6ccfd2163"
dependencies:
"@vx/group" "0.0.165"
"@vx/point" "0.0.165"
"@vx/shape" "0.0.168"
classnames "^2.2.5"
"@vx/group@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/group/-/group-0.0.140.tgz#cba9b0b3f2f007e5be7346f3c86f73f70e038a23"
@ -358,6 +470,12 @@
dependencies:
classnames "^2.2.5"
"@vx/group@0.0.165", "@vx/group@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/group/-/group-0.0.165.tgz#2342523225de94859b5be49c3072dc6bb6795e78"
dependencies:
classnames "^2.2.5"
"@vx/legend@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/legend/-/legend-0.0.140.tgz#4062c27d6bc9c4d607309d77eff12b844727ae99"
@ -373,6 +491,13 @@
classnames "^2.2.5"
prop-types "^15.5.10"
"@vx/pattern@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/pattern/-/pattern-0.0.165.tgz#0d317cb9a13205e35691f702442739ff0256711d"
dependencies:
classnames "^2.2.5"
prop-types "^15.5.10"
"@vx/point@0.0.136":
version "0.0.136"
resolved "https://registry.yarnpkg.com/@vx/point/-/point-0.0.136.tgz#93b325b4b95c9d5b96df740f4204017f57396559"
@ -381,6 +506,10 @@
version "0.0.143"
resolved "https://registry.yarnpkg.com/@vx/point/-/point-0.0.143.tgz#7b6dfa611175ee1b74e3c392072589a79dadf265"
"@vx/point@0.0.165", "@vx/point@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/point/-/point-0.0.165.tgz#7ebde5da3d86954fe31a56f923f31550f0b4b867"
"@vx/responsive@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/responsive/-/responsive-0.0.140.tgz#c73ec68b9e89a181605f1ac9ecc09f35216779a8"
@ -394,12 +523,26 @@
lodash "^4.0.8"
resize-observer-polyfill "1.5.0"
"@vx/responsive@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/responsive/-/responsive-0.0.165.tgz#04b17a52be102a75fc036a8ed3f5db1efd4e8ee5"
dependencies:
lodash "^4.17.10"
prop-types "^15.6.1"
resize-observer-polyfill "1.5.0"
"@vx/scale@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/scale/-/scale-0.0.140.tgz#1eb087d11d0000b250c2cdc4061b9e2212edb10d"
dependencies:
d3-scale "^1.0.5"
"@vx/scale@0.0.165", "@vx/scale@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/scale/-/scale-0.0.165.tgz#8575880c48296a80c0e9459057f826e8f903bc07"
dependencies:
d3-scale "^2.0.0"
"@vx/shape@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/shape/-/shape-0.0.140.tgz#6a282d5fdf3a5752b6e938bb3debe983e89ff6d3"
@ -422,6 +565,48 @@
d3-shape "^1.2.0"
prop-types "^15.5.10"
"@vx/shape@0.0.168", "@vx/shape@^0.0.168":
version "0.0.168"
resolved "https://registry.yarnpkg.com/@vx/shape/-/shape-0.0.168.tgz#172bc1cf4dade47076018efd559e0ecc4e959aec"
dependencies:
"@vx/curve" "0.0.165"
"@vx/group" "0.0.165"
"@vx/point" "0.0.165"
classnames "^2.2.5"
d3-path "^1.0.5"
d3-shape "^1.2.0"
prop-types "^15.5.10"
"@vx/shape@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/shape/-/shape-0.0.165.tgz#3424121f45d83dd8e7ba62b6adf8b0aea2fb9cf8"
dependencies:
"@vx/curve" "0.0.165"
"@vx/group" "0.0.165"
"@vx/point" "0.0.165"
classnames "^2.2.5"
d3-path "^1.0.5"
d3-shape "^1.2.0"
prop-types "^15.5.10"
"@vx/stats@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/stats/-/stats-0.0.165.tgz#32413a144383367e51628bbea61b3b0ce980f1fd"
dependencies:
"@vx/group" "0.0.165"
"@vx/scale" "0.0.165"
classnames "^2.2.5"
d3-shape "^1.2.0"
"@vx/text@0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/text/-/text-0.0.165.tgz#e7f22979a1e744216be1a535414752c2ceb2f97a"
dependencies:
babel-plugin-lodash "^3.3.2"
classnames "^2.2.5"
lodash "^4.17.4"
reduce-css-calc "^1.3.0"
"@vx/tooltip@0.0.140":
version "0.0.140"
resolved "https://registry.yarnpkg.com/@vx/tooltip/-/tooltip-0.0.140.tgz#c5c8306272877c1bbd4e8b478ea5291f1019ffe3"
@ -438,6 +623,23 @@
classnames "^2.2.5"
prop-types "^15.5.10"
"@vx/tooltip@0.0.165", "@vx/tooltip@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/tooltip/-/tooltip-0.0.165.tgz#0d17a1b445a7bc70d7840e36593b780a6e7b40e2"
dependencies:
"@vx/bounds" "0.0.165"
classnames "^2.2.5"
prop-types "^15.5.10"
"@vx/voronoi@^0.0.165":
version "0.0.165"
resolved "https://registry.yarnpkg.com/@vx/voronoi/-/voronoi-0.0.165.tgz#11ab585199b0dccf403544a6ad378a505bfb913b"
dependencies:
"@vx/group" "0.0.165"
classnames "^2.2.5"
d3-voronoi "^1.1.2"
prop-types "^15.6.1"
"@webassemblyjs/ast@1.5.13":
version "1.5.13"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.5.13.tgz#81155a570bd5803a30ec31436bc2c9c0ede38f25"
@ -1262,6 +1464,16 @@ babel-plugin-dynamic-import-node@^1.2.0:
dependencies:
babel-plugin-syntax-dynamic-import "^6.18.0"
babel-plugin-lodash@^3.3.2:
version "3.3.4"
resolved "https://registry.yarnpkg.com/babel-plugin-lodash/-/babel-plugin-lodash-3.3.4.tgz#4f6844358a1340baed182adbeffa8df9967bc196"
dependencies:
"@babel/helper-module-imports" "^7.0.0-beta.49"
"@babel/types" "^7.0.0-beta.49"
glob "^7.1.1"
lodash "^4.17.10"
require-package-name "^2.0.1"
babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
@ -2435,7 +2647,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@2.x, classnames@^2.1.2, classnames@^2.2.3, classnames@^2.2.4, classnames@^2.2.5:
classnames@^2.1.2, classnames@^2.2.3, classnames@^2.2.4, classnames@^2.2.5:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
@ -3080,7 +3292,7 @@ d3-interpolate@1:
dependencies:
d3-color "1"
d3-path@1:
d3-path@1, d3-path@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.5.tgz#241eb1849bd9e9e8021c0d0a799f8a0e8e441764"
@ -3112,6 +3324,17 @@ d3-scale@^1.0.5:
d3-time "1"
d3-time-format "2"
d3-scale@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.1.0.tgz#8d3fd3e2a7c9080782a523c08507c5248289eef8"
dependencies:
d3-array "^1.2.0"
d3-collection "1"
d3-format "1"
d3-interpolate "1"
d3-time "1"
d3-time-format "2"
d3-selection@1, d3-selection@^1.1.0, d3-selection@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.3.0.tgz#d53772382d3dc4f7507bfb28bcd2d6aed2a0ad6d"
@ -3158,6 +3381,10 @@ d3-transition@1:
d3-selection "^1.1.0"
d3-timer "1"
d3-voronoi@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c"
d3-zoom@^1.3.0:
version "1.7.1"
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.7.1.tgz#02f43b3c3e2db54f364582d7e4a236ccc5506b63"
@ -6400,7 +6627,7 @@ lodash.isarray@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
lodash.isequal@^4.0.0, lodash.isequal@^4.1.1:
lodash.isequal@^4.1.1:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
@ -8842,7 +9069,7 @@ react-dom@^15.6.2:
object-assign "^4.1.0"
prop-types "^15.5.10"
react-draggable@3.x, "react-draggable@^2.2.6 || ^3.0.3":
"react-draggable@^2.2.6 || ^3.0.3":
version "3.0.5"
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.0.5.tgz#c031e0ed4313531f9409d6cd84c8ebcec0ddfe2d"
dependencies:
@ -8857,16 +9084,6 @@ react-gravatar@^2.6.1:
md5 "^2.1.0"
query-string "^4.2.2"
react-grid-layout@0.16.6:
version "0.16.6"
resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-0.16.6.tgz#9b2407a2b946c2260ebaf66f13b556e1da4efeb2"
dependencies:
classnames "2.x"
lodash.isequal "^4.0.0"
prop-types "15.x"
react-draggable "3.x"
react-resizable "1.x"
react-input-autosize@^2.1.2:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8"
@ -8938,7 +9155,7 @@ react-redux@^5.0.2:
loose-envify "^1.1.0"
prop-types "^15.6.0"
react-resizable@1.x, react-resizable@^1.3.3:
react-resizable@^1.3.3:
version "1.7.5"
resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-1.7.5.tgz#83eb75bb3684da6989bbbf4f826e1470f0af902e"
dependencies:
@ -9304,7 +9521,7 @@ redeyed@~0.4.0:
dependencies:
esprima "~1.0.4"
reduce-css-calc@^1.2.6:
reduce-css-calc@^1.2.6, reduce-css-calc@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
dependencies:
@ -9581,6 +9798,10 @@ require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
require-package-name@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"

4
yarn.lock Normal file
View File

@ -0,0 +1,4 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1