Skip to content

Commit

Permalink
Merge c8149e8 into e5adfc1
Browse files Browse the repository at this point in the history
  • Loading branch information
williaster committed Nov 18, 2020
2 parents e5adfc1 + c8149e8 commit f1df125
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 42 deletions.
80 changes: 45 additions & 35 deletions packages/visx-annotation/src/components/EditableAnnotation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export type EditableAnnotationProps = Pick<AnnotationContextType, 'x' | 'y' | 'd
height: number;
/** Annotation children (Subject, Label, Connector) */
children: React.ReactNode;
/** Whether the Label position (dx, dy) is editable. */
canEditLabel?: boolean;
/** Whether the Subject position (x, y) is editable. */
canEditSubject?: boolean;
/** Optional circle props to set on the subject drag handle. */
subjectDragHandleProps?: React.SVGProps<SVGCircleElement>;
/** Optional circle props to set on the label drag handle. */
Expand Down Expand Up @@ -40,18 +44,20 @@ const defaultDragHandleProps = {
};

export default function EditableAnnotation({
x: subjectX = 0,
y: subjectY = 0,
canEditLabel = true,
canEditSubject = true,
children,
dx: labelDx = 0,
dy: labelDy = 0,
children,
width,
height,
subjectDragHandleProps,
labelDragHandleProps,
onDragStart,
onDragMove,
onDragEnd,
onDragMove,
onDragStart,
subjectDragHandleProps,
width,
x: subjectX = 0,
y: subjectY = 0,
}: EditableAnnotationProps) {
// chicken before the egg, we need these to reference drag state
// in drag callbacks which are defined before useDrag() state is available
Expand Down Expand Up @@ -142,20 +148,22 @@ export default function EditableAnnotation({
fill="transparent"
/>
)}
<circle
cx={subjectX}
cy={subjectY}
transform={`translate(${subjectDrag.dx},${subjectDrag.dy})`}
onMouseMove={subjectDrag.dragMove}
onMouseUp={subjectDrag.dragEnd}
onMouseDown={subjectDrag.dragStart}
onTouchStart={subjectDrag.dragStart}
onTouchMove={subjectDrag.dragMove}
onTouchEnd={subjectDrag.dragEnd}
cursor={subjectDrag.isDragging ? 'grabbing' : 'grab'}
{...defaultDragHandleProps}
{...subjectDragHandleProps}
/>
{canEditSubject && (
<circle
cx={subjectX}
cy={subjectY}
transform={`translate(${subjectDrag.dx},${subjectDrag.dy})`}
onMouseMove={subjectDrag.dragMove}
onMouseUp={subjectDrag.dragEnd}
onMouseDown={subjectDrag.dragStart}
onTouchStart={subjectDrag.dragStart}
onTouchMove={subjectDrag.dragMove}
onTouchEnd={subjectDrag.dragEnd}
cursor={subjectDrag.isDragging ? 'grabbing' : 'grab'}
{...defaultDragHandleProps}
{...subjectDragHandleProps}
/>
)}
{labelDrag.isDragging && (
<rect
width={width}
Expand All @@ -165,20 +173,22 @@ export default function EditableAnnotation({
fill="transparent"
/>
)}
<circle
cx={subjectX + subjectDrag.dx + labelDx}
cy={subjectY + subjectDrag.dy + labelDy}
transform={`translate(${labelDrag.dx},${labelDrag.dy})`}
onMouseMove={labelDrag.dragMove}
onMouseUp={labelDrag.dragEnd}
onMouseDown={labelDrag.dragStart}
onTouchStart={labelDrag.dragStart}
onTouchMove={labelDrag.dragMove}
onTouchEnd={labelDrag.dragEnd}
cursor={labelDrag.isDragging ? 'grabbing' : 'grab'}
{...defaultDragHandleProps}
{...labelDragHandleProps}
/>
{canEditLabel && (
<circle
cx={subjectX + subjectDrag.dx + labelDx}
cy={subjectY + subjectDrag.dy + labelDy}
transform={`translate(${labelDrag.dx},${labelDrag.dy})`}
onMouseMove={labelDrag.dragMove}
onMouseUp={labelDrag.dragEnd}
onMouseDown={labelDrag.dragStart}
onTouchStart={labelDrag.dragStart}
onTouchMove={labelDrag.dragMove}
onTouchEnd={labelDrag.dragEnd}
cursor={labelDrag.isDragging ? 'grabbing' : 'grab'}
{...defaultDragHandleProps}
{...labelDragHandleProps}
/>
)}
</>
);
}
9 changes: 7 additions & 2 deletions packages/visx-annotation/test/EditableAnnotation.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import { shallow } from 'enzyme';
import { Annotation, EditableAnnotation } from '../src';
import { EditableAnnotationProps } from '../lib/components/EditableAnnotation';

describe('<EditableAnnotation />', () => {
function setup() {
function setup(props?: Partial<EditableAnnotationProps>) {
return shallow(
<EditableAnnotation width={100} height={100}>
<EditableAnnotation width={100} height={100} {...props}>
<div />
</EditableAnnotation>,
);
Expand All @@ -16,6 +17,10 @@ describe('<EditableAnnotation />', () => {
it('should render two resize handles', () => {
expect(setup().find('circle')).toHaveLength(2);
});
it('should render one resize handle if canEditLabel or canEditSubject are false', () => {
expect(setup({ canEditLabel: false }).find('circle')).toHaveLength(1);
expect(setup({ canEditSubject: false }).find('circle')).toHaveLength(1);
});
it('should render an Annotation', () => {
expect(setup().find(Annotation)).toHaveLength(1);
});
Expand Down
4 changes: 4 additions & 0 deletions packages/visx-demo/src/sandboxes/visx-annotation/Example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export default function Example({ width, height, compact = false }: AnnotationPr
approxTooltipHeight,
connectorType,
data,
editLabelPosition,
editSubjectPosition,
getDate,
getStockValue,
horizontalAnchor,
Expand Down Expand Up @@ -51,6 +53,8 @@ export default function Example({ width, height, compact = false }: AnnotationPr
y={annotationPosition.y}
dx={annotationPosition.dx}
dy={annotationPosition.dy}
canEditLabel={editLabelPosition}
canEditSubject={editSubjectPosition}
onDragEnd={({ event, ...nextPosition }) => {
// snap Annotation to the nearest data point
const nearestDatum = findNearestDatum({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type ProvidedProps = {
approxTooltipHeight: number;
connectorType: 'line' | 'elbow';
data: AppleStock[];
editLabelPosition: boolean;
editSubjectPosition: boolean;
getDate: (d: AppleStock) => number;
getStockValue: (d: AppleStock) => number;
horizontalAnchor?: 'left' | 'middle' | 'right';
Expand Down Expand Up @@ -62,7 +64,8 @@ export default function ExampleControls({
[height],
);

const [editAnnotation, setEditAnnotation] = useState(false);
const [editLabelPosition, setEditLabelPosition] = useState(false);
const [editSubjectPosition, setEditSubjectPosition] = useState(false);
const [title, setTitle] = useState('Title');
const [subtitle, setSubtitle] = useState(
compact ? 'Subtitle' : 'Subtitle with deets and deets and deets and deets',
Expand All @@ -87,11 +90,14 @@ export default function ExampleControls({
return (
<>
{children({
AnnotationComponent: editAnnotation ? EditableAnnotation : Annotation,
AnnotationComponent:
editLabelPosition || editSubjectPosition ? EditableAnnotation : Annotation,
annotationPosition,
approxTooltipHeight,
connectorType,
data,
editLabelPosition,
editSubjectPosition,
getDate,
getStockValue,
horizontalAnchor: horizontalAnchor === 'auto' ? undefined : horizontalAnchor,
Expand Down Expand Up @@ -121,10 +127,19 @@ export default function ExampleControls({
<label>
<input
type="checkbox"
onChange={() => setEditAnnotation(!editAnnotation)}
checked={editAnnotation}
onChange={() => setEditSubjectPosition(!editSubjectPosition)}
checked={editSubjectPosition}
/>
Edit annotation
Edit subject position
</label>
&nbsp;&nbsp;
<label>
<input
type="checkbox"
onChange={() => setEditLabelPosition(!editLabelPosition)}
checked={editLabelPosition}
/>
Edit label position
</label>
</div>
<div>
Expand Down

0 comments on commit f1df125

Please sign in to comment.