diff --git a/docs/clip.md b/docs/clip.md new file mode 100644 index 000000000..63c264e96 --- /dev/null +++ b/docs/clip.md @@ -0,0 +1,24 @@ +## Clip + +Depending on the data and domain, sometimes the series in the plot will extend into the axis. This can either be solved with a [Border](border.md), or the elements can be clipped. + +To have the rendered series, clipped you will need to set up a `clipPath` (see [MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath)) and tell the series to use it. + +As seen below, the `clipPath` can be created with the `ContentClipArea` component, and its `id` can be referenced by the components that want to be clipped. + +```jsx + + + + +``` + + + +## API Reference + +#### id (optional) + +Type: `String` + +The id to assign to the `clipArea`. If not provided, this will default to `content-area` diff --git a/packages/react-vis/jest.config.js b/packages/react-vis/jest.config.js index 46a594b3f..1d5586ff3 100644 --- a/packages/react-vis/jest.config.js +++ b/packages/react-vis/jest.config.js @@ -5,5 +5,6 @@ module.exports = { transform: { '^.+\\.js$': path.resolve(__dirname, './jestBabelTransform.js') }, - setupFilesAfterEnv: ['./jest.setup.js'] + setupFilesAfterEnv: ['./jest.setup.js'], + snapshotSerializers: ['enzyme-to-json/serializer'] }; diff --git a/packages/react-vis/package.json b/packages/react-vis/package.json index 99af88d90..8abe0a0a9 100644 --- a/packages/react-vis/package.json +++ b/packages/react-vis/package.json @@ -63,15 +63,16 @@ "@babel/preset-react": "^7.0.0", "@babel/register": "^7.0.0", "babel-eslint": "^10.1.0", - "babel-jest":"^25.5.1", + "babel-jest": "^25.5.1", "babel-plugin-module-resolver": "^4.0.0", "babelify": "^10.0.0", "browserify": "^14.3.0", "canvas-prebuilt": "^1.6.11", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.2", - "eslint-plugin-jest":"^23.13.2", - "jest":"^25.5.4", + "enzyme-to-json": "^3.5.0", + "eslint-plugin-jest": "^23.13.2", + "jest": "^25.5.4", "jsdom": "^9.9.1", "node-sass": "^4.9.3", "prettier": "^1.14.2", diff --git a/packages/react-vis/src/index.js b/packages/react-vis/src/index.js index 42ab80644..6a0b11d3e 100644 --- a/packages/react-vis/src/index.js +++ b/packages/react-vis/src/index.js @@ -72,6 +72,8 @@ export Sankey from 'sankey'; export Sunburst from 'sunburst'; export Treemap from 'treemap'; +export ContentClipPath from './plot/content-clip-path'; + export { makeHeightFlexible, makeVisFlexible, diff --git a/packages/react-vis/src/plot/content-clip-path.js b/packages/react-vis/src/plot/content-clip-path.js new file mode 100644 index 000000000..0679c38b1 --- /dev/null +++ b/packages/react-vis/src/plot/content-clip-path.js @@ -0,0 +1,15 @@ +import React from 'react'; + +export default function ContentClipPath(props) { + const {id = 'content-area', innerWidth, innerHeight} = props; + return ( + + + + + + ); +} + +ContentClipPath.requiresSVG = true; +ContentClipPath.displayName = 'ContentClipPath'; diff --git a/packages/react-vis/tests/jsconfig.json b/packages/react-vis/tests/jsconfig.json new file mode 100644 index 000000000..444de5133 --- /dev/null +++ b/packages/react-vis/tests/jsconfig.json @@ -0,0 +1,8 @@ +{ + "typeAcquisition": { + "enable": true, + "include": [ + "jest" + ] + } +} \ No newline at end of file diff --git a/packages/react-vis/tests/plot/__snapshots__/content-clip-path.test.js.snap b/packages/react-vis/tests/plot/__snapshots__/content-clip-path.test.js.snap new file mode 100644 index 000000000..8cdf90811 --- /dev/null +++ b/packages/react-vis/tests/plot/__snapshots__/content-clip-path.test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`content-clip-path should render 1`] = ` + + + + + +`; diff --git a/packages/react-vis/tests/plot/content-clip-path.test.js b/packages/react-vis/tests/plot/content-clip-path.test.js new file mode 100644 index 000000000..2eb940e1d --- /dev/null +++ b/packages/react-vis/tests/plot/content-clip-path.test.js @@ -0,0 +1,20 @@ +import React from 'react'; +import {shallow} from 'enzyme'; +import ContentClipPath from '../../src/plot/content-clip-path'; + +describe('content-clip-path', () => { + it('should render', () => { + const wrapper = shallow( + + ); + expect(wrapper).toMatchSnapshot(); + }); + + it('should default id to content-area', () => { + const wrapper = shallow( + + ); + const clip = wrapper.find('clipPath'); + expect(clip.prop('id')).toEqual('content-area'); + }); +}); diff --git a/packages/showcase/index.js b/packages/showcase/index.js index 52d1a5ef7..0adda4160 100644 --- a/packages/showcase/index.js +++ b/packages/showcase/index.js @@ -124,6 +124,7 @@ import HorizontalDiscreteCustomPalette from './legends/horizontal-discrete-custo import AnimationExample from './misc/animation-example'; import LabelSeriesExample from './misc/label-series-example'; import GradientExample from './misc/gradient-example'; +import ClipExample from './misc/clip-example'; import NullDataExample from './misc/null-data-example'; import SyncedCharts from './misc/synced-charts'; import TimeChart from './misc/time-chart'; @@ -226,6 +227,7 @@ const mainShowCase = { CustomAxes, LabelSeriesExample, GradientExample, + ClipExample, NullDataExample, ZoomableChartExample, SelectionPlotExample, diff --git a/packages/showcase/misc/clip-example.js b/packages/showcase/misc/clip-example.js new file mode 100644 index 000000000..d381fafcb --- /dev/null +++ b/packages/showcase/misc/clip-example.js @@ -0,0 +1,53 @@ +import React, {useState} from 'react'; + +import { + XYPlot, + XAxis, + YAxis, + VerticalGridLines, + HorizontalGridLines, + AreaSeries, + ContentClipPath +} from 'react-vis'; + +export default function ClipExample() { + const [clip, setClip] = useState(true); + + return ( + <> + + + {clip && } + + + + + + + + + + + ); +} diff --git a/packages/showcase/package.json b/packages/showcase/package.json index 6986bf7e7..50e2dcfcf 100644 --- a/packages/showcase/package.json +++ b/packages/showcase/package.json @@ -4,6 +4,7 @@ "version": "0.1.0", "scripts": { "start": "webpack-dev-server --progress --hot --port 3001", + "lint": "eslint .", "build": "NODE_ENV=production webpack", "build:windows": "set NODE_ENV=production&&.\\node_modules\\.bin\\webpack" }, diff --git a/packages/showcase/showcase-links.js b/packages/showcase/showcase-links.js index 4b6cf0464..f3c1bead2 100644 --- a/packages/showcase/showcase-links.js +++ b/packages/showcase/showcase-links.js @@ -31,6 +31,7 @@ export const SHOWCASE_LINKS = { TriangleExample: `${SHOWCASE_BASE_URL}/misc/triangle-example.js`, VoronoiLineChart: `${SHOWCASE_BASE_URL}/misc/voronoi-line-chart.js`, GradientExample: `${SHOWCASE_BASE_URL}/misc/gradient-example.js`, + ClipExample: `${SHOWCASE_BASE_URL}/misc/clip-example.js`, AnimationExample: `${SHOWCASE_BASE_URL}/misc/animation-example.js`, LabelSeriesExample: `${SHOWCASE_BASE_URL}/misc/label-series-example.js`, NullDataExample: `${SHOWCASE_BASE_URL}/misc/null-data-example.js`, diff --git a/packages/showcase/showcase-sections/misc-showcase.js b/packages/showcase/showcase-sections/misc-showcase.js index 24cdc3406..860383501 100644 --- a/packages/showcase/showcase-sections/misc-showcase.js +++ b/packages/showcase/showcase-sections/misc-showcase.js @@ -14,7 +14,8 @@ const { ZoomableChartExample, SelectionPlotExample, DragableChartExample, - BidirectionDragChart + BidirectionDragChart, + ClipExample } = showCase; const MISC = [ @@ -49,6 +50,13 @@ const MISC = [ docsLink: 'http://uber.github.io/react-vis/documentation/api-reference/gradients' }, + { + name: 'Content Area Clipping', + component: ClipExample, + componentName: 'ClipExample', + sourceLink: `${SHOWCASE_BASE_URL}/misc/clip-example.js`, + docsLink: 'http://uber.github.io/react-vis/documentation/api-reference/clip' + }, { name: 'Animation Example', component: AnimationExample, diff --git a/packages/showcase/showcase-sections/parallel-coordinates-showcase.js b/packages/showcase/showcase-sections/parallel-coordinates-showcase.js index dea1d39d8..2f282f43d 100644 --- a/packages/showcase/showcase-sections/parallel-coordinates-showcase.js +++ b/packages/showcase/showcase-sections/parallel-coordinates-showcase.js @@ -2,7 +2,7 @@ import React from 'react'; import {mapSection} from '../showcase-components/showcase-utils'; import {showCase} from '../index'; -import {REACTVIS_BASE_URL} from '../index'; +import {REACTVIS_BASE_URL} from '../showcase-links'; const { AnimatedParallelCoordinates, BasicParallelCoordinates, diff --git a/packages/website/src/mdRoutes.js b/packages/website/src/mdRoutes.js index 9ab397e52..e17cf50bb 100644 --- a/packages/website/src/mdRoutes.js +++ b/packages/website/src/mdRoutes.js @@ -59,6 +59,7 @@ import treemap from '../../docs/treemap.md'; import voronoi from '../../docs/voronoi.md'; import whiskerSeries from '../../docs/whisker-series.md'; import xy from '../../docs/xy-plot.md'; +import clip from '../../docs/clip.md'; const mdRoutes = [ { @@ -238,6 +239,7 @@ const mdRoutes = [ name: 'Flexible plots', markdown: flexiblePlots }, + {name: 'Clipping', markdown: clip}, { name: 'Borders', markdown: borders diff --git a/packages/website/storybook/index.js b/packages/website/storybook/index.js index 82acb2d66..2bf1dd14c 100644 --- a/packages/website/storybook/index.js +++ b/packages/website/storybook/index.js @@ -9,3 +9,5 @@ import './radial-story'; import './axis-story'; import './legend-story'; + +import './misc-story'; diff --git a/packages/website/storybook/misc-story.js b/packages/website/storybook/misc-story.js new file mode 100644 index 000000000..ba14d3c88 --- /dev/null +++ b/packages/website/storybook/misc-story.js @@ -0,0 +1,31 @@ +/* eslint-env node */ + +import React from 'react'; + +import {storiesOf} from '@storybook/react'; + +import {withKnobs, boolean} from '@storybook/addon-knobs/react'; +import {SimpleChartWrapper} from './storybook-utils'; +import {generateLinearData} from './storybook-data'; + +import {LineSeries, ContentClipPath} from 'react-vis'; + +const data = generateLinearData({randomFactor: 10}); + +storiesOf('Misc', module) + .addDecorator(withKnobs) + .addWithJSX('Clip Content', () => { + const margin = {left: 40, top: 40, bottom: 40, right: 40}; + const xDomain = [data[1].x, data[data.length - 2].x]; + const shouldClip = boolean( + 'Enable Clipping', + false, + 'General chart options' + ); + return ( + + {shouldClip && } + + + ); + }); diff --git a/yarn.lock b/yarn.lock index dd358d7d2..52b54f597 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6335,6 +6335,14 @@ enzyme-shallow-equal@^1.0.1: has "^1.0.3" object-is "^1.0.2" +enzyme-to-json@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.5.0.tgz#3d536f1e8fb50d972360014fe2bd64e6a672f7dd" + integrity sha1-PVNvHo+1DZcjYAFP4r1k5qZy990= + dependencies: + lodash "^4.17.15" + react-is "^16.12.0" + enzyme@^3.11.0: version "3.11.0" resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.11.0.tgz#71d680c580fe9349f6f5ac6c775bc3e6b7a79c28" @@ -9549,7 +9557,7 @@ js-base64@^2.1.8, js-base64@^2.1.9: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" integrity sha1-MTtidN2nGPcU0AszMLuubjjpAgk= -js-beautify@1.10.3, js-beautify@^1.8.8: +js-beautify@^1.8.8: version "1.10.3" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.3.tgz#c73fa10cf69d3dfa52d8ed624f23c64c0a6a94c1" integrity sha1-xz+hDPadPfpS2O1iTyPGTApqlME=