Skip to content
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

fix(vx-brush): Fix initialBrushPosition #667

Merged
merged 7 commits into from
May 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 47 additions & 58 deletions packages/vx-brush/src/BaseBrush.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Drag, { HandlerArgs as DragArgs } from '@vx/drag/lib/Drag';
import BrushHandle from './BrushHandle';
import BrushCorner from './BrushCorner';
import BrushSelection from './BrushSelection';
import { MarginShape, Point, BrushShape, BrushStartEnd, ResizeTriggerAreas } from './types';
import { MarginShape, Point, BrushShape, ResizeTriggerAreas, PartialBrushStartEnd } from './types';

const BRUSH_OVERLAY_STYLES = { cursor: 'crosshair' };

Expand All @@ -16,7 +16,7 @@ type MouseHandlerEvent =

export type BaseBrushProps = {
brushDirection?: 'horizontal' | 'vertical' | 'both';
initialBrushPosition?: BrushStartEnd;
initialBrushPosition?: PartialBrushStartEnd;
width: number;
height: number;
left: number;
Expand Down Expand Up @@ -49,18 +49,19 @@ export type UpdateBrush =
export default class BaseBrush extends React.Component<BaseBrushProps, BaseBrushState> {
private constructor(props: BaseBrushProps) {
super(props);
const { initialBrushPosition } = props;
const extent = initialBrushPosition
? this.getExtent(initialBrushPosition.start, initialBrushPosition.end)
: {
x0: -1,
x1: -1,
y0: -1,
y1: -1,
};
this.state = {
start: { x: 0, y: 0 },
end: { x: 0, y: 0 },
...this.props.initialBrushPosition,
extent: this.props.initialBrushPosition
? this.getExtent(this.props.initialBrushPosition.start, this.props.initialBrushPosition.end)
: {
x0: -1,
x1: -1,
y0: -1,
y1: -1,
},
start: { x: Math.max(0, extent.x0), y: Math.max(0, extent.y0) },
end: { x: Math.max(0, extent.x1), y: Math.max(0, extent.y1) },
extent,
bounds: {
x0: 0,
x1: this.props.width,
Expand Down Expand Up @@ -98,14 +99,6 @@ export default class BaseBrush extends React.Component<BaseBrushProps, BaseBrush
initialBrushPosition: null,
};

componentDidMount() {
window.addEventListener('mouseup', this.handleDragEnd);
}

componentWillUnmount() {
window.removeEventListener('mouseup', this.handleDragEnd);
}

componentDidUpdate(prevProps: BaseBrushProps) {
if (this.props.width !== prevProps.width || this.props.height !== prevProps.height) {
// eslint-disable-next-line react/no-did-update-set-state
Expand All @@ -120,12 +113,12 @@ export default class BaseBrush extends React.Component<BaseBrushProps, BaseBrush
}
}

getExtent = (start: Point, end: Point) => {
getExtent = (start: Partial<Point>, end: Partial<Point>) => {
const { brushDirection, width, height } = this.props;
const x0 = brushDirection === 'vertical' ? 0 : Math.min(start.x, end.x);
const x1 = brushDirection === 'vertical' ? width : Math.max(start.x, end.x);
const y0 = brushDirection === 'horizontal' ? 0 : Math.min(start.y, end.y);
const y1 = brushDirection === 'horizontal' ? height : Math.max(start.y, end.y);
const x0 = brushDirection === 'vertical' ? 0 : Math.min(start.x || 0, end.x || 0);
const x1 = brushDirection === 'vertical' ? width : Math.max(start.x || 0, end.x || 0);
const y0 = brushDirection === 'horizontal' ? 0 : Math.min(start.y || 0, end.y || 0);
const y1 = brushDirection === 'horizontal' ? height : Math.max(start.y || 0, end.y || 0);

return {
x0,
Expand Down Expand Up @@ -163,19 +156,18 @@ export default class BaseBrush extends React.Component<BaseBrushProps, BaseBrush
}));
};

handleDragMove = (draw: DragArgs) => {
handleDragMove = (drag: DragArgs) => {
const { left, top, inheritedMargin } = this.props;
if (!draw.isDragging) return;
if (!drag.isDragging) return;
const marginLeft = (inheritedMargin && inheritedMargin.left) || 0;
const marginTop = (inheritedMargin && inheritedMargin.top) || 0;
const end = {
x: (draw.x || 0) + draw.dx - left - marginLeft,
y: (draw.y || 0) + draw.dy - top - marginTop,
x: (drag.x || 0) + drag.dx - left - marginLeft,
y: (drag.y || 0) + drag.dy - top - marginTop,
};
this.updateBrush((prevBrush: BaseBrushState) => {
const { start } = prevBrush;
const extent = this.getExtent(start, end);

return {
...prevBrush,
end,
Expand All @@ -185,36 +177,33 @@ export default class BaseBrush extends React.Component<BaseBrushProps, BaseBrush
};

handleDragEnd = () => {
const { isBrushing } = this.state;
if (isBrushing) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noting to document:
by the time this function is called state has been updated isBrushing usually has been updated to false and so this feature didn't work as intended.

const { onBrushEnd, resetOnEnd } = this.props;
this.updateBrush((prevBrush: BaseBrushState) => {
const { extent } = prevBrush;
const newState = {
...prevBrush,
start: {
x: extent.x0,
y: extent.y0,
},
end: {
x: extent.x1,
y: extent.y1,
},
isBrushing: false,
activeHandle: null,
};
const { onBrushEnd, resetOnEnd } = this.props;
this.updateBrush((prevBrush: BaseBrushState) => {
const { extent } = prevBrush;
const newState = {
...prevBrush,
start: {
x: extent.x0,
y: extent.y0,
},
end: {
x: extent.x1,
y: extent.y1,
},
isBrushing: false,
activeHandle: null,
};

if (onBrushEnd) {
onBrushEnd(newState);
}
if (onBrushEnd) {
onBrushEnd(newState);
}

if (resetOnEnd) {
this.reset();
}
if (resetOnEnd) {
this.reset();
}

return newState;
});
}
return newState;
});
};

getBrushWidth = () => {
Expand Down
11 changes: 9 additions & 2 deletions packages/vx-brush/src/Brush.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React from 'react';
import BaseBrush, { BaseBrushProps, BaseBrushState } from './BaseBrush';
import { Bounds, BrushStartEnd, MarginShape, Point, ResizeTriggerAreas, Scale } from './types';
import {
Bounds,
PartialBrushStartEnd,
MarginShape,
Point,
ResizeTriggerAreas,
Scale,
} from './types';
import { scaleInvert, getDomainFromExtent } from './utils';

const SAFE_PIXEL = 2;
Expand All @@ -20,7 +27,7 @@ export type BrushProps = {
onClick: BaseBrushProps['onClick'];
margin: MarginShape;
brushDirection: 'vertical' | 'horizontal' | 'both';
initialBrushPosition?: BrushStartEnd;
initialBrushPosition?: PartialBrushStartEnd;
resizeTriggerAreas: ResizeTriggerAreas[];
brushRegion: 'xAxis' | 'yAxis' | 'chart';
yAxisOrientation: 'left' | 'right';
Expand Down
5 changes: 5 additions & 0 deletions packages/vx-brush/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export interface BrushStartEnd {
end: Point;
}

export interface PartialBrushStartEnd {
start: Partial<Point>;
end: Partial<Point>;
}

export type ResizeTriggerAreas =
| 'left'
| 'right'
Expand Down
2 changes: 1 addition & 1 deletion packages/vx-demo/src/components/Gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const items = [
const tiltOptions = { max: 8, scale: 1 };
const detailsHeight = 76;

export default function() {
export default function Gallery() {
return (
<div>
<div className="gallery">
Expand Down
8 changes: 7 additions & 1 deletion packages/vx-demo/src/components/tiles/Brush.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { ShowProvidedProps, MarginShape } from '../../types';
/**
* Initialize some variables
*/
const stock = appleStock.slice(1200);
const stock = appleStock.slice(1000);
const axisColor = '#fff';
const axisBottomTickLabelProps = {
textAnchor: 'middle' as const,
Expand Down Expand Up @@ -155,6 +155,11 @@ function BrushChart({
nice: true,
});

const initialBrushPosition = {
start: { x: brushDateScale(getDate(stock[50])) },
end: { x: brushDateScale(getDate(stock[100])) },
};

return (
<div>
<svg width={width} height={height}>
Expand Down Expand Up @@ -203,6 +208,7 @@ function BrushChart({
handleSize={8}
resizeTriggerAreas={['left', 'right', 'bottomRight']}
brushDirection="horizontal"
initialBrushPosition={initialBrushPosition}
onChange={onBrushChange}
onClick={() => setFilteredStock(stock)}
selectedBoxStyle={{
Expand Down
4 changes: 2 additions & 2 deletions packages/vx-tooltip/test/Tooltip.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('<Tooltip />', () => {
const wrapper = shallow(<Tooltip unstyled>Hello</Tooltip>);
const styles = wrapper.props().style;
Object.keys(defaultStyles).forEach(key => {
expect(styles[key]).toBe(undefined);
expect(styles[key]).toBeUndefined();
});
});

Expand All @@ -34,7 +34,7 @@ describe('<Tooltip />', () => {
boxShadow: '0 2px 3px rgba(133,133,133,0.5)',
lineHeight: '2em',
};
const wrapper = shallow(<Tooltip style={newStyles}></Tooltip>);
const wrapper = shallow(<Tooltip style={newStyles} />);
const styles = wrapper.props().style;
Object.entries(newStyles).forEach(([key, value]) => {
expect(styles[key]).toBe(value);
Expand Down