Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(xychart): include zero in scale domains by default #1008

Merged
merged 6 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/visx-scale/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { default as inferScaleType } from './utils/inferScaleType';
export { default as coerceNumber } from './utils/coerceNumber';
export { default as getTicks } from './utils/getTicks';
export { default as toString } from './utils/toString';
export { default as scaleCanBeZeroed } from './utils/scaleCanBeZeroed';

// export types
export * from './types/Base';
Expand Down
26 changes: 26 additions & 0 deletions packages/visx-scale/src/utils/scaleCanBeZeroed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { DefaultOutput, StringLike } from '../types/Base';
import { DefaultThresholdInput } from '../types/Scale';
import {
LinearScaleConfig,
PowScaleConfig,
QuantizeScaleConfig,
ScaleConfig,
ScaleType,
SqrtScaleConfig,
SymlogScaleConfig,
} from '../types/ScaleConfig';

type ZeroableScaleConfigs<Output = DefaultOutput> =
| LinearScaleConfig<Output>
| PowScaleConfig<Output>
| SqrtScaleConfig<Output>
| SymlogScaleConfig<Output>
| QuantizeScaleConfig<Output>;

const zeroableScaleTypes = new Set<ScaleType>(['linear', 'pow', 'quantize', 'sqrt', 'symlog']);

export default function scaleCanBeZeroed<Output = DefaultOutput>(
scaleConfig: ScaleConfig<Output>,
): scaleConfig is ZeroableScaleConfigs<Output> {
return zeroableScaleTypes.has(scaleConfig.type);
}
2 changes: 1 addition & 1 deletion packages/visx-scale/test/utils/getTicks.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import getTicks from '../../src/utils/getTicks';
import { scaleLinear, scaleBand } from '../../lib';
import { scaleLinear, scaleBand } from '../../src';

describe('getTicks(scale)', () => {
it('linear', () => {
Expand Down
24 changes: 24 additions & 0 deletions packages/visx-scale/test/utils/scaleCanBeZeroed.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import scaleCanBeZeroed from '../../src/utils/scaleCanBeZeroed';

describe('scaleCanBeZeroed(scaleConfig)', () => {
it('returns true for zero-able scales', () => {
const zeroAble = ['linear', 'pow', 'quantize', 'sqrt', 'symlog'] as const;
expect.assertions(zeroAble.length);
zeroAble.forEach(type => expect(scaleCanBeZeroed({ type })).toBe(true));
});
it('returns false for non-zero-able scales', () => {
const notZeroAble = [
'log',
'radial',
'time',
'utc',
'quantile',
'threshold',
'ordinal',
'point',
'band',
] as const;
expect.assertions(notZeroAble.length);
notZeroAble.forEach(type => expect(scaleCanBeZeroed({ type })).toBe(false));
});
});
4 changes: 4 additions & 0 deletions packages/visx-xychart/src/components/XYChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export type XYChartProps<
xScale?: DataProviderProps<XScaleConfig, YScaleConfig>['xScale'];
/** If DataContext is not available, XYChart will wrap itself in a DataProvider and set this as the yScale config. */
yScale?: DataProviderProps<XScaleConfig, YScaleConfig>['yScale'];
/* If DataContext is not available, XYChart will wrap itself in a DataProvider and set this as horizontal. Determines whether Series will be plotted horizontally (e.g., horizontal bars). By default this will try to be inferred based on scale types. */
horizontal?: boolean | 'auto';
/** Callback invoked for onPointerMove events for the nearest Datum to the PointerEvent _for each Series with pointerEvents={true}_. */
onPointerMove?: ({
datum,
Expand Down Expand Up @@ -84,6 +86,7 @@ export default function XYChart<
captureEvents = true,
children,
height,
horizontal,
margin = DEFAULT_MARGIN,
onPointerMove,
onPointerOut,
Expand Down Expand Up @@ -128,6 +131,7 @@ export default function XYChart<
yScale={yScale}
theme={theme}
initialDimensions={{ width, height, margin }}
horizontal={horizontal}
>
<XYChart {...props} />
</DataProvider>
Expand Down
40 changes: 27 additions & 13 deletions packages/visx-xychart/src/hooks/useScales.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AxisScaleOutput, AxisScale } from '@visx/axis';
import { ScaleConfig, createScale, ScaleInput } from '@visx/scale';
import { ScaleConfig, createScale, ScaleInput, scaleCanBeZeroed } from '@visx/scale';
import { extent as d3Extent } from 'd3-array';
import { useMemo } from 'react';
import DataRegistry from '../classes/DataRegistry';
Expand All @@ -11,11 +11,11 @@ export default function useScales<
YScale extends AxisScale,
Datum extends object
>({
xScaleConfig,
yScaleConfig,
dataRegistry,
xRange,
xScaleConfig,
yRange,
yScaleConfig,
}: {
xScaleConfig: ScaleConfig<AxisScaleOutput>;
yScaleConfig: ScaleConfig<AxisScaleOutput>;
Expand All @@ -41,11 +41,18 @@ export default function useScales<

const xDomain = isDiscreteScale(xScaleConfig) ? xValues : d3Extent(xValues);

let xScale = createScale({
range: [xMin, xMax],
domain: xDomain as [number, number],
...xScaleConfig,
}) as XScale;
let xScale = (scaleCanBeZeroed(xScaleConfig)
? createScale({
range: [xMin, xMax],
domain: xDomain as [XScaleInput, XScaleInput],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noting that the domain was updated from number => ScaleInput (leftover from my comment here)

zero: true,
...xScaleConfig,
})
: createScale({
range: [xMin, xMax],
domain: xDomain as [XScaleInput, XScaleInput],
...xScaleConfig,
})) as XScale;

// apply any scale updates from the registy
registryEntries.forEach(entry => {
Expand All @@ -69,11 +76,18 @@ export default function useScales<

const yDomain = isDiscreteScale(yScaleConfig) ? yValues : d3Extent(yValues);

let yScale = createScale({
range: [yMin, yMax],
domain: yDomain as [number, number],
...yScaleConfig,
}) as YScale;
let yScale = (scaleCanBeZeroed(yScaleConfig)
? createScale({
range: [yMin, yMax],
domain: yDomain as [YScaleInput, YScaleInput],
zero: true,
...yScaleConfig,
})
: createScale({
range: [yMin, yMax],
domain: yDomain as [YScaleInput, YScaleInput],
...yScaleConfig,
})) as YScale;

// apply any scale updates from the registy
registryEntries.forEach(entry => {
Expand Down
2 changes: 1 addition & 1 deletion packages/visx-xychart/src/providers/DataProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type DataProviderProps<
yScale: YScaleConfig;
/* Any React children. */
children: React.ReactNode;
/* Determines whether data will be plotted horizontally. @TODO elaborate */
/* Determines whether Series will be plotted horizontally (e.g., horizontal bars). By default this will try to be inferred based on scale types. */
horizontal?: boolean | 'auto';
};

Expand Down