-
Notifications
You must be signed in to change notification settings - Fork 121
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(xy): add null bars to geometry indexing #1226
feat(xy): add null bars to geometry indexing #1226
Conversation
const absMinHeight = Math.abs(minBarHeight); | ||
|
||
// safeguard against null y values | ||
let height = isNil(y0Scaled) || isNil(y) ? 0 : y0Scaled - y; |
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.
Minor: this could be substituted with height = y0Scaled - y || 0
; using isNil
doesn't add a lot of documentational value as the types already reveal they can be undefined or null. Still, it's a subjective call.
Also, as the row below sets y
to zero if either is nil (in row 86) maybe reordering helps simplify a bit (eg. setting y and y0Scaled to 0 before; in which case the subtraction will result zero)
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 can't replace it with height = y0Scaled - y || 0
because y0Scaled and y can be null and TS rise a warning/error here
@@ -125,7 +124,7 @@ export function renderBars( | |||
const width = clamp(seriesStyle.rect.widthPixel ?? xScale.bandwidth, minPixelWidth, maxPixelWidth); | |||
const x = xScaled + xScale.bandwidth * orderIndex + xScale.bandwidth / 2 - width / 2; | |||
|
|||
const originalY1Value = stackMode === StackMode.Percentage ? y1 - (y0 ?? 0) : initialY1; | |||
const originalY1Value = stackMode === StackMode.Percentage ? (isNil(y1) ? null : y1 - (y0 ?? 0)) : initialY1; |
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.
May be tangential to this PR, but GeometryValue
has x
and y
as any
, and maybe it could be tightened up. If it's not possible to do it globally, it could start by perhaps mapping to NaN
instead of null
so that eventually, y
in GeometryValue
is always a number
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.
Yes agree, we can push this into a separate PR I think
if (y1 !== null && initialY1 !== null && filled?.y1 === undefined) { | ||
barGeometries.push(barGeometry); | ||
} |
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.
Should indexedGeometryMap.set(barGeometry)
still be called unconditionally? If that were conditionalized, this predicate could go to the top of the forEach
.
Btw. this function is almost 200 lines long with a bunch of let
and co-dependent mutations and non-obvious type narrowings to number
, and I don't comprehend it enough to do a good review, would be great to refactor before, or as part of feature work otherwise it'll be more and more complicated
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.
indexedGeometryMap.set(barGeometry)
needs to be called unconditionally to take the advantage of the current picking logic.
Definitely a refactoring here is required!
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.
Changes LGTM. This is a really clean solution! 🎉
export function getShowNullValues(settings: SettingsSpec): TooltipProps['showNullValues'] { | ||
const { tooltip } = settings; |
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.
nit
export function getShowNullValues(settings: SettingsSpec): TooltipProps['showNullValues'] { | |
const { tooltip } = settings; | |
export function getShowNullValues({ tooltip }: SettingsSpec): TooltipProps['showNullValues'] { |
} | ||
|
||
const absMinHeight = Math.abs(minBarHeight); | ||
let height = y0Scaled - y; | ||
if (absMinHeight !== undefined && height !== 0 && Math.abs(height) < absMinHeight) { |
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.
absMinHeight
is always a number
, so this part of the condition can be removed.
Also, using a sign rather than retaining the if(height < 0)
means that the height !== 0
check is easy to make redundant:
const heightDelta = absMinHeight - Math.abs(height);
if (heightDelta > 0) {
const heightSign = Math.sign(height);
height = heightSign * absMinHeight;
y -= heightSign * heightDelta;
}
@@ -81,12 +77,15 @@ export function renderBars( | |||
y0Scaled = y0 === null ? yScale.scale(0) : yScale.scale(y0); |
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.
The let
/ if
imperative construct for y0Scaled
may be replaced with a single assignment:
// prettier-ignore
const y0Scaled = yScale.type === ScaleType.Log
? (y0 ?? 0) > 0 ? yScale.scale(y0) : yScale.range[yScale.isInverted ? 1 : 0]
: yScale.scale(y0 || 0);
It's not super pretty, there may be ways to more deeply simplify though
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.
LGTM, my comments are only about how the render function could be simplified or at least made easier to understand
Thanks @monfera I will consider the simplification in a subsequent PR |
# [33.0.0](v32.0.0...v33.0.0) (2021-07-14) ### Features * **xy:** add null bars to geometry indexing ([#1226](#1226)) ([20b81a9](20b81a9)), closes [#950](#950) * **xy:** hide labels that protrude the bar geometry ([#1233](#1233)) ([be1fb3d](be1fb3d)), closes [#1234](#1234) ### BREAKING CHANGES * **xy:** an API change is introduced: `hideClippedValue` is removed in favor of `overflowConstraints?: Array<LabelOverflowConstraint>;`. The array can contain one or multiple overflow constraints enumerated as `LabelOverflowConstraint`
🎉 This PR is included in version 33.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
The
showNullValues
prop is now available in theSettings.tooltip
to allow displayingnull
Y values in the tooltip.This should goes hand in hand with the right tooltip formatter to catch and correctly format these
null
values.Details
This PR replace: #1206 reducing the scope to only show
null
values, keeping the current typings intact.The PR consist of removing the null values checks in the geometry generation phase, moving every geometry (visible or not) within the geometry index map (the map used by the tooltip to detect the cursor-geometry collisions). The geometries with null values are not pushed within the arrays of renderable geometries.
Issues
close #950
Checklist
packages/charts/src/index.ts
(and stories only import from../src
except for test data & storybook)