PieChart: Progress on new core pie chart (#28020)

Use visx for the Pie chart plugin.

Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
This commit is contained in:
Torkel Ödegaard
2021-02-11 14:32:33 +01:00
committed by GitHub
parent f9199ecc0c
commit cb5928fdb7
15 changed files with 1006 additions and 191 deletions

View File

@ -0,0 +1,468 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": 231,
"links": [],
"panels": [
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-saturated"
},
"custom": {},
"decimals": 1,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 8,
"x": 0,
"y": 3
},
"id": 2,
"options": {
"labelOptions": {
"showName": true,
"showPercent": false,
"showValue": false
},
"pieType": "donut",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"showLegend": true,
"strokeWidth": 1
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"alias": "__house_locations",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 5
}
],
"timeFrom": null,
"timeShift": null,
"title": "Donut name",
"type": "piechart"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-saturated"
},
"custom": {},
"decimals": 1,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 8,
"x": 8,
"y": 3
},
"id": 11,
"options": {
"labelOptions": {
"showName": true,
"showPercent": true,
"showValue": false
},
"pieType": "pie",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"showLegend": true,
"strokeWidth": 1
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"alias": "__house_locations",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 5
}
],
"timeFrom": null,
"timeShift": null,
"title": "Name and Percent",
"type": "piechart"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-saturated"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 14,
"w": 8,
"x": 16,
"y": 3
},
"id": 8,
"options": {
"labelOptions": {
"showName": true,
"showPercent": false,
"showValue": false
},
"pieType": "pie",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"showLegend": false,
"strokeWidth": 1
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"alias": "__server_names",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 4
}
],
"timeFrom": null,
"timeShift": null,
"title": "Name",
"type": "piechart"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-saturated"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 5,
"x": 0,
"y": 17
},
"id": 3,
"options": {
"labelOptions": {
"showName": false,
"showPercent": true,
"showValue": false
},
"pieType": "pie",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"showLegend": false,
"strokeWidth": 1
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"alias": "__server_names",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 4
}
],
"timeFrom": null,
"timeShift": null,
"title": "Percent",
"type": "piechart"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-saturated"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 5,
"x": 5,
"y": 17
},
"id": 9,
"options": {
"labelOptions": {
"showName": false,
"showPercent": false,
"showValue": true
},
"pieType": "pie",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"showLegend": false,
"strokeWidth": 1
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"alias": "__server_names",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 4
}
],
"timeFrom": null,
"timeShift": null,
"title": "Value",
"type": "piechart"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-saturated"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 6,
"x": 10,
"y": 17
},
"id": 6,
"options": {
"labelOptions": {
"showName": true,
"showPercent": false,
"showValue": false
},
"pieType": "donut",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"showLegend": false,
"strokeWidth": 1
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"alias": "__server_names",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 4
}
],
"timeFrom": null,
"timeShift": null,
"title": "Name",
"type": "piechart"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 8,
"x": 16,
"y": 17
},
"id": 10,
"options": {
"labelOptions": {
"showName": true,
"showPercent": false,
"showValue": false
},
"pieType": "pie",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"showLegend": false,
"strokeWidth": 1
},
"pluginVersion": "7.3.0-pre",
"targets": [
{
"alias": "__server_names",
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 4
}
],
"timeFrom": null,
"timeShift": null,
"title": "Memory",
"type": "piechart"
}
],
"schemaVersion": 26,
"style": "dark",
"tags": ["gdev", "panel-tests"],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Panel Tests - Pie chart",
"uid": "lVE-2YFMz",
"version": 1
}

View File

@ -216,6 +216,7 @@
"@types/react-virtualized-auto-sizer": "1.0.0",
"@types/sockjs-client": "^1.1.1",
"@types/uuid": "8.3.0",
"@types/hoist-non-react-statics": "3.3.1",
"@welldone-software/why-did-you-render": "4.0.6",
"abortcontroller-polyfill": "1.4.0",
"angular": "1.8.2",

View File

@ -37,7 +37,7 @@ export const fieldColorModeRegistry = new Registry<FieldColorMode>(() => {
},
// new FieldColorSchemeMode({
// id: FieldColorModeId.PaletteSaturated,
// name: 'By series / Saturated palette',
// name: 'Saturated palette',
// //description: 'Assigns color based on series or field index',
// isContinuous: false,
// isByValue: false,
@ -45,7 +45,7 @@ export const fieldColorModeRegistry = new Registry<FieldColorMode>(() => {
// 'blue',
// 'red',
// 'green',
// 'yellow',
// 'orange',
// 'purple',
// 'orange',
// 'dark-blue',

View File

@ -43,6 +43,11 @@
"@types/react-table": "7.0.12",
"@types/slate": "0.47.1",
"@types/slate-react": "0.22.5",
"@visx/event": "1.3.0",
"@visx/gradient": "1.0.0",
"@visx/scale": "1.4.0",
"@visx/shape": "1.4.0",
"@visx/tooltip": "1.3.0",
"classnames": "2.2.6",
"d3": "5.15.0",
"emotion": "10.0.27",

View File

@ -1,5 +1,5 @@
import React from 'react';
import { number, object, select } from '@storybook/addon-knobs';
import { object, select, number, boolean } from '@storybook/addon-knobs';
import { PieChart, PieChartType } from '@grafana/ui';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
@ -12,24 +12,39 @@ export default {
const getKnobs = () => {
return {
datapoints: object('datapoints', [
{
numeric: 100,
text: '100',
color: '#7EB26D',
},
{
numeric: 200,
text: '200',
color: '#6ED0E0',
},
{ numeric: 100, text: '100', title: 'USA' },
{ numeric: 200, text: '200', title: 'Canada' },
{ numeric: 20, text: '20', title: 'Sweden' },
{ numeric: 50, text: '50', title: 'Spain' },
{ numeric: 70, text: '70', title: 'Germeny' },
]),
pieType: select('pieType', [PieChartType.PIE, PieChartType.DONUT], PieChartType.PIE),
strokeWidth: number('strokeWidth', 1),
width: number('Width', 500),
height: number('Height', 500),
pieType: select('pieType', [PieChartType.Pie, PieChartType.Donut], PieChartType.Pie),
showLabelName: boolean('Label.showName', true),
showLabelValue: boolean('Label.showValue', false),
showLabelPercent: boolean('Label.showPercent', false),
};
};
export const basic = () => {
const { datapoints, pieType, strokeWidth } = getKnobs();
const { datapoints, pieType, width, height, showLabelName, showLabelPercent, showLabelValue } = getKnobs();
const labelOptions = { showName: showLabelName, showPercent: showLabelPercent, showValue: showLabelValue };
return <PieChart width={200} height={400} values={datapoints} pieType={pieType} strokeWidth={strokeWidth} />;
return <PieChart width={width} height={height} values={datapoints} pieType={pieType} labelOptions={labelOptions} />;
};
export const donut = () => {
const { datapoints, width, height, showLabelName, showLabelPercent, showLabelValue } = getKnobs();
const labelOptions = { showName: showLabelName, showPercent: showLabelPercent, showValue: showLabelValue };
return (
<PieChart
width={width}
height={height}
values={datapoints}
pieType={PieChartType.Donut}
labelOptions={labelOptions}
/>
);
};

View File

@ -1,142 +1,225 @@
import React, { PureComponent } from 'react';
import { select, pie, arc, event } from 'd3';
import sum from 'lodash/sum';
import { DisplayValue, GrafanaThemeType, formattedValueToString } from '@grafana/data';
import { Themeable } from '../../index';
import { colors as grafana_colors } from '../../utils/index';
import React, { FC } from 'react';
import { DisplayValue, formattedValueToString, GrafanaTheme } from '@grafana/data';
import { useStyles, useTheme } from '../../themes/ThemeContext';
import tinycolor from 'tinycolor2';
import Pie, { PieArcDatum } from '@visx/shape/lib/shapes/Pie';
import { Group } from '@visx/group';
import { RadialGradient } from '@visx/gradient';
import { localPoint } from '@visx/event';
import { useTooltip, useTooltipInPortal } from '@visx/tooltip';
import { useComponentInstanceId } from '../../utils/useComponetInstanceId';
import { css } from 'emotion';
export enum PieChartType {
PIE = 'pie',
DONUT = 'donut',
}
export interface Props extends Themeable {
export interface Props {
height: number;
width: number;
values: DisplayValue[];
pieType: PieChartType;
strokeWidth: number;
labelOptions?: PieChartLabelOptions;
}
export class PieChart extends PureComponent<Props> {
containerElement: any;
svgElement: any;
tooltipElement: any;
tooltipValueElement: any;
export enum PieChartType {
Pie = 'pie',
Donut = 'donut',
}
static defaultProps = {
pieType: 'pie',
format: 'short',
stat: 'current',
strokeWidth: 1,
theme: GrafanaThemeType.Dark,
export interface PieChartLabelOptions {
showName?: boolean;
showValue?: boolean;
showPercent?: boolean;
}
export const PieChart: FC<Props> = ({ values, pieType, width, height, labelOptions = { showName: true } }) => {
const theme = useTheme();
const componentInstanceId = useComponentInstanceId('PieChart');
const styles = useStyles(getStyles);
const { tooltipData, tooltipLeft, tooltipTop, tooltipOpen, showTooltip, hideTooltip } = useTooltip<DisplayValue>();
const { containerRef, TooltipInPortal } = useTooltipInPortal({
detectBounds: true,
scroll: true,
});
if (values.length < 0) {
return <div>No data</div>;
}
const margin = 16;
const size = Math.min(width, height);
const outerRadius = (size - margin * 2) / 2;
const donutThickness = pieType === PieChartType.Pie ? outerRadius : Math.max(outerRadius / 3, 20);
const innerRadius = outerRadius - donutThickness;
const centerOffset = (size - margin * 2) / 2;
const total = values.reduce((acc, item) => item.numeric + acc, 0);
// for non donut pie charts shift gradient out a bit
const gradientFromOffset = 1 - (outerRadius - innerRadius) / outerRadius;
const showLabel = labelOptions.showName || labelOptions.showPercent || labelOptions.showValue;
const getValue = (d: DisplayValue) => d.numeric;
const getGradientId = (idx: number) => `${componentInstanceId}-${idx}`;
const getColor = (arc: PieArcDatum<DisplayValue>) => `url(#${getGradientId(arc.index)})`;
const onMouseMoveOverArc = (event: any, datum: any) => {
const coords = localPoint(event.target.ownerSVGElement, event);
showTooltip({
tooltipLeft: coords!.x,
tooltipTop: coords!.y,
tooltipData: datum,
});
};
componentDidMount() {
this.draw();
}
componentDidUpdate() {
this.draw();
}
draw() {
const { values, pieType, strokeWidth } = this.props;
if (values.length === 0) {
return;
}
const data = values.map((datapoint) => datapoint.numeric);
const names = values.map((datapoint) => formattedValueToString(datapoint));
const colors = values.map((p, idx) => {
if (p.color) {
return p.color;
}
return grafana_colors[idx % grafana_colors.length];
});
const total = sum(data) || 1;
const percents = data.map((item: number) => (item / total) * 100);
const width = this.containerElement.offsetWidth;
const height = this.containerElement.offsetHeight;
const radius = Math.min(width, height) / 2;
const outerRadius = radius - radius / 10;
const innerRadius = pieType === PieChartType.PIE ? 0 : radius - radius / 3;
const svg = select(this.svgElement)
.html('')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${width / 2},${height / 2})`);
const pieChart = pie();
const customArc = arc().outerRadius(outerRadius).innerRadius(innerRadius).padAngle(0);
svg
.selectAll('path')
.data(pieChart(data))
.enter()
.append('path')
.attr('d', customArc as any)
.attr('fill', (d: any, idx: number) => colors[idx])
.style('fill-opacity', 0.15)
.style('stroke', (d: any, idx: number) => colors[idx])
.style('stroke-width', `${strokeWidth}px`)
.on('mouseover', (d: any, idx: any) => {
select(this.tooltipElement).style('opacity', 1);
select(this.tooltipValueElement).text(`${names[idx]} (${percents[idx].toFixed(2)}%)`);
})
.on('mousemove', () => {
select(this.tooltipElement)
.style('top', `${event.pageY - height / 2}px`)
.style('left', `${event.pageX}px`);
})
.on('mouseout', () => {
select(this.tooltipElement).style('opacity', 0);
});
}
render() {
const { height, width, values } = this.props;
if (values.length > 0) {
return (
<div className="piechart-panel">
<div
ref={(element) => (this.containerElement = element)}
className="piechart-container"
style={{
height: `${height * 0.9}px`,
width: `${Math.min(width, height * 1.3)}px`,
}}
>
<svg ref={(element) => (this.svgElement = element)} />
</div>
<div className="piechart-tooltip" ref={(element) => (this.tooltipElement = element)}>
<div className="piechart-tooltip-time">
<div
id="tooltip-value"
className="piechart-tooltip-value"
ref={(element) => (this.tooltipValueElement = element)}
return (
<div className={styles.container}>
<svg width={size} height={size} ref={containerRef}>
<Group top={centerOffset + margin} left={centerOffset + margin}>
{values.map((value, idx) => {
const color = value.color ?? 'gray';
return (
<RadialGradient
key={idx}
id={getGradientId(idx)}
from={getGradientColorFrom(color, theme)}
to={getGradientColorTo(color, theme)}
fromOffset={gradientFromOffset}
toOffset="1"
gradientUnits="userSpaceOnUse"
cx={0}
cy={0}
radius={outerRadius}
/>
</div>
</div>
</div>
);
} else {
return (
<div className="piechart-panel">
<div className="datapoints-warning">
<span className="small">No data points</span>
</div>
</div>
);
}
);
})}
<Pie
data={values}
pieValue={getValue}
outerRadius={outerRadius}
innerRadius={innerRadius}
cornerRadius={3}
padAngle={0.005}
>
{(pie) => {
return pie.arcs.map((arc) => {
return (
<g
key={arc.data.title}
className={styles.svgArg}
onMouseMove={(event) => onMouseMoveOverArc(event, arc.data)}
onMouseOut={hideTooltip}
>
<path
d={pie.path({ ...arc })!}
fill={getColor(arc)}
stroke={theme.colors.panelBg}
strokeWidth={1}
/>
{showLabel && (
<PieLabel
arc={arc}
outerRadius={outerRadius}
innerRadius={innerRadius}
labelOptions={labelOptions}
total={total}
/>
)}
</g>
);
});
}}
</Pie>
</Group>
</svg>
{tooltipOpen && (
<TooltipInPortal key={Math.random()} top={tooltipTop} left={tooltipLeft}>
{tooltipData!.title} {formattedValueToString(tooltipData!)}
</TooltipInPortal>
)}
</div>
);
};
const PieLabel: FC<{
arc: PieArcDatum<DisplayValue>;
outerRadius: number;
innerRadius: number;
labelOptions: PieChartLabelOptions;
total: number;
}> = ({ arc, outerRadius, innerRadius, labelOptions, total }) => {
const labelRadius = innerRadius === 0 ? outerRadius / 6 : innerRadius;
const [labelX, labelY] = getLabelPos(arc, outerRadius, labelRadius);
const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.3;
if (!hasSpaceForLabel) {
return null;
}
let labelFontSize = labelOptions.showName
? Math.min(Math.max((outerRadius / 150) * 14, 12), 30)
: Math.min(Math.max((outerRadius / 100) * 14, 12), 36);
return (
<g>
<text
fill="white"
x={labelX}
y={labelY}
dy=".33em"
fontSize={labelFontSize}
textAnchor="middle"
pointerEvents="none"
>
{labelOptions.showName && (
<tspan x={labelX} dy="1.2em">
{arc.data.title}
</tspan>
)}
{labelOptions.showValue && (
<tspan x={labelX} dy="1.2em">
{formattedValueToString(arc.data)}
</tspan>
)}
{labelOptions.showPercent && (
<tspan x={labelX} dy="1.2em">
{((arc.data.numeric / total) * 100).toFixed(0) + '%'}
</tspan>
)}
</text>
</g>
);
};
function getLabelPos(arc: PieArcDatum<DisplayValue>, outerRadius: number, innerRadius: number) {
const r = (outerRadius + innerRadius) / 2;
const a = (+arc.startAngle + +arc.endAngle) / 2 - Math.PI / 2;
return [Math.cos(a) * r, Math.sin(a) * r];
}
function getGradientColorFrom(color: string, theme: GrafanaTheme) {
return tinycolor(color)
.darken(20 * (theme.isDark ? 1 : -0.7))
.spin(8)
.toRgbString();
}
function getGradientColorTo(color: string, theme: GrafanaTheme) {
return tinycolor(color)
.darken(10 * (theme.isDark ? 1 : -0.7))
.spin(-8)
.toRgbString();
}
const getStyles = (theme: GrafanaTheme) => {
return {
container: css`
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
`,
svgArg: css`
transition: all 200ms ease-in-out;
&:hover {
transform: scale3d(1.03, 1.03, 1);
}
`,
};
};

View File

@ -0,0 +1,8 @@
import React, { FC } from 'react';
import { Props as PieChartProps } from './PieChart';
export interface Props extends PieChartProps {}
export const PieChartWithLegend: FC<Props> = ({ width, height, ...restProps }) => {
return <div>Need VizLayout in grafana/ui</div>;
};

View File

@ -17,7 +17,7 @@ export { LoadingPlaceholder, LoadingPlaceholderProps } from './LoadingPlaceholde
export { ColorPicker, SeriesColorPicker } from './ColorPicker/ColorPicker';
export { SeriesColorPickerPopover, SeriesColorPickerPopoverWithTheme } from './ColorPicker/SeriesColorPickerPopover';
export { EmptySearchResult } from './EmptySearchResult/EmptySearchResult';
export { PieChart, PieChartType } from './PieChart/PieChart';
export { PieChart, PieChartType, PieChartLabelOptions } from './PieChart/PieChart';
export { UnitPicker } from './UnitPicker/UnitPicker';
export { StatsPicker } from './StatsPicker/StatsPicker';
export { RefreshPicker, defaultIntervals } from './RefreshPicker/RefreshPicker';

View File

@ -0,0 +1,14 @@
import { useRef } from 'react';
let uniqueId = 0;
const getUniqueId = () => uniqueId++;
export function useComponentInstanceId(prefix: string): string {
const idRef = useRef<string | null>(null);
if (idRef.current === null) {
idRef.current = prefix + getUniqueId();
}
return idRef.current!.toString();
}

View File

@ -670,7 +670,7 @@ func randomWalk(query backend.DataQuery, model *simplejson.Json, index int) *dat
return data.NewFrame("",
data.NewField("time", nil, timeVec),
data.NewField(frameNameForQuery(query, model, 0), parseLabels(model), floatVec),
data.NewField(frameNameForQuery(query, model, index), parseLabels(model), floatVec),
)
}

View File

@ -3,22 +3,20 @@ import { LegacyForms, InlineFormLabel, PieChartType } from '@grafana/ui';
import { PanelEditorProps } from '@grafana/data';
import { PieChartOptions } from './types';
const { Select, FormField } = LegacyForms;
const { Select } = LegacyForms;
const labelWidth = 8;
const pieChartOptions = [
{ value: PieChartType.PIE, label: 'Pie' },
{ value: PieChartType.DONUT, label: 'Donut' },
{ value: PieChartType.Pie, label: 'Pie' },
{ value: PieChartType.Donut, label: 'Donut' },
];
export class PieChartOptionsBox extends PureComponent<PanelEditorProps<PieChartOptions>> {
onPieTypeChange = (pieType: any) => this.props.onOptionsChange({ ...this.props.options, pieType: pieType.value });
onStrokeWidthChange = ({ target }: any) =>
this.props.onOptionsChange({ ...this.props.options, strokeWidth: target.value });
render() {
const { options } = this.props;
const { pieType, strokeWidth } = options;
const { pieType } = options;
return (
<>
@ -31,14 +29,6 @@ export class PieChartOptionsBox extends PureComponent<PanelEditorProps<PieChartO
value={pieChartOptions.find((option) => option.value === pieType)}
/>
</div>
<div className="gf-form">
<FormField
label="Divider width"
labelWidth={labelWidth}
onChange={this.onStrokeWidthChange}
value={strokeWidth}
/>
</div>
</>
);
}

View File

@ -25,8 +25,7 @@ export class PieChartPanel extends PureComponent<Props> {
height={height}
values={values}
pieType={options.pieType}
strokeWidth={options.strokeWidth}
theme={config.theme}
labelOptions={options.labelOptions}
/>
);
}

View File

@ -1,29 +1,53 @@
import { PanelPlugin } from '@grafana/data';
import { FieldColorModeId, FieldConfigProperty, PanelPlugin } from '@grafana/data';
import { PieChartPanel } from './PieChartPanel';
import { PieChartOptions } from './types';
import { addStandardDataReduceOptions } from '../stat/types';
import { PieChartType } from '@grafana/ui';
export const plugin = new PanelPlugin<PieChartOptions>(PieChartPanel).setPanelOptions((builder) => {
addStandardDataReduceOptions(builder, false);
builder
.addRadio({
name: 'Piechart type',
description: 'How the piechart should be rendered',
path: 'pieType',
settings: {
options: [
{ value: PieChartType.PIE, label: 'Pie' },
{ value: PieChartType.DONUT, label: 'Donut' },
],
export const plugin = new PanelPlugin<PieChartOptions>(PieChartPanel)
.useFieldConfig({
standardOptions: {
[FieldConfigProperty.Color]: {
settings: {
byValueSupport: false,
bySeriesSupport: true,
preferThresholdsMode: false,
},
defaultValue: {
mode: FieldColorModeId.PaletteClassic,
},
},
defaultValue: PieChartType.PIE,
})
.addNumberInput({
name: 'Width',
description: 'Width of the piechart outline',
path: 'strokeWidth',
defaultValue: 1,
});
});
},
})
.setPanelOptions((builder) => {
addStandardDataReduceOptions(builder, false);
builder
.addRadio({
name: 'Piechart type',
description: 'How the piechart should be rendered',
path: 'pieType',
settings: {
options: [
{ value: PieChartType.Pie, label: 'Pie' },
{ value: PieChartType.Donut, label: 'Donut' },
],
},
defaultValue: PieChartType.Pie,
})
.addBooleanSwitch({
name: 'Show name',
path: 'labelOptions.showName',
defaultValue: true,
})
.addBooleanSwitch({
name: 'Show value',
path: 'labelOptions.showValue',
defaultValue: false,
})
.addBooleanSwitch({
name: 'Show percent',
path: 'labelOptions.showPercent',
defaultValue: false,
});
});

View File

@ -1,6 +1,6 @@
import { PieChartType, SingleStatBaseOptions } from '@grafana/ui';
import { PieChartType, SingleStatBaseOptions, PieChartLabelOptions } from '@grafana/ui';
export interface PieChartOptions extends SingleStatBaseOptions {
pieType: PieChartType;
strokeWidth: number;
labelOptions: PieChartLabelOptions;
}

212
yarn.lock
View File

@ -5932,6 +5932,11 @@
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.10.tgz#cc658ca319b6355399efc1f5b9e818f1a24bf999"
integrity sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ==
"@types/classnames@^2.2.9":
version "2.2.11"
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.11.tgz#2521cc86f69d15c5b90664e4829d84566052c1cf"
integrity sha512-2koNhpWm3DgWRp5tpkiJ8JGc1xTn2q0l+jUNUE7oMKXUf5NpI9AIdC4kbjGNFBdHtcxBD18LAksoudAVhFKCjw==
"@types/clean-css@*":
version "4.2.1"
resolved "https://registry.yarnpkg.com/@types/clean-css/-/clean-css-4.2.1.tgz#cb0134241ec5e6ede1b5344bc829668fd9871a8d"
@ -6084,6 +6089,11 @@
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.8.tgz#48e6945a8ff43ee0a1ce85c8cfa2337de85c7c79"
integrity sha512-AZGHWslq/oApTAHu9+yH/Bnk63y9oFOMROtqPAtxl5uB6qm1x2lueWdVEjsjjV3Qc2+QfuzKIwIR5MvVBakfzA==
"@types/d3-path@^1", "@types/d3-path@^1.0.8":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c"
integrity sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==
"@types/d3-polygon@*":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-1.0.7.tgz#7b3947aa2d48287ff535230d3d396668ab17bfdf"
@ -6111,6 +6121,13 @@
dependencies:
"@types/d3-time" "*"
"@types/d3-scale@^3.2.1":
version "3.2.2"
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-3.2.2.tgz#5e28d0b1c599328aaec6094219f10a2570be6d74"
integrity sha512-qpQe8G02tzUwt9sdWX1h8A/W0Q1+N48wMnYXVOkrzeLUkCfvzJYV9Ee3aORCS4dN4ONRLFmMvaXdziQ29XGLjQ==
dependencies:
"@types/d3-time" "*"
"@types/d3-selection@*":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-1.4.1.tgz#fa1f8710a6b5d7cfe5c6caa61d161be7cae4a022"
@ -6123,6 +6140,13 @@
dependencies:
"@types/d3-path" "*"
"@types/d3-shape@^1.3.1":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.3.5.tgz#c0164c1be1429473016f855871d487f806c4e968"
integrity sha512-aPEax03owTAKynoK8ZkmkZEDZvvT4Y5pWgii4Jp4oQt0gH45j6siDl9gNDVC5kl64XHN2goN9jbYoHK88tFAcA==
dependencies:
"@types/d3-path" "^1"
"@types/d3-time-format@*":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-2.1.1.tgz#dd2c79ec4575f1355484ab6b10407824668eba42"
@ -6133,6 +6157,11 @@
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-1.0.10.tgz#d338c7feac93a98a32aac875d1100f92c7b61f4f"
integrity sha512-aKf62rRQafDQmSiv1NylKhIMmznsjRN+MnXRXTqHoqm0U/UZzVpdrtRnSIfdiLS616OuC1soYeX1dBg2n1u8Xw==
"@types/d3-time@^1.0.10":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-1.1.1.tgz#6cf3a4242c3bbac00440dfb8ba7884f16bedfcbf"
integrity sha512-ULX7LoqXTCYtM+tLYOaeAJK7IwCT+4Gxlm2MaH0ErKLi07R5lh8NHCAyWcDkCCmx1AfRcBEV6H9QE9R25uP7jw==
"@types/d3-timer@*":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-1.0.9.tgz#aed1bde0cf18920d33f5d44839d73de393633fd3"
@ -6483,6 +6512,11 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440"
integrity sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==
"@types/lodash@^4.14.146":
version "4.14.168"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008"
integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==
"@types/long@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
@ -7263,6 +7297,97 @@
"@typescript-eslint/types" "4.0.1"
eslint-visitor-keys "^2.0.0"
"@visx/bounds@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@visx/bounds/-/bounds-1.0.0.tgz#a54eb43a7ddf1bb7f0cd6bf8bf5f94fa5ec562b8"
integrity sha512-QxD/OkZVkzpeP6L0YxUnIAsxlFemkDPfOumchVDRlrO4lZ3YXLmsnaEEiJpU5tSgNamZAUh+Tz3d2RbHp3qqxA==
dependencies:
"@types/react" "*"
"@types/react-dom" "*"
prop-types "^15.5.10"
"@visx/curve@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@visx/curve/-/curve-1.0.0.tgz#f1928821c0beea05d019f3066b28459b4b185c5b"
integrity sha512-rN9TUf4uRmPuQ5Rd4kbvinSDsTbR61YB26+ucK6RNMHIr9aLmujpcPJhVwk22EWphRRGIxzK2OSp0d5dgpNppQ==
dependencies:
"@types/d3-shape" "^1.3.1"
d3-shape "^1.0.6"
"@visx/event@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@visx/event/-/event-1.3.0.tgz#bdbcf40910faf873bcfa972c8ba2c5a192c2dd6a"
integrity sha512-Nq0xz7c1eMc8j3CTt94hTZO+veQ1Ti7u22LZF4M2W36yKh5PtZRfM4O6tILSdO7cxigeNd1vbmZo9MSDmk5lbQ==
dependencies:
"@types/react" "*"
"@visx/point" "1.0.0"
"@visx/gradient@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@visx/gradient/-/gradient-1.0.0.tgz#51a9fe47eb5155620369b3fa8f33fb51c3f36881"
integrity sha512-Y+Xoz4dRF5+1Ru693Ik7v/Bb4d9kyVWz4iTBB2Oyfu7Ceo2VC7bh7McmLgmYmsnbbFWeJiAnow2Qzx0EHR5eCg==
dependencies:
"@types/react" "*"
prop-types "^15.5.7"
"@visx/group@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@visx/group/-/group-1.0.0.tgz#d47ac94abec1d191602a501a4fdf7455dfaad0be"
integrity sha512-2YlhGHTINUl7do046p/bkIYiD4xDv/sJ4JAaGrqFXwX68EJZ5Er/0gpZZ4nrADQlxB8/uyJvZzp1Q54ySfTMiA==
dependencies:
"@types/classnames" "^2.2.9"
"@types/react" "*"
classnames "^2.2.5"
prop-types "^15.6.2"
"@visx/point@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@visx/point/-/point-1.0.0.tgz#c93cd540989ded394aab8d56cbdc7ca4891c3dd9"
integrity sha512-0L3ILwv6ro0DsQVbA1lo8fo6q3wvIeSTt9C8NarUUkoTNSFZaJtlmvwg2238r8fwwmSv0v9QFBj1hBz4o0bHrg==
"@visx/scale@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@visx/scale/-/scale-1.4.0.tgz#16cf4ba63dbc595e446397f5bf262591ffe9efd6"
integrity sha512-uNy/hsZCmCtL1hC7rTasMUtf9/faG/QcXNtQioe6VYwtbZxCMR53+yvz3W1oqAW8Y0bslGfKRMzT8T29OjAD/g==
dependencies:
"@types/d3-interpolate" "^1.3.1"
"@types/d3-scale" "^3.2.1"
"@types/d3-time" "^1.0.10"
d3-interpolate "^1.4.0"
d3-scale "^3.2.3"
d3-time "^1.1.0"
"@visx/shape@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@visx/shape/-/shape-1.4.0.tgz#a8ab713c7df775db357341618c7c0fdbb813f272"
integrity sha512-iTeFGtsidHXoeEyfriwRj7vkgs3BYqXWuDVe/uW4kpn76u7M0LhRCy59ADlufYDn+19qdA/rVPv4oD6nrWMhCw==
dependencies:
"@types/classnames" "^2.2.9"
"@types/d3-path" "^1.0.8"
"@types/d3-shape" "^1.3.1"
"@types/lodash" "^4.14.146"
"@types/react" "*"
"@visx/curve" "1.0.0"
"@visx/group" "1.0.0"
"@visx/scale" "1.4.0"
classnames "^2.2.5"
d3-path "^1.0.5"
d3-shape "^1.2.0"
lodash "^4.17.15"
prop-types "^15.5.10"
"@visx/tooltip@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@visx/tooltip/-/tooltip-1.3.0.tgz#32b3969eed51cc83e7f16d61d929258ef52b50ca"
integrity sha512-8ZliQmcE3R2TvNHyCnViPlT9Msnx/prn6gfsa1QMgWySQzVhFlL4Man9hkmbbIvpwU1i1OarbANF7hUqz86jZQ==
dependencies:
"@types/classnames" "^2.2.9"
"@types/react" "*"
"@visx/bounds" "1.0.0"
classnames "^2.2.5"
prop-types "^15.5.10"
react-use-measure "2.0.1"
"@webassemblyjs/ast@1.8.5":
version "1.8.5"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
@ -11184,6 +11309,13 @@ d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0:
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
d3-array@^2.3.0:
version "2.11.0"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.11.0.tgz#5ed6a2869bc7d471aec8df9ff6ed9fef798facc4"
integrity sha512-26clcwmHQEdsLv34oNKq5Ia9tQ26Y/4HqS3dQzF42QBUqymZJ+9PORcN1G52bt37NsL2ABoX4lvyYZc+A9Y0zw==
dependencies:
internmap "^1.0.0"
d3-axis@1:
version "1.0.12"
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9"
@ -11218,6 +11350,11 @@ d3-color@1:
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.0.tgz#89c45a995ed773b13314f06460df26d60ba0ecaf"
integrity sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg==
"d3-color@1 - 2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e"
integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==
d3-contour@1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3"
@ -11293,6 +11430,11 @@ d3-format@1:
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.1.tgz#c45f74b17c5a290c072a4ba7039dd19662cd5ce6"
integrity sha512-TUswGe6hfguUX1CtKxyG2nymO+1lyThbkS1ifLX0Sr+dOQtAD5gkrffpHnx+yHNKUZ0Bmg5T4AjUQwugPDrm0g==
"d3-format@1 - 2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767"
integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==
d3-geo@1:
version "1.11.6"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.11.6.tgz#134f2ef035ff75a448075fafdea92702a2e0e0cf"
@ -11312,6 +11454,20 @@ d3-interpolate@1:
dependencies:
d3-color "1"
"d3-interpolate@1.2.0 - 2":
version "2.0.1"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163"
integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==
dependencies:
d3-color "1 - 2"
d3-interpolate@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.4.0.tgz#526e79e2d80daa383f9e0c1c1c7dcc0f0583e987"
integrity sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==
dependencies:
d3-color "1"
d3-interpolate@~1.1.5:
version "1.1.6"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.6.tgz#2cf395ae2381804df08aa1bf766b7f97b5f68fb6"
@ -11324,6 +11480,11 @@ d3-path@1:
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.8.tgz#4a0606a794d104513ec4a8af43525f374b278719"
integrity sha512-J6EfUNwcMQ+aM5YPOB8ZbgAZu6wc82f/0WFxrxwV6Ll8wBwLaHLKCqQ5Imub02JriCVVdPjgI+6P3a4EWJCxAg==
d3-path@^1.0.5:
version "1.0.9"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf"
integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==
d3-polygon@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.5.tgz#9a645a0a64ff6cbf9efda96ee0b4a6909184c363"
@ -11364,6 +11525,17 @@ d3-scale@2:
d3-time "1"
d3-time-format "2"
d3-scale@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.2.3.tgz#be380f57f1f61d4ff2e6cbb65a40593a51649cfd"
integrity sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g==
dependencies:
d3-array "^2.3.0"
d3-format "1 - 2"
d3-interpolate "1.2.0 - 2"
d3-time "1 - 2"
d3-time-format "2 - 3"
d3-selection@1, d3-selection@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.0.tgz#ab9ac1e664cf967ebf1b479cc07e28ce9908c474"
@ -11381,6 +11553,13 @@ d3-shape@1:
dependencies:
d3-path "1"
d3-shape@^1.0.6, d3-shape@^1.2.0:
version "1.3.7"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7"
integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==
dependencies:
d3-path "1"
d3-time-format@2:
version "2.1.3"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.3.tgz#ae06f8e0126a9d60d6364eac5b1533ae1bac826b"
@ -11388,11 +11567,23 @@ d3-time-format@2:
dependencies:
d3-time "1"
d3-time@1:
"d3-time-format@2 - 3":
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6"
integrity sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==
dependencies:
d3-time "1 - 2"
d3-time@1, d3-time@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1"
integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==
"d3-time@1 - 2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.0.0.tgz#ad7c127d17c67bd57a4c61f3eaecb81108b1e0ab"
integrity sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q==
d3-timer@1:
version "1.0.9"
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.9.tgz#f7bb8c0d597d792ff7131e1c24a36dd471a471ba"
@ -11555,6 +11746,11 @@ debounce-promise@3.1.2:
resolved "https://registry.yarnpkg.com/debounce-promise/-/debounce-promise-3.1.2.tgz#320fb8c7d15a344455cd33cee5ab63530b6dc7c5"
integrity sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==
debounce@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131"
integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==
debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -15594,6 +15790,11 @@ internal-slot@^1.0.2:
has "^1.0.3"
side-channel "^1.0.2"
internmap@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.0.tgz#3c6bf0944b0eae457698000412108752bbfddb56"
integrity sha512-SdoDWwNOTE2n4JWUsLn4KXZGuZPjPF9yyOGc8bnfWnBQh7BD/l80rzSznKc/r4Y0aQ7z3RTk9X+tV4tHBpu+dA==
interpret@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
@ -21212,7 +21413,7 @@ prop-types-exact@^1.2.0:
object.assign "^4.1.0"
reflect.ownkeys "^0.2.0"
prop-types@15.7.2, prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@15.7.2, prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -22250,6 +22451,13 @@ react-transition-group@4.4.1:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-use-measure@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/react-use-measure/-/react-use-measure-2.0.1.tgz#4f23f94c832cd4512da55acb300d1915dcbf3ae8"
integrity sha512-lFfHiqcXbJ2/6aUkZwt8g5YYM7EGqNVxJhMqMPqv1BVXRKp8D7jYLlmma0SvhRY4WYxxkZpCdbJvhDylb5gcEA==
dependencies:
debounce "^1.2.0"
react-use@13.27.0:
version "13.27.0"
resolved "https://registry.yarnpkg.com/react-use/-/react-use-13.27.0.tgz#53a619dc9213e2cbe65d6262e8b0e76641ade4aa"