Skip to content

Commit

Permalink
fix: datum type
Browse files Browse the repository at this point in the history
  • Loading branch information
kristw committed Jul 28, 2020
1 parent d3e9fbc commit 0263b9b
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 21 deletions.
7 changes: 3 additions & 4 deletions packages/vx-stats/src/BoxPlot.tsx
Expand Up @@ -13,10 +13,8 @@ function verticalToHorizontal({ x1, x2, y1, y2 }: LineCoords) {
};
}

type ScaleInput = number;

export type BoxPlotProps = SharedProps & {
/** Scale for converting ScaleInput values to pixel offsets. */
/** Scale for converting input values to pixel offsets. */
valueScale: PickD3Scale<ContinuousDomainScaleType, number>;
/** Maximum BoxPlot value. */
max?: number;
Expand All @@ -43,7 +41,7 @@ export type BoxPlotProps = SharedProps & {
/** Ry to apply to BoxPlot rect. */
ry?: number;
/** Array of outlier values to be rendered. */
outliers?: ScaleInput[];
outliers?: number[];
/** Props to pass to the median glyph line. */
medianProps?: React.SVGProps<SVGLineElement>;
/** Props to pass to the maximum glyph line. */
Expand Down Expand Up @@ -161,6 +159,7 @@ export default function BoxPlot({
boxplot.container.y1 = Math.min(...valueRange);
}

// eslint-disable-next-line react/jsx-no-useless-fragment
if (children) return <>{children(boxplot)}</>;

return (
Expand Down
37 changes: 21 additions & 16 deletions packages/vx-stats/src/ViolinPlot.tsx
Expand Up @@ -2,37 +2,41 @@ import React from 'react';
import cx from 'classnames';
import { scaleLinear, PickD3Scale, ContinuousDomainScaleType } from '@vx/scale';
import { line, curveCardinal } from 'd3-shape';
import { BinDatum, SharedProps } from './types';
import { SharedProps } from './types';

export type ViolinPlotProps<ScaleInput> = SharedProps & {
export type ViolinPlotProps<Datum extends object> = SharedProps & {
/** Scale for converting values to pixel offsets. */
valueScale: PickD3Scale<ContinuousDomainScaleType, number>;
/** Data used to draw the violin plot glyph. Violin plot values and counts should be able to be derived from data. */
data: ScaleInput[];
/** Given an ScaleInput datum, returns the count for it. */
count?: (d: ScaleInput) => number;
/** Given an ScaleInput datum, returns the value for it. */
value?: (d: ScaleInput) => number;
data: Datum[];
/** Given an datum, returns the count for it. */
count?: (d: Datum) => number;
/** Given an datum, returns the value for it. */
value?: (d: Datum) => number;
/** Width of the violin plot glyph. */
width?: number;
/** Override render function to fully control the rendering of the ViolinPlot glyph. */
children?: (providedProps: { path: string }) => React.ReactNode;
};

export default function ViolinPlot<ScaleInput extends object = BinDatum>({
const defaultCountAccessor = (d: { count?: unknown }) =>
typeof d.count === 'number' ? d.count : 0;
const defaultValueAccessor = (d: { value?: unknown }) =>
typeof d.value === 'number' ? d.value : 0;

export default function ViolinPlot<Datum extends object>({
left = 0,
top = 0,
className,
data,
width = 10,
count = (d?: { count?: number }) => d?.count || 0,
value = (d?: { value?: number }) => d?.value || 0,
count = defaultCountAccessor,
value = defaultValueAccessor,
valueScale,
horizontal,
children,
...restProps
}: ViolinPlotProps<ScaleInput> &
Omit<React.SVGProps<SVGPathElement>, keyof ViolinPlotProps<ScaleInput>>) {
}: ViolinPlotProps<Datum> & Omit<React.SVGProps<SVGPathElement>, keyof ViolinPlotProps<Datum>>) {
const center = (horizontal ? top : left) + width / 2;
const binCounts = data.map(bin => count(bin));
const widthScale = scaleLinear<number>({
Expand All @@ -44,12 +48,12 @@ export default function ViolinPlot<ScaleInput extends object = BinDatum>({
let path = '';

if (horizontal) {
const topCurve = line<ScaleInput>()
const topCurve = line<Datum>()
.x(d => valueScale(value(d)))
.y(d => center - widthScale(count(d)))
.curve(curveCardinal);

const bottomCurve = line<ScaleInput>()
const bottomCurve = line<Datum>()
.x(d => valueScale(value(d)))
.y(d => center + widthScale(count(d)))
.curve(curveCardinal);
Expand All @@ -58,12 +62,12 @@ export default function ViolinPlot<ScaleInput extends object = BinDatum>({
const bottomCurvePath = bottomCurve([...data].reverse()) || '';
path = `${topCurvePath} ${bottomCurvePath.replace('M', 'L')} Z`;
} else {
const rightCurve = line<ScaleInput>()
const rightCurve = line<Datum>()
.x(d => center + widthScale(count(d)))
.y(d => valueScale(value(d)))
.curve(curveCardinal);

const leftCurve = line<ScaleInput>()
const leftCurve = line<Datum>()
.x(d => center - widthScale(count(d)))
.y(d => valueScale(value(d)))
.curve(curveCardinal);
Expand All @@ -72,6 +76,7 @@ export default function ViolinPlot<ScaleInput extends object = BinDatum>({
const leftCurvePath = leftCurve([...data].reverse()) || '';
path = `${rightCurvePath} ${leftCurvePath.replace('M', 'L')} Z`;
}
// eslint-disable-next-line react/jsx-no-useless-fragment
if (children) return <>{children({ path })}</>;
return <path className={cx('vx-violin', className)} d={path} {...restProps} />;
}
2 changes: 1 addition & 1 deletion packages/vx-stats/test/ViolinPlot.test.tsx
Expand Up @@ -6,7 +6,7 @@ import { ViolinPlot, computeStats } from '../src';
const data = [1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 1];
const { binData } = computeStats(data);

const valueScale = scaleLinear<number>({
const valueScale = scaleLinear({
range: [10, 0],
round: true,
domain: [0, 10],
Expand Down

0 comments on commit 0263b9b

Please sign in to comment.