Skip to content

Commit

Permalink
feat(bar): add support for valueFormat
Browse files Browse the repository at this point in the history
  • Loading branch information
wyze committed Jun 28, 2021
1 parent 82262a2 commit e142895
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 21 deletions.
8 changes: 5 additions & 3 deletions packages/bar/src/Bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
useMotionConfig,
usePropertyAccessor,
useTheme,
useValueFormatter,
} from '@nivo/core'
import { Fragment, ReactNode, createElement, useCallback, useMemo, useState } from 'react'
import { generateGroupedBars, generateStackedBars, getLegendData } from './compute'
Expand Down Expand Up @@ -82,8 +83,9 @@ const InnerBar = <RawDatum extends BarDatum>({
legendLabel,
tooltipLabel = svgDefaultProps.tooltipLabel,

valueFormat,

isInteractive = svgDefaultProps.isInteractive,
tooltipFormat,
tooltip = svgDefaultProps.tooltip,
onClick,
onMouseEnter,
Expand All @@ -110,6 +112,7 @@ const InnerBar = <RawDatum extends BarDatum>({
partialMargin
)

const formatValue = useValueFormatter(valueFormat)
const getBorderColor = useInheritedColor<ComputedBarDatum<RawDatum>>(borderColor, theme)
const getColor = useOrdinalColorScale(colors, colorBy)
const getIndex = usePropertyAccessor(indexBy)
Expand All @@ -134,6 +137,7 @@ const InnerBar = <RawDatum extends BarDatum>({
valueScale,
indexScale,
hiddenIds,
formatValue,
})

const legendData = useMemo(
Expand Down Expand Up @@ -198,7 +202,6 @@ const InnerBar = <RawDatum extends BarDatum>({
onMouseEnter,
onMouseLeave,
getTooltipLabel,
tooltipFormat,
tooltip,
}),
[
Expand All @@ -213,7 +216,6 @@ const InnerBar = <RawDatum extends BarDatum>({
onMouseEnter,
onMouseLeave,
tooltip,
tooltipFormat,
]
)

Expand Down
12 changes: 4 additions & 8 deletions packages/bar/src/BarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export const BarItem = <RawDatum extends BarDatum>({

getTooltipLabel,
tooltip,
tooltipFormat,
}: BarItemProps<RawDatum>) => {
const theme = useTheme()
const { showTooltipFromEvent, hideTooltip } = useTooltip()
Expand All @@ -40,20 +39,17 @@ export const BarItem = <RawDatum extends BarDatum>({
const handleTooltip = useCallback(
(event: React.MouseEvent<SVGRectElement>) =>
showTooltipFromEvent(
createElement(tooltip, { ...data, color, getTooltipLabel, tooltipFormat }),
createElement(tooltip, { ...data, color, getTooltipLabel }),
event
),
[color, data, getTooltipLabel, showTooltipFromEvent, tooltip, tooltipFormat]
[color, data, getTooltipLabel, showTooltipFromEvent, tooltip]
)
const handleMouseEnter = useCallback(
(event: React.MouseEvent<SVGRectElement>) => {
onMouseEnter?.(data, event)
showTooltipFromEvent(
createElement(tooltip, { ...data, color, getTooltipLabel, tooltipFormat }),
event
)
showTooltipFromEvent(createElement(tooltip, { ...data, color, getTooltipLabel }), event)
},
[color, data, getTooltipLabel, onMouseEnter, showTooltipFromEvent, tooltip, tooltipFormat]
[color, data, getTooltipLabel, onMouseEnter, showTooltipFromEvent, tooltip]
)
const handleMouseLeave = useCallback(
(event: React.MouseEvent<SVGRectElement>) => {
Expand Down
4 changes: 1 addition & 3 deletions packages/bar/src/BarTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import { BasicTooltip } from '@nivo/tooltip'
export const BarTooltip = <RawDatum,>({
color,
getTooltipLabel,
tooltipFormat,
...data
}: BarTooltipProps<RawDatum>) => {
return (
<BasicTooltip
id={getTooltipLabel(data)}
value={data.value}
value={data.formattedValue}
enableChip={true}
color={color}
format={tooltipFormat}
/>
)
}
6 changes: 6 additions & 0 deletions packages/bar/src/compute/grouped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { computeScale } from '@nivo/scales'

type Params<RawDatum, XScaleInput, YScaleInput> = {
data: RawDatum[]
formatValue: (value: number) => string
getColor: OrdinalColorScale<ComputedDatum<RawDatum>>
getIndex: (datum: RawDatum) => string
innerPadding: number
Expand All @@ -30,6 +31,7 @@ const zeroIfNotFinite = (value: number) => (isFinite(value) ? value : 0)
const generateVerticalGroupedBars = <RawDatum extends Record<string, unknown>>(
{
data,
formatValue,
getIndex,
keys,
getColor,
Expand Down Expand Up @@ -57,6 +59,7 @@ const generateVerticalGroupedBars = <RawDatum extends Record<string, unknown>>(
const barData = {
id: key,
value: rawValue === null ? rawValue : value,
formattedValue: formatValue(value),
index,
indexValue,
data: cleanedData[index],
Expand Down Expand Up @@ -84,6 +87,7 @@ const generateVerticalGroupedBars = <RawDatum extends Record<string, unknown>>(
const generateHorizontalGroupedBars = <RawDatum extends Record<string, unknown>>(
{
data,
formatValue,
getIndex,
keys,
getColor,
Expand Down Expand Up @@ -111,6 +115,7 @@ const generateHorizontalGroupedBars = <RawDatum extends Record<string, unknown>>
const barData = {
id: key,
value: rawValue === null ? rawValue : value,
formattedValue: formatValue(value),
index,
indexValue,
data: cleanedData[index],
Expand Down Expand Up @@ -163,6 +168,7 @@ export const generateGroupedBars = <RawDatum extends BarDatum>({
| 'valueScale'
| 'width'
> & {
formatValue: (value: number) => string
getColor: OrdinalColorScale<ComputedDatum<RawDatum>>
getIndex: (datum: RawDatum) => string
hiddenIds: string[]
Expand Down
6 changes: 6 additions & 0 deletions packages/bar/src/compute/stacked.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { coerceValue, filterNullValues, getIndexScale, normalizeData } from './c
type StackDatum<RawDatum> = SeriesPoint<RawDatum>

type Params<RawDatum, XScaleInput, YScaleInput> = {
formatValue: (value: number) => string
getColor: OrdinalColorScale<ComputedDatum<RawDatum>>
getIndex: (datum: RawDatum) => string
innerPadding: number
Expand All @@ -26,6 +27,7 @@ const filterZerosIfLog = (array: number[], type: string) =>
*/
const generateVerticalStackedBars = <RawDatum extends Record<string, unknown>>(
{
formatValue,
getIndex,
getColor,
innerPadding,
Expand All @@ -51,6 +53,7 @@ const generateVerticalStackedBars = <RawDatum extends Record<string, unknown>>(
const barData = {
id: stackedDataItem.key,
value: rawValue === null ? rawValue : value,
formattedValue: formatValue(value),
index: i,
indexValue: index,
data: filterNullValues(d.data),
Expand All @@ -77,6 +80,7 @@ const generateVerticalStackedBars = <RawDatum extends Record<string, unknown>>(
*/
const generateHorizontalStackedBars = <RawDatum extends Record<string, unknown>>(
{
formatValue,
getIndex,
getColor,
innerPadding,
Expand All @@ -102,6 +106,7 @@ const generateHorizontalStackedBars = <RawDatum extends Record<string, unknown>>
const barData = {
id: stackedDataItem.key,
value: rawValue === null ? rawValue : value,
formattedValue: formatValue(value),
index: i,
indexValue: index,
data: filterNullValues(d.data),
Expand Down Expand Up @@ -154,6 +159,7 @@ export const generateStackedBars = <RawDatum extends BarDatum>({
| 'valueScale'
| 'width'
> & {
formatValue: (value: number) => string
getColor: OrdinalColorScale<ComputedDatum<RawDatum>>
getIndex: (datum: RawDatum) => string
hiddenIds: string[]
Expand Down
2 changes: 1 addition & 1 deletion packages/bar/src/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const defaultProps = {
barComponent: BarItem,

enableLabel: true,
label: 'value',
label: 'formattedValue',
labelSkipWidth: 0,
labelSkipHeight: 0,
labelLinkColor: 'theme',
Expand Down
8 changes: 4 additions & 4 deletions packages/bar/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type BarDatumWithColor = BarDatum & {
export type ComputedDatum<RawDatum> = {
id: string | number
value: number | null
formattedValue: string
index: number
indexValue: string | number
data: Exclude<RawDatum, null | undefined | false | '' | 0>
Expand Down Expand Up @@ -100,7 +101,6 @@ export interface BarCustomLayerProps<RawDatum>
| 'labelSkipHeight'
| 'labelSkipWidth'
| 'tooltip'
| 'tooltipFormat'
>,
BarHandlers<RawDatum, SVGRectElement> {
bars: ComputedBarDatum<RawDatum>[]
Expand All @@ -119,7 +119,7 @@ export type BarLayer<RawDatum> = BarLayerId | BarCustomLayer<RawDatum>
export interface BarItemProps<RawDatum>
extends Pick<
BarCommonProps<RawDatum>,
'borderRadius' | 'borderWidth' | 'isInteractive' | 'tooltip' | 'tooltipFormat'
'borderRadius' | 'borderWidth' | 'isInteractive' | 'tooltip'
>,
ComputedBarDatum<RawDatum>,
BarHandlers<RawDatum, SVGRectElement> {
Expand All @@ -146,7 +146,6 @@ export interface BarItemProps<RawDatum>
export interface BarTooltipProps<RawDatum> extends ComputedDatum<RawDatum> {
color: string
getTooltipLabel: (datum: ComputedDatum<RawDatum>) => string | number
tooltipFormat: BarCommonProps<RawDatum>['tooltipFormat']
value: number
}

Expand Down Expand Up @@ -199,7 +198,8 @@ export type BarCommonProps<RawDatum> = {
isInteractive: boolean

tooltip: React.FC<BarTooltipProps<RawDatum>>
tooltipFormat?: ValueFormat<string | number | Date>

valueFormat?: ValueFormat<number>

legendLabel?: PropertyAccessor<LegendLabelDatum<RawDatum>, string>
tooltipLabel: PropertyAccessor<ComputedDatum<RawDatum>, string>
Expand Down
8 changes: 6 additions & 2 deletions packages/bar/stories/bar.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const divergingCommonProps = {
maxValue: 100,
enableGridX: true,
enableGridY: false,
label: d => Math.abs(d.value),
valueFormat: value => Math.abs(value),
labelTextColor: 'inherit:darker(1.2)',
axisTop: {
tickSize: 0,
Expand Down Expand Up @@ -136,7 +136,7 @@ stories.add('diverging stacked', () => (
keys={['gained <= 100$', 'gained > 100$', 'lost <= 100$', 'lost > 100$']}
padding={0.4}
colors={['#97e3d5', '#61cdbb', '#f47560', '#e25c3b']}
labelFormat={v => `${v}%`}
valueFormat={v => `${v}%`}
/>
))

Expand Down Expand Up @@ -438,3 +438,7 @@ stories.add('custom legend labels', () => (
]}
/>
))

stories.add('with formatted value', () => (
<Bar {...commonProps} valueFormat={value => `${value}`.split('').join('.')} />
))
6 changes: 6 additions & 0 deletions packages/bar/tests/Bar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ it(`should generate grouped bars correctly when keys are mismatched`, () => {
index: 0,
indexValue: 'one',
value: 10,
formattedValue: '10',
})
expect(bars.at(0).prop('x')).toEqual(24)
expect(bars.at(0).prop('y')).toEqual(0)
Expand All @@ -277,6 +278,7 @@ it(`should generate grouped bars correctly when keys are mismatched`, () => {
index: 1,
indexValue: 'two',
value: 9,
formattedValue: '9',
})
expect(bars.at(1).prop('x')).toEqual(333.3333333333333)
expect(bars.at(1).prop('y')).toEqual(30)
Expand All @@ -289,6 +291,7 @@ it(`should generate grouped bars correctly when keys are mismatched`, () => {
index: 0,
indexValue: 'one',
value: 3,
formattedValue: '3',
})
expect(bars.at(2).prop('x')).toEqual(166.66666666666666)
expect(bars.at(2).prop('y')).toEqual(210)
Expand Down Expand Up @@ -320,6 +323,7 @@ it(`should generate stacked bars correctly when keys are mismatched`, () => {
index: 0,
indexValue: 'one',
value: 10,
formattedValue: '10',
})
expect(bars.at(0).prop('x')).toEqual(24)
expect(bars.at(0).prop('y')).toEqual(69)
Expand All @@ -332,6 +336,7 @@ it(`should generate stacked bars correctly when keys are mismatched`, () => {
index: 1,
indexValue: 'two',
value: 9,
formattedValue: '9',
})
expect(bars.at(1).prop('x')).toEqual(262)
expect(bars.at(1).prop('y')).toEqual(92)
Expand All @@ -344,6 +349,7 @@ it(`should generate stacked bars correctly when keys are mismatched`, () => {
index: 0,
indexValue: 'one',
value: 3,
formattedValue: '3',
})
expect(bars.at(2).prop('x')).toEqual(24)
expect(bars.at(2).prop('y')).toEqual(0)
Expand Down

0 comments on commit e142895

Please sign in to comment.