},
"devDependencies": {
"@types/classnames": "2.2.0",
+ "@types/d3-array": "1.2.1",
+ "@types/d3-scale": "1.0.10",
"@types/date-fns": "2.6.0",
"@types/enzyme": "2.8.6",
"@types/escape-html": "0.0.19",
<LanguageDistributionContainer
alignTicks={true}
distribution={secondaryMeasure.value}
+ width={260}
/>
</div>
)}
return languageDistribution ? (
<div id="overview-language-distribution" className="overview-meta-size-lang-dist">
- <LanguageDistributionContainer distribution={languageDistribution.value} />
+ <LanguageDistributionContainer distribution={languageDistribution.value} width={160} />
</div>
) : null;
};
</ul>
{nclocDistribution && (
- <div className="huge-spacer-top" style={{ width: 260 }}>
- <LanguageDistributionContainer distribution={nclocDistribution} />
+ <div className="huge-spacer-top">
+ <LanguageDistributionContainer distribution={nclocDistribution} width={260} />
</div>
)}
</section>
</ul>
<div
className="huge-spacer-top"
- style={
- Object {
- "width": 260,
- }
- }
>
<Connect(LanguageDistribution)
distribution="java=13;js=17"
+ width={260}
/>
</div>
</section>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { max } from 'd3-array';
+import { scaleLinear, scaleBand, ScaleLinear, ScaleBand } from 'd3-scale';
+import Tooltip from '../controls/Tooltip';
+
+interface Props {
+ alignTicks?: boolean;
+ bars: number[];
+ height: number;
+ padding?: [number, number, number, number];
+ yTicks?: string[];
+ yTooltips?: string[];
+ yValues?: string[];
+ width: number;
+}
+
+const BAR_HEIGHT = 10;
+const DEFAULT_PADDING = [10, 10, 10, 10];
+
+type XScale = ScaleLinear<number, number>;
+type YScale = ScaleBand<number>;
+
+export default class Histogram extends React.PureComponent<Props> {
+ wrapWithTooltip(element: React.ReactNode, index: number) {
+ const tooltip = this.props.yTooltips && this.props.yTooltips[index];
+ return tooltip ? (
+ <Tooltip key={index} overlay={tooltip} placement="top">
+ {element}
+ </Tooltip>
+ ) : (
+ element
+ );
+ }
+
+ renderBar(d: number, index: number, xScale: XScale, yScale: YScale) {
+ const { alignTicks, padding = DEFAULT_PADDING } = this.props;
+
+ const width = Math.round(xScale(d)) + /* minimum bar width */ 1;
+ const x = xScale.range()[0] + (alignTicks ? padding[3] : 0);
+ const y = Math.round(yScale(index)! + yScale.bandwidth() / 2);
+
+ return <rect className="bar-chart-bar" x={x} y={y} width={width} height={BAR_HEIGHT} />;
+ }
+
+ renderValue(d: number, index: number, xScale: XScale, yScale: YScale) {
+ const { alignTicks, padding = DEFAULT_PADDING, yValues } = this.props;
+
+ const value = yValues && yValues[index];
+
+ if (!value) {
+ return null;
+ }
+
+ const x = xScale(d) + (alignTicks ? padding[3] : 0);
+ const y = Math.round(yScale(index)! + yScale.bandwidth() / 2 + BAR_HEIGHT / 2);
+
+ return this.wrapWithTooltip(
+ <text className="bar-chart-tick histogram-value" x={x} y={y} dx="1em" dy="0.3em">
+ {value}
+ </text>,
+ index
+ );
+ }
+
+ renderTick(index: number, xScale: XScale, yScale: YScale) {
+ const { alignTicks, yTicks } = this.props;
+
+ const tick = yTicks && yTicks[index];
+
+ if (!tick) {
+ return null;
+ }
+
+ const x = xScale.range()[0];
+ const y = Math.round(yScale(index)! + yScale.bandwidth() / 2 + BAR_HEIGHT / 2);
+ const historyTickClass = alignTicks ? 'histogram-tick-start' : 'histogram-tick';
+
+ return (
+ <text
+ className={'bar-chart-tick ' + historyTickClass}
+ x={x}
+ y={y}
+ dx={alignTicks ? 0 : '-1em'}
+ dy="0.3em">
+ {tick}
+ </text>
+ );
+ }
+
+ renderBars(xScale: XScale, yScale: YScale) {
+ return (
+ <g>
+ {this.props.bars.map((d, index) => {
+ return (
+ <g key={index}>
+ {this.renderBar(d, index, xScale, yScale)}
+ {this.renderValue(d, index, xScale, yScale)}
+ {this.renderTick(index, xScale, yScale)}
+ </g>
+ );
+ })}
+ </g>
+ );
+ }
+
+ render() {
+ const { bars, width, height, padding = DEFAULT_PADDING } = this.props;
+
+ const availableWidth = width - padding[1] - padding[3];
+ const xScale: XScale = scaleLinear()
+ .domain([0, max(bars)!])
+ .range([0, availableWidth]);
+
+ const availableHeight = height - padding[0] - padding[2];
+ const yScale: YScale = scaleBand<number>()
+ .domain(bars.map((_, index) => index))
+ .rangeRound([0, availableHeight]);
+
+ return (
+ <svg className="bar-chart" width={this.props.width} height={this.props.height}>
+ <g transform={`translate(${this.props.alignTicks ? 4 : padding[3]}, ${padding[0]})`}>
+ {this.renderBars(xScale, yScale)}
+ </g>
+ </svg>
+ );
+ }
+}
*/
import * as React from 'react';
import { find, sortBy } from 'lodash';
-import { Histogram } from './histogram';
+import Histogram from './Histogram';
import { formatMeasure } from '../../helpers/measures';
import { Language } from '../../api/languages';
import { translate } from '../../helpers/l10n';
alignTicks?: boolean;
distribution: string;
languages?: Language[];
+ width: number;
}
export default function LanguageDistribution(props: Props) {
- let data = props.distribution.split(';').map((point, index) => {
+ let distribution = props.distribution.split(';').map(point => {
const tokens = point.split('=');
- return { x: parseInt(tokens[1], 10), y: index, value: tokens[0] };
+ return { language: tokens[0], lines: parseInt(tokens[1], 10) };
});
- data = sortBy(data, d => -d.x);
+ distribution = sortBy(distribution, d => -d.lines);
- const yTicks = data.map(point => getLanguageName(point.value)).map(cutLanguageName);
- const yValues = data.map(point => formatMeasure(point.x, 'SHORT_INT'));
+ const data = distribution.map(d => d.lines);
+ const yTicks = distribution.map(d => getLanguageName(d.language)).map(cutLanguageName);
+ const yTooltips = distribution.map(d => (d.lines > 1000 ? formatMeasure(d.lines, 'INT') : ''));
+ const yValues = distribution.map(d => formatMeasure(d.lines, 'SHORT_INT'));
return (
<Histogram
alignTicks={props.alignTicks}
- data={data}
+ bars={data}
+ height={distribution.length * 25}
+ padding={[0, 60, 0, 80]}
yTicks={yTicks}
+ yTooltips={yTooltips}
yValues={yValues}
- barsWidth={10}
- height={data.length * 25}
- padding={[0, 60, 0, 80]}
+ width={props.width}
/>
);
function getLanguageName(langKey: string) {
+ if (langKey === '<null>') {
+ return translate('unknown');
+ }
const lang = find(props.languages, { key: langKey });
- return lang ? lang.name : translate('unknown');
+ return lang ? lang.name : langKey;
}
+}
- function cutLanguageName(name: string) {
- return name.length > 10 ? `${name.substr(0, 7)}...` : name;
- }
+function cutLanguageName(name: string) {
+ return name.length > 10 ? `${name.substr(0, 7)}...` : name;
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import Histogram from '../Histogram';
+
+it('renders', () => {
+ expect(shallow(<Histogram bars={[100, 75, 150]} height={75} width={100} />)).toMatchSnapshot();
+});
+
+it('renders with yValues', () => {
+ expect(
+ shallow(
+ <Histogram
+ bars={[100, 75, 150]}
+ height={75}
+ yValues={['100.0', '75.0', '150.0']}
+ width={100}
+ />
+ )
+ ).toMatchSnapshot();
+});
+
+it('renders with yValues and yTicks', () => {
+ expect(
+ shallow(
+ <Histogram
+ bars={[100, 75, 150]}
+ height={75}
+ yTicks={['a', 'b', 'c']}
+ yValues={['100.0', '75.0', '150.0']}
+ width={100}
+ />
+ )
+ ).toMatchSnapshot();
+});
+
+it('renders with yValues, yTicks and yTooltips', () => {
+ expect(
+ shallow(
+ <Histogram
+ bars={[100, 75, 150]}
+ height={75}
+ yTicks={['a', 'b', 'c']}
+ yTooltips={['a - 100', 'b - 75', 'c - 150']}
+ yValues={['100.0', '75.0', '150.0']}
+ width={100}
+ />
+ )
+ ).toMatchSnapshot();
+});
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import LanguageDistribution from '../LanguageDistribution';
+
+it('renders', () => {
+ expect(
+ shallow(
+ <LanguageDistribution
+ distribution="java=1734;js=845;cpp=73;<null>=15"
+ languages={[{ key: 'java', name: 'Java' }, { key: 'js', name: 'JavaScript' }]}
+ width={100}
+ />
+ )
+ ).toMatchSnapshot();
+});
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<svg
+ className="bar-chart"
+ height={75}
+ width={100}
+>
+ <g
+ transform="translate(10, 10)"
+ >
+ <g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={54}
+ x={0}
+ y={10}
+ />
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={41}
+ x={0}
+ y={28}
+ />
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={81}
+ x={0}
+ y={46}
+ />
+ </g>
+ </g>
+ </g>
+</svg>
+`;
+
+exports[`renders with yValues 1`] = `
+<svg
+ className="bar-chart"
+ height={75}
+ width={100}
+>
+ <g
+ transform="translate(10, 10)"
+ >
+ <g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={54}
+ x={0}
+ y={10}
+ />
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={53.33333333333333}
+ y={15}
+ >
+ 100.0
+ </text>
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={41}
+ x={0}
+ y={28}
+ />
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={40}
+ y={33}
+ >
+ 75.0
+ </text>
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={81}
+ x={0}
+ y={46}
+ />
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={80}
+ y={51}
+ >
+ 150.0
+ </text>
+ </g>
+ </g>
+ </g>
+</svg>
+`;
+
+exports[`renders with yValues and yTicks 1`] = `
+<svg
+ className="bar-chart"
+ height={75}
+ width={100}
+>
+ <g
+ transform="translate(10, 10)"
+ >
+ <g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={54}
+ x={0}
+ y={10}
+ />
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={53.33333333333333}
+ y={15}
+ >
+ 100.0
+ </text>
+ <text
+ className="bar-chart-tick histogram-tick"
+ dx="-1em"
+ dy="0.3em"
+ x={0}
+ y={15}
+ >
+ a
+ </text>
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={41}
+ x={0}
+ y={28}
+ />
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={40}
+ y={33}
+ >
+ 75.0
+ </text>
+ <text
+ className="bar-chart-tick histogram-tick"
+ dx="-1em"
+ dy="0.3em"
+ x={0}
+ y={33}
+ >
+ b
+ </text>
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={81}
+ x={0}
+ y={46}
+ />
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={80}
+ y={51}
+ >
+ 150.0
+ </text>
+ <text
+ className="bar-chart-tick histogram-tick"
+ dx="-1em"
+ dy="0.3em"
+ x={0}
+ y={51}
+ >
+ c
+ </text>
+ </g>
+ </g>
+ </g>
+</svg>
+`;
+
+exports[`renders with yValues, yTicks and yTooltips 1`] = `
+<svg
+ className="bar-chart"
+ height={75}
+ width={100}
+>
+ <g
+ transform="translate(10, 10)"
+ >
+ <g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={54}
+ x={0}
+ y={10}
+ />
+ <Tooltip
+ overlay="a - 100"
+ placement="top"
+ >
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={53.33333333333333}
+ y={15}
+ >
+ 100.0
+ </text>
+ </Tooltip>
+ <text
+ className="bar-chart-tick histogram-tick"
+ dx="-1em"
+ dy="0.3em"
+ x={0}
+ y={15}
+ >
+ a
+ </text>
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={41}
+ x={0}
+ y={28}
+ />
+ <Tooltip
+ overlay="b - 75"
+ placement="top"
+ >
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={40}
+ y={33}
+ >
+ 75.0
+ </text>
+ </Tooltip>
+ <text
+ className="bar-chart-tick histogram-tick"
+ dx="-1em"
+ dy="0.3em"
+ x={0}
+ y={33}
+ >
+ b
+ </text>
+ </g>
+ <g>
+ <rect
+ className="bar-chart-bar"
+ height={10}
+ width={81}
+ x={0}
+ y={46}
+ />
+ <Tooltip
+ overlay="c - 150"
+ placement="top"
+ >
+ <text
+ className="bar-chart-tick histogram-value"
+ dx="1em"
+ dy="0.3em"
+ x={80}
+ y={51}
+ >
+ 150.0
+ </text>
+ </Tooltip>
+ <text
+ className="bar-chart-tick histogram-tick"
+ dx="-1em"
+ dy="0.3em"
+ x={0}
+ y={51}
+ >
+ c
+ </text>
+ </g>
+ </g>
+ </g>
+</svg>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<Histogram
+ bars={
+ Array [
+ 1734,
+ 845,
+ 73,
+ 15,
+ ]
+ }
+ height={100}
+ padding={
+ Array [
+ 0,
+ 60,
+ 0,
+ 80,
+ ]
+ }
+ width={100}
+ yTicks={
+ Array [
+ "Java",
+ "JavaScript",
+ "cpp",
+ "unknown",
+ ]
+ }
+ yTooltips={
+ Array [
+ "1,734",
+ "",
+ "",
+ "",
+ ]
+ }
+ yValues={
+ Array [
+ "1.7k",
+ "845",
+ "73",
+ "15",
+ ]
+ }
+/>
+`;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import React from 'react';
-import createReactClass from 'create-react-class';
-import PropTypes from 'prop-types';
-import { max } from 'd3-array';
-import { scaleLinear, scaleBand } from 'd3-scale';
-import { ResizeMixin } from './../mixins/resize-mixin';
-import { TooltipsMixin } from './../mixins/tooltips-mixin';
-
-export const Histogram = createReactClass({
- displayName: 'Histogram',
-
- propTypes: {
- alignTicks: PropTypes.bool,
- data: PropTypes.arrayOf(PropTypes.object).isRequired,
- yTicks: PropTypes.arrayOf(PropTypes.any),
- yValues: PropTypes.arrayOf(PropTypes.any),
- width: PropTypes.number,
- height: PropTypes.number,
- padding: PropTypes.arrayOf(PropTypes.number),
- barsHeight: PropTypes.number,
- onBarClick: PropTypes.func
- },
-
- mixins: [ResizeMixin, TooltipsMixin],
-
- getDefaultProps() {
- return {
- xTicks: [],
- xValues: [],
- padding: [10, 10, 10, 10],
- barsHeight: 10
- };
- },
-
- getInitialState() {
- return { width: this.props.width, height: this.props.height };
- },
-
- handleClick(point) {
- this.props.onBarClick(point);
- },
-
- renderTicks(xScale, yScale) {
- if (!this.props.yTicks.length) {
- return null;
- }
- const ticks = this.props.yTicks.map((tick, index) => {
- const point = this.props.data[index];
- const x = xScale.range()[0];
- const y = Math.round(yScale(point.y) + yScale.bandwidth() / 2 + this.props.barsHeight / 2);
- const label = tick.label ? tick.label : tick;
- const tooltip = tick.tooltip ? tick.tooltip : null;
- const historyTickClass = this.props.alignTicks ? 'histogram-tick-start' : 'histogram-tick';
- return (
- <text
- key={index}
- className={'bar-chart-tick ' + historyTickClass}
- onClick={this.props.onBarClick && this.handleClick.bind(this, point)}
- style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
- data-title={tooltip}
- data-toggle={tooltip ? 'tooltip' : null}
- x={x}
- y={y}
- dx={this.props.alignTicks ? 0 : '-1em'}
- dy="0.3em">
- {label}
- </text>
- );
- });
- return <g>{ticks}</g>;
- },
-
- renderValues(xScale, yScale) {
- if (!this.props.yValues.length) {
- return null;
- }
- const ticks = this.props.yValues.map((value, index) => {
- const point = this.props.data[index];
- const x = xScale(point.x) + (this.props.alignTicks ? this.props.padding[3] : 0);
- const y = Math.round(yScale(point.y) + yScale.bandwidth() / 2 + this.props.barsHeight / 2);
- return (
- <text
- key={index}
- onClick={this.props.onBarClick && this.handleClick.bind(this, point)}
- className="bar-chart-tick histogram-value"
- style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
- x={x}
- y={y}
- dx="1em"
- dy="0.3em">
- {value}
- </text>
- );
- });
- return <g>{ticks}</g>;
- },
-
- renderBars(xScale, yScale) {
- const bars = this.props.data.map((d, index) => {
- const width = Math.round(xScale(d.x)) + /* minimum bar width */ 1;
- const x = xScale.range()[0] + (this.props.alignTicks ? this.props.padding[3] : 0);
- const y = Math.round(yScale(d.y) + yScale.bandwidth() / 2);
- return (
- <rect
- key={index}
- className="bar-chart-bar"
- onClick={this.props.onBarClick && this.handleClick.bind(this, d)}
- style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
- x={x}
- y={y}
- width={width}
- height={this.props.barsHeight}
- />
- );
- });
- return <g>{bars}</g>;
- },
-
- render() {
- if (!this.state.width || !this.state.height) {
- return <div />;
- }
-
- const availableWidth = this.state.width - this.props.padding[1] - this.props.padding[3];
- const availableHeight = this.state.height - this.props.padding[0] - this.props.padding[2];
-
- const maxX = max(this.props.data, d => d.x);
- const xScale = scaleLinear()
- .domain([0, maxX])
- .range([0, availableWidth]);
- const yScale = scaleBand()
- .domain(this.props.data.map(d => d.y))
- .rangeRound([0, availableHeight]);
-
- return (
- <svg className="bar-chart" width={this.state.width} height={this.state.height}>
- <g
- transform={`translate(${this.props.alignTicks ? 4 : this.props.padding[3]}, ${this.props
- .padding[0]})`}>
- {this.renderTicks(xScale, yScale)}
- {this.renderValues(xScale, yScale)}
- {this.renderBars(xScale, yScale)}
- </g>
- </svg>
- );
- }
-});
version "2.2.0"
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.0.tgz#f2312039e780bdf89d7d4102a26ec11de5ec58aa"
+"@types/d3-array@1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-1.2.1.tgz#e489605208d46a1c9d980d2e5772fa9c75d9ec65"
+
+"@types/d3-scale@1.0.10":
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-1.0.10.tgz#8c5c1dca54a159eed042b46719dbb3bdb7e8c842"
+ dependencies:
+ "@types/d3-time" "*"
+
+"@types/d3-time@*":
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-1.0.7.tgz#4266d7c9be15fa81256a88d1d052d61cd8dc572c"
+
"@types/date-fns@2.6.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@types/date-fns/-/date-fns-2.6.0.tgz#b062ca46562002909be0c63a6467ed173136acc1"