Skip to content

Commit

Permalink
fix(scales): fix a TypeScript bug when creating log scales (#2001)
Browse files Browse the repository at this point in the history
* return a log scale object with 'type' field (helps ts to understand return value is a Scale)

* adjusted types for scale objects in @nivo/bar, @nivo/scatterplot, @nivo/marimekko, and @nivo/stream

* fine-tuning on @nivo/bar imports and types
  • Loading branch information
tkonopka committed May 17, 2022
1 parent c11fb3b commit 43af675
Show file tree
Hide file tree
Showing 17 changed files with 233 additions and 105 deletions.
54 changes: 42 additions & 12 deletions packages/bar/src/Bar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { Axes, Grid } from '@nivo/axes'
import { BarAnnotations } from './BarAnnotations'
import { BarDatum, BarLayer, BarLayerId, BarSvgProps, ComputedBarDatumWithValue } from './types'
import {
BarCustomLayerProps,
BarDatum,
BarLayer,
BarLayerId,
BarSvgProps,
ComputedBarDatumWithValue,
} from './types'
import { BarLegends } from './BarLegends'
import {
CartesianMarkers,
Expand Down Expand Up @@ -54,10 +61,10 @@ const InnerBar = <RawDatum extends BarDatum>({
layers = svgDefaultProps.layers as BarLayer<RawDatum>[],
barComponent = svgDefaultProps.barComponent,

enableLabel,
enableLabel = svgDefaultProps.enableLabel,
label,
labelSkipWidth,
labelSkipHeight,
labelSkipWidth = svgDefaultProps.labelSkipWidth,
labelSkipHeight = svgDefaultProps.labelSkipHeight,
labelTextColor,

markers = svgDefaultProps.markers,
Expand Down Expand Up @@ -287,8 +294,8 @@ const InnerBar = <RawDatum extends BarDatum>({
layerById.axes = (
<Axes
key="axes"
xScale={xScale as any}
yScale={yScale as any}
xScale={xScale}
yScale={yScale}
width={innerWidth}
height={innerHeight}
top={axisTop}
Expand Down Expand Up @@ -321,8 +328,8 @@ const InnerBar = <RawDatum extends BarDatum>({
key="grid"
width={innerWidth}
height={innerHeight}
xScale={enableGridX ? (xScale as any) : null}
yScale={enableGridY ? (yScale as any) : null}
xScale={enableGridX ? xScale : null}
yScale={enableGridY ? yScale : null}
xValues={gridXValues}
yValues={gridYValues}
/>
Expand Down Expand Up @@ -354,20 +361,43 @@ const InnerBar = <RawDatum extends BarDatum>({
)
}

// We use `any` here until we can figure out the best way to type xScale/yScale
const layerContext: any = useMemo(
const layerContext: BarCustomLayerProps<RawDatum> = useMemo(
() => ({
...commonProps,
margin,
width,
height,
innerWidth,
innerHeight,
bars,
legendData: legendsWithData,
enableLabel,
xScale,
yScale,
tooltip,
getTooltipLabel,
onClick,
onMouseEnter,
onMouseLeave,
}),
[
commonProps,
margin,
width,
height,
innerWidth,
innerHeight,
bars,
legendsWithData,
enableLabel,
xScale,
yScale,
}),
[commonProps, margin, innerWidth, innerHeight, width, height, bars, xScale, yScale]
tooltip,
getTooltipLabel,
onClick,
onMouseEnter,
onMouseLeave,
]
)

return (
Expand Down
63 changes: 36 additions & 27 deletions packages/bar/src/BarCanvas.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { BarCanvasLayer, BarCanvasProps, BarDatum, ComputedBarDatum } from './types'
import {
BarCanvasCustomLayerProps,
BarCanvasLayer,
BarCanvasProps,
BarDatum,
ComputedBarDatum,
} from './types'
import {
Container,
Margin,
Expand Down Expand Up @@ -130,10 +136,10 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
}
},

enableLabel,
enableLabel = canvasDefaultProps.enableLabel,
label,
labelSkipWidth,
labelSkipHeight,
labelSkipWidth = canvasDefaultProps.labelSkipWidth,
labelSkipHeight = canvasDefaultProps.labelSkipHeight,
labelTextColor,

colorBy,
Expand Down Expand Up @@ -231,48 +237,51 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
})

// We use `any` here until we can figure out the best way to type xScale/yScale
const layerContext: any = useMemo(
const layerContext: BarCanvasCustomLayerProps<RawDatum> = useMemo(
() => ({
borderRadius,
borderWidth,
enableLabel,
isInteractive,
isFocusable: false,
labelSkipWidth,
labelSkipHeight,
onClick,
onMouseEnter,
onMouseLeave,
getTooltipLabel,
tooltip,
margin,
innerWidth,
innerHeight,
width,
height,
innerWidth,
innerHeight,
bars,
legendData: legendsWithData,
enableLabel,
xScale,
yScale,
tooltip,
getTooltipLabel,
onClick,
onMouseEnter,
onMouseLeave,
}),
[
borderRadius,
borderWidth,
enableLabel,
getTooltipLabel,
height,
innerHeight,
innerWidth,
isInteractive,
labelSkipHeight,
labelSkipWidth,
labelSkipHeight,
margin,
onClick,
onMouseEnter,
onMouseLeave,
width,
height,
innerWidth,
innerHeight,
bars,
legendsWithData,
enableLabel,
xScale,
yScale,
tooltip,
width,
getTooltipLabel,
onClick,
onMouseEnter,
onMouseLeave,
]
)

Expand Down Expand Up @@ -301,7 +310,7 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
renderGridLinesToCanvas<string | number>(ctx, {
width,
height,
scale: xScale as any,
scale: xScale,
axis: 'x',
values: gridXValues,
})
Expand All @@ -311,16 +320,16 @@ const InnerBarCanvas = <RawDatum extends BarDatum>({
renderGridLinesToCanvas<string | number>(ctx, {
width,
height,
scale: yScale as any,
scale: yScale,
axis: 'y',
values: gridYValues,
})
}
}
} else if (layer === 'axes') {
renderAxesToCanvas(ctx, {
xScale: xScale as any,
yScale: yScale as any,
xScale: xScale,
yScale: yScale,
width: innerWidth,
height: innerHeight,
top: axisTop,
Expand Down
25 changes: 17 additions & 8 deletions packages/bar/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@nivo/core'
import { InheritedColorConfig, OrdinalColorScaleConfig } from '@nivo/colors'
import { LegendProps } from '@nivo/legends'
import { Scale, ScaleSpec, ScaleBandSpec } from '@nivo/scales'
import { AnyScale, ScaleSpec, ScaleBandSpec } from '@nivo/scales'
import { SpringValues } from '@react-spring/web'

export interface BarDatum {
Expand Down Expand Up @@ -97,7 +97,7 @@ export type ValueFormatter = (value: number) => string | number

export type BarLayerId = 'grid' | 'axes' | 'bars' | 'markers' | 'legends' | 'annotations'

export interface BarCustomLayerProps<RawDatum>
interface BarCustomLayerBaseProps<RawDatum>
extends Pick<
BarCommonProps<RawDatum>,
| 'borderRadius'
Expand All @@ -108,24 +108,33 @@ export interface BarCustomLayerProps<RawDatum>
| 'labelSkipWidth'
| 'tooltip'
>,
Dimensions,
BarHandlers<RawDatum, SVGRectElement> {
Dimensions {
bars: ComputedBarDatum<RawDatum>[]
legendData: BarsWithHidden<RawDatum>
legendData: [BarLegendProps, LegendData[]][]

margin: Margin
innerWidth: number
innerHeight: number

isFocusable: boolean

getTooltipLabel: (datum: ComputedDatum<RawDatum>) => string | number

xScale: Scale<any, any>
yScale: Scale<any, any>
xScale: AnyScale
yScale: AnyScale
}

export interface BarCustomLayerProps<RawDatum>
extends BarCustomLayerBaseProps<RawDatum>,
BarHandlers<RawDatum, SVGRectElement> {}

export interface BarCanvasCustomLayerProps<RawDatum>
extends BarCustomLayerBaseProps<RawDatum>,
BarHandlers<RawDatum, HTMLCanvasElement> {}

export type BarCanvasCustomLayer<RawDatum> = (
context: CanvasRenderingContext2D,
props: BarCustomLayerProps<RawDatum>
props: BarCanvasCustomLayerProps<RawDatum>
) => void
export type BarCustomLayer<RawDatum> = React.FC<BarCustomLayerProps<RawDatum>>

Expand Down
3 changes: 1 addition & 2 deletions packages/marimekko/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@
"@nivo/axes": "0.79.0",
"@nivo/colors": "0.79.1",
"@nivo/legends": "0.79.1",
"@nivo/scales": "0.79.0",
"@react-spring/web": "9.4.5",
"d3-scale": "^3.2.3",
"d3-shape": "^1.3.5",
"lodash": "^4.17.21"
},
"devDependencies": {
"@nivo/core": "0.79.0",
"@types/d3-scale": "^3.2.2",
"@types/d3-shape": "^2.0.0"
},
"peerDependencies": {
Expand Down
8 changes: 4 additions & 4 deletions packages/marimekko/src/Marimekko.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ const InnerMarimekko = <RawDatum,>({
layerById.grid = (
<Grid
key="grid"
xScale={enableGridX ? (xScale as any) : undefined}
yScale={enableGridY ? (yScale as any) : undefined}
xScale={enableGridX ? xScale : undefined}
yScale={enableGridY ? yScale : undefined}
width={innerWidth}
height={innerHeight}
xValues={gridXValues}
Expand All @@ -122,8 +122,8 @@ const InnerMarimekko = <RawDatum,>({
layerById.axes = (
<Axes
key="axes"
xScale={xScale as any}
yScale={yScale as any}
xScale={xScale}
yScale={yScale}
width={innerWidth}
height={innerHeight}
top={axisTop}
Expand Down
35 changes: 14 additions & 21 deletions packages/marimekko/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMemo } from 'react'
import { get } from 'lodash'
import { stack as d3Stack, Stack, Series } from 'd3-shape'
import { ScaleLinear, scaleLinear } from 'd3-scale'
import { useValueFormatter, useTheme } from '@nivo/core'
import { InheritedColorConfig, useInheritedColor, useOrdinalColorScale } from '@nivo/colors'
import { createLinearScale, ScaleLinear } from '@nivo/scales'
import {
NormalizedDatum,
ComputedDatum,
Expand Down Expand Up @@ -84,11 +84,11 @@ export const useDimensionsScale = (
layout: Layout
) =>
useMemo(() => {
if (layout === 'vertical') {
return scaleLinear().domain([max, min]).range([0, height])
}

return scaleLinear().domain([min, max]).range([0, width])
const scaleData = { all: [min, max], min, max }
const size = layout === 'vertical' ? height : width
const axis = layout === 'vertical' ? 'y' : 'x'
// here 'axis' determines whether the domain should be reversed or not
return createLinearScale({ type: 'linear', min, max }, scaleData, size, axis)
}, [min, max, width, height, layout])

export const useNormalizedData = <RawDatum>(
Expand Down Expand Up @@ -136,18 +136,11 @@ export const useThicknessScale = <RawDatum>({
}) =>
useMemo(() => {
const totalValue = data.reduce((acc, datum) => acc + datum.value, 0)

const thicknessScale = scaleLinear().domain([0, totalValue])

const scaleData = { all: [0, totalValue], min: 0, max: totalValue }
const totalPadding = 2 * outerPadding + (data.length - 1) * innerPadding

if (layout === 'vertical') {
thicknessScale.range([0, width - totalPadding])
} else {
thicknessScale.range([0, height - totalPadding])
}

return thicknessScale
const size = layout === 'vertical' ? width - totalPadding : height - totalPadding
// here 'axis' means that the scale will be going forward, i.e. not reversed
return createLinearScale({ type: 'linear' }, scaleData, size, 'x')
}, [data, width, height, layout])

export const useComputedData = <RawDatum>({
Expand All @@ -166,8 +159,8 @@ export const useComputedData = <RawDatum>({
stacked: Series<RawDatum, string>[]
dimensionIds: string[]
valueFormat: DataProps<RawDatum>['valueFormat']
thicknessScale: ScaleLinear<number, number>
dimensionsScale: ScaleLinear<number, number>
thicknessScale: ScaleLinear<number>
dimensionsScale: ScaleLinear<number>
colors: CommonProps<RawDatum>['colors']
layout: Layout
outerPadding: number
Expand Down Expand Up @@ -368,8 +361,8 @@ export const useLayerContext = <RawDatum>({
}: {
data: ComputedDatum<RawDatum>[]
bars: BarDatum<RawDatum>[]
thicknessScale: ScaleLinear<number, number>
dimensionsScale: ScaleLinear<number, number>
thicknessScale: ScaleLinear<number>
dimensionsScale: ScaleLinear<number>
}): CustomLayerProps<RawDatum> =>
useMemo(
() => ({
Expand Down

0 comments on commit 43af675

Please sign in to comment.