Skip to content

Commit

Permalink
feat(scale): add reverse operator
Browse files Browse the repository at this point in the history
  • Loading branch information
kristw committed Aug 15, 2020
1 parent e6b394d commit da5ab27
Show file tree
Hide file tree
Showing 18 changed files with 60 additions and 6 deletions.
26 changes: 26 additions & 0 deletions packages/vx-scale/src/operators/reverse.ts
@@ -0,0 +1,26 @@
import { DefaultThresholdInput, D3Scale } from '../types/Scale';
import { StringLike } from '../types/Base';
import { ScaleConfigWithoutType } from '../types/ScaleConfig';

export default function applyReverse<
Output,
DiscreteInput extends StringLike,
ThresholdInput extends DefaultThresholdInput
>(
scale: D3Scale<Output, DiscreteInput, ThresholdInput>,
config: ScaleConfigWithoutType<Output, DiscreteInput, ThresholdInput>,
) {
if (config.reverse) {
const reversedRange = scale
.range()
.slice()
.reverse();
if ('padding' in scale) {
// point and band scales
scale.range(reversedRange as [number, number]);
} else {
// the rest
scale.range(reversedRange as Output[]);
}
}
}
7 changes: 6 additions & 1 deletion packages/vx-scale/src/operators/scaleOperator.ts
Expand Up @@ -11,6 +11,7 @@ import exponent from './exponent';
import interpolate from './interpolate';
import nice from './nice';
import padding from './padding';
import reverse from './reverse';
import round from './round';
import unknown from './unknown';
import zero from './zero';
Expand All @@ -28,14 +29,17 @@ export const ALL_OPERATORS = [
'interpolate',
'round',

// set range then reverse
'range',
'reverse',

// Order does not matter for these operators
'align',
'base',
'clamp',
'constant',
'exponent',
'padding',
'range',
'unknown',
] as const;

Expand All @@ -55,6 +59,7 @@ const operators: Record<OperatorType, typeof domain> = {
exponent,
padding,
range,
reverse,
unknown,
};

Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/band.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updateBandScale = scaleOperator<'band'>(
'domain',
'range',
'reverse',
'align',
'padding',
'round',
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/linear.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updateLinearScale = scaleOperator<'linear'>(
'domain',
'range',
'reverse',
'clamp',
'interpolate',
'nice',
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/log.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updateLogScale = scaleOperator<'log'>(
'domain',
'range',
'reverse',
'base',
'clamp',
'interpolate',
Expand Down
2 changes: 1 addition & 1 deletion packages/vx-scale/src/scales/ordinal.ts
Expand Up @@ -3,7 +3,7 @@ import { DefaultOutput, StringLike } from '../types/Base';
import { PickScaleConfigWithoutType } from '../types/ScaleConfig';
import scaleOperator from '../operators/scaleOperator';

export const updateOrdinalScale = scaleOperator<'ordinal'>('domain', 'range', 'unknown');
export const updateOrdinalScale = scaleOperator<'ordinal'>('domain', 'range', 'reverse', 'unknown');

export default function createOrdinalScale<
DiscreteInput extends StringLike = StringLike,
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/point.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updatePointScale = scaleOperator<'point'>(
'domain',
'range',
'reverse',
'align',
'padding',
'round',
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/power.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updatePowScale = scaleOperator<'pow'>(
'domain',
'range',
'reverse',
'clamp',
'exponent',
'interpolate',
Expand Down
2 changes: 1 addition & 1 deletion packages/vx-scale/src/scales/quantile.ts
Expand Up @@ -3,7 +3,7 @@ import { DefaultOutput } from '../types/Base';
import { PickScaleConfigWithoutType } from '../types/ScaleConfig';
import scaleOperator from '../operators/scaleOperator';

export const updateQuantileScale = scaleOperator<'quantile'>('domain', 'range');
export const updateQuantileScale = scaleOperator<'quantile'>('domain', 'range', 'reverse');

export default function createQuantileScale<Output = DefaultOutput>(
config?: PickScaleConfigWithoutType<'quantile', Output>,
Expand Down
8 changes: 7 additions & 1 deletion packages/vx-scale/src/scales/quantize.ts
Expand Up @@ -3,7 +3,13 @@ import { DefaultOutput } from '../types/Base';
import { PickScaleConfigWithoutType } from '../types/ScaleConfig';
import scaleOperator from '../operators/scaleOperator';

export const updateQuantizeScale = scaleOperator<'quantize'>('domain', 'range', 'nice', 'zero');
export const updateQuantizeScale = scaleOperator<'quantize'>(
'domain',
'range',
'reverse',
'nice',
'zero',
);

export default function createQuantizeScale<Output = DefaultOutput>(
config?: PickScaleConfigWithoutType<'quantize', Output>,
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/squareRoot.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updateSqrtScale = scaleOperator<'sqrt'>(
'domain',
'range',
'reverse',
'clamp',
'interpolate',
'nice',
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/symlog.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updateSymlogScale = scaleOperator<'symlog'>(
'domain',
'range',
'reverse',
'clamp',
'constant',
'nice',
Expand Down
2 changes: 1 addition & 1 deletion packages/vx-scale/src/scales/threshold.ts
Expand Up @@ -4,7 +4,7 @@ import { PickScaleConfigWithoutType } from '../types/ScaleConfig';
import { DefaultThresholdInput } from '../types/Scale';
import scaleOperator from '../operators/scaleOperator';

export const updateThresholdScale = scaleOperator<'threshold'>('domain', 'range');
export const updateThresholdScale = scaleOperator<'threshold'>('domain', 'range', 'reverse');

export default function createThresholdScale<
ThresholdInput extends DefaultThresholdInput = DefaultThresholdInput,
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/time.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updateTimeScale = scaleOperator<'time'>(
'domain',
'range',
'reverse',
'clamp',
'interpolate',
'nice',
Expand Down
1 change: 1 addition & 0 deletions packages/vx-scale/src/scales/utc.ts
Expand Up @@ -6,6 +6,7 @@ import scaleOperator from '../operators/scaleOperator';
export const updateUtcScale = scaleOperator<'utc'>(
'domain',
'range',
'reverse',
'clamp',
'interpolate',
'nice',
Expand Down
2 changes: 1 addition & 1 deletion packages/vx-scale/src/types/ScaleConfig.ts
Expand Up @@ -17,7 +17,7 @@ export type ContinuousDomain = ContinuousInput[];
// and add `type` property as discriminant of union type.
type CreateScaleConfig<T, D, R, Fields extends keyof BaseScaleConfig<T, D, R> = 'type'> = Pick<
BaseScaleConfig<T, D, R>,
'type' | 'domain' | 'range' | Fields
'type' | 'domain' | 'range' | 'reverse' | Fields
>;

export type LinearScaleConfig<Output = DefaultOutput> = CreateScaleConfig<
Expand Down
4 changes: 4 additions & 0 deletions packages/vx-scale/test/scaleLinear.test.ts
Expand Up @@ -13,6 +13,10 @@ describe('scaleLinear()', () => {
const range = [1, 2];
expect(scaleLinear({ range: [1, 2] }).range()).toEqual(range);
});
it('set reverse', () => {
expect(scaleLinear({ reverse: true }).range()).toEqual([1, 0]);
expect(scaleLinear({ range: [1, 2], reverse: true }).range()).toEqual([2, 1]);
});
describe('set clamp', () => {
it('true', () => {
const scale = scaleLinear({ clamp: true });
Expand Down
4 changes: 4 additions & 0 deletions packages/vx-scale/test/scalePoint.test.ts
Expand Up @@ -13,6 +13,10 @@ describe('scalePoint', () => {
const scale = scalePoint({ range: [2, 3] });
expect(scale.range()).toEqual([2, 3]);
});
it('set reverse', () => {
expect(scalePoint({ reverse: true }).range()).toEqual([1, 0]);
expect(scalePoint({ range: [1, 2], reverse: true }).range()).toEqual([2, 1]);
});
it('set align', () => {
expect(scalePoint({ align: 0.5 }).align()).toEqual(0.5);
});
Expand Down

0 comments on commit da5ab27

Please sign in to comment.