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=