-
Notifications
You must be signed in to change notification settings - Fork 715
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
feat: update vx/axis types #773
Merged
Merged
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
59bd755
refactor: replace types in vx/axis
kristw b31fdcc
refactor: simplify specific axes
kristw ef0f86f
refactor: separate renderer and axis
kristw 665f8c2
correct typing of the functions
kristw 4555456
reduce generics
kristw e1033dd
fix: types in test
kristw d6472a0
test: update unit tests
kristw 79f9f79
fix: helper function types
kristw 4fc90e9
feat: add AnyD3Scale type
kristw 04fd1c4
fix: types
kristw d679ea3
test: fix unit tests
kristw 593d71c
refactor: point creation
kristw 451e9c0
fix: revert inferscaletype
kristw 39bf2ff
fix: create point
kristw 4b1cb11
fix: demo
kristw 8d6729e
refactor: add ScaleInput type
kristw 11e27a2
refactor: orientation
kristw 82422d7
fix: examples
kristw 234cd61
refactor: move util files
kristw 6817e40
fix: demo
kristw 73e2174
test: add unit tests
kristw 881d6e2
refactor: rename labelTransform to getLabelTransform
kristw e62f03d
feat: add align to getTickPosition
kristw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,216 +1,86 @@ | ||
import React from 'react'; | ||
import cx from 'classnames'; | ||
import { Line } from '@vx/shape'; | ||
import { Point } from '@vx/point'; | ||
import { Group } from '@vx/group'; | ||
import { Text } from '@vx/text'; | ||
import center from '../utils/center'; | ||
import getLabelTransform from '../utils/labelTransform'; | ||
import ORIENT from '../constants/orientation'; | ||
import toString from '../utils/toString'; | ||
import toNumberOrUndefined from '../utils/toNumberOrUndefined'; | ||
import { SharedAxisProps, AxisOrientation } from '../types'; | ||
import { getTicks, coerceNumber } from '@vx/scale'; | ||
import { SharedAxisProps, AxisScale } from '../types'; | ||
import AxisRenderer from './AxisRenderer'; | ||
import getTickPosition from '../utils/getTickPosition'; | ||
import getTickFormatter from '../utils/getTickFormatter'; | ||
import createPoint from '../utils/createPoint'; | ||
import Orientation from '../constants/orientation'; | ||
|
||
export type AxisProps<ScaleInput> = SharedAxisProps<ScaleInput> & { | ||
orientation?: AxisOrientation; | ||
export type AxisProps<Scale extends AxisScale> = SharedAxisProps<Scale> & { | ||
orientation?: Orientation; | ||
}; | ||
|
||
export default function Axis<ScaleInput>({ | ||
children, | ||
export default function Axis<Scale extends AxisScale>({ | ||
children = AxisRenderer, | ||
axisClassName, | ||
axisLineClassName, | ||
hideAxisLine = false, | ||
hideTicks = false, | ||
hideZero = false, | ||
label = '', | ||
labelClassName, | ||
labelOffset = 14, | ||
labelProps = { | ||
textAnchor: 'middle', | ||
fontFamily: 'Arial', | ||
fontSize: 10, | ||
fill: '#222', | ||
}, | ||
left = 0, | ||
numTicks = 10, | ||
orientation = ORIENT.bottom, | ||
orientation = Orientation.bottom, | ||
rangePadding = 0, | ||
scale, | ||
stroke = '#222', | ||
strokeWidth = 1, | ||
strokeDasharray, | ||
tickClassName, | ||
tickFormat, | ||
tickLabelProps = (/** tickValue, index */) => ({ | ||
textAnchor: 'middle', | ||
fontFamily: 'Arial', | ||
fontSize: 10, | ||
fill: '#222', | ||
}), | ||
tickLength = 8, | ||
tickStroke = '#222', | ||
tickTransform, | ||
tickValues, | ||
tickComponent, | ||
top = 0, | ||
}: AxisProps<ScaleInput>) { | ||
const values = | ||
tickValues || | ||
(scale.ticks | ||
? scale.ticks(numTicks) | ||
: scale | ||
.domain() | ||
.filter( | ||
(_, index, arr) => | ||
numTicks == null || | ||
arr.length <= numTicks || | ||
index % Math.round((arr.length - 1) / numTicks) === 0, | ||
)); | ||
const format = tickFormat || (scale.tickFormat ? scale.tickFormat() : toString); | ||
...restProps | ||
}: AxisProps<Scale>) { | ||
const format = tickFormat ?? getTickFormatter(scale); | ||
|
||
const range = scale.range(); | ||
const range0 = Number(range[0]) + 0.5 - rangePadding; | ||
const range1 = Number(range[range.length - 1]) + 0.5 + rangePadding; | ||
const isLeft = orientation === Orientation.left; | ||
const isTop = orientation === Orientation.top; | ||
const horizontal = isTop || orientation === Orientation.bottom; | ||
|
||
const isLeft = orientation === ORIENT.left; | ||
const isTop = orientation === ORIENT.top; | ||
const axisIsHorizontal = isTop || orientation === ORIENT.bottom; | ||
const tickPosition = getTickPosition(scale); | ||
const tickSign = isLeft || isTop ? -1 : 1; | ||
|
||
const position = center(scale.copy()); | ||
|
||
const axisFromPoint = new Point({ | ||
x: axisIsHorizontal ? range0 : 0, | ||
y: axisIsHorizontal ? 0 : range0, | ||
}); | ||
const axisToPoint = new Point({ | ||
x: axisIsHorizontal ? range1 : 0, | ||
y: axisIsHorizontal ? 0 : range1, | ||
}); | ||
const range = scale.range(); | ||
const axisFromPoint = createPoint({ x: Number(range[0]) + 0.5 - rangePadding, y: 0 }, horizontal); | ||
const axisToPoint = createPoint( | ||
{ x: Number(range[range.length - 1]) + 0.5 + rangePadding, y: 0 }, | ||
horizontal, | ||
); | ||
|
||
let tickLabelFontSize = 10; // track the max tick label size to compute label offset | ||
const ticks = (tickValues ?? getTicks(scale, numTicks)) | ||
.map((value, index) => ({ value, index })) | ||
.filter(({ value }) => !hideZero || (value !== 0 && value !== '0')) | ||
.map(({ value, index }) => { | ||
const scaledValue = coerceNumber(tickPosition(value)); | ||
|
||
if (children) { | ||
return ( | ||
<Group className={cx('vx-axis', axisClassName)} top={top} left={left}> | ||
{children({ | ||
axisFromPoint, | ||
axisToPoint, | ||
horizontal: axisIsHorizontal, | ||
tickSign, | ||
numTicks, | ||
label, | ||
rangePadding, | ||
tickLength, | ||
tickFormat: format, | ||
tickPosition: position, | ||
ticks: values.map((value, index) => { | ||
const scaledValue = toNumberOrUndefined(position(value)); | ||
const from = new Point({ | ||
x: axisIsHorizontal ? scaledValue : 0, | ||
y: axisIsHorizontal ? 0 : scaledValue, | ||
}); | ||
const to = new Point({ | ||
x: axisIsHorizontal ? scaledValue : tickSign * tickLength, | ||
y: axisIsHorizontal ? tickLength * tickSign : scaledValue, | ||
}); | ||
return { | ||
value, | ||
index, | ||
from, | ||
to, | ||
formattedValue: format(value, index), | ||
}; | ||
}), | ||
})} | ||
</Group> | ||
); | ||
} | ||
return { | ||
value, | ||
index, | ||
from: createPoint({ x: scaledValue, y: 0 }, horizontal), | ||
to: createPoint({ x: scaledValue, y: tickLength * tickSign }, horizontal), | ||
formattedValue: format(value, index), | ||
}; | ||
}); | ||
|
||
return ( | ||
<Group className={cx('vx-axis', axisClassName)} top={top} left={left}> | ||
{values.map((val, index) => { | ||
if ( | ||
hideZero && | ||
((typeof val === 'number' && val === 0) || (typeof val === 'string' && val === '0')) | ||
) { | ||
return null; | ||
} | ||
const scaledValue = toNumberOrUndefined(position(val)); | ||
const tickFromPoint = new Point({ | ||
x: axisIsHorizontal ? scaledValue : 0, | ||
y: axisIsHorizontal ? 0 : scaledValue, | ||
}); | ||
const tickToPoint = new Point({ | ||
x: axisIsHorizontal ? scaledValue : tickSign * tickLength, | ||
y: axisIsHorizontal ? tickLength * tickSign : scaledValue, | ||
}); | ||
|
||
const tickLabelPropsObj = tickLabelProps(val, index); | ||
tickLabelFontSize = Math.max( | ||
tickLabelFontSize, | ||
(typeof tickLabelPropsObj.fontSize === 'number' && tickLabelPropsObj.fontSize) || 0, | ||
); | ||
|
||
const tickYCoord = tickToPoint.y + (axisIsHorizontal && !isTop ? tickLabelFontSize : 0); | ||
const formattedValue = format(val, index); | ||
return ( | ||
<Group | ||
key={`vx-tick-${val}-${index}`} | ||
className={cx('vx-axis-tick', tickClassName)} | ||
transform={tickTransform} | ||
> | ||
{!hideTicks && ( | ||
<Line | ||
from={tickFromPoint} | ||
to={tickToPoint} | ||
stroke={tickStroke} | ||
strokeLinecap="square" | ||
/> | ||
)} | ||
{tickComponent ? ( | ||
tickComponent({ | ||
...tickLabelPropsObj, | ||
x: tickToPoint.x, | ||
y: tickYCoord, | ||
formattedValue, | ||
}) | ||
) : ( | ||
<Text x={tickToPoint.x} y={tickYCoord} {...tickLabelPropsObj}> | ||
{formattedValue} | ||
</Text> | ||
)} | ||
</Group> | ||
); | ||
{children({ | ||
...restProps, | ||
axisFromPoint, | ||
axisToPoint, | ||
hideAxisLine, | ||
hideTicks, | ||
hideZero, | ||
horizontal, | ||
numTicks, | ||
orientation, | ||
rangePadding, | ||
scale, | ||
tickFormat: format, | ||
tickLength, | ||
tickPosition, | ||
tickSign, | ||
ticks, | ||
})} | ||
|
||
{!hideAxisLine && ( | ||
<Line | ||
className={cx('vx-axis-line', axisLineClassName)} | ||
from={axisFromPoint} | ||
to={axisToPoint} | ||
stroke={stroke} | ||
strokeWidth={strokeWidth} | ||
strokeDasharray={strokeDasharray} | ||
/> | ||
)} | ||
|
||
{label && ( | ||
<Text | ||
className={cx('vx-axis-label', labelClassName)} | ||
{...getLabelTransform({ | ||
labelOffset, | ||
labelProps, | ||
orientation, | ||
range, | ||
tickLabelFontSize, | ||
tickLength, | ||
})} | ||
{...labelProps} | ||
> | ||
{label} | ||
</Text> | ||
)} | ||
</Group> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,12 @@ | ||
import React from 'react'; | ||
import cx from 'classnames'; | ||
import Axis from './Axis'; | ||
import ORIENT from '../constants/orientation'; | ||
import { SharedAxisProps } from '../types'; | ||
import Orientation from '../constants/orientation'; | ||
import { SharedAxisProps, AxisScale } from '../types'; | ||
|
||
export type AxisBottomProps<ScaleInput> = SharedAxisProps<ScaleInput>; | ||
|
||
export default function AxisBottom<ScaleInput>({ | ||
children, | ||
export default function AxisBottom<Scale extends AxisScale>({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. only destructure fields that are modified or used. |
||
axisClassName, | ||
axisLineClassName, | ||
hideAxisLine, | ||
hideTicks, | ||
hideZero, | ||
label, | ||
labelClassName, | ||
labelOffset = 8, | ||
labelProps, | ||
left, | ||
numTicks, | ||
rangePadding, | ||
scale, | ||
stroke, | ||
strokeWidth, | ||
strokeDasharray, | ||
tickClassName, | ||
tickFormat, | ||
tickLabelProps = (/** tickValue, index */) => ({ | ||
dy: '0.25em', | ||
fill: '#222', | ||
|
@@ -34,41 +15,16 @@ export default function AxisBottom<ScaleInput>({ | |
textAnchor: 'middle', | ||
}), | ||
tickLength = 8, | ||
tickStroke, | ||
tickTransform, | ||
tickValues, | ||
tickComponent, | ||
top, | ||
}: AxisBottomProps<ScaleInput>) { | ||
...restProps | ||
}: SharedAxisProps<Scale>) { | ||
return ( | ||
<Axis | ||
axisClassName={cx('vx-axis-bottom', axisClassName)} | ||
axisLineClassName={axisLineClassName} | ||
hideAxisLine={hideAxisLine} | ||
hideTicks={hideTicks} | ||
hideZero={hideZero} | ||
label={label} | ||
labelClassName={labelClassName} | ||
labelOffset={labelOffset} | ||
labelProps={labelProps} | ||
left={left} | ||
numTicks={numTicks} | ||
orientation={ORIENT.bottom} | ||
rangePadding={rangePadding} | ||
scale={scale} | ||
stroke={stroke} | ||
strokeWidth={strokeWidth} | ||
strokeDasharray={strokeDasharray} | ||
tickClassName={tickClassName} | ||
tickFormat={tickFormat} | ||
orientation={Orientation.bottom} | ||
tickLabelProps={tickLabelProps} | ||
tickLength={tickLength} | ||
tickStroke={tickStroke} | ||
tickTransform={tickTransform} | ||
tickValues={tickValues} | ||
tickComponent={tickComponent} | ||
top={top} | ||
children={children} | ||
{...restProps} | ||
/> | ||
); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I extracted the logic for flipping
x
andy
into util functioncreatePoint({x, y}, horizontal)
.