From 114ed7cde0f669e36aef185cb165cd13489ed8f1 Mon Sep 17 00:00:00 2001 From: Harry Shoff Date: Fri, 12 Jan 2018 14:13:00 -0500 Subject: [PATCH 1/2] [legend] make legend items clickable. fixes #209 --- packages/vx-demo/components/tiles/legends.js | 59 ++++++++++++- packages/vx-demo/pages/legends.js | 85 +++++++++++++++++-- packages/vx-legend/src/legends/Legend.js | 2 + packages/vx-legend/src/legends/LegendItem.js | 8 +- .../vx-legend/src/util/additionalProps.js | 8 ++ packages/vx-legend/src/util/callOrValue.js | 6 ++ 6 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 packages/vx-legend/src/util/additionalProps.js create mode 100644 packages/vx-legend/src/util/callOrValue.js diff --git a/packages/vx-demo/components/tiles/legends.js b/packages/vx-demo/components/tiles/legends.js index d9144ad30..da1a8c35f 100644 --- a/packages/vx-demo/components/tiles/legends.js +++ b/packages/vx-demo/components/tiles/legends.js @@ -134,6 +134,15 @@ export default ({ width, height, margin }) => { shapeMargin="5px 0" itemDirection="row" scale={size} + onClick={data => event => { + alert(`clicked: ${JSON.stringify(data)}`); + }} + onMouseOver={data => event => { + console.log( + `mouse over: ${data.text}`, + `index: ${data.index}`, + ); + }} shapeStyle={props => { return { fill: sizeColor(props.datum), @@ -155,7 +164,19 @@ export default ({ width, height, margin }) => { /> - + event => { + alert(`clicked: ${JSON.stringify(data)}`); + }} + onMouseOver={data => event => { + console.log( + `mouse over: ${data.text}`, + `index: ${data.index}`, + ); + }} + /> { if (i % 2 === 0) return oneDecimalFormat(d); return ''; }} + onClick={data => event => { + alert(`clicked: ${JSON.stringify(data)}`); + }} + onMouseOver={data => event => { + console.log( + `mouse over: ${data.text}`, + `index: ${data.index}`, + ); + }} /> @@ -174,6 +204,15 @@ export default ({ width, height, margin }) => { labelMargin="2px 0 0 10px" shapeMargin="1px 0 0" scale={threshold} + onClick={data => event => { + alert(`clicked: ${JSON.stringify(data)}`); + }} + onMouseOver={data => event => { + console.log( + `mouse over: ${data.text}`, + `index: ${data.index}`, + ); + }} /> @@ -187,6 +226,15 @@ export default ({ width, height, margin }) => { shape="rect" fill={({ datum }) => ordinalColor(datum)} labelFormat={label => `${label.toUpperCase()}`} + onClick={data => event => { + alert(`clicked: ${JSON.stringify(data)}`); + }} + onMouseOver={data => event => { + console.log( + `mouse over: ${data.text}`, + `index: ${data.index}`, + ); + }} /> @@ -199,6 +247,15 @@ export default ({ width, height, margin }) => { scale={ordinalShape} fill={({ datum }) => ordinalColor2(datum)} shapeWidth={15} + onClick={data => event => { + alert(`clicked: ${JSON.stringify(data)}`); + }} + onMouseOver={data => event => { + console.log( + `mouse over: ${data.text}`, + `index: ${data.index}`, + ); + }} shape={props => { return ( diff --git a/packages/vx-demo/pages/legends.js b/packages/vx-demo/pages/legends.js index 482fc09d2..e6d414f58 100644 --- a/packages/vx-demo/pages/legends.js +++ b/packages/vx-demo/pages/legends.js @@ -79,15 +79,16 @@ const ordinalShape = scaleOrdinal({ left={50 / 6} fill="#df905f" />, - props => + props => ( $ - , + + ), ], }); const threshold = scaleThreshold({ - domain: [0.02, 0.04, 0.06, 0.08, 0.1], + domain: [0.01, 0.02, 0.04, 0.06, 0.08, 0.1], range: [ '#f2f0f7', '#dadaeb', @@ -118,6 +119,24 @@ function LegendDemo({ title, children }) {
{title}
{children} +
); } @@ -132,6 +151,15 @@ export default ({ width, height, margin }) => { shapeMargin="5px 0" itemDirection="row" scale={size} + onClick={data => event => { + alert(\`clicked: \`\${JSON.stringify(data)}\`); + }} + onMouseOver={data => event => { + console.log( + \`mouse over: \${data.text}\`, + \`index: \${data.index}\`, + ); + }} shapeStyle={props => { return { fill: sizeColor(props.datum), @@ -153,7 +181,19 @@ export default ({ width, height, margin }) => { />
- + event => { + alert(\`clicked: \`\${JSON.stringify(data)}\`); + }} + onMouseOver={data => event => { + console.log( + \`mouse over: \${data.text}\`, + \`index: \${data.index}\`, + ); + }} + /> { if (i % 2 === 0) return oneDecimalFormat(d); return ''; }} + onClick={data => event => { + alert(\`clicked: \`\${JSON.stringify(data)}\`); + }} + onMouseOver={data => event => { + console.log( + \`mouse over: \${data.text}\`, + \`index: \${data.index}\`, + ); + }} /> @@ -172,6 +221,15 @@ export default ({ width, height, margin }) => { labelMargin="2px 0 0 10px" shapeMargin="1px 0 0" scale={threshold} + onClick={data => event => { + alert(\`clicked: \`\${JSON.stringify(data)}\`); + }} + onMouseOver={data => event => { + console.log( + \`mouse over: \${data.text}\`, + \`index: \${data.index}\`, + ); + }} /> @@ -185,6 +243,15 @@ export default ({ width, height, margin }) => { shape="rect" fill={({ datum }) => ordinalColor(datum)} labelFormat={label => \`\${label.toUpperCase()}\`} + onClick={data => event => { + alert(\`clicked: \`\${JSON.stringify(data)}\`); + }} + onMouseOver={data => event => { + console.log( + \`mouse over: \${data.text}\`, + \`index: \${data.index}\`, + ); + }} /> @@ -197,6 +264,15 @@ export default ({ width, height, margin }) => { scale={ordinalShape} fill={({ datum }) => ordinalColor2(datum)} shapeWidth={15} + onClick={data => event => { + alert(\`clicked: \`\${JSON.stringify(data)}\`); + }} + onMouseOver={data => event => { + console.log( + \`mouse over: \${data.text}\`, + \`index: \${data.index}\`, + ); + }} shape={props => { return ( @@ -221,7 +297,6 @@ export default ({ width, height, margin }) => { ); }; - `} ); diff --git a/packages/vx-legend/src/legends/Legend.js b/packages/vx-legend/src/legends/Legend.js index 2bc8f26a3..be6e61547 100644 --- a/packages/vx-legend/src/legends/Legend.js +++ b/packages/vx-legend/src/legends/Legend.js @@ -72,6 +72,8 @@ export default function Legend({ key={`legend-${label}-${i}`} margin={itemMargin} flexDirection={itemDirection} + label={label} + {...restProps} > {children} ); -} \ No newline at end of file +} diff --git a/packages/vx-legend/src/util/additionalProps.js b/packages/vx-legend/src/util/additionalProps.js new file mode 100644 index 000000000..b3ac93bc3 --- /dev/null +++ b/packages/vx-legend/src/util/additionalProps.js @@ -0,0 +1,8 @@ +import callOrValue from './callOrValue'; + +export default function additionalProps(restProps, data) { + return Object.keys(restProps).reduce((ret, cur) => { + ret[cur] = callOrValue(restProps[cur], data); + return ret; + }, {}); +} diff --git a/packages/vx-legend/src/util/callOrValue.js b/packages/vx-legend/src/util/callOrValue.js new file mode 100644 index 000000000..77afb1a09 --- /dev/null +++ b/packages/vx-legend/src/util/callOrValue.js @@ -0,0 +1,6 @@ +export default function callOrValue(maybeFn, data) { + if (typeof maybeFn === 'function') { + return maybeFn(data); + } + return maybeFn; +} From e68125328ff171c0e88190984d86e70bec47a72c Mon Sep 17 00:00:00 2001 From: Harry Shoff Date: Fri, 12 Jan 2018 14:44:16 -0500 Subject: [PATCH 2/2] [legend] add LegenItem propTypes, add click test --- packages/vx-legend/src/legends/LegendItem.js | 6 +++++ packages/vx-legend/test/Legend.test.js | 25 +++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/vx-legend/src/legends/LegendItem.js b/packages/vx-legend/src/legends/LegendItem.js index 49eb18cb8..5ec975d9f 100644 --- a/packages/vx-legend/src/legends/LegendItem.js +++ b/packages/vx-legend/src/legends/LegendItem.js @@ -2,6 +2,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import additonalProps from '../util/additionalProps'; +LegendItem.propTypes = { + flexDirection: PropTypes.string, + margin: PropTypes.string, + label: PropTypes.object.isRequired, +}; + export default function LegendItem({ children, flexDirection, diff --git a/packages/vx-legend/test/Legend.test.js b/packages/vx-legend/test/Legend.test.js index 707ba42f8..07d66ca1a 100644 --- a/packages/vx-legend/test/Legend.test.js +++ b/packages/vx-legend/test/Legend.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, mount } from 'enzyme'; import { Legend } from '../src'; import { scaleLinear } from '../../vx-scale'; @@ -42,4 +42,27 @@ describe('', () => { flexDirection: 'row', }); }); + + test('it should pass onClick prop to ', () => { + const event = jest.fn(event => jest.fn()); + const onClick = jest.fn(data => event); + const wrapper = mount( + , + ); + wrapper + .find('LegendItem') + .last() + .simulate('click'); + // called twice, once to bind data, once when click event + expect(onClick.mock.calls.length).toEqual(2); + expect(event.mock.calls.length).toEqual(1); + // called with click event + expect(event.mock.calls[0][0].type).toEqual('click'); + expect(onClick.mock.calls[1][0]).toEqual({ + datum: 10, + index: 1, + text: '10', + value: 0, + }); + }); });