Skip to content

Commit

Permalink
Merge c630c11 into c0eb0b2
Browse files Browse the repository at this point in the history
  • Loading branch information
williaster committed Oct 7, 2020
2 parents c0eb0b2 + c630c11 commit 58bcdcd
Show file tree
Hide file tree
Showing 15 changed files with 517 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { DataContext } from '@visx/xychart';
const patternId = 'xy-chart-pattern';

export default function CustomChartBackground() {
const { theme, margin, width, height } = useContext(DataContext);
const { theme, margin, width, height, innerWidth, innerHeight } = useContext(DataContext);

// early return values not available in context
if (width == null || height == null || margin == null || theme == null) return null;
Expand All @@ -24,8 +24,8 @@ export default function CustomChartBackground() {
<rect
x={margin.left}
y={margin.top}
width={width - margin.left - margin.right}
height={height - margin.top - margin.bottom}
width={innerWidth}
height={innerHeight}
fill={`url(#${patternId})`}
fillOpacity={0.3}
/>
Expand Down
54 changes: 48 additions & 6 deletions packages/visx-demo/src/sandboxes/visx-xychart/Example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const xScaleConfig = { type: 'band', paddingInner: 0.3 } as const;
const yScaleConfig = { type: 'linear' } as const;
const numTicks = 4;
const data = cityTemperature.slice(150, 225);
const getDate = (d: CityTemperature) => d.date; // new Date(d.date);
const getDate = (d: CityTemperature) => d.date;
const getSfTemperature = (d: CityTemperature) => Number(d['San Francisco']);
const getNyTemperature = (d: CityTemperature) => Number(d['New York']);

Expand All @@ -33,8 +33,14 @@ export default function Example({ height }: Props) {
renderBarSeries,
renderHorizontally,
renderLineSeries,
sharedTooltip,
showGridColumns,
showGridRows,
showHorizontalCrosshair,
showTooltip,
showVerticalCrosshair,
snapTooltipToDatumX,
snapTooltipToDatumY,
theme,
xAxisOrientation,
yAxisOrientation,
Expand All @@ -55,7 +61,7 @@ export default function Example({ height }: Props) {
/>
{renderBarSeries && (
<BarSeries
dataKey="ny"
dataKey="New York"
data={data}
xAccessor={renderHorizontally ? getNyTemperature : getDate}
yAccessor={renderHorizontally ? getDate : getNyTemperature}
Expand All @@ -64,10 +70,11 @@ export default function Example({ height }: Props) {
)}
{renderLineSeries && (
<LineSeries
dataKey="sf"
dataKey="San Francisco"
data={data}
xAccessor={renderHorizontally ? getSfTemperature : getDate}
yAccessor={renderHorizontally ? getDate : getSfTemperature}
horizontal={!renderHorizontally}
/>
)}
<AnimatedAxis
Expand All @@ -83,9 +90,44 @@ export default function Example({ height }: Props) {
numTicks={numTicks}
animationTrajectory={animationTrajectory}
/>
<Tooltip
renderTooltip={({ tooltipData }) => <pre>{JSON.stringify(tooltipData, null, 2)}</pre>}
/>
{showTooltip && (
<Tooltip<CityTemperature>
showHorizontalCrosshair={showHorizontalCrosshair}
showVerticalCrosshair={showVerticalCrosshair}
snapTooltipToDatumX={snapTooltipToDatumX}
snapTooltipToDatumY={snapTooltipToDatumY}
showDatumGlyph={snapTooltipToDatumX || snapTooltipToDatumY}
showSeriesGlyphs={sharedTooltip}
renderTooltip={({ tooltipData, colorScale }) => (
<>
{/** date */}
{tooltipData?.nearestDatum?.datum
? getDate(tooltipData?.nearestDatum?.datum)
: 'No date'}
<br />
<br />
{/** temperatures */}
{((sharedTooltip
? Object.keys(tooltipData?.datumByKey ?? {})
: [tooltipData?.nearestDatum?.key]
).filter(key => key) as string[]).map(key => (
<div key={key}>
<em
style={{
color: colorScale?.(key),
textDecoration:
tooltipData?.nearestDatum?.key === key ? 'underline' : undefined,
}}
>
{key}
</em>{' '}
{tooltipData?.datumByKey[key].datum[key as keyof CityTemperature]}° F
</div>
))}
</>
)}
/>
)}
</XYChart>
</DataProvider>
)}
Expand Down
75 changes: 75 additions & 0 deletions packages/visx-demo/src/sandboxes/visx-xychart/ExampleControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ type ProvidedProps = {
renderHorizontally: boolean;
renderBarSeries: boolean;
renderLineSeries: boolean;
sharedTooltip: boolean;
showGridColumns: boolean;
showGridRows: boolean;
showHorizontalCrosshair: boolean;
showTooltip: boolean;
showVerticalCrosshair: boolean;
snapTooltipToDatumX: boolean;
snapTooltipToDatumY: boolean;
theme: XYChartTheme;
xAxisOrientation: 'top' | 'bottom';
yAxisOrientation: 'left' | 'right';
Expand All @@ -28,6 +34,12 @@ export default function ExampleControls({ children }: ControlsProps) {
const [xAxisOrientation, setXAxisOrientation] = useState<'top' | 'bottom'>('bottom');
const [yAxisOrientation, setYAxisOrientation] = useState<'left' | 'right'>('right');
const [renderHorizontally, setRenderHorizontally] = useState(false);
const [showTooltip, setShowTooltip] = useState(true);
const [showVerticalCrosshair, setShowVerticalCrosshair] = useState(true);
const [showHorizontalCrosshair, setShowHorizontalCrosshair] = useState(false);
const [snapTooltipToDatumX, setSnapTooltipToDatumX] = useState(true);
const [snapTooltipToDatumY, setSnapTooltipToDatumY] = useState(true);
const [sharedTooltip, setSharedTooltip] = useState(true);
const [renderBarSeries, setRenderBarSeries] = useState(true);
const [renderLineSeries, setRenderLineSeries] = useState(true);

Expand All @@ -38,8 +50,14 @@ export default function ExampleControls({ children }: ControlsProps) {
renderBarSeries,
renderHorizontally,
renderLineSeries,
sharedTooltip,
showGridColumns,
showGridRows,
showHorizontalCrosshair,
showTooltip,
showVerticalCrosshair,
snapTooltipToDatumX,
snapTooltipToDatumY,
theme,
xAxisOrientation,
yAxisOrientation,
Expand Down Expand Up @@ -205,6 +223,63 @@ export default function ExampleControls({ children }: ControlsProps) {
from max
</label>
</div>
{/** tooltip */}
<div>
<strong>tooltip</strong>
<label>
<input
type="checkbox"
onChange={() => setShowTooltip(!showTooltip)}
checked={showTooltip}
/>{' '}
show tooltip
</label>
<label>
<input
type="checkbox"
disabled={!showTooltip}
onChange={() => setSnapTooltipToDatumX(!snapTooltipToDatumX)}
checked={showTooltip && snapTooltipToDatumX}
/>{' '}
snap tooltip to datum x
</label>
<label>
<input
type="checkbox"
disabled={!showTooltip}
onChange={() => setSnapTooltipToDatumY(!snapTooltipToDatumY)}
checked={showTooltip && snapTooltipToDatumY}
/>{' '}
snap tooltip to datum y
</label>
<label>
<input
type="checkbox"
disabled={!showTooltip}
onChange={() => setShowVerticalCrosshair(!showVerticalCrosshair)}
checked={showTooltip && showVerticalCrosshair}
/>{' '}
vertical crosshair
</label>
<label>
<input
type="checkbox"
disabled={!showTooltip}
onChange={() => setShowHorizontalCrosshair(!showHorizontalCrosshair)}
checked={showTooltip && showHorizontalCrosshair}
/>{' '}
horizontal crosshair
</label>
<label>
<input
type="checkbox"
disabled={!showTooltip}
onChange={() => setSharedTooltip(!sharedTooltip)}
checked={showTooltip && sharedTooltip}
/>{' '}
shared tooltip
</label>
</div>
{/** series */}
<div>
<strong>series</strong>
Expand Down
44 changes: 19 additions & 25 deletions packages/visx-tooltip/src/hooks/useTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,57 +13,51 @@ type UseTooltipState<TooltipData> = Pick<
UseTooltipParams<TooltipData>,
'tooltipOpen' | 'tooltipLeft' | 'tooltipTop' | 'tooltipData'
>;
type ShowTooltipArgs<TooltipData> = Omit<UseTooltipState<TooltipData>, 'tooltipOpen'>;
type UpdateTooltipArgs<TooltipData> = UseTooltipState<TooltipData>;
type ValueOrFunc<T> = T | ((t: T) => T);
type ShowTooltipArgs<TooltipData> = ValueOrFunc<Omit<UseTooltipState<TooltipData>, 'tooltipOpen'>>;
type UpdateTooltipArgs<TooltipData> = ValueOrFunc<UseTooltipState<TooltipData>>;

export default function useTooltip<TooltipData = {}>(
/** Optional initial TooltipState. */
initialTooltipState?: Partial<UseTooltipParams<TooltipData>>,
): UseTooltipParams<TooltipData> {
const [tooltipState, setTooltipState] = useState<UseTooltipState<TooltipData>>({
tooltipOpen: false,
...initialTooltipState,
});

const updateTooltip = useCallback(
({ tooltipOpen, tooltipLeft, tooltipTop, tooltipData }: UpdateTooltipArgs<TooltipData>) =>
setTooltipState(prevState => ({
...prevState,
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
})),
[],
);

const showTooltip = useCallback(
({ tooltipLeft, tooltipTop, tooltipData }: ShowTooltipArgs<TooltipData>) =>
updateTooltip({
tooltipOpen: true,
tooltipLeft,
tooltipTop,
tooltipData,
}),
[updateTooltip],
(showArgs: ShowTooltipArgs<TooltipData>) =>
setTooltipState(
typeof showArgs === 'function'
? ({ tooltipOpen, ...show }) => ({ ...showArgs(show), tooltipOpen: true })
: {
tooltipOpen: true,
tooltipLeft: showArgs.tooltipLeft,
tooltipTop: showArgs.tooltipTop,
tooltipData: showArgs.tooltipData,
},
),
[setTooltipState],
);

const hideTooltip = useCallback(
() =>
updateTooltip({
setTooltipState({
tooltipOpen: false,
tooltipLeft: undefined,
tooltipTop: undefined,
tooltipData: undefined,
}),
[updateTooltip],
[setTooltipState],
);

return {
tooltipOpen: tooltipState.tooltipOpen,
tooltipLeft: tooltipState.tooltipLeft,
tooltipTop: tooltipState.tooltipTop,
tooltipData: tooltipState.tooltipData,
updateTooltip,
updateTooltip: setTooltipState,
showTooltip,
hideTooltip,
};
Expand Down
16 changes: 12 additions & 4 deletions packages/visx-tooltip/src/hooks/useTooltipInPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import Portal from '../Portal';
import Tooltip, { TooltipProps } from '../tooltips/Tooltip';
import TooltipWithBounds from '../tooltips/TooltipWithBounds';

export type TooltipInPortalProps = TooltipProps & Pick<UseTooltipPortalOptions, 'detectBounds'>;

export type UseTooltipInPortal = {
containerRef: (element: HTMLElement | SVGElement | null) => void;
containerBounds: RectReadOnly;
TooltipInPortal: React.FC<TooltipProps>;
TooltipInPortal: React.FC<TooltipInPortalProps>;
};

export type UseTooltipPortalOptions = {
Expand All @@ -27,13 +29,19 @@ export type UseTooltipPortalOptions = {
* Handles conversion of container coordinates to page coordinates using the container bounds.
*/
export default function useTooltipInPortal({
detectBounds = true,
detectBounds: detectBoundsOption = true,
...useMeasureOptions
}: UseTooltipPortalOptions | undefined = {}): UseTooltipInPortal {
const [containerRef, containerBounds] = useMeasure(useMeasureOptions);

const TooltipInPortal = useMemo(
() => ({ left: containerLeft = 0, top: containerTop = 0, ...tooltipProps }: TooltipProps) => {
() => ({
left: containerLeft = 0,
top: containerTop = 0,
detectBounds: detectBoundsProp, // allow override at component-level
...tooltipProps
}: TooltipInPortalProps) => {
const detectBounds = detectBoundsProp == null ? detectBoundsOption : detectBoundsProp;
const TooltipComponent = detectBounds ? TooltipWithBounds : Tooltip;
// convert container coordinates to page coordinates
const portalLeft = containerLeft + (containerBounds.left || 0) + window.scrollX;
Expand All @@ -45,7 +53,7 @@ export default function useTooltipInPortal({
</Portal>
);
},
[detectBounds, containerBounds.left, containerBounds.top],
[detectBoundsOption, containerBounds.left, containerBounds.top],
);

return {
Expand Down
2 changes: 2 additions & 0 deletions packages/visx-xychart/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
},
"dependencies": {
"@types/classnames": "^2.2.9",
"@types/lodash": "^4.14.146",
"@types/react": "*",
"lodash": "^4.17.10",
"@visx/axis": "1.0.0",
"@visx/event": "1.0.0",
"@visx/grid": "1.0.0",
Expand Down

0 comments on commit 58bcdcd

Please sign in to comment.