diff --git a/.playground/index.html b/.playground/index.html index 266524c14d..d28529866b 100644 --- a/.playground/index.html +++ b/.playground/index.html @@ -19,22 +19,15 @@ position: absolute; top: 0px; left: 0px; + width: 100%; } .chart { background: white; display: inline-block; position: relative; - width: 900px; - height: 600px; - margin: 10px; - /* overflow: hidden; */ - } - button { - padding: 10px !important; - background: black !important; - border: 1px solid white !important; - color: white !important; - margin: 4px !important; + width: 1000px; + height: 350px; + margin: 0px; } </style> </head> diff --git a/.playground/playgroud.tsx b/.playground/playgroud.tsx index 6288fb748e..778fbcb2af 100644 --- a/.playground/playgroud.tsx +++ b/.playground/playgroud.tsx @@ -6,10 +6,13 @@ import { getSpecId, Position, ScaleType, - HistogramBarSeries, Settings, LIGHT_THEME, niceTimeFormatter, + LineAnnotation, + AnnotationDomainTypes, + BarSeries, + RectAnnotation, } from '../src'; import { KIBANA_METRICS } from '../src/utils/data_samples/test_dataset_kibana'; export class Playground extends React.Component { @@ -39,7 +42,7 @@ export class Playground extends React.Component { } }; render() { - const data = KIBANA_METRICS.metrics.kibana_os_load[0].data.slice(0, 100); + const data = KIBANA_METRICS.metrics.kibana_os_load[0].data.slice(0, 7); return ( <> @@ -53,8 +56,29 @@ export class Playground extends React.Component { tickFormat={niceTimeFormatter([data[0][0], data[data.length - 1][0]])} /> <Axis id={getAxisId('count')} position={Position.Left} /> - - <HistogramBarSeries + <LineAnnotation + id="line annotation" + dataValues={[ + { + dataValue: data[5][0], + details: 'hello tooltip', + }, + ]} + domainType={AnnotationDomainTypes.XDomain} + marker={<div style={{ width: 10, height: 10, background: 'red' }} />} + /> + <RectAnnotation + id="rect annotation" + dataValues={[ + { + coordinates: { + x1: data[3][0], + }, + details: 'hello', + }, + ]} + /> + <BarSeries id={getSpecId('series bars chart')} xScaleType={ScaleType.Linear} yScaleType={ScaleType.Linear} diff --git a/.playground/webpack.config.js b/.playground/webpack.config.js index 3d24a4f4f9..4564fb6053 100644 --- a/.playground/webpack.config.js +++ b/.playground/webpack.config.js @@ -13,6 +13,7 @@ module.exports = { exclude: /node_modules/, options: { configFile: 'tsconfig.json', + transpileOnly: true, }, }, { diff --git a/integration/page_objects/common.ts b/integration/page_objects/common.ts index 2a0bd73307..abc72aea65 100644 --- a/integration/page_objects/common.ts +++ b/integration/page_objects/common.ts @@ -21,7 +21,7 @@ class CommonPage { return `${baseUrl}?${query}${query ? '&' : ''}knob-debug=false`; } - async getBoundingClientRect(selector = '.echChart[data-ech-render-complete=true]') { + async getBoundingClientRect(selector = '.echChart') { return await page.evaluate((selector) => { const element = document.querySelector(selector); @@ -37,10 +37,7 @@ class CommonPage { /** * Capture screenshot or chart element only */ - async screenshotDOMElement( - selector = '.echChart[data-ech-render-complete=true]', - opts?: ScreenshotDOMElementOptions, - ) { + async screenshotDOMElement(selector = '.echChart', opts?: ScreenshotDOMElementOptions) { const padding: number = opts && opts.padding ? opts.padding : 0; const path: string | undefined = opts && opts.path ? opts.path : undefined; const rect = await this.getBoundingClientRect(selector); @@ -56,10 +53,7 @@ class CommonPage { }); } - async moveMouseRelativeToDOMElement( - mousePosition: { x: number; y: number }, - selector = '.echChart[data-ech-render-complete=true]', - ) { + async moveMouseRelativeToDOMElement(mousePosition: { x: number; y: number }, selector = '.echChart') { const chartContainer = await this.getBoundingClientRect(selector); await page.mouse.move(chartContainer.left + mousePosition.x, chartContainer.top + mousePosition.y); } @@ -113,9 +107,14 @@ class CommonPage { async loadChartFromURL(url: string) { const cleanUrl = CommonPage.parseUrl(url); await page.goto(cleanUrl); + this.waitForElement(); } - - async waitForElement(selector = '.echChart[data-ech-render-complete=true]', timeout = 10000) { + /** + * Wait for an element to be on the DOM + * @param {string} [selector] the DOM selector to wait for, default to '.echChartStatus[data-ech-render-complete=true]' + * @param {number} [timeout] - the timeout for the operation, default to 10000ms + */ + async waitForElement(selector = '.echChartStatus[data-ech-render-complete=true]', timeout = 10000) { await page.waitForSelector(selector, { timeout }); } } diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-stacked-with-separated-specs-same-naming-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-stacked-with-separated-specs-same-naming-visually-looks-correct-1-snap.png index ec4a40e69e..7656229b36 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-stacked-with-separated-specs-same-naming-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-stacked-with-separated-specs-same-naming-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-linear-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-linear-visually-looks-correct-1-snap.png index b3edb0a61b..c85776c82f 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-linear-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-linear-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-time-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-time-visually-looks-correct-1-snap.png index d7777d4019..22e96bafb3 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-time-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-test-time-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-w-axis-and-legend-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-w-axis-and-legend-visually-looks-correct-1-snap.png index 627aa22fca..de6f227bd4 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-w-axis-and-legend-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-w-axis-and-legend-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-with-4-axes-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-with-4-axes-visually-looks-correct-1-snap.png index 49f9e2ad60..923f01d36c 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-with-4-axes-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-area-chart-with-4-axes-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-4-axes-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-4-axes-visually-looks-correct-1-snap.png index 1d35b1600b..c75c19bc5f 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-4-axes-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-4-axes-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-linear-chart-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-linear-chart-visually-looks-correct-1-snap.png index 5724397a8a..e5d222a7cb 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-linear-chart-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-linear-chart-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-ordinal-linear-x-domain-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-ordinal-linear-x-domain-visually-looks-correct-1-snap.png index 9bacef38a6..d9bf398224 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-ordinal-linear-x-domain-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-mixed-ordinal-linear-x-domain-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-only-one-bound-defined-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-only-one-bound-defined-visually-looks-correct-1-snap.png index 5cccc53db0..f6922e4113 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-only-one-bound-defined-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-customizing-domain-limits-only-one-bound-defined-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-tick-label-rotation-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-tick-label-rotation-visually-looks-correct-1-snap.png index 2e8c6b8e34..e9e6190f3c 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-tick-label-rotation-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-tick-label-rotation-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-with-multi-axis-bar-lines-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-with-multi-axis-bar-lines-visually-looks-correct-1-snap.png index 895c56542d..9936ef26a5 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-with-multi-axis-bar-lines-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axis-with-multi-axis-bar-lines-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-1-g-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-1-g-visually-looks-correct-1-snap.png index cd96262897..170c01726d 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-1-g-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-1-g-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-2-g-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-2-g-visually-looks-correct-1-snap.png index a80adea3a6..1928eb6866 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-2-g-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-1-y-2-g-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-2-y-1-g-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-2-y-1-g-visually-looks-correct-1-snap.png index d0fbbd1df0..4e11f96bd0 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-2-y-1-g-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-2-y-1-g-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-multiple-series-specs-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-multiple-series-specs-visually-looks-correct-1-snap.png index 133d5a50d2..baf6c86df0 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-multiple-series-specs-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-multiple-series-specs-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-with-axis-and-legend-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-with-axis-and-legend-visually-looks-correct-1-snap.png index 4f3d9c873a..36faac9f74 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-with-axis-and-legend-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-clustered-with-axis-and-legend-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-min-height-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-min-height-visually-looks-correct-1-snap.png index d31ba777c3..ef3bc95f1d 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-min-height-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-min-height-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-single-data-chart-ordinal-visually-looks-correct-2-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-single-data-chart-ordinal-visually-looks-correct-2-snap.png new file mode 100644 index 0000000000..753b701224 Binary files /dev/null and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-single-data-chart-ordinal-visually-looks-correct-2-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-clustered-bar-chart-with-null-bars-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-clustered-bar-chart-with-null-bars-visually-looks-correct-1-snap.png index 56393b1959..b1e9e661eb 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-clustered-bar-chart-with-null-bars-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-clustered-bar-chart-with-null-bars-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-linear-clustered-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-linear-clustered-visually-looks-correct-1-snap.png index 09c4fb24a5..bb222cc068 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-linear-clustered-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-linear-clustered-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-switch-ordinal-linear-x-axis-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-switch-ordinal-linear-x-axis-visually-looks-correct-1-snap.png index 72cc4a3d4e..cddb83dd77 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-switch-ordinal-linear-x-axis-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-switch-ordinal-linear-x-axis-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-clustered-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-clustered-visually-looks-correct-1-snap.png index 2d872e6bee..5ae354e2aa 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-clustered-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-clustered-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-visually-looks-correct-1-snap.png index 7e2f1d2d80..3fa958e7b6 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-test-time-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-and-legend-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-and-legend-visually-looks-correct-1-snap.png index f9ef7508e0..b9e5b8746b 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-and-legend-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-and-legend-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-visually-looks-correct-1-snap.png index 72cc4a3d4e..cddb83dd77 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-axis-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-high-data-volume-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-high-data-volume-visually-looks-correct-1-snap.png index c8ece4cf5f..7f8db335a8 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-high-data-volume-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-high-data-volume-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-linear-x-axis-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-linear-x-axis-visually-looks-correct-1-snap.png index f4010a359a..751746c0c7 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-linear-x-axis-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-linear-x-axis-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-ordinal-x-axis-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-ordinal-x-axis-visually-looks-correct-1-snap.png index 295fb3edff..df3b41a445 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-ordinal-x-axis-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-ordinal-x-axis-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-value-label-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-value-label-visually-looks-correct-1-snap.png index 8ca3071d03..3b749d7a76 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-value-label-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-value-label-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-basic-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-basic-visually-looks-correct-1-snap.png index 5bb21ebcd2..8452dab797 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-basic-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-basic-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-multiple-axes-with-the-same-position-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-multiple-axes-with-the-same-position-visually-looks-correct-1-snap.png index 228c026a4a..a30017dede 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-multiple-axes-with-the-same-position-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-grids-multiple-axes-with-the-same-position-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-area-point-clicks-and-hovers-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-area-point-clicks-and-hovers-visually-looks-correct-1-snap.png index 678d99a66d..c58cc3588a 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-area-point-clicks-and-hovers-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-area-point-clicks-and-hovers-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-bar-clicks-and-hovers-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-bar-clicks-and-hovers-visually-looks-correct-1-snap.png index 6292dd9a42..3fc7bd6117 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-bar-clicks-and-hovers-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-bar-clicks-and-hovers-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-bar-chart-linear-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-bar-chart-linear-visually-looks-correct-1-snap.png index bdf2e92fb5..d73ed187ed 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-bar-chart-linear-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-bar-chart-linear-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-histogram-time-charts-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-histogram-time-charts-visually-looks-correct-1-snap.png new file mode 100644 index 0000000000..0099161c11 Binary files /dev/null and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-histogram-time-charts-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-linear-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-linear-visually-looks-correct-1-snap.png index 1d35b1600b..c75c19bc5f 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-linear-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-linear-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-time-charts-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-time-charts-visually-looks-correct-1-snap.png index b4fd16e478..0f0e3426a0 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-time-charts-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-selection-tool-on-time-charts-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-click-hovers-on-legend-items-line-chart-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-click-hovers-on-legend-items-line-chart-visually-looks-correct-1-snap.png index 11fea9ecc2..2bae67388a 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-click-hovers-on-legend-items-line-chart-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-click-hovers-on-legend-items-line-chart-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-cursor-update-action-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-cursor-update-action-visually-looks-correct-1-snap.png index 6292dd9a42..3fc7bd6117 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-cursor-update-action-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-cursor-update-action-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-area-bar-point-clicks-and-hovers-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-area-bar-point-clicks-and-hovers-visually-looks-correct-1-snap.png index f6a069fc30..724c199905 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-area-bar-point-clicks-and-hovers-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-area-bar-point-clicks-and-hovers-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-point-clicks-and-hovers-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-point-clicks-and-hovers-visually-looks-correct-1-snap.png index ea61fd21b1..e850a8819b 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-point-clicks-and-hovers-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-line-point-clicks-and-hovers-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-png-export-action-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-png-export-action-visually-looks-correct-1-snap.png index d381a3b146..2ff8ed4ad9 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-png-export-action-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-png-export-action-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-render-change-action-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-render-change-action-visually-looks-correct-1-snap.png index 6292dd9a42..3fc7bd6117 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-render-change-action-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-render-change-action-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-bottom-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-bottom-visually-looks-correct-1-snap.png index 3f0eb59be0..859c4c54c1 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-bottom-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-bottom-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-display-values-in-legend-elements-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-display-values-in-legend-elements-visually-looks-correct-1-snap.png index 5654907524..f9c91eea50 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-display-values-in-legend-elements-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-display-values-in-legend-elements-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-legend-spacing-buffer-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-legend-spacing-buffer-visually-looks-correct-1-snap.png index 5c95cde5fd..cf8b08664c 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-legend-spacing-buffer-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-legend-legend-spacing-buffer-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-curved-w-axis-and-legend-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-curved-w-axis-and-legend-visually-looks-correct-1-snap.png index ac13b8fdb6..9a86b8cf20 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-curved-w-axis-and-legend-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-curved-w-axis-and-legend-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multi-series-with-log-values-limit-0-or-negative-values-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multi-series-with-log-values-limit-0-or-negative-values-visually-looks-correct-1-snap.png index 753c14736e..8b9569bb67 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multi-series-with-log-values-limit-0-or-negative-values-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multi-series-with-log-values-limit-0-or-negative-values-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multiple-w-axis-and-legend-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multiple-w-axis-and-legend-visually-looks-correct-1-snap.png index 1121c9d238..181d63dafc 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multiple-w-axis-and-legend-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-multiple-w-axis-and-legend-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-stacked-w-axis-and-legend-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-stacked-w-axis-and-legend-visually-looks-correct-1-snap.png index 0fb2fe6134..383a6f826e 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-stacked-w-axis-and-legend-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-stacked-w-axis-and-legend-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-w-axis-and-legend-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-w-axis-and-legend-visually-looks-correct-1-snap.png index 6ebe43eb9c..bea9f66473 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-w-axis-and-legend-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-line-chart-w-axis-and-legend-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-areas-and-bars-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-areas-and-bars-visually-looks-correct-1-snap.png index 698fcf17c2..dcaba5207d 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-areas-and-bars-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-areas-and-bars-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-lines-and-areas-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-lines-and-areas-visually-looks-correct-1-snap.png index 0a3d66de5c..9a5b2bab57 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-lines-and-areas-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-lines-and-areas-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-linear-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-linear-visually-looks-correct-1-snap.png index 54b298242f..1b4b2e339f 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-linear-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-linear-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-time-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-time-visually-looks-correct-1-snap.png index 2c2d57dbc6..3b83c3ab19 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-time-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-mixed-charts-test-bar-lines-time-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-rotations-with-ordinal-axis-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-rotations-with-ordinal-axis-visually-looks-correct-1-snap.png index 5b75cc1781..2644f58005 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-rotations-with-ordinal-axis-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-rotations-with-ordinal-axis-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-line-chart-with-different-timezones-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-line-chart-with-different-timezones-visually-looks-correct-1-snap.png index d689e3d86c..53df6b37a3 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-line-chart-with-different-timezones-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-line-chart-with-different-timezones-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-remove-duplicate-scales-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-remove-duplicate-scales-visually-looks-correct-1-snap.png index 99329bd201..eaad6f2e0e 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-remove-duplicate-scales-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-remove-duplicate-scales-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-local-tooltip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-local-tooltip-visually-looks-correct-1-snap.png index d689e3d86c..53df6b37a3 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-local-tooltip-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-local-tooltip-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-utc-tooltip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-utc-tooltip-visually-looks-correct-1-snap.png index d689e3d86c..53df6b37a3 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-utc-tooltip-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-utc-time-zone-utc-tooltip-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-year-scale-custom-timezone-same-zone-tooltip-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-year-scale-custom-timezone-same-zone-tooltip-visually-looks-correct-1-snap.png index a7c33ba459..f335e70b8a 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-year-scale-custom-timezone-same-zone-tooltip-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-scales-x-scale-year-scale-custom-timezone-same-zone-tooltip-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-axis-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-axis-visually-looks-correct-1-snap.png index ec86ac4d13..807c47161d 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-axis-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-axis-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-margins-and-paddings-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-margins-and-paddings-visually-looks-correct-1-snap.png index 12f29cd34f..79b9563647 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-margins-and-paddings-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-margins-and-paddings-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-style-accessor-overrides-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-style-accessor-overrides-visually-looks-correct-1-snap.png index 1917d368cc..4275dcc88c 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-style-accessor-overrides-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-style-accessor-overrides-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-theme-style-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-theme-style-visually-looks-correct-1-snap.png index 0905daf933..09f1febeaa 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-theme-style-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-theme-style-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-tick-label-padding-both-prop-and-theme-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-tick-label-padding-both-prop-and-theme-visually-looks-correct-1-snap.png index 8e19b41b86..8b9db30b91 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-tick-label-padding-both-prop-and-theme-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-stylings-tick-label-padding-both-prop-and-theme-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/area-stories-test-ts-area-series-stories-accessor-formats-should-show-custom-format-1-snap.png b/integration/tests/__image_snapshots__/area-stories-test-ts-area-series-stories-accessor-formats-should-show-custom-format-1-snap.png index 0527889acd..5cfee5c36c 100644 Binary files a/integration/tests/__image_snapshots__/area-stories-test-ts-area-series-stories-accessor-formats-should-show-custom-format-1-snap.png and b/integration/tests/__image_snapshots__/area-stories-test-ts-area-series-stories-accessor-formats-should-show-custom-format-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png index 1261e797d2..f633f54844 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png index 57dcd868ce..9eda9241cf 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png index a9d01ed270..842bd72b6b 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png index f7dc5bace4..13f3ba54f9 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png index 2d1341d46a..af6b3b5958 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/bar-stories-test-ts-bar-series-stories-test-switch-ordinal-linear-x-axis-using-ordinal-x-axis-1-snap.png b/integration/tests/__image_snapshots__/bar-stories-test-ts-bar-series-stories-test-switch-ordinal-linear-x-axis-using-ordinal-x-axis-1-snap.png index 72cc4a3d4e..cddb83dd77 100644 Binary files a/integration/tests/__image_snapshots__/bar-stories-test-ts-bar-series-stories-test-switch-ordinal-linear-x-axis-using-ordinal-x-axis-1-snap.png and b/integration/tests/__image_snapshots__/bar-stories-test-ts-bar-series-stories-test-switch-ordinal-linear-x-axis-using-ordinal-x-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-0-legend-buffer-1-snap.png b/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-0-legend-buffer-1-snap.png index 9b9898945d..c140c9a2b4 100644 Binary files a/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-0-legend-buffer-1-snap.png and b/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-0-legend-buffer-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-hide-line-series-legend-item-1-snap.png b/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-hide-line-series-legend-item-1-snap.png index 2e5b70b955..d6aeff8e70 100644 Binary files a/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-hide-line-series-legend-item-1-snap.png and b/integration/tests/__image_snapshots__/legend-stories-test-ts-legend-stories-should-hide-line-series-legend-item-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-90-1-snap.png b/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-90-1-snap.png index 26677d3bb2..7d26012345 100644 Binary files a/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-90-1-snap.png and b/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-90-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-negative-90-1-snap.png b/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-negative-90-1-snap.png index bb3e6dbb9d..4260f0f5cd 100644 Binary files a/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-negative-90-1-snap.png and b/integration/tests/__image_snapshots__/line-stories-test-ts-line-series-stories-rotation-rotation-negative-90-1-snap.png differ diff --git a/package.json b/package.json index 31bd2b20e2..18681e3d0e 100644 --- a/package.json +++ b/package.json @@ -83,10 +83,11 @@ "@types/puppeteer": "^1.19.1", "@types/react": "^16.8.5", "@types/react-dom": "^16.8.2", + "@types/react-redux": "^7.1.1", "@types/seedrandom": "^2.4.28", "@types/storybook__addon-actions": "^3.4.3", "@types/storybook__addon-info": "^4.1.2", - "@types/storybook__addon-knobs": "^5.0.3", + "@types/storybook__addon-knobs": "5.0.4", "@types/storybook__react": "^4.0.2", "@types/url-parse": "^1.4.3", "@types/uuid": "^3.4.4", @@ -126,6 +127,7 @@ "puppeteer": "^1.20.0", "react-docgen-typescript-loader": "^3.0.1", "react-docgen-typescript-webpack-plugin": "^1.1.0", + "redux-devtools-extension": "^2.13.8", "sass-graph": "^3.0.4", "sass-loader": "^7.1.0", "seedrandom": "^3.0.5", @@ -147,16 +149,17 @@ "d3-collection": "^1.0.7", "d3-scale": "^1.0.7", "d3-shape": "^1.3.4", - "fp-ts": "^1.14.2", "konva": "^2.6.0", - "mobx": "^4.9.2", - "mobx-react": "^5.4.3", "newtype-ts": "^0.2.4", "prop-types": "^15.7.2", + "re-reselect": "^3.4.0", "react": "^16.8.3", "react-dom": "^16.8.3", "react-konva": "16.8.3", + "react-redux": "^7.1.0", "react-spring": "^8.0.8", + "redux": "^4.0.4", + "reselect": "^4.0.0", "resize-observer-polyfill": "^1.5.1", "ts-debounce": "^1.0.0", "uuid": "^3.3.2" diff --git a/scripts/custom_matchers.ts b/scripts/custom_matchers.ts index bf6d226a8e..0f6ebfe8db 100644 --- a/scripts/custom_matchers.ts +++ b/scripts/custom_matchers.ts @@ -15,7 +15,8 @@ type MatcherParameters<T extends (this: any, received: any, ...args: any[]) => a : never; declare global { - namespace jest { // eslint-disable-line + // eslint-disable-next-line + namespace jest { interface Matchers<R> { /** * Expect array to be filled with value, and optionally length diff --git a/src/chart_types/index.ts b/src/chart_types/index.ts new file mode 100644 index 0000000000..12f7dc46a2 --- /dev/null +++ b/src/chart_types/index.ts @@ -0,0 +1,9 @@ +import { $Values } from 'utility-types'; + +export const ChartTypes = Object.freeze({ + Global: 'global' as 'global', + Pie: 'pie' as 'pie', + XYAxis: 'xy_axis' as 'xy_axis', +}); + +export type ChartTypes = $Values<typeof ChartTypes>; diff --git a/src/chart_types/specs.ts b/src/chart_types/specs.ts new file mode 100644 index 0000000000..c969027460 --- /dev/null +++ b/src/chart_types/specs.ts @@ -0,0 +1,9 @@ +export { + AreaSeries, + BarSeries, + LineSeries, + Axis, + LineAnnotation, + RectAnnotation, + HistogramBarSeries, +} from './xy_chart/specs'; diff --git a/src/chart_types/xy_chart/annotations/annotation_marker.test.tsx b/src/chart_types/xy_chart/annotations/annotation_marker.test.tsx index dfa7e1c5de..46b9bc0b49 100644 --- a/src/chart_types/xy_chart/annotations/annotation_marker.test.tsx +++ b/src/chart_types/xy_chart/annotations/annotation_marker.test.tsx @@ -1,20 +1,16 @@ import * as React from 'react'; -import { AnnotationDomainTypes, AnnotationSpec, Position, Rotation } from '../utils/specs'; +import { AnnotationDomainTypes, AnnotationSpec, Position, Rotation, SpecTypes, AnnotationTypes } from '../utils/specs'; import { DEFAULT_ANNOTATION_LINE_STYLE } from '../../../utils/themes/theme'; import { Dimensions } from '../../../utils/dimensions'; -import { getAnnotationId, getGroupId, GroupId } from '../../../utils/ids'; +import { GroupId } from '../../../utils/ids'; import { ScaleContinuous } from '../../../utils/scales/scale_continuous'; import { Scale, ScaleType } from '../../../utils/scales/scales'; -import { - computeLineAnnotationDimensions, - isWithinLineMarkerBounds, - AnnotationMarker, - AnnotationLineProps, -} from './annotation_utils'; +import { computeLineAnnotationDimensions, AnnotationLineProps } from './line_annotation_tooltip'; +import { ChartTypes } from '../..'; describe('annotation marker', () => { - const groupId = getGroupId('foo-group'); + const groupId = 'foo-group'; const minRange = 0; const maxRange = 100; @@ -41,10 +37,12 @@ describe('annotation marker', () => { test('should compute line annotation dimensions with marker if defined (y domain)', () => { const chartRotation: Rotation = 0; - const annotationId = getAnnotationId('foo-line'); + const id = 'foo-line'; const lineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -95,10 +93,11 @@ describe('annotation marker', () => { test('should compute line annotation dimensions with marker if defined (y domain: 180 deg rotation)', () => { const chartRotation: Rotation = 180; - const annotationId = getAnnotationId('foo-line'); const lineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: 'foo-line', domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -148,10 +147,11 @@ describe('annotation marker', () => { test('should compute line annotation dimensions with marker if defined (x domain)', () => { const chartRotation: Rotation = 0; - const annotationId = getAnnotationId('foo-line'); const lineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: 'foo-line', domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -197,26 +197,4 @@ describe('annotation marker', () => { ]; expect(dimensions).toEqual(expectedDimensions); }); - - test('should compute if a point is within an annotation line marker bounds', () => { - const marker: AnnotationMarker = { - icon: <div />, - color: 'custom-color', - position: { top: 0, left: 0 }, - dimension: { width: 10, height: 10 }, - }; - expect(isWithinLineMarkerBounds({ x: -1, y: 0 }, marker)).toBe(false); - - expect(isWithinLineMarkerBounds({ x: 0, y: -1 }, marker)).toBe(false); - - expect(isWithinLineMarkerBounds({ x: 0, y: 0 }, marker)).toBe(true); - - expect(isWithinLineMarkerBounds({ x: 10, y: 10 }, marker)).toBe(true); - - expect(isWithinLineMarkerBounds({ x: 11, y: 10 }, marker)).toBe(false); - - expect(isWithinLineMarkerBounds({ x: 11, y: 10 }, { ...marker, position: { top: 0, left: 1 } })).toBe(true); - - expect(isWithinLineMarkerBounds({ x: 15, y: 15 }, { ...marker, position: { top: 10, left: 10 } })).toBe(true); - }); }); diff --git a/src/chart_types/xy_chart/annotations/annotation_utils.test.ts b/src/chart_types/xy_chart/annotations/annotation_utils.test.ts index 4b2c2ebaa5..465bc59a4d 100644 --- a/src/chart_types/xy_chart/annotations/annotation_utils.test.ts +++ b/src/chart_types/xy_chart/annotations/annotation_utils.test.ts @@ -7,37 +7,41 @@ import { Position, RectAnnotationSpec, Rotation, + SpecTypes, + AnnotationTypes, } from '../utils/specs'; import { DEFAULT_ANNOTATION_LINE_STYLE } from '../../../utils/themes/theme'; import { Dimensions } from '../../../utils/dimensions'; -import { AnnotationId, AxisId, getAnnotationId, getAxisId, getGroupId, GroupId } from '../../../utils/ids'; +import { getAxisId, getGroupId, GroupId, AnnotationId } from '../../../utils/ids'; import { ScaleBand } from '../../../utils/scales/scale_band'; import { ScaleContinuous } from '../../../utils/scales/scale_continuous'; import { Scale, ScaleType } from '../../../utils/scales/scales'; import { - AnnotationLineProps, computeAnnotationDimensions, computeAnnotationTooltipState, computeClusterOffset, - computeLineAnnotationDimensions, - computeLineAnnotationTooltipState, - computeRectAnnotationDimensions, - computeRectAnnotationTooltipState, - computeRectTooltipLeft, - computeRectTooltipTop, getAnnotationAxis, - getAnnotationLineTooltipXOffset, - getAnnotationLineTooltipYOffset, getRotatedCursor, - isBottomRectTooltip, - isRightRectTooltip, - isVerticalAnnotationLine, - isWithinRectBounds, scaleAndValidateDatum, - AnnotationTooltipState, AnnotationDimensions, + AnnotationTooltipState, + Bounds, } from './annotation_utils'; -import { Point } from '../store/chart_state'; +import { + AnnotationLineProps, + computeLineAnnotationDimensions, + computeLineAnnotationTooltipState, + isVerticalAnnotationLine, + getAnnotationLineTooltipXOffset, + getAnnotationLineTooltipYOffset, +} from './line_annotation_tooltip'; +import { + computeRectAnnotationDimensions, + isWithinRectBounds, + computeRectAnnotationTooltipState, +} from './rect_annotation_tooltip'; +import { Point } from '../../../utils/point'; +import { ChartTypes } from '../..'; describe('annotation utils', () => { const minRange = 0; @@ -65,8 +69,10 @@ describe('annotation utils', () => { const groupId = getGroupId('foo-group'); - const axesSpecs: Map<AxisId, AxisSpec> = new Map(); + const axesSpecs: AxisSpec[] = []; const verticalAxisSpec: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, id: getAxisId('vertical_axis'), groupId, hide: false, @@ -79,6 +85,8 @@ describe('annotation utils', () => { showGridLines: true, }; const horizontalAxisSpec: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, id: getAxisId('horizontal_axis'), groupId, hide: false, @@ -91,7 +99,7 @@ describe('annotation utils', () => { showGridLines: true, }; - axesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + axesSpecs.push(verticalAxisSpec); test('should compute annotation dimensions', () => { const chartRotation: Rotation = 0; @@ -100,27 +108,31 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; - const annotations: Map<AnnotationId, AnnotationSpec> = new Map(); - const annotationId = getAnnotationId('foo'); + const annotations: AnnotationSpec[] = []; + const annotationId = 'foo'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, style: DEFAULT_ANNOTATION_LINE_STYLE, }; - const rectAnnotationId = getAnnotationId('rect'); + const rectAnnotationId = 'rect'; const rectAnnotation: AnnotationSpec = { - annotationId: rectAnnotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: rectAnnotationId, groupId, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [{ coordinates: { x0: 'a', x1: 'b', y0: 3, y1: 5 } }], }; - annotations.set(annotationId, lineAnnotation); - annotations.set(rectAnnotationId, rectAnnotation); + annotations.push(lineAnnotation); + annotations.push(rectAnnotation); const dimensions = computeAnnotationDimensions( annotations, @@ -159,18 +171,20 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; - const annotations: Map<AnnotationId, AnnotationSpec> = new Map(); - const annotationId = getAnnotationId('foo'); + const annotations: AnnotationSpec[] = []; + const id = 'foo'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, style: DEFAULT_ANNOTATION_LINE_STYLE, }; - annotations.set(annotationId, lineAnnotation); + annotations.push(lineAnnotation); const dimensions = computeAnnotationDimensions( annotations, @@ -178,7 +192,7 @@ describe('annotation utils', () => { chartRotation, yScales, xScale, - new Map(), // empty axesSpecs + [], // empty axesSpecs 1, false, ); @@ -193,10 +207,12 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; - const annotationId = getAnnotationId('foo-line'); + const id = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -237,10 +253,12 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -281,10 +299,12 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -324,10 +344,12 @@ describe('annotation utils', () => { const yScales: Map<GroupId, Scale> = new Map(); const xScale: Scale = ordinalScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [], groupId, @@ -352,10 +374,12 @@ describe('annotation utils', () => { const yScales: Map<GroupId, Scale> = new Map(); const xScale: Scale = ordinalScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 'a', details: 'foo' }], groupId, @@ -394,10 +418,12 @@ describe('annotation utils', () => { const yScales: Map<GroupId, Scale> = new Map(); const xScale: Scale = continuousScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -437,10 +463,12 @@ describe('annotation utils', () => { const yScales: Map<GroupId, Scale> = new Map(); const xScale: Scale = continuousScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -480,10 +508,12 @@ describe('annotation utils', () => { const yScales: Map<GroupId, Scale> = new Map(); const xScale: Scale = continuousScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 10.5, details: 'foo' }], groupId, @@ -524,10 +554,12 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 'a', details: 'foo' }], groupId, @@ -568,10 +600,12 @@ describe('annotation utils', () => { const xScale: Scale = continuousScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -612,10 +646,12 @@ describe('annotation utils', () => { const xScale: Scale = continuousScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -656,10 +692,12 @@ describe('annotation utils', () => { const xScale: Scale = continuousScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -699,10 +737,12 @@ describe('annotation utils', () => { const yScales: Map<GroupId, Scale> = new Map(); const xScale: Scale = continuousScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -744,10 +784,12 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; - const annotationId = getAnnotationId('foo-line'); + const annotationId = 'foo-line'; const invalidXLineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 'e', details: 'foo' }], groupId, @@ -768,8 +810,10 @@ describe('annotation utils', () => { expect(emptyXDimensions).toEqual([]); const invalidStringXLineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: '', details: 'foo' }], groupId, @@ -790,8 +834,10 @@ describe('annotation utils', () => { expect(invalidStringXDimensions).toEqual([]); const outOfBoundsXLineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: -999, details: 'foo' }], groupId, @@ -812,8 +858,10 @@ describe('annotation utils', () => { expect(emptyOutOfBoundsXDimensions).toEqual([]); const invalidYLineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 'e', details: 'foo' }], groupId, @@ -834,8 +882,10 @@ describe('annotation utils', () => { expect(emptyYDimensions).toEqual([]); const outOfBoundsYLineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: -999, details: 'foo' }], groupId, @@ -856,8 +906,10 @@ describe('annotation utils', () => { expect(emptyOutOfBoundsYDimensions).toEqual([]); const invalidStringYLineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: '', details: 'foo' }], groupId, @@ -878,8 +930,10 @@ describe('annotation utils', () => { expect(invalidStringYDimensions).toEqual([]); const validHiddenAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.XDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -1007,7 +1061,8 @@ describe('annotation utils', () => { }, }, ]; - const localAxesSpecs = new Map(); + + const localAxesSpecs: AxisSpec[] = []; // missing annotation axis (xDomain) const missingTooltipState = computeLineAnnotationTooltipState( @@ -1021,7 +1076,7 @@ describe('annotation utils', () => { expect(missingTooltipState).toEqual({ isVisible: false }); // add axis for xDomain annotation - localAxesSpecs.set(horizontalAxisSpec.id, horizontalAxisSpec); + localAxesSpecs.push(horizontalAxisSpec); const xDomainTooltipState = computeLineAnnotationTooltipState( cursorPosition, @@ -1032,7 +1087,7 @@ describe('annotation utils', () => { ); const expectedXDomainTooltipState = { isVisible: true, - annotationType: 'line', + annotationType: AnnotationTypes.Line, anchor: { position: Position.Left, top: 0, @@ -1057,13 +1112,13 @@ describe('annotation utils', () => { top: 0, left: 0, }, - annotationType: 'line', + annotationType: AnnotationTypes.Line, }; expect(xDomainRotatedTooltipState).toEqual(expectedXDomainRotatedTooltipState); // add axis for yDomain annotation - localAxesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + localAxesSpecs.push(verticalAxisSpec); const yDomainTooltipState = computeLineAnnotationTooltipState( cursorPosition, @@ -1079,7 +1134,7 @@ describe('annotation utils', () => { top: 0, left: 0, }, - annotationType: 'line', + annotationType: AnnotationTypes.Line, }; expect(yDomainTooltipState).toEqual(expectedYDomainTooltipState); @@ -1098,7 +1153,7 @@ describe('annotation utils', () => { top: 0, left: 0, }, - annotationType: 'line', + annotationType: AnnotationTypes.Line, }; expect(flippedYDomainTooltipState).toEqual(expectedFlippedYDomainTooltipState); @@ -1117,18 +1172,20 @@ describe('annotation utils', () => { top: 0, left: 0, }, - annotationType: 'line', + annotationType: AnnotationTypes.Line, }; expect(rotatedYDomainTooltipState).toEqual(expectedRotatedYDomainTooltipState); }); test('should compute the tooltip state for an annotation', () => { - const annotations: Map<AnnotationId, AnnotationSpec> = new Map(); - const annotationId = getAnnotationId('foo'); + const annotations: AnnotationSpec[] = []; + const annotationId = 'foo'; const lineAnnotation: LineAnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -1155,7 +1212,7 @@ describe('annotation utils', () => { }, ]; const chartRotation: Rotation = 0; - const localAxesSpecs: Map<AxisId, AxisSpec> = new Map(); + const localAxesSpecs: AxisSpec[] = []; const annotationDimensions = new Map(); annotationDimensions.set(annotationId, annotationLines); @@ -1173,8 +1230,8 @@ describe('annotation utils', () => { expect(missingSpecTooltipState).toBe(null); // add valid annotation axis - annotations.set(annotationId, lineAnnotation); - localAxesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + annotations.push(lineAnnotation); + localAxesSpecs.push(verticalAxisSpec); // hide tooltipState lineAnnotation.hideTooltips = true; @@ -1220,7 +1277,7 @@ describe('annotation utils', () => { const expectedTooltipState = { isVisible: true, - annotationType: 'line', + annotationType: AnnotationTypes.Line, anchor: { top: 0, left: 0, @@ -1232,17 +1289,19 @@ describe('annotation utils', () => { // rect annotation tooltip const annotationRectangle: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [{ coordinates: { x0: 1, x1: 2, y0: 3, y1: 5 } }], }; - const rectAnnotations = new Map(); - rectAnnotations.set(annotationRectangle.annotationId, annotationRectangle); + const rectAnnotations: RectAnnotationSpec[] = []; + rectAnnotations.push(annotationRectangle); const rectAnnotationDimensions = [{ rect: { x: 2, y: 3, width: 3, height: 5 } }]; - annotationDimensions.set(annotationRectangle.annotationId, rectAnnotationDimensions); + annotationDimensions.set(annotationRectangle.id, rectAnnotationDimensions); const rectTooltipState = computeAnnotationTooltipState( { x: 3, y: 4 }, @@ -1255,7 +1314,7 @@ describe('annotation utils', () => { expect(rectTooltipState).toEqual({ isVisible: true, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, anchor: { top: 4, left: 3, @@ -1276,13 +1335,13 @@ describe('annotation utils', () => { }); test('should get associated axis for an annotation', () => { - const localAxesSpecs = new Map(); + const localAxesSpecs: AxisSpec[] = []; const noAxis = getAnnotationAxis(localAxesSpecs, groupId, AnnotationDomainTypes.XDomain, 0); expect(noAxis).toBe(null); - localAxesSpecs.set(horizontalAxisSpec.id, horizontalAxisSpec); - localAxesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + localAxesSpecs.push(horizontalAxisSpec); + localAxesSpecs.push(verticalAxisSpec); const xAnnotationAxisPosition = getAnnotationAxis(localAxesSpecs, groupId, AnnotationDomainTypes.XDomain, 0); expect(xAnnotationAxisPosition).toEqual(Position.Bottom); @@ -1297,9 +1356,11 @@ describe('annotation utils', () => { const xScale: Scale = continuousScale; const annotationRectangle: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId: getGroupId('foo'), - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [{ coordinates: { x0: 1, x1: 2, y0: 3, y1: 5 } }], }; @@ -1314,9 +1375,11 @@ describe('annotation utils', () => { const xScale: Scale = continuousScale; const annotationRectangle: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [ { coordinates: { x0: 1, x1: 2, y0: -10, y1: 5 } }, { coordinates: { x0: null, x1: null, y0: null, y1: null } }, @@ -1337,9 +1400,11 @@ describe('annotation utils', () => { ); const annotationRectangle: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [ { coordinates: { x0: 1, x1: null, y0: null, y1: null } }, { coordinates: { x0: null, x1: 1, y0: null, y1: null } }, @@ -1378,9 +1443,11 @@ describe('annotation utils', () => { const xScale: Scale = continuousScale; const annotationRectangle: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [ { coordinates: { x0: 1, x1: null, y0: null, y1: null } }, { coordinates: { x0: null, x1: 1, y0: null, y1: null } }, @@ -1407,9 +1474,11 @@ describe('annotation utils', () => { const xScale: Scale = continuousScale; const annotationRectangle: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [{ coordinates: { x0: 1, x1: 2, y0: 3, y1: 5 } }], }; @@ -1424,9 +1493,11 @@ describe('annotation utils', () => { const xScale: Scale = ordinalScale; const annotationRectangle: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [{ coordinates: { x0: 'a', x1: 'b', y0: 0, y1: 2 } }], }; @@ -1454,11 +1525,11 @@ describe('annotation utils', () => { test('should determine if a point is within a rectangle annotation', () => { const cursorPosition = { x: 3, y: 4 }; - const outOfXBounds = { startX: 4, endX: 5, startY: 3, endY: 5 }; - const outOfYBounds = { startX: 2, endX: 4, startY: 5, endY: 6 }; - const withinBounds = { startX: 2, endX: 4, startY: 3, endY: 5 }; - const withinBoundsReverseXScale = { startX: 4, endX: 2, startY: 3, endY: 5 }; - const withinBoundsReverseYScale = { startX: 2, endX: 4, startY: 5, endY: 3 }; + const outOfXBounds: Bounds = { startX: 4, endX: 5, startY: 3, endY: 5 }; + const outOfYBounds: Bounds = { startX: 2, endX: 4, startY: 5, endY: 6 }; + const withinBounds: Bounds = { startX: 2, endX: 4, startY: 3, endY: 5 }; + const withinBoundsReverseXScale: Bounds = { startX: 4, endX: 2, startY: 3, endY: 5 }; + const withinBoundsReverseYScale: Bounds = { startX: 2, endX: 4, startY: 5, endY: 3 }; // chart rotation 0 expect(isWithinRectBounds(cursorPosition, outOfXBounds)).toBe(false); @@ -1488,66 +1559,6 @@ describe('annotation utils', () => { expect(isWithinRectBounds(cursorPosition, withinBoundsReverseXScale)).toBe(false); expect(isWithinRectBounds(cursorPosition, withinBoundsReverseYScale)).toBe(false); }); - test('should determine if an annotation has a rightward tooltip based on cursor position', () => { - const cursor1 = { x: 8, y: 0 }; - const cursor2 = { x: 0, y: 8 }; - - // chart rotation 0 - expect(isRightRectTooltip(0, cursor1, 10)).toBe(false); - expect(isRightRectTooltip(0, cursor2, 10)).toBe(true); - - // chart rotation 180 - expect(isRightRectTooltip(180, cursor1, 10)).toBe(false); - expect(isRightRectTooltip(180, cursor2, 10)).toBe(true); - - // chart rotation 90 - expect(isRightRectTooltip(90, cursor1, 10)).toBe(true); - expect(isRightRectTooltip(90, cursor2, 10)).toBe(false); - - // chart rotation -90 - expect(isRightRectTooltip(-90, cursor1, 10)).toBe(false); - expect(isRightRectTooltip(-90, cursor2, 10)).toBe(true); - }); - test('should determine if an annotation has a bottomward tooltip based on cursor position', () => { - const cursor1 = { x: 8, y: 0 }; - const cursor2 = { x: 0, y: 8 }; - - // chart rotation 0 - expect(isBottomRectTooltip(0, cursor1, 10)).toBe(true); - expect(isBottomRectTooltip(0, cursor2, 10)).toBe(false); - - // chart rotation 180 - expect(isBottomRectTooltip(180, cursor1, 10)).toBe(false); - expect(isBottomRectTooltip(180, cursor2, 10)).toBe(true); - - // chart rotation 90 - expect(isBottomRectTooltip(90, cursor1, 10)).toBe(false); - expect(isBottomRectTooltip(90, cursor2, 10)).toBe(true); - - // chart rotation -90 - expect(isBottomRectTooltip(-90, cursor1, 10)).toBe(false); - expect(isBottomRectTooltip(-90, cursor2, 10)).toBe(true); - }); - test('should compute rect annotation tooltip left', () => { - const isRightTooltip = true; - const xPosition = { startX: 2, endX: 4 }; - const cursorX = 3; - const chartWidth = 10; - - expect(computeRectTooltipLeft(0, isRightTooltip, xPosition, cursorX, chartWidth)).toBe(4); - expect(computeRectTooltipLeft(180, !isRightTooltip, xPosition, cursorX, chartWidth)).toBe(8); - expect(computeRectTooltipLeft(90, isRightTooltip, xPosition, cursorX, chartWidth)).toBe(3); - }); - test('should compute rect annotation tooltip top', () => { - const isBottomTooltip = true; - const xPosition = { startX: 2, endX: 4 }; - const cursorY = 3; - const chartHeight = 10; - - expect(computeRectTooltipTop(0, isBottomTooltip, xPosition, cursorY, chartHeight)).toBe(3); - expect(computeRectTooltipTop(90, isBottomTooltip, xPosition, cursorY, chartHeight)).toBe(4); - expect(computeRectTooltipTop(-90, !isBottomTooltip, xPosition, cursorY, chartHeight)).toBe(8); - }); test('should compute tooltip state for rect annotation', () => { const cursorPosition = { x: 3, y: 4 }; const annotationRects = [{ rect: { x: 2, y: 3, width: 3, height: 5 } }]; @@ -1555,7 +1566,7 @@ describe('annotation utils', () => { const visibleTooltip = computeRectAnnotationTooltipState(cursorPosition, annotationRects, 0, chartDimensions); const expectedVisibleTooltipState: AnnotationTooltipState = { isVisible: true, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, anchor: { top: 4, left: 3, diff --git a/src/chart_types/xy_chart/annotations/annotation_utils.ts b/src/chart_types/xy_chart/annotations/annotation_utils.ts index e0cdc4e110..a278287ebf 100644 --- a/src/chart_types/xy_chart/annotations/annotation_utils.ts +++ b/src/chart_types/xy_chart/annotations/annotation_utils.ts @@ -3,25 +3,28 @@ import { AnnotationDomainTypes, AnnotationSpec, AnnotationType, - AnnotationTypes, AxisSpec, HistogramModeAlignments, isLineAnnotation, isRectAnnotation, - LineAnnotationDatum, - LineAnnotationSpec, Position, - RectAnnotationDatum, - RectAnnotationSpec, Rotation, } from '../utils/specs'; -import { isHorizontalAxis } from '../utils/axis_utils'; -import { LineAnnotationStyle } from '../../../utils/themes/theme'; import { Dimensions } from '../../../utils/dimensions'; -import { AnnotationId, AxisId, GroupId } from '../../../utils/ids'; +import { AnnotationId, GroupId } from '../../../utils/ids'; import { Scale, ScaleType } from '../../../utils/scales/scales'; -import { Point } from '../store/chart_state'; -import { computeXScaleOffset, getAxesSpecForSpecId, isHorizontalRotation } from '../store/utils'; +import { computeXScaleOffset, getAxesSpecForSpecId, isHorizontalRotation, getSpecsById } from '../state/utils'; +import { Point } from '../../../utils/point'; +import { + computeLineAnnotationTooltipState, + AnnotationLineProps, + computeLineAnnotationDimensions, +} from './line_annotation_tooltip'; +import { + computeRectAnnotationTooltipState, + AnnotationRectProps, + computeRectAnnotationDimensions, +} from './rect_annotation_tooltip'; export type AnnotationTooltipFormatter = (details?: string) => JSX.Element | null; @@ -37,11 +40,17 @@ export interface AnnotationTooltipVisibleState { export interface AnnotationTooltipHiddenState { isVisible: false; } +/** + * The header and description strings for an Annotation + */ export interface AnnotationDetails { headerText?: string; detailsText?: string; } +/** + * The marker for an Annotation. Usually a JSX element + */ export interface AnnotationMarker { icon: JSX.Element; position: { top: number; left: number }; @@ -49,344 +58,9 @@ export interface AnnotationMarker { color: string; } -/** - * The path points of a line annotation. - */ -export type AnnotationLinePathPoints = { - /** x1,y1 the start point anchored to the linked axis */ - start: { - x1: number; - y1: number; - }; - /** x2,y2 the end point */ - end: { - x2: number; - y2: number; - }; -}; - -export interface AnnotationLineProps { - /** the position of the start point relative to the Chart */ - anchor: { - position: Position; - top: number; - left: number; - }; - /** - * The path points of a line annotation - */ - linePathPoints: AnnotationLinePathPoints; - details: AnnotationDetails; - marker?: AnnotationMarker; -} - -export interface AnnotationRectProps { - rect: { - x: number; - y: number; - width: number; - height: number; - }; - details?: string; -} - -// TODO: add AnnotationTextProps export type AnnotationDimensions = AnnotationLineProps[] | AnnotationRectProps[]; -export function computeYDomainLineAnnotationDimensions( - dataValues: LineAnnotationDatum[], - yScale: Scale, - chartRotation: Rotation, - axisPosition: Position, - chartDimensions: Dimensions, - lineColor: string, - marker?: JSX.Element, - markerDimension = { width: 0, height: 0 }, -): AnnotationLineProps[] { - const chartHeight = chartDimensions.height; - const chartWidth = chartDimensions.width; - const isHorizontalChartRotation = isHorizontalRotation(chartRotation); - - const lineProps: AnnotationLineProps[] = []; - - dataValues.forEach((datum: LineAnnotationDatum) => { - const { dataValue } = datum; - - // avoid rendering invalid annotation value - if (dataValue === null || dataValue === undefined || dataValue === '') { - return; - } - - const annotationValueYposition = yScale.scale(dataValue); - // avoid rendering non scalable annotation values - if (isNaN(annotationValueYposition)) { - return; - } - - const [domainStart, domainEnd] = yScale.domain; - // avoid rendering annotation with values outside the scale domain - if (domainStart > dataValue || domainEnd < dataValue) { - return; - } - const anchor = { - position: axisPosition, - top: 0, - left: 0, - }; - const markerPosition = { top: 0, left: 0 }; - const linePathPoints: AnnotationLinePathPoints = { - start: { x1: 0, y1: 0 }, - end: { x2: 0, y2: 0 }, - }; - // the Y axis is vertical, X axis is horizontal y|--x--|y - if (isHorizontalChartRotation) { - // y|__x__ - if (axisPosition === Position.Left) { - anchor.left = 0; - markerPosition.left = -markerDimension.width; - linePathPoints.start.x1 = 0; - linePathPoints.end.x2 = chartWidth; - // __x__|y - } else { - anchor.left = chartWidth; - markerPosition.left = chartWidth; - linePathPoints.start.x1 = chartWidth; - linePathPoints.end.x2 = 0; - } - // __x__ - if (chartRotation === 0) { - anchor.top = annotationValueYposition; - markerPosition.top = annotationValueYposition - markerDimension.height / 2; - // ¯¯x¯¯ - } else { - anchor.top = chartHeight - annotationValueYposition; - markerPosition.top = chartHeight - annotationValueYposition - markerDimension.height / 2; - } - linePathPoints.start.y1 = annotationValueYposition; - linePathPoints.end.y2 = annotationValueYposition; - // the Y axis is horizontal, X axis is vertical x|--y--|x - } else { - // ¯¯y¯¯ - if (axisPosition === Position.Top) { - anchor.top = 0; - markerPosition.top = -markerDimension.height; - linePathPoints.start.x1 = 0; - linePathPoints.end.x2 = chartHeight; - // __y__ - } else { - anchor.top = chartHeight; - markerPosition.top = chartHeight; - linePathPoints.start.x1 = chartHeight; - linePathPoints.end.x2 = 0; - } - // __y__|x - if (chartRotation === -90) { - anchor.left = annotationValueYposition; - markerPosition.left = annotationValueYposition - markerDimension.width / 2; - // x|__y__ - } else { - anchor.left = chartWidth - annotationValueYposition; - markerPosition.left = chartWidth - annotationValueYposition - markerDimension.width / 2; - } - linePathPoints.start.y1 = annotationValueYposition; - linePathPoints.end.y2 = annotationValueYposition; - } - - const annotationMarker: AnnotationMarker | undefined = marker - ? { - icon: marker, - color: lineColor, - dimension: markerDimension, - position: markerPosition, - } - : undefined; - const lineProp: AnnotationLineProps = { - anchor, - linePathPoints, - marker: annotationMarker, - details: { - detailsText: datum.details, - headerText: datum.header || dataValue.toString(), - }, - }; - - lineProps.push(lineProp); - }); - - return lineProps; -} - -export function computeXDomainLineAnnotationDimensions( - dataValues: LineAnnotationDatum[], - xScale: Scale, - chartRotation: Rotation, - axisPosition: Position, - chartDimensions: Dimensions, - lineColor: string, - xScaleOffset: number, - enableHistogramMode: boolean, - marker?: JSX.Element, - markerDimension = { width: 0, height: 0 }, -): AnnotationLineProps[] { - const chartHeight = chartDimensions.height; - const chartWidth = chartDimensions.width; - const lineProps: AnnotationLineProps[] = []; - const isHorizontalChartRotation = isHorizontalRotation(chartRotation); - - const alignWithTick = xScale.bandwidth > 0 && !enableHistogramMode; - dataValues.forEach((datum: LineAnnotationDatum) => { - const { dataValue } = datum; - - const scaledXValue = scaleAndValidateDatum(dataValue, xScale, alignWithTick); - - if (scaledXValue == null) { - return; - } - - const offset = xScale.bandwidth / 2 - xScaleOffset; - const annotationValueXposition = scaledXValue + offset; - - const markerPosition = { top: 0, left: 0 }; - const linePathPoints: AnnotationLinePathPoints = { - start: { x1: 0, y1: 0 }, - end: { x2: 0, y2: 0 }, - }; - const anchor = { - position: axisPosition, - top: 0, - left: 0, - }; - // the Y axis is vertical, X axis is horizontal y|--x--|y - if (isHorizontalChartRotation) { - // __x__ - if (axisPosition === Position.Bottom) { - linePathPoints.start.y1 = chartHeight; - linePathPoints.end.y2 = 0; - anchor.top = chartHeight; - markerPosition.top = chartHeight; - // ¯¯x¯¯ - } else { - linePathPoints.start.y1 = 0; - linePathPoints.end.y2 = chartHeight; - anchor.top = 0; - markerPosition.top = 0 - markerDimension.height; - } - // __x__ - if (chartRotation === 0) { - anchor.left = annotationValueXposition; - markerPosition.left = annotationValueXposition - markerDimension.width / 2; - // ¯¯x¯¯ - } else { - anchor.left = chartWidth - annotationValueXposition; - markerPosition.left = chartWidth - annotationValueXposition - markerDimension.width / 2; - } - linePathPoints.start.x1 = annotationValueXposition; - linePathPoints.end.x2 = annotationValueXposition; - // the Y axis is horizontal, X axis is vertical x|--y--|x - } else { - // x|--y-- - if (axisPosition === Position.Left) { - anchor.left = 0; - markerPosition.left = -markerDimension.width; - linePathPoints.start.x1 = annotationValueXposition; - linePathPoints.end.x2 = annotationValueXposition; - // --y--|x - } else { - anchor.left = chartWidth; - markerPosition.left = chartWidth; - linePathPoints.start.x1 = annotationValueXposition; - linePathPoints.end.x2 = annotationValueXposition; - } - // __y__|x - if (chartRotation === -90) { - anchor.top = chartHeight - annotationValueXposition; - markerPosition.top = chartHeight - annotationValueXposition - markerDimension.height / 2; - linePathPoints.start.y1 = 0; - linePathPoints.end.y2 = chartWidth; - // x|__y__ - } else { - anchor.top = annotationValueXposition; - markerPosition.top = annotationValueXposition - markerDimension.height / 2; - linePathPoints.start.y1 = 0; - linePathPoints.end.y2 = chartWidth; - } - } - - const annotationMarker: AnnotationMarker | undefined = marker - ? { - icon: marker, - color: lineColor, - dimension: markerDimension, - position: markerPosition, - } - : undefined; - const lineProp: AnnotationLineProps = { - anchor, - linePathPoints, - details: { - detailsText: datum.details, - headerText: datum.header || dataValue.toString(), - }, - marker: annotationMarker, - }; - lineProps.push(lineProp); - }); - - return lineProps; -} - -export function computeLineAnnotationDimensions( - annotationSpec: LineAnnotationSpec, - chartDimensions: Dimensions, - chartRotation: Rotation, - yScales: Map<GroupId, Scale>, - xScale: Scale, - axisPosition: Position, - xScaleOffset: number, - enableHistogramMode: boolean, -): AnnotationLineProps[] | null { - const { domainType, dataValues, marker, markerDimensions, hideLines } = annotationSpec; - - if (hideLines) { - return null; - } - - // this type is guaranteed as this has been merged with default - const lineStyle = annotationSpec.style as LineAnnotationStyle; - const lineColor = lineStyle.line.stroke; - - if (domainType === AnnotationDomainTypes.XDomain) { - return computeXDomainLineAnnotationDimensions( - dataValues, - xScale, - chartRotation, - axisPosition, - chartDimensions, - lineColor, - xScaleOffset, - enableHistogramMode, - marker, - markerDimensions, - ); - } - - const groupId = annotationSpec.groupId; - const yScale = yScales.get(groupId); - if (!yScale) { - return null; - } - - return computeYDomainLineAnnotationDimensions( - dataValues, - yScale, - chartRotation, - axisPosition, - chartDimensions, - lineColor, - marker, - markerDimensions, - ); -} +export type Bounds = { startX: number; endX: number; startY: number; endY: number }; export function scaleAndValidateDatum(dataValue: any, scale: Scale, alignWithTick: boolean): number | null { const isContinuous = scale.type !== ScaleType.Ordinal; @@ -410,107 +84,8 @@ export function scaleAndValidateDatum(dataValue: any, scale: Scale, alignWithTic return scaledValue; } -export function computeRectAnnotationDimensions( - annotationSpec: RectAnnotationSpec, - yScales: Map<GroupId, Scale>, - xScale: Scale, - enableHistogramMode: boolean, - barsPadding: number, -): AnnotationRectProps[] | null { - const { dataValues } = annotationSpec; - - const groupId = annotationSpec.groupId; - const yScale = yScales.get(groupId); - if (!yScale) { - return null; - } - - const xDomain = xScale.domain; - const yDomain = yScale.domain; - const lastX = xDomain[xDomain.length - 1]; - const xMinInterval = xScale.minInterval; - const rectsProps: AnnotationRectProps[] = []; - - dataValues.forEach((dataValue: RectAnnotationDatum) => { - let { x0, x1, y0, y1 } = dataValue.coordinates; - - // if everything is null, return; otherwise we coerce the other coordinates - if (x0 == null && x1 == null && y0 == null && y1 == null) { - return; - } - - if (x1 == null) { - // if x1 is defined, we want the rect to draw to the end of the scale - // if we're in histogram mode, extend domain end by min interval - x1 = enableHistogramMode && !xScale.isSingleValue() ? lastX + xMinInterval : lastX; - } - - if (x0 == null) { - // if x0 is defined, we want the rect to draw to the start of the scale - x0 = xDomain[0]; - } - - if (y0 == null) { - // if y0 is defined, we want the rect to draw to the end of the scale - y0 = yDomain[yDomain.length - 1]; - } - - if (y1 == null) { - // if y1 is defined, we want the rect to draw to the start of the scale - y1 = yDomain[0]; - } - - const alignWithTick = xScale.bandwidth > 0 && !enableHistogramMode; - - let x0Scaled = scaleAndValidateDatum(x0, xScale, alignWithTick); - let x1Scaled = scaleAndValidateDatum(x1, xScale, alignWithTick); - const y0Scaled = scaleAndValidateDatum(y0, yScale, false); - const y1Scaled = scaleAndValidateDatum(y1, yScale, false); - - // TODO: surface this as a warning - if (x0Scaled === null || x1Scaled === null || y0Scaled === null || y1Scaled === null) { - return; - } - - let xOffset = 0; - if (xScale.bandwidth > 0) { - const xBand = xScale.bandwidth / (1 - xScale.barsPadding); - xOffset = enableHistogramMode ? (xBand - xScale.bandwidth) / 2 : barsPadding; - } - - x0Scaled = x0Scaled - xOffset; - x1Scaled = x1Scaled - xOffset; - - const minX = Math.min(x0Scaled, x1Scaled); - const minY = Math.min(y0Scaled, y1Scaled); - - const deltaX = Math.abs(x0Scaled - x1Scaled); - const deltaY = Math.abs(y0Scaled - y1Scaled); - - const xOrigin = minX; - const yOrigin = minY; - - const width = deltaX; - const height = deltaY; - - const rectDimensions = { - x: xOrigin, - y: yOrigin, - width, - height, - }; - - rectsProps.push({ - rect: rectDimensions, - details: dataValue.details, - }); - }); - - return rectsProps; -} - export function getAnnotationAxis( - axesSpecs: Map<AxisId, AxisSpec>, + axesSpecs: AxisSpec[], groupId: GroupId, domainType: AnnotationDomainType, chartRotation: Rotation, @@ -531,13 +106,37 @@ export function computeClusterOffset(totalBarsInCluster: number, barsShift: numb return 0; } +export function isXDomain(domainType: AnnotationDomainType): boolean { + return domainType === AnnotationDomainTypes.XDomain; +} + +export function getRotatedCursor( + /** the cursor position relative to the projection area */ + cursorPosition: Point, + chartDimensions: Dimensions, + chartRotation: Rotation, +): Point { + const { x, y } = cursorPosition; + const { height, width } = chartDimensions; + switch (chartRotation) { + case 0: + return { x, y }; + case 90: + return { x: y, y: width - x }; + case -90: + return { x: height - y, y: x }; + case 180: + return { x: width - x, y: height - y }; + } +} + export function computeAnnotationDimensions( - annotations: Map<AnnotationId, AnnotationSpec>, + annotations: AnnotationSpec[], chartDimensions: Dimensions, chartRotation: Rotation, yScales: Map<GroupId, Scale>, xScale: Scale, - axesSpecs: Map<AxisId, AxisSpec>, + axesSpecs: AxisSpec[], totalBarsInCluster: number, enableHistogramMode: boolean, ): Map<AnnotationId, AnnotationDimensions> { @@ -553,7 +152,8 @@ export function computeAnnotationDimensions( // Annotations should always align with the axis line in histogram mode const xScaleOffset = computeXScaleOffset(xScale, enableHistogramMode, HistogramModeAlignments.Start); - annotations.forEach((annotationSpec: AnnotationSpec, annotationId: AnnotationId) => { + annotations.forEach((annotationSpec) => { + const { id } = annotationSpec; if (isLineAnnotation(annotationSpec)) { const { groupId, domainType } = annotationSpec; const annotationAxisPosition = getAnnotationAxis(axesSpecs, groupId, domainType, chartRotation); @@ -573,7 +173,7 @@ export function computeAnnotationDimensions( ); if (dimensions) { - annotationDimensions.set(annotationId, dimensions); + annotationDimensions.set(id, dimensions); } } else if (isRectAnnotation(annotationSpec)) { const dimensions = computeRectAnnotationDimensions( @@ -585,7 +185,7 @@ export function computeAnnotationDimensions( ); if (dimensions) { - annotationDimensions.set(annotationId, dimensions); + annotationDimensions.set(id, dimensions); } } }); @@ -593,210 +193,16 @@ export function computeAnnotationDimensions( return annotationDimensions; } -/** - * Checks if the cursorPosition is within the line annotation marker - * @param cursorPosition the cursor position relative to the projected area - * @param marker the line annotation marker - */ -export function isWithinLineMarkerBounds(cursorPosition: Point, marker: AnnotationMarker): boolean { - const { top, left } = marker.position; - const { width, height } = marker.dimension; - const markerRect = { startX: left, startY: top, endX: left + width, endY: top + height }; - return isWithinRectBounds(cursorPosition, markerRect); -} - -export function isVerticalAnnotationLine(isXDomainAnnotation: boolean, isHorizontalChartRotation: boolean): boolean { - if (isXDomainAnnotation) { - return isHorizontalChartRotation; - } - - return !isHorizontalChartRotation; -} - -export function getAnnotationLineTooltipXOffset(chartRotation: Rotation, axisPosition: Position): number { - let xOffset = 0; - const isChartHorizontalRotation = isHorizontalRotation(chartRotation); - - if (isHorizontalAxis(axisPosition)) { - xOffset = isChartHorizontalRotation ? 50 : 0; - } else { - xOffset = isChartHorizontalRotation ? (axisPosition === Position.Right ? 100 : 0) : 50; - } - - return xOffset; -} - -export function getAnnotationLineTooltipYOffset(chartRotation: Rotation, axisPosition: Position): number { - let yOffset = 0; - const isChartHorizontalRotation = isHorizontalRotation(chartRotation); - - if (isHorizontalAxis(axisPosition)) { - yOffset = isChartHorizontalRotation ? (axisPosition === Position.Top ? 0 : 100) : 50; - } else { - yOffset = isChartHorizontalRotation ? 50 : 100; - } - - return yOffset; -} - -export function isXDomain(domainType: AnnotationDomainType): boolean { - return domainType === AnnotationDomainTypes.XDomain; -} - -export function computeLineAnnotationTooltipState( - cursorPosition: Point, - annotationLines: AnnotationLineProps[], - groupId: GroupId, - domainType: AnnotationDomainType, - axesSpecs: Map<AxisId, AxisSpec>, -): AnnotationTooltipState { - const { xAxis, yAxis } = getAxesSpecForSpecId(axesSpecs, groupId); - const isXDomainAnnotation = isXDomain(domainType); - const annotationAxis = isXDomainAnnotation ? xAxis : yAxis; - - if (!annotationAxis) { - return { - isVisible: false, - }; - } - - const totalAnnotationLines = annotationLines.length; - for (let i = 0; i < totalAnnotationLines; i++) { - const line = annotationLines[i]; - const isWithinBounds = line.marker && isWithinLineMarkerBounds(cursorPosition, line.marker); - - if (isWithinBounds) { - return { - annotationType: AnnotationTypes.Line, - isVisible: true, - anchor: { - ...line.anchor, - }, - ...(line.details && { header: line.details.headerText }), - ...(line.details && { details: line.details.detailsText }), - }; - } - } - return { - isVisible: false, - }; -} - -export function isWithinRectBounds( - cursorPosition: Point, - { startX, endX, startY, endY }: { startX: number; endX: number; startY: number; endY: number }, -): boolean { - const withinXBounds = cursorPosition.x >= startX && cursorPosition.x <= endX; - const withinYBounds = cursorPosition.y >= startY && cursorPosition.y <= endY; - - return withinXBounds && withinYBounds; -} - -export function isRightRectTooltip(chartRotation: Rotation, cursorPosition: Point, chartWidth: number) { - const xPosition = isHorizontalRotation(chartRotation) ? cursorPosition.x : cursorPosition.y; - - return chartRotation === -90 ? xPosition > chartWidth / 2 : xPosition < chartWidth / 2; -} - -export function isBottomRectTooltip(chartRotation: Rotation, cursorPosition: Point, chartHeight: number) { - const yPosition = isHorizontalRotation(chartRotation) ? cursorPosition.y : cursorPosition.x; - return chartRotation === 180 ? yPosition > chartHeight / 2 : yPosition < chartHeight / 2; -} - -export function computeRectTooltipLeft( - chartRotation: Rotation, - isRightTooltip: boolean, - { startX, endX }: { startX: number; endX: number }, - cursorX: number, - chartWidth: number, -): number { - const isHorizontalChartRotation = isHorizontalRotation(chartRotation); - const horizontalLeft = isRightTooltip ? endX : startX; - return isHorizontalChartRotation ? (chartRotation === 180 ? chartWidth - horizontalLeft : horizontalLeft) : cursorX; -} - -export function computeRectTooltipTop( - chartRotation: Rotation, - isBottomTooltip: boolean, - { startX, endX }: { startX: number; endX: number }, - cursorY: number, - chartHeight: number, -): number { - const isHorizontalChartRotation = isHorizontalRotation(chartRotation); - const verticalTop = isBottomTooltip ? endX : startX; - - return isHorizontalChartRotation ? cursorY : chartRotation === -90 ? chartHeight - verticalTop : verticalTop; -} - -export function getRotatedCursor( - /** the cursor position relative to the projection area */ - cursorPosition: Point, - chartDimensions: Dimensions, - chartRotation: Rotation, -): Point { - const { x, y } = cursorPosition; - const { height, width } = chartDimensions; - switch (chartRotation) { - case 0: - return { x, y }; - case 90: - return { x: y, y: width - x }; - case -90: - return { x: height - y, y: x }; - case 180: - return { x: width - x, y: height - y }; - } -} - -export function computeRectAnnotationTooltipState( - /** the cursor position relative to the projection area */ - cursorPosition: Point, - annotationRects: AnnotationRectProps[], - chartRotation: Rotation, - chartDimensions: Dimensions, - renderTooltip?: AnnotationTooltipFormatter, -): AnnotationTooltipState { - const rotatedCursorPosition = getRotatedCursor(cursorPosition, chartDimensions, chartRotation); - - const totalAnnotationRect = annotationRects.length; - for (let i = 0; i < totalAnnotationRect; i++) { - const rectProps = annotationRects[i]; - const { rect, details } = rectProps; - const startX = rect.x; - const endX = startX + rect.width; - - const startY = rect.y; - const endY = startY + rect.height; - - const isWithinBounds = isWithinRectBounds(rotatedCursorPosition, { startX, endX, startY, endY }); - if (isWithinBounds) { - return { - isVisible: true, - annotationType: AnnotationTypes.Rectangle, - anchor: { - left: rotatedCursorPosition.x, - top: rotatedCursorPosition.y, - }, - ...(details && { details }), - ...(renderTooltip && { renderTooltip }), - }; - } - } - return { - isVisible: false, - }; -} - export function computeAnnotationTooltipState( cursorPosition: Point, annotationDimensions: Map<AnnotationId, any>, - annotationSpecs: Map<AnnotationId, AnnotationSpec>, + annotationSpecs: AnnotationSpec[], chartRotation: Rotation, - axesSpecs: Map<AxisId, AxisSpec>, + axesSpecs: AxisSpec[], chartDimensions: Dimensions, ): AnnotationTooltipState | null { for (const [annotationId, annotationDimension] of annotationDimensions) { - const spec = annotationSpecs.get(annotationId); + const spec = getSpecsById<AnnotationSpec>(annotationSpecs, annotationId); if (!spec || spec.hideTooltips) { continue; diff --git a/src/chart_types/xy_chart/annotations/line_annotation_tooltip.ts b/src/chart_types/xy_chart/annotations/line_annotation_tooltip.ts new file mode 100644 index 0000000000..6b681b98cc --- /dev/null +++ b/src/chart_types/xy_chart/annotations/line_annotation_tooltip.ts @@ -0,0 +1,447 @@ +import { + AnnotationDomainType, + AnnotationDomainTypes, + AnnotationTypes, + Position, + Rotation, + LineAnnotationSpec, + LineAnnotationDatum, + AxisSpec, +} from '../utils/specs'; +import { + AnnotationTooltipState, + AnnotationDetails, + AnnotationMarker, + scaleAndValidateDatum, + isXDomain, + Bounds, +} from './annotation_utils'; +import { isHorizontalRotation, getAxesSpecForSpecId } from '../state/utils'; +import { isHorizontalAxis } from '../utils/axis_utils'; +import { Dimensions } from '../../../utils/dimensions'; +import { Scale } from '../../../utils/scales/scales'; +import { GroupId } from '../../../utils/ids'; +import { LineAnnotationStyle } from '../../../utils/themes/theme'; +import { Point } from '../../../utils/point'; +import { isWithinRectBounds } from './rect_annotation_tooltip'; + +export type AnnotationLinePosition = [number, number, number, number]; + +/** Start and end points of a line annotation */ +export interface AnnotationLinePathPoints { + /** x1,y1 the start point anchored to the linked axis */ + start: { + x1: number; + y1: number; + }; + /** x2,y2 the end point */ + end: { + x2: number; + y2: number; + }; +} + +export interface AnnotationLineProps { + /** the position of the start point relative to the Chart */ + anchor: { + position: Position; + top: number; + left: number; + }; + /** + * The path points of a line annotation + */ + linePathPoints: AnnotationLinePathPoints; + details: AnnotationDetails; + marker?: AnnotationMarker; +} + +export const DEFAULT_LINE_OVERFLOW = 0; + +export function computeYDomainLineAnnotationDimensions( + dataValues: LineAnnotationDatum[], + yScale: Scale, + chartRotation: Rotation, + axisPosition: Position, + chartDimensions: Dimensions, + lineColor: string, + marker?: JSX.Element, + markerDimension = { width: 0, height: 0 }, +): AnnotationLineProps[] { + const chartHeight = chartDimensions.height; + const chartWidth = chartDimensions.width; + const isHorizontalChartRotation = isHorizontalRotation(chartRotation); + + const lineProps: AnnotationLineProps[] = []; + + dataValues.forEach((datum: LineAnnotationDatum) => { + const { dataValue } = datum; + + // avoid rendering invalid annotation value + if (dataValue === null || dataValue === undefined || dataValue === '') { + return; + } + + const annotationValueYposition = yScale.scale(dataValue); + // avoid rendering non scalable annotation values + if (isNaN(annotationValueYposition)) { + return; + } + + const [domainStart, domainEnd] = yScale.domain; + // avoid rendering annotation with values outside the scale domain + if (domainStart > dataValue || domainEnd < dataValue) { + return; + } + const anchor = { + position: axisPosition, + top: 0, + left: 0, + }; + const markerPosition = { top: 0, left: 0 }; + const linePathPoints: AnnotationLinePathPoints = { + start: { x1: 0, y1: 0 }, + end: { x2: 0, y2: 0 }, + }; + // the Y axis is vertical, X axis is horizontal y|--x--|y + if (isHorizontalChartRotation) { + // y|__x__ + if (axisPosition === Position.Left) { + anchor.left = 0; + markerPosition.left = -markerDimension.width; + linePathPoints.start.x1 = 0; + linePathPoints.end.x2 = chartWidth; + // __x__|y + } else { + anchor.left = chartWidth; + markerPosition.left = chartWidth; + linePathPoints.start.x1 = chartWidth; + linePathPoints.end.x2 = 0; + } + // __x__ + if (chartRotation === 0) { + anchor.top = annotationValueYposition; + markerPosition.top = annotationValueYposition - markerDimension.height / 2; + // ¯¯x¯¯ + } else { + anchor.top = chartHeight - annotationValueYposition; + markerPosition.top = chartHeight - annotationValueYposition - markerDimension.height / 2; + } + linePathPoints.start.y1 = annotationValueYposition; + linePathPoints.end.y2 = annotationValueYposition; + // the Y axis is horizontal, X axis is vertical x|--y--|x + } else { + // ¯¯y¯¯ + if (axisPosition === Position.Top) { + anchor.top = 0; + markerPosition.top = -markerDimension.height; + linePathPoints.start.x1 = 0; + linePathPoints.end.x2 = chartHeight; + // __y__ + } else { + anchor.top = chartHeight; + markerPosition.top = chartHeight; + linePathPoints.start.x1 = chartHeight; + linePathPoints.end.x2 = 0; + } + // __y__|x + if (chartRotation === -90) { + anchor.left = annotationValueYposition; + markerPosition.left = annotationValueYposition - markerDimension.width / 2; + // x|__y__ + } else { + anchor.left = chartWidth - annotationValueYposition; + markerPosition.left = chartWidth - annotationValueYposition - markerDimension.width / 2; + } + linePathPoints.start.y1 = annotationValueYposition; + linePathPoints.end.y2 = annotationValueYposition; + } + + const annotationMarker: AnnotationMarker | undefined = marker + ? { + icon: marker, + color: lineColor, + dimension: markerDimension, + position: markerPosition, + } + : undefined; + const lineProp: AnnotationLineProps = { + anchor, + linePathPoints, + marker: annotationMarker, + details: { + detailsText: datum.details, + headerText: datum.header || dataValue.toString(), + }, + }; + + lineProps.push(lineProp); + }); + + return lineProps; +} + +export function computeXDomainLineAnnotationDimensions( + dataValues: LineAnnotationDatum[], + xScale: Scale, + chartRotation: Rotation, + axisPosition: Position, + chartDimensions: Dimensions, + lineColor: string, + xScaleOffset: number, + enableHistogramMode: boolean, + marker?: JSX.Element, + markerDimension = { width: 0, height: 0 }, +): AnnotationLineProps[] { + const chartHeight = chartDimensions.height; + const chartWidth = chartDimensions.width; + const lineProps: AnnotationLineProps[] = []; + const isHorizontalChartRotation = isHorizontalRotation(chartRotation); + + const alignWithTick = xScale.bandwidth > 0 && !enableHistogramMode; + dataValues.forEach((datum: LineAnnotationDatum) => { + const { dataValue } = datum; + + const scaledXValue = scaleAndValidateDatum(dataValue, xScale, alignWithTick); + + if (scaledXValue == null) { + return; + } + + const offset = xScale.bandwidth / 2 - xScaleOffset; + const annotationValueXposition = scaledXValue + offset; + + const markerPosition = { top: 0, left: 0 }; + const linePathPoints: AnnotationLinePathPoints = { + start: { x1: 0, y1: 0 }, + end: { x2: 0, y2: 0 }, + }; + const anchor = { + position: axisPosition, + top: 0, + left: 0, + }; + // the Y axis is vertical, X axis is horizontal y|--x--|y + if (isHorizontalChartRotation) { + // __x__ + if (axisPosition === Position.Bottom) { + linePathPoints.start.y1 = chartHeight; + linePathPoints.end.y2 = 0; + anchor.top = chartHeight; + markerPosition.top = chartHeight; + // ¯¯x¯¯ + } else { + linePathPoints.start.y1 = 0; + linePathPoints.end.y2 = chartHeight; + anchor.top = 0; + markerPosition.top = 0 - markerDimension.height; + } + // __x__ + if (chartRotation === 0) { + anchor.left = annotationValueXposition; + markerPosition.left = annotationValueXposition - markerDimension.width / 2; + // ¯¯x¯¯ + } else { + anchor.left = chartWidth - annotationValueXposition; + markerPosition.left = chartWidth - annotationValueXposition - markerDimension.width / 2; + } + linePathPoints.start.x1 = annotationValueXposition; + linePathPoints.end.x2 = annotationValueXposition; + // the Y axis is horizontal, X axis is vertical x|--y--|x + } else { + // x|--y-- + if (axisPosition === Position.Left) { + anchor.left = 0; + markerPosition.left = -markerDimension.width; + linePathPoints.start.x1 = annotationValueXposition; + linePathPoints.end.x2 = annotationValueXposition; + // --y--|x + } else { + anchor.left = chartWidth; + markerPosition.left = chartWidth; + linePathPoints.start.x1 = annotationValueXposition; + linePathPoints.end.x2 = annotationValueXposition; + } + // __y__|x + if (chartRotation === -90) { + anchor.top = chartHeight - annotationValueXposition; + markerPosition.top = chartHeight - annotationValueXposition - markerDimension.height / 2; + linePathPoints.start.y1 = 0; + linePathPoints.end.y2 = chartWidth; + // x|__y__ + } else { + anchor.top = annotationValueXposition; + markerPosition.top = annotationValueXposition - markerDimension.height / 2; + linePathPoints.start.y1 = 0; + linePathPoints.end.y2 = chartWidth; + } + } + + const annotationMarker: AnnotationMarker | undefined = marker + ? { + icon: marker, + color: lineColor, + dimension: markerDimension, + position: markerPosition, + } + : undefined; + const lineProp: AnnotationLineProps = { + anchor, + linePathPoints, + details: { + detailsText: datum.details, + headerText: datum.header || dataValue.toString(), + }, + marker: annotationMarker, + }; + lineProps.push(lineProp); + }); + + return lineProps; +} + +export function computeLineAnnotationDimensions( + annotationSpec: LineAnnotationSpec, + chartDimensions: Dimensions, + chartRotation: Rotation, + yScales: Map<GroupId, Scale>, + xScale: Scale, + axisPosition: Position, + xScaleOffset: number, + enableHistogramMode: boolean, +): AnnotationLineProps[] | null { + const { domainType, dataValues, marker, markerDimensions, hideLines } = annotationSpec; + + if (hideLines) { + return null; + } + + // this type is guaranteed as this has been merged with default + const lineStyle = annotationSpec.style as LineAnnotationStyle; + const lineColor = lineStyle.line.stroke; + + if (domainType === AnnotationDomainTypes.XDomain) { + return computeXDomainLineAnnotationDimensions( + dataValues, + xScale, + chartRotation, + axisPosition, + chartDimensions, + lineColor, + xScaleOffset, + enableHistogramMode, + marker, + markerDimensions, + ); + } + + const groupId = annotationSpec.groupId; + const yScale = yScales.get(groupId); + if (!yScale) { + return null; + } + + return computeYDomainLineAnnotationDimensions( + dataValues, + yScale, + chartRotation, + axisPosition, + chartDimensions, + lineColor, + marker, + markerDimensions, + ); +} + +export function getAnnotationLineTooltipXOffset(chartRotation: Rotation, axisPosition: Position): number { + let xOffset = 0; + const isChartHorizontalRotation = isHorizontalRotation(chartRotation); + + if (isHorizontalAxis(axisPosition)) { + xOffset = isChartHorizontalRotation ? 50 : 0; + } else { + if (isChartHorizontalRotation) { + xOffset = axisPosition === Position.Right ? 100 : 0; + } else { + xOffset = 50; + } + } + + return xOffset; +} + +export function getAnnotationLineTooltipYOffset(chartRotation: Rotation, axisPosition: Position): number { + let yOffset = 0; + const isChartHorizontalRotation = isHorizontalRotation(chartRotation); + + if (isHorizontalAxis(axisPosition)) { + if (isChartHorizontalRotation) { + yOffset = axisPosition === Position.Top ? 0 : 100; + } else { + yOffset = 50; + } + } else { + yOffset = isChartHorizontalRotation ? 50 : 100; + } + + return yOffset; +} + +export function isVerticalAnnotationLine(isXDomainAnnotation: boolean, isHorizontalChartRotation: boolean): boolean { + if (isXDomainAnnotation) { + return isHorizontalChartRotation; + } + + return !isHorizontalChartRotation; +} + +/** + * Checks if the cursorPosition is within the line annotation marker + * @param cursorPosition the cursor position relative to the projected area + * @param marker the line annotation marker + */ +export function isWithinLineMarkerBounds(cursorPosition: Point, marker: AnnotationMarker): boolean { + const { top, left } = marker.position; + const { width, height } = marker.dimension; + const markerRect: Bounds = { startX: left, startY: top, endX: left + width, endY: top + height }; + return isWithinRectBounds(cursorPosition, markerRect); +} + +export function computeLineAnnotationTooltipState( + cursorPosition: Point, + annotationLines: AnnotationLineProps[], + groupId: GroupId, + domainType: AnnotationDomainType, + axesSpecs: AxisSpec[], +): AnnotationTooltipState { + const { xAxis, yAxis } = getAxesSpecForSpecId(axesSpecs, groupId); + const isXDomainAnnotation = isXDomain(domainType); + const annotationAxis = isXDomainAnnotation ? xAxis : yAxis; + + if (!annotationAxis) { + return { + isVisible: false, + }; + } + + const totalAnnotationLines = annotationLines.length; + for (let i = 0; i < totalAnnotationLines; i++) { + const line = annotationLines[i]; + const isWithinBounds = line.marker && isWithinLineMarkerBounds(cursorPosition, line.marker); + + if (isWithinBounds) { + return { + annotationType: AnnotationTypes.Line, + isVisible: true, + anchor: { + ...line.anchor, + }, + ...(line.details && { header: line.details.headerText }), + ...(line.details && { details: line.details.detailsText }), + }; + } + } + return { + isVisible: false, + }; +} diff --git a/src/chart_types/xy_chart/annotations/rect_annotation_tooltip.ts b/src/chart_types/xy_chart/annotations/rect_annotation_tooltip.ts new file mode 100644 index 0000000000..1794af0fa9 --- /dev/null +++ b/src/chart_types/xy_chart/annotations/rect_annotation_tooltip.ts @@ -0,0 +1,169 @@ +import { AnnotationTypes, RectAnnotationDatum, RectAnnotationSpec, Rotation } from '../utils/specs'; +import { Dimensions } from '../../../utils/dimensions'; +import { GroupId } from '../../../utils/ids'; +import { Scale } from '../../../utils/scales/scales'; +import { Point } from '../../../utils/point'; +import { + AnnotationTooltipFormatter, + AnnotationTooltipState, + getRotatedCursor, + scaleAndValidateDatum, + Bounds, +} from './annotation_utils'; + +export interface AnnotationRectProps { + rect: { + x: number; + y: number; + width: number; + height: number; + }; + details?: string; +} + +export function computeRectAnnotationTooltipState( + /** the cursor position relative to the projection area */ + cursorPosition: Point, + annotationRects: AnnotationRectProps[], + chartRotation: Rotation, + chartDimensions: Dimensions, + renderTooltip?: AnnotationTooltipFormatter, +): AnnotationTooltipState { + const rotatedCursorPosition = getRotatedCursor(cursorPosition, chartDimensions, chartRotation); + + const totalAnnotationRect = annotationRects.length; + for (let i = 0; i < totalAnnotationRect; i++) { + const rectProps = annotationRects[i]; + const { rect, details } = rectProps; + const startX = rect.x; + const endX = startX + rect.width; + + const startY = rect.y; + const endY = startY + rect.height; + + const bounds: Bounds = { startX, endX, startY, endY }; + + const isWithinBounds = isWithinRectBounds(rotatedCursorPosition, bounds); + if (isWithinBounds) { + return { + isVisible: true, + annotationType: AnnotationTypes.Rectangle, + anchor: { + left: rotatedCursorPosition.x, + top: rotatedCursorPosition.y, + }, + ...(details && { details }), + ...(renderTooltip && { renderTooltip }), + }; + } + } + return { + isVisible: false, + }; +} + +export function isWithinRectBounds({ x, y }: Point, { startX, endX, startY, endY }: Bounds): boolean { + const withinXBounds = x >= startX && x <= endX; + const withinYBounds = y >= startY && y <= endY; + + return withinXBounds && withinYBounds; +} + +export function computeRectAnnotationDimensions( + annotationSpec: RectAnnotationSpec, + yScales: Map<GroupId, Scale>, + xScale: Scale, + enableHistogramMode: boolean, + barsPadding: number, +): AnnotationRectProps[] | null { + const { dataValues } = annotationSpec; + + const groupId = annotationSpec.groupId; + const yScale = yScales.get(groupId); + if (!yScale) { + return null; + } + + const xDomain = xScale.domain; + const yDomain = yScale.domain; + const lastX = xDomain[xDomain.length - 1]; + const xMinInterval = xScale.minInterval; + const rectsProps: AnnotationRectProps[] = []; + + dataValues.forEach((dataValue: RectAnnotationDatum) => { + let { x0, x1, y0, y1 } = dataValue.coordinates; + + // if everything is null, return; otherwise we coerce the other coordinates + if (x0 == null && x1 == null && y0 == null && y1 == null) { + return; + } + + if (x1 == null) { + // if x1 is defined, we want the rect to draw to the end of the scale + // if we're in histogram mode, extend domain end by min interval + x1 = enableHistogramMode && !xScale.isSingleValue() ? lastX + xMinInterval : lastX; + } + + if (x0 == null) { + // if x0 is defined, we want the rect to draw to the start of the scale + x0 = xDomain[0]; + } + + if (y0 == null) { + // if y0 is defined, we want the rect to draw to the end of the scale + y0 = yDomain[yDomain.length - 1]; + } + + if (y1 == null) { + // if y1 is defined, we want the rect to draw to the start of the scale + y1 = yDomain[0]; + } + + const alignWithTick = xScale.bandwidth > 0 && !enableHistogramMode; + + let x0Scaled = scaleAndValidateDatum(x0, xScale, alignWithTick); + let x1Scaled = scaleAndValidateDatum(x1, xScale, alignWithTick); + const y0Scaled = scaleAndValidateDatum(y0, yScale, false); + const y1Scaled = scaleAndValidateDatum(y1, yScale, false); + + // TODO: surface this as a warning + if (x0Scaled === null || x1Scaled === null || y0Scaled === null || y1Scaled === null) { + return; + } + + let xOffset = 0; + if (xScale.bandwidth > 0) { + const xBand = xScale.bandwidth / (1 - xScale.barsPadding); + xOffset = enableHistogramMode ? (xBand - xScale.bandwidth) / 2 : barsPadding; + } + + x0Scaled = x0Scaled - xOffset; + x1Scaled = x1Scaled - xOffset; + + const minX = Math.min(x0Scaled, x1Scaled); + const minY = Math.min(y0Scaled, y1Scaled); + + const deltaX = Math.abs(x0Scaled - x1Scaled); + const deltaY = Math.abs(y0Scaled - y1Scaled); + + const xOrigin = minX; + const yOrigin = minY; + + const width = deltaX; + const height = deltaY; + + const rectDimensions = { + x: xOrigin, + y: yOrigin, + width, + height, + }; + + rectsProps.push({ + rect: rectDimensions, + details: dataValue.details, + }); + }); + + return rectsProps; +} diff --git a/src/chart_types/xy_chart/crosshair/crosshair_utils.linear_snap.test.ts b/src/chart_types/xy_chart/crosshair/crosshair_utils.linear_snap.test.ts index ad5f31a77e..9617ebe45f 100644 --- a/src/chart_types/xy_chart/crosshair/crosshair_utils.linear_snap.test.ts +++ b/src/chart_types/xy_chart/crosshair/crosshair_utils.linear_snap.test.ts @@ -1,10 +1,11 @@ import { computeXScale } from '../utils/scales'; -import { BasicSeriesSpec } from '../utils/specs'; +import { BasicSeriesSpec, SpecTypes, SeriesTypes } from '../utils/specs'; import { Dimensions } from '../../../utils/dimensions'; import { getGroupId, getSpecId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { getCursorBandPosition, getSnapPosition } from './crosshair_utils'; -import { computeSeriesDomains } from '../store/utils'; +import { computeSeriesDomains } from '../state/utils'; +import { ChartTypes } from '../..'; describe('Crosshair utils linear scale', () => { const barSeries1SpecId = getSpecId('barSeries1'); @@ -13,9 +14,11 @@ describe('Crosshair utils linear scale', () => { const lineSeries2SpecId = getSpecId('lineSeries2'); const barSeries1: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: barSeries1SpecId, groupId: getGroupId('group1'), - seriesType: 'bar', + seriesType: SeriesTypes.Bar, data: [[0, 0], [1, 0], [2, 0]], xAccessor: 0, yAccessors: [1], @@ -24,9 +27,11 @@ describe('Crosshair utils linear scale', () => { yScaleToDataExtent: true, }; const barSeries2: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: barSeries2SpecId, groupId: getGroupId('group1'), - seriesType: 'bar', + seriesType: SeriesTypes.Bar, data: [[0, 2], [1, 2], [2, 2]], xAccessor: 0, yAccessors: [1], @@ -35,9 +40,11 @@ describe('Crosshair utils linear scale', () => { yScaleToDataExtent: true, }; const lineSeries1: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: lineSeries1SpecId, groupId: getGroupId('group1'), - seriesType: 'line', + seriesType: SeriesTypes.Line, data: [[0, 0], [1, 0], [2, 0]], xAccessor: 0, yAccessors: [1], @@ -46,9 +53,11 @@ describe('Crosshair utils linear scale', () => { yScaleToDataExtent: true, }; const lineSeries2: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: lineSeries2SpecId, groupId: getGroupId('group1'), - seriesType: 'line', + seriesType: SeriesTypes.Line, data: [[0, 2], [1, 2], [2, 2]], xAccessor: 0, yAccessors: [1], @@ -57,54 +66,44 @@ describe('Crosshair utils linear scale', () => { yScaleToDataExtent: true, }; - const barSeriesMap = new Map(); - barSeriesMap.set(barSeries1SpecId, barSeries1); - const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); + const barSeries = [barSeries1]; + const barSeriesDomains = computeSeriesDomains(barSeries); - const multiBarSeriesMap = new Map(); - multiBarSeriesMap.set(barSeries1SpecId, barSeries1); - multiBarSeriesMap.set(barSeries2SpecId, barSeries2); - const multiBarSeriesDomains = computeSeriesDomains(multiBarSeriesMap, new Map()); + const multiBarSeries = [barSeries1, barSeries2]; + const multiBarSeriesDomains = computeSeriesDomains(multiBarSeries); - const lineSeriesMap = new Map(); - lineSeriesMap.set(lineSeries1SpecId, lineSeries1); - const lineSeriesDomains = computeSeriesDomains(lineSeriesMap, new Map()); + const lineSeries = [lineSeries1]; + const lineSeriesDomains = computeSeriesDomains(lineSeries); - const multiLineSeriesMap = new Map(); - multiLineSeriesMap.set(lineSeries1SpecId, lineSeries1); - multiLineSeriesMap.set(lineSeries2SpecId, lineSeries2); - const multiLineSeriesDomains = computeSeriesDomains(multiLineSeriesMap, new Map()); + const multiLineSeries = [lineSeries1, lineSeries2]; + const multiLineSeriesDomains = computeSeriesDomains(multiLineSeries); - const mixedLinesBarsMap = new Map(); - mixedLinesBarsMap.set(lineSeries1SpecId, lineSeries1); - mixedLinesBarsMap.set(lineSeries2SpecId, lineSeries2); - mixedLinesBarsMap.set(barSeries1SpecId, barSeries1); - mixedLinesBarsMap.set(barSeries2SpecId, barSeries2); - const mixedLinesBarsSeriesDomains = computeSeriesDomains(mixedLinesBarsMap, new Map()); + const mixedLinesBars = [lineSeries1, lineSeries2, barSeries1, barSeries2]; + const mixedLinesBarsSeriesDomains = computeSeriesDomains(mixedLinesBars); const barSeriesScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeries.length, range: [0, 120], }); const multiBarSeriesScale = computeXScale({ xDomain: multiBarSeriesDomains.xDomain, - totalBarsInCluster: multiBarSeriesMap.size, + totalBarsInCluster: multiBarSeries.length, range: [0, 120], }); const lineSeriesScale = computeXScale({ xDomain: lineSeriesDomains.xDomain, - totalBarsInCluster: lineSeriesMap.size, + totalBarsInCluster: lineSeries.length, range: [0, 120], }); const multiLineSeriesScale = computeXScale({ xDomain: multiLineSeriesDomains.xDomain, - totalBarsInCluster: multiLineSeriesMap.size, + totalBarsInCluster: multiLineSeries.length, range: [0, 120], }); const mixedLinesBarsSeriesScale = computeXScale({ xDomain: mixedLinesBarsSeriesDomains.xDomain, - totalBarsInCluster: mixedLinesBarsMap.size, + totalBarsInCluster: mixedLinesBars.length, range: [0, 120], }); @@ -205,7 +204,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 200, y: 0 }, - lineSeriesScale.invertWithStep(200, [0, 1, 2]), + lineSeriesScale.invertWithStep(200, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -216,7 +215,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 200 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -227,7 +226,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: -1, y: 0 }, - lineSeriesScale.invertWithStep(-1, [0, 1, 2]), + lineSeriesScale.invertWithStep(-1, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -238,7 +237,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: -1 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -258,7 +257,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -277,7 +276,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 45 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -296,7 +295,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 40, y: 0 }, - lineSeriesScale.invertWithStep(40, [0, 1, 2]), + lineSeriesScale.invertWithStep(40, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -315,7 +314,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 90, y: 0 }, - lineSeriesScale.invertWithStep(90, [0, 1, 2]), + lineSeriesScale.invertWithStep(90, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -334,7 +333,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 200, y: 0 }, - lineSeriesScale.invertWithStep(200, [0, 1, 2]), + lineSeriesScale.invertWithStep(200, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -351,7 +350,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -370,7 +369,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 45 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -389,7 +388,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 20, y: 0 }, - lineSeriesScale.invertWithStep(20, [0, 1, 2]), + lineSeriesScale.invertWithStep(20, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -408,7 +407,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 40, y: 0 }, - lineSeriesScale.invertWithStep(40, [0, 1, 2]), + lineSeriesScale.invertWithStep(40, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -427,7 +426,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 95, y: 0 }, - lineSeriesScale.invertWithStep(95, [0, 1, 2]), + lineSeriesScale.invertWithStep(95, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -446,7 +445,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 200, y: 0 }, - lineSeriesScale.invertWithStep(200, [0, 1, 2]), + lineSeriesScale.invertWithStep(200, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -464,7 +463,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -484,7 +483,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 45 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -503,7 +502,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 40, y: 0 }, - lineSeriesScale.invertWithStep(40, [0, 1, 2]), + lineSeriesScale.invertWithStep(40, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -522,7 +521,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 90, y: 0 }, - lineSeriesScale.invertWithStep(90, [0, 1, 2]), + lineSeriesScale.invertWithStep(90, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -541,7 +540,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 200, y: 0 }, - lineSeriesScale.invertWithStep(200, [0, 1, 2]), + lineSeriesScale.invertWithStep(200, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -559,7 +558,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -578,7 +577,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 45 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -597,7 +596,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 20, y: 0 }, - lineSeriesScale.invertWithStep(20, [0, 1, 2]), + lineSeriesScale.invertWithStep(20, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -616,7 +615,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 40, y: 0 }, - lineSeriesScale.invertWithStep(40, [0, 1, 2]), + lineSeriesScale.invertWithStep(40, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -635,7 +634,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 95, y: 0 }, - lineSeriesScale.invertWithStep(95, [0, 1, 2]), + lineSeriesScale.invertWithStep(95, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -654,7 +653,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 200, y: 0 }, - lineSeriesScale.invertWithStep(200, [0, 1, 2]), + lineSeriesScale.invertWithStep(200, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -672,7 +671,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -691,7 +690,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 45, y: 0 }, - lineSeriesScale.invertWithStep(45, [0, 1, 2]), + lineSeriesScale.invertWithStep(45, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -710,7 +709,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 40 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -729,7 +728,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 90 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -748,7 +747,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 200 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -766,7 +765,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -785,7 +784,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 45, y: 0 }, - lineSeriesScale.invertWithStep(45, [0, 1, 2]), + lineSeriesScale.invertWithStep(45, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -804,7 +803,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 20 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -823,7 +822,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 40 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -842,7 +841,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 95 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -861,7 +860,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 200 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -879,7 +878,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -898,7 +897,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 45, y: 0 }, - lineSeriesScale.invertWithStep(45, [0, 1, 2]), + lineSeriesScale.invertWithStep(45, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -917,7 +916,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 40 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -936,7 +935,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 90 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -955,7 +954,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 200 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -973,7 +972,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -992,7 +991,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 45, y: 0 }, - lineSeriesScale.invertWithStep(45, [0, 1, 2]), + lineSeriesScale.invertWithStep(45, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -1011,7 +1010,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 20 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -1030,7 +1029,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 40 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -1049,7 +1048,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 95 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -1068,7 +1067,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 200 }, - lineSeriesScale.invertWithStep(0, [0, 1, 2]), + lineSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, lineSeriesScale, 1, @@ -1089,7 +1088,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1108,7 +1107,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 45 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1127,7 +1126,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 40, y: 0 }, - barSeriesScale.invertWithStep(40, [0, 1, 2]), + barSeriesScale.invertWithStep(40, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1143,7 +1142,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 41, y: 0 }, - barSeriesScale.invertWithStep(41, [0, 1, 2]), + barSeriesScale.invertWithStep(41, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1162,7 +1161,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 90, y: 0 }, - barSeriesScale.invertWithStep(90, [0, 1, 2]), + barSeriesScale.invertWithStep(90, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1181,7 +1180,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 200, y: 0 }, - barSeriesScale.invertWithStep(200, [0, 1, 2]), + barSeriesScale.invertWithStep(200, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1199,7 +1198,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1218,7 +1217,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 45 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1237,7 +1236,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 41, y: 0 }, - barSeriesScale.invertWithStep(41, [0, 1, 2]), + barSeriesScale.invertWithStep(41, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1256,7 +1255,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 90, y: 0 }, - barSeriesScale.invertWithStep(90, [0, 1, 2]), + barSeriesScale.invertWithStep(90, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1275,7 +1274,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 200, y: 0 }, - barSeriesScale.invertWithStep(200, [0, 1, 2]), + barSeriesScale.invertWithStep(200, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1293,7 +1292,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1312,7 +1311,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 45, y: 0 }, - barSeriesScale.invertWithStep(45, [0, 1, 2]), + barSeriesScale.invertWithStep(45, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1331,7 +1330,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 40 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1350,7 +1349,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 90 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1369,7 +1368,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 200 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1387,7 +1386,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 0 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1406,7 +1405,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 45, y: 0 }, - barSeriesScale.invertWithStep(45, [0, 1, 2]), + barSeriesScale.invertWithStep(45, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1425,7 +1424,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 40 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1444,7 +1443,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 90 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1463,7 +1462,7 @@ describe('Crosshair utils linear scale', () => { chartRotation, chartDimensions, { x: 0, y: 200 }, - barSeriesScale.invertWithStep(0, [0, 1, 2]), + barSeriesScale.invertWithStep(0, [0, 1, 2])!, snapPosition, barSeriesScale, 1, @@ -1516,7 +1515,7 @@ describe('Crosshair utils linear scale', () => { scaleType: ScaleType.Linear, type: 'xDomain', }, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeries.length, range: [0, 120], }); const bandPosition = getCursorBandPosition( @@ -1580,7 +1579,7 @@ describe('Crosshair utils linear scale', () => { scaleType: ScaleType.Linear, type: 'xDomain', }, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeries.length, range: [0, 120], }); const bandPosition = getCursorBandPosition( diff --git a/src/chart_types/xy_chart/crosshair/crosshair_utils.ordinal_snap.test.ts b/src/chart_types/xy_chart/crosshair/crosshair_utils.ordinal_snap.test.ts index 74edfdeb1f..d0480af837 100644 --- a/src/chart_types/xy_chart/crosshair/crosshair_utils.ordinal_snap.test.ts +++ b/src/chart_types/xy_chart/crosshair/crosshair_utils.ordinal_snap.test.ts @@ -1,9 +1,10 @@ import { computeXScale } from '../utils/scales'; -import { BasicSeriesSpec } from '../utils/specs'; +import { BasicSeriesSpec, SpecTypes, SeriesTypes } from '../utils/specs'; import { getGroupId, getSpecId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { getSnapPosition } from './crosshair_utils'; -import { computeSeriesDomains } from '../store/utils'; +import { computeSeriesDomains } from '../state/utils'; +import { ChartTypes } from '../..'; describe('Crosshair utils ordinal scales', () => { const barSeries1SpecId = getSpecId('barSeries1'); @@ -12,9 +13,11 @@ describe('Crosshair utils ordinal scales', () => { const lineSeries2SpecId = getSpecId('lineSeries2'); const barSeries1: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: barSeries1SpecId, groupId: getGroupId('group1'), - seriesType: 'bar', + seriesType: SeriesTypes.Bar, data: [['a', 0], ['b', 0], ['c', 0]], xAccessor: 0, yAccessors: [1], @@ -23,9 +26,11 @@ describe('Crosshair utils ordinal scales', () => { yScaleToDataExtent: true, }; const barSeries2: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: barSeries2SpecId, groupId: getGroupId('group1'), - seriesType: 'bar', + seriesType: SeriesTypes.Bar, data: [['a', 2], ['b', 2], ['c', 2]], xAccessor: 0, yAccessors: [1], @@ -34,9 +39,11 @@ describe('Crosshair utils ordinal scales', () => { yScaleToDataExtent: true, }; const lineSeries1: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: lineSeries1SpecId, groupId: getGroupId('group1'), - seriesType: 'line', + seriesType: SeriesTypes.Line, data: [['a', 0], ['b', 0], ['c', 0]], xAccessor: 0, yAccessors: [1], @@ -45,9 +52,11 @@ describe('Crosshair utils ordinal scales', () => { yScaleToDataExtent: true, }; const lineSeries2: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: lineSeries2SpecId, groupId: getGroupId('group1'), - seriesType: 'line', + seriesType: SeriesTypes.Line, data: [['a', 2], ['b', 2], ['c', 2]], xAccessor: 0, yAccessors: [1], @@ -56,54 +65,44 @@ describe('Crosshair utils ordinal scales', () => { yScaleToDataExtent: true, }; - const barSeriesMap = new Map(); - barSeriesMap.set(barSeries1SpecId, barSeries1); - const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); + const barSeries = [barSeries1]; + const barSeriesDomains = computeSeriesDomains(barSeries); - const multiBarSeriesMap = new Map(); - multiBarSeriesMap.set(barSeries1SpecId, barSeries1); - multiBarSeriesMap.set(barSeries2SpecId, barSeries2); - const multiBarSeriesDomains = computeSeriesDomains(multiBarSeriesMap, new Map()); + const multiBarSeries = [barSeries1, barSeries2]; + const multiBarSeriesDomains = computeSeriesDomains(multiBarSeries); - const lineSeriesMap = new Map(); - lineSeriesMap.set(lineSeries1SpecId, lineSeries1); - const lineSeriesDomains = computeSeriesDomains(lineSeriesMap, new Map()); + const lineSeries = [lineSeries1]; + const lineSeriesDomains = computeSeriesDomains(lineSeries); - const multiLineSeriesMap = new Map(); - multiLineSeriesMap.set(lineSeries1SpecId, lineSeries1); - multiLineSeriesMap.set(lineSeries2SpecId, lineSeries2); - const multiLineSeriesDomains = computeSeriesDomains(multiLineSeriesMap, new Map()); + const multiLineSeries = [lineSeries1, lineSeries2]; + const multiLineSeriesDomains = computeSeriesDomains(multiLineSeries); - const mixedLinesBarsMap = new Map(); - mixedLinesBarsMap.set(lineSeries1SpecId, lineSeries1); - mixedLinesBarsMap.set(lineSeries2SpecId, lineSeries2); - mixedLinesBarsMap.set(barSeries1SpecId, barSeries1); - mixedLinesBarsMap.set(barSeries2SpecId, barSeries2); - const mixedLinesBarsSeriesDomains = computeSeriesDomains(mixedLinesBarsMap, new Map()); + const mixedLinesBars = [lineSeries1, lineSeries2, barSeries1, barSeries2]; + const mixedLinesBarsSeriesDomains = computeSeriesDomains(mixedLinesBars); const barSeriesScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeries.length, range: [0, 120], }); const multiBarSeriesScale = computeXScale({ xDomain: multiBarSeriesDomains.xDomain, - totalBarsInCluster: multiBarSeriesMap.size, + totalBarsInCluster: multiBarSeries.length, range: [0, 120], }); const lineSeriesScale = computeXScale({ xDomain: lineSeriesDomains.xDomain, - totalBarsInCluster: lineSeriesMap.size, + totalBarsInCluster: lineSeries.length, range: [0, 120], }); const multiLineSeriesScale = computeXScale({ xDomain: multiLineSeriesDomains.xDomain, - totalBarsInCluster: multiLineSeriesMap.size, + totalBarsInCluster: multiLineSeries.length, range: [0, 120], }); const mixedLinesBarsSeriesScale = computeXScale({ xDomain: mixedLinesBarsSeriesDomains.xDomain, - totalBarsInCluster: mixedLinesBarsMap.size, + totalBarsInCluster: mixedLinesBars.length, range: [0, 120], }); diff --git a/src/chart_types/xy_chart/crosshair/crosshair_utils.ts b/src/chart_types/xy_chart/crosshair/crosshair_utils.ts index 7b72cb6c0e..1231469ef9 100644 --- a/src/chart_types/xy_chart/crosshair/crosshair_utils.ts +++ b/src/chart_types/xy_chart/crosshair/crosshair_utils.ts @@ -1,8 +1,8 @@ import { Rotation } from '../utils/specs'; import { Dimensions } from '../../../utils/dimensions'; import { Scale } from '../../../utils/scales/scales'; -import { isHorizontalRotation } from '../store/utils'; -import { Point } from '../store/chart_state'; +import { isHorizontalRotation } from '../state/utils'; +import { Point } from '../../../utils/point'; export interface SnappedPosition { position: number; @@ -56,12 +56,12 @@ export function getSnapPosition( export function getCursorLinePosition( chartRotation: Rotation, chartDimensions: Dimensions, - cursorPosition: { x: number; y: number }, + projectedPointerPosition: { x: number; y: number }, ): Dimensions { const { left, top, width, height } = chartDimensions; const isHorizontalRotated = isHorizontalRotation(chartRotation); if (isHorizontalRotated) { - const crosshairTop = cursorPosition.y + top; + const crosshairTop = projectedPointerPosition.y + top; return { left, width, @@ -69,7 +69,7 @@ export function getCursorLinePosition( height: 0, }; } else { - const crosshairLeft = cursorPosition.x + left; + const crosshairLeft = projectedPointerPosition.x + left; return { top, @@ -187,7 +187,7 @@ export function getTooltipPosition( }; } -export function getHorizontalTooltipPosition( +function getHorizontalTooltipPosition( cursorXPosition: number, cursorBandPosition: Dimensions, chartDimensions: Dimensions, @@ -207,7 +207,7 @@ export function getHorizontalTooltipPosition( } } -export function getVerticalTooltipPosition( +function getVerticalTooltipPosition( cursorYPosition: number, cursorBandPosition: Dimensions, chartDimensions: Dimensions, diff --git a/src/chart_types/xy_chart/domains/x_domain.test.ts b/src/chart_types/xy_chart/domains/x_domain.test.ts index f3142e5dad..f63ddc0a61 100644 --- a/src/chart_types/xy_chart/domains/x_domain.test.ts +++ b/src/chart_types/xy_chart/domains/x_domain.test.ts @@ -1,8 +1,8 @@ -import { getGroupId, getSpecId, SpecId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { getSplittedSeries } from '../utils/series'; -import { BasicSeriesSpec } from '../utils/specs'; +import { BasicSeriesSpec, SpecTypes, SeriesTypes } from '../utils/specs'; import { convertXScaleTypes, findMinInterval, mergeXDomain } from './x_domain'; +import { ChartTypes } from '../..'; describe('X Domain', () => { test('Should return null when missing specs or specs types', () => { @@ -20,7 +20,7 @@ describe('X Domain', () => { test('Should return correct scale type with single bar', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, ]; @@ -34,7 +34,7 @@ describe('X Domain', () => { test('Should return correct scale type with single bar with Ordinal', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Ordinal, }, ]; @@ -48,7 +48,7 @@ describe('X Domain', () => { test('Should return correct scale type with single area', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, xScaleType: ScaleType.Linear, }, ]; @@ -61,7 +61,7 @@ describe('X Domain', () => { test('Should return correct scale type with single line (time)', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType' | 'timeZone'>[] = [ { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Time, timeZone: 'utc-3', }, @@ -76,12 +76,12 @@ describe('X Domain', () => { test('Should return correct scale type with multi line with same scale types (time) same tz', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType' | 'timeZone'>[] = [ { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Time, timeZone: 'UTC-3', }, { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Time, timeZone: 'utc-3', }, @@ -96,12 +96,12 @@ describe('X Domain', () => { test('Should return correct scale type with multi line with same scale types (time) coerce to UTC', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType' | 'timeZone'>[] = [ { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Time, timeZone: 'utc-3', }, { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Time, timeZone: 'utc+3', }, @@ -117,11 +117,11 @@ describe('X Domain', () => { test('Should return correct scale type with multi line with different scale types (linear, ordinal)', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Linear, }, { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Ordinal, }, ]; @@ -134,11 +134,11 @@ describe('X Domain', () => { test('Should return correct scale type with multi bar, area with different scale types (linear, ordinal)', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, { - seriesType: 'area', + seriesType: SeriesTypes.Area, xScaleType: ScaleType.Ordinal, }, ]; @@ -151,11 +151,11 @@ describe('X Domain', () => { test('Should return correct scale type with multi bar, area with same scale types (linear, linear)', () => { const seriesSpecs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType' | 'timeZone'>[] = [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, { - seriesType: 'area', + seriesType: SeriesTypes.Area, xScaleType: ScaleType.Time, timeZone: 'utc+3', }, @@ -169,9 +169,11 @@ describe('X Domain', () => { test('Should merge line series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Line, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -180,9 +182,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g1', + seriesType: SeriesTypes.Line, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -190,14 +194,12 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries: BasicSeriesSpec[] = [ds1, ds2]; const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Linear, }, ], @@ -207,9 +209,11 @@ describe('X Domain', () => { }); test('Should merge bar series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -218,9 +222,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g1'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g1', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -228,14 +234,13 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, ], @@ -245,9 +250,11 @@ describe('X Domain', () => { }); test('Should merge multi bar series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -256,9 +263,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g2', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -266,18 +275,17 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, ], @@ -287,9 +295,11 @@ describe('X Domain', () => { }); test('Should merge multi bar series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -298,9 +308,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g2', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -308,18 +320,17 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, ], @@ -329,9 +340,11 @@ describe('X Domain', () => { }); test('Should merge multi bar linear/bar ordinal series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -340,9 +353,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g2', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Ordinal, @@ -350,18 +365,17 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Ordinal, }, ], @@ -371,9 +385,11 @@ describe('X Domain', () => { }); test('Should merge multi bar/line ordinal series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -382,9 +398,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g2', + seriesType: SeriesTypes.Line, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Ordinal, @@ -392,18 +410,17 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear, }, { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Ordinal, }, ], @@ -413,9 +430,11 @@ describe('X Domain', () => { }); test('Should merge multi bar/line time series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Bar, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Ordinal, @@ -424,9 +443,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g2', + seriesType: SeriesTypes.Line, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Time, @@ -434,18 +455,17 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'bar', + seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Ordinal, }, { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Time, }, ], @@ -455,9 +475,11 @@ describe('X Domain', () => { }); test('Should merge multi lines series correctly', () => { const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Line, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Ordinal, @@ -466,9 +488,11 @@ describe('X Domain', () => { data: [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 5, y: 0 }], }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g2', + seriesType: SeriesTypes.Line, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -476,18 +500,17 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: [{ x: 0, y: 0 }, { x: 7, y: 0 }], }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Ordinal, }, { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Linear, }, ], @@ -499,9 +522,11 @@ describe('X Domain', () => { test('Should merge X multi high volume of data', () => { const maxValues = 10000; const ds1: BasicSeriesSpec = { - id: getSpecId('ds1'), - groupId: getGroupId('g1'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds1', + groupId: 'g1', + seriesType: SeriesTypes.Area, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Linear, @@ -510,9 +535,11 @@ describe('X Domain', () => { data: new Array(maxValues).fill(0).map((d, i) => ({ x: i, y: i })), }; const ds2: BasicSeriesSpec = { - id: getSpecId('ds2'), - groupId: getGroupId('g2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'ds2', + groupId: 'g2', + seriesType: SeriesTypes.Line, xAccessor: 'x', yAccessors: ['y'], xScaleType: ScaleType.Ordinal, @@ -520,19 +547,18 @@ describe('X Domain', () => { yScaleToDataExtent: false, data: new Array(maxValues).fill(0).map((d, i) => ({ x: i, y: i })), }; - const specDataSeries = new Map<SpecId, BasicSeriesSpec>(); - specDataSeries.set(ds1.id, ds1); - specDataSeries.set(ds2.id, ds2); + const specDataSeries = [ds1, ds2]; + const { xValues } = getSplittedSeries(specDataSeries); const mergedDomain = mergeXDomain( [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, xScaleType: ScaleType.Linear, }, { - seriesType: 'line', + seriesType: SeriesTypes.Line, xScaleType: ScaleType.Ordinal, }, ], @@ -572,7 +598,7 @@ describe('X Domain', () => { const xValues = new Set([1, 2, 3, 4, 5]); const xDomain = { min: 0, max: 3 }; const specs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ - { seriesType: 'line', xScaleType: ScaleType.Linear }, + { seriesType: SeriesTypes.Line, xScaleType: ScaleType.Linear }, ]; const basicMergedDomain = mergeXDomain(specs, xValues, xDomain); @@ -596,7 +622,7 @@ describe('X Domain', () => { const xValues = new Set([1, 2, 3, 4, 5]); const xDomain = { min: 0 }; const specs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ - { seriesType: 'line', xScaleType: ScaleType.Linear }, + { seriesType: SeriesTypes.Line, xScaleType: ScaleType.Linear }, ]; const mergedDomain = mergeXDomain(specs, xValues, xDomain); @@ -613,7 +639,7 @@ describe('X Domain', () => { const xValues = new Set([1, 2, 3, 4, 5]); const xDomain = { max: 3 }; const specs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ - { seriesType: 'line', xScaleType: ScaleType.Linear }, + { seriesType: SeriesTypes.Line, xScaleType: ScaleType.Linear }, ]; const mergedDomain = mergeXDomain(specs, xValues, xDomain); @@ -630,7 +656,7 @@ describe('X Domain', () => { const xValues = new Set(['a', 'b', 'c', 'd']); const xDomain = ['a', 'b', 'c']; const specs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ - { seriesType: 'bar', xScaleType: ScaleType.Ordinal }, + { seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Ordinal }, ]; const basicMergedDomain = mergeXDomain(specs, xValues, xDomain); expect(basicMergedDomain.domain).toEqual(['a', 'b', 'c']); @@ -646,7 +672,7 @@ describe('X Domain', () => { describe('should account for custom minInterval', () => { const xValues = new Set([1, 2, 3, 4, 5]); const specs: Pick<BasicSeriesSpec, 'seriesType' | 'xScaleType'>[] = [ - { seriesType: 'bar', xScaleType: ScaleType.Linear }, + { seriesType: SeriesTypes.Bar, xScaleType: ScaleType.Linear }, ]; test('with valid minInterval', () => { diff --git a/src/chart_types/xy_chart/domains/x_domain.ts b/src/chart_types/xy_chart/domains/x_domain.ts index 280d527787..f2aef2bd2f 100644 --- a/src/chart_types/xy_chart/domains/x_domain.ts +++ b/src/chart_types/xy_chart/domains/x_domain.ts @@ -2,7 +2,7 @@ import { isCompleteBound, isLowerBound, isUpperBound } from '../utils/axis_utils import { compareByValueAsc, identity, isNumberArray } from '../../../utils/commons'; import { computeContinuousDataDomain, computeOrdinalDataDomain, Domain } from '../../../utils/domain'; import { ScaleType } from '../../../utils/scales/scales'; -import { BasicSeriesSpec, DomainRange } from '../utils/specs'; +import { BasicSeriesSpec, DomainRange, SeriesTypes } from '../utils/specs'; import { BaseDomain } from './domain'; export type XDomain = BaseDomain & { @@ -155,7 +155,7 @@ export function convertXScaleTypes( if (specs.length === 0 || seriesTypes.size === 0 || scaleTypes.size === 0) { return null; } - const isBandScale = seriesTypes.has('bar'); + const isBandScale = seriesTypes.has(SeriesTypes.Bar); if (scaleTypes.size === 1) { const scaleType = scaleTypes.values().next().value; let timeZone: string | undefined; diff --git a/src/chart_types/xy_chart/domains/y_domain.test.ts b/src/chart_types/xy_chart/domains/y_domain.test.ts index 1b10b48127..8e2a3d3303 100644 --- a/src/chart_types/xy_chart/domains/y_domain.test.ts +++ b/src/chart_types/xy_chart/domains/y_domain.test.ts @@ -1,7 +1,6 @@ -import { getGroupId, getSpecId, GroupId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { RawDataSeries } from '../utils/series'; -import { BasicSeriesSpec, DomainRange } from '../utils/specs'; +import { BasicSeriesSpec, DomainRange, SpecTypes, SeriesTypes } from '../utils/specs'; import { BARCHART_1Y0G } from '../../../utils/data_samples/test_dataset'; import { coerceYScaleTypes, @@ -10,33 +9,35 @@ import { splitSpecsByGroupId, YBasicSeriesSpec, } from './y_domain'; +import { GroupId } from '../../../utils/ids'; +import { ChartTypes } from '../..'; describe('Y Domain', () => { test('Should merge Y domain', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries); + specDataSeries.set('a', dataSeries); const mergedDomain = mergeYDomain( specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, - groupId: getGroupId('a'), - id: getSpecId('a'), + groupId: 'a', + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -56,13 +57,13 @@ describe('Y Domain', () => { test('Should merge Y domain different group', () => { const dataSeries1: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], @@ -70,31 +71,31 @@ describe('Y Domain', () => { ]; const dataSeries2: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 10 }, { x: 2, y1: 10 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries1); - specDataSeries.set(getSpecId('b'), dataSeries2); + specDataSeries.set('a', dataSeries1); + specDataSeries.set('b', dataSeries2); const mergedDomain = mergeYDomain( specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, - groupId: getGroupId('a'), - id: getSpecId('a'), + groupId: 'a', + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, - groupId: getGroupId('b'), - id: getSpecId('b'), + groupId: 'b', + id: 'b', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -121,13 +122,13 @@ describe('Y Domain', () => { test('Should merge Y domain same group all stacked', () => { const dataSeries1: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], @@ -135,31 +136,31 @@ describe('Y Domain', () => { ]; const dataSeries2: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 10 }, { x: 2, y1: 10 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries1); - specDataSeries.set(getSpecId('b'), dataSeries2); + specDataSeries.set('a', dataSeries1); + specDataSeries.set('b', dataSeries2); const mergedDomain = mergeYDomain( specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, - groupId: getGroupId('a'), - id: getSpecId('a'), + groupId: 'a', + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, - groupId: getGroupId('a'), - id: getSpecId('b'), + groupId: 'a', + id: 'b', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -179,13 +180,13 @@ describe('Y Domain', () => { test('Should merge Y domain same group partially stacked', () => { const dataSeries1: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], @@ -193,31 +194,31 @@ describe('Y Domain', () => { ]; const dataSeries2: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 10 }, { x: 2, y1: 10 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries1); - specDataSeries.set(getSpecId('b'), dataSeries2); + specDataSeries.set('a', dataSeries1); + specDataSeries.set('b', dataSeries2); const mergedDomain = mergeYDomain( specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, - groupId: getGroupId('a'), - id: getSpecId('a'), + groupId: 'a', + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, - groupId: getGroupId('a'), - id: getSpecId('b'), + groupId: 'a', + id: 'b', yScaleToDataExtent: true, }, ], @@ -237,13 +238,13 @@ describe('Y Domain', () => { const maxValues = 10000; const dataSeries1: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: new Array(maxValues).fill(0).map((d, i) => ({ x: i, y1: i })), }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: new Array(maxValues).fill(0).map((d, i) => ({ x: i, y1: i })), @@ -251,31 +252,31 @@ describe('Y Domain', () => { ]; const dataSeries2: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: new Array(maxValues).fill(0).map((d, i) => ({ x: i, y1: i })), }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries1); - specDataSeries.set(getSpecId('b'), dataSeries2); + specDataSeries.set('a', dataSeries1); + specDataSeries.set('b', dataSeries2); const mergedDomain = mergeYDomain( specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, - groupId: getGroupId('a'), - id: getSpecId('a'), + groupId: 'a', + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, - groupId: getGroupId('a'), - id: getSpecId('b'), + groupId: 'a', + id: 'b', yScaleToDataExtent: true, }, ], @@ -285,9 +286,11 @@ describe('Y Domain', () => { }); test('Should split specs by groupId, two groups, non stacked', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -296,9 +299,11 @@ describe('Y Domain', () => { data: BARCHART_1Y0G, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -318,9 +323,11 @@ describe('Y Domain', () => { }); test('Should split specs by groupId, two groups, stacked', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -330,9 +337,11 @@ describe('Y Domain', () => { data: BARCHART_1Y0G, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -353,9 +362,11 @@ describe('Y Domain', () => { }); test('Should split specs by groupId, 1 group, stacked', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec1', + groupId: 'group', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -365,9 +376,11 @@ describe('Y Domain', () => { data: BARCHART_1Y0G, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec2', + groupId: 'group', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -386,9 +399,11 @@ describe('Y Domain', () => { }); test('Should 3 split specs by groupId, 2 group, semi/stacked', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -398,9 +413,11 @@ describe('Y Domain', () => { data: BARCHART_1Y0G, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec2', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -410,9 +427,11 @@ describe('Y Domain', () => { data: BARCHART_1Y0G, }; const spec3: BasicSeriesSpec = { - id: getSpecId('spec3'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec3', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -440,27 +459,27 @@ describe('Y Domain', () => { test('Should getDataSeriesOnGroup for matching specs', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('b'), dataSeries); + specDataSeries.set('b', dataSeries); const specs: YBasicSeriesSpec[] = [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, - groupId: getGroupId('a'), - id: getSpecId('a'), + groupId: 'a', + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -470,24 +489,24 @@ describe('Y Domain', () => { expect(rawDataSeries).toEqual([]); }); test('Should merge Y domain accounting for custom domain limits: complete bounded domain', () => { - const groupId = getGroupId('a'); + const groupId = 'a'; const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries); + specDataSeries.set('a', dataSeries); const domainsByGroupId = new Map<GroupId, DomainRange>(); domainsByGroupId.set(groupId, { min: 0, max: 20 }); @@ -495,10 +514,10 @@ describe('Y Domain', () => { specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, groupId, - id: getSpecId('a'), + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -516,24 +535,24 @@ describe('Y Domain', () => { ]); }); test('Should merge Y domain accounting for custom domain limits: partial lower bounded domain', () => { - const groupId = getGroupId('a'); + const groupId = 'a'; const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries); + specDataSeries.set('a', dataSeries); const domainsByGroupId = new Map<GroupId, DomainRange>(); domainsByGroupId.set(groupId, { min: 0 }); @@ -541,10 +560,10 @@ describe('Y Domain', () => { specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, groupId, - id: getSpecId('a'), + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -562,24 +581,24 @@ describe('Y Domain', () => { ]); }); test('Should not merge Y domain with invalid custom domain limits: partial lower bounded domain', () => { - const groupId = getGroupId('a'); + const groupId = 'a'; const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries); + specDataSeries.set('a', dataSeries); const domainsByGroupId = new Map<GroupId, DomainRange>(); domainsByGroupId.set(groupId, { min: 20 }); @@ -588,10 +607,10 @@ describe('Y Domain', () => { specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, groupId, - id: getSpecId('a'), + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -604,24 +623,24 @@ describe('Y Domain', () => { expect(attemptToMerge).toThrowError(errorMessage); }); test('Should merge Y domain accounting for custom domain limits: partial upper bounded domain', () => { - const groupId = getGroupId('a'); + const groupId = 'a'; const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries); + specDataSeries.set('a', dataSeries); const domainsByGroupId = new Map<GroupId, DomainRange>(); domainsByGroupId.set(groupId, { max: 20 }); @@ -629,10 +648,10 @@ describe('Y Domain', () => { specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, groupId, - id: getSpecId('a'), + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -650,24 +669,24 @@ describe('Y Domain', () => { ]); }); test('Should not merge Y domain with invalid custom domain limits: partial upper bounded domain', () => { - const groupId = getGroupId('a'); + const groupId = 'a'; const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries); + specDataSeries.set('a', dataSeries); const domainsByGroupId = new Map<GroupId, DomainRange>(); domainsByGroupId.set(groupId, { max: -1 }); @@ -676,10 +695,10 @@ describe('Y Domain', () => { specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, groupId, - id: getSpecId('a'), + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, }, @@ -694,13 +713,13 @@ describe('Y Domain', () => { test('Should merge Y domain with stacked as percentage', () => { const dataSeries1: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], @@ -708,32 +727,32 @@ describe('Y Domain', () => { ]; const dataSeries2: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 10 }, { x: 2, y1: 10 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries1); - specDataSeries.set(getSpecId('b'), dataSeries2); + specDataSeries.set('a', dataSeries1); + specDataSeries.set('b', dataSeries2); const mergedDomain = mergeYDomain( specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, - groupId: getGroupId('a'), - id: getSpecId('a'), + groupId: 'a', + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, stackAsPercentage: true, }, { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, - groupId: getGroupId('a'), - id: getSpecId('b'), + groupId: 'a', + id: 'b', yScaleToDataExtent: true, }, ], @@ -750,24 +769,24 @@ describe('Y Domain', () => { ]); }); test('Should merge Y domain with as percentage regadless of custom domains', () => { - const groupId = getGroupId('a'); + const groupId = 'a'; const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 2, y1: 2 }, { x: 3, y1: 2 }, { x: 4, y1: 5 }], }, { - specId: getSpecId('a'), + specId: 'a', key: [''], seriesColorKey: '', data: [{ x: 1, y1: 2 }, { x: 4, y1: 7 }], }, ]; const specDataSeries = new Map(); - specDataSeries.set(getSpecId('a'), dataSeries); + specDataSeries.set('a', dataSeries); const domainsByGroupId = new Map<GroupId, DomainRange>(); domainsByGroupId.set(groupId, { min: 2, max: 20 }); @@ -775,10 +794,10 @@ describe('Y Domain', () => { specDataSeries, [ { - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Linear, groupId, - id: getSpecId('a'), + id: 'a', stackAccessors: ['a'], yScaleToDataExtent: true, stackAsPercentage: true, diff --git a/src/chart_types/xy_chart/domains/y_domain.ts b/src/chart_types/xy_chart/domains/y_domain.ts index 945bfce29a..5e0fd2a232 100644 --- a/src/chart_types/xy_chart/domains/y_domain.ts +++ b/src/chart_types/xy_chart/domains/y_domain.ts @@ -1,4 +1,4 @@ -import { BasicSeriesSpec, DomainRange, DEFAULT_GLOBAL_ID } from '../utils/specs'; +import { BasicSeriesSpec, DomainRange, DEFAULT_GLOBAL_ID, SeriesTypes } from '../utils/specs'; import { GroupId, SpecId, getGroupId } from '../../../utils/ids'; import { ScaleContinuousType, ScaleType } from '../../../utils/scales/scales'; import { isCompleteBound, isLowerBound, isUpperBound } from '../utils/axis_utils'; @@ -17,7 +17,7 @@ export type YDomain = BaseDomain & { export type YBasicSeriesSpec = Pick< BasicSeriesSpec, 'id' | 'seriesType' | 'yScaleType' | 'groupId' | 'stackAccessors' | 'yScaleToDataExtent' | 'useDefaultGroupDomain' -> & { stackAsPercentage?: boolean }; +> & { stackAsPercentage?: boolean; enableHistogramMode?: boolean }; interface GroupSpecs { isPercentageStack: boolean; @@ -160,6 +160,7 @@ function computeYStackedDomain(dataseries: RawDataSeries[], scaleToExtent: boole } return computeContinuousDataDomain(dataValues, identity, scaleToExtent); } + function computeYNonStackedDomain(dataseries: RawDataSeries[], scaleToExtent: boolean) { const yValues = new Set<any>(); dataseries.forEach((ds) => { @@ -175,11 +176,18 @@ function computeYNonStackedDomain(dataseries: RawDataSeries[], scaleToExtent: bo } return computeContinuousDataDomain([...yValues.values()], identity, scaleToExtent); } + export function splitSpecsByGroupId(specs: YBasicSeriesSpec[]) { const specsByGroupIds = new Map< GroupId, { isPercentageStack: boolean; stacked: YBasicSeriesSpec[]; nonStacked: YBasicSeriesSpec[] } >(); + // After mobx->redux https://github.com/elastic/elastic-charts/pull/281 we keep the specs untouched on mount + // in MobX version, the stackAccessors was programmatically added to every histogram specs + // in ReduX version, we left untouched the specs, so we have to manually check that + const isHistogramEnabled = specs.some(({ seriesType, enableHistogramMode }) => { + return seriesType === SeriesTypes.Bar && enableHistogramMode; + }); // split each specs by groupId and by stacked or not specs.forEach((spec) => { const group = specsByGroupIds.get(spec.groupId) || { @@ -187,7 +195,12 @@ export function splitSpecsByGroupId(specs: YBasicSeriesSpec[]) { stacked: [], nonStacked: [], }; - if (spec.stackAccessors && spec.stackAccessors.length > 0) { + // stack every bars if using histogram mode + // independenyly from lines and areas + if ( + (spec.seriesType === SeriesTypes.Bar && isHistogramEnabled) || + (spec.stackAccessors && spec.stackAccessors.length > 0) + ) { group.stacked.push(spec); } else { group.nonStacked.push(spec); diff --git a/src/chart_types/xy_chart/legend/legend.test.ts b/src/chart_types/xy_chart/legend/legend.test.ts index d8369f8d87..e931947703 100644 --- a/src/chart_types/xy_chart/legend/legend.test.ts +++ b/src/chart_types/xy_chart/legend/legend.test.ts @@ -1,8 +1,9 @@ -import { AxisId, getAxisId, getGroupId, getSpecId, SpecId } from '../../../utils/ids'; +import { getAxisId, getGroupId, getSpecId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { computeLegend, getSeriesColorLabel } from './legend'; import { DataSeriesColorsValues } from '../utils/series'; -import { AxisSpec, BasicSeriesSpec, Position } from '../utils/specs'; +import { AxisSpec, BasicSeriesSpec, Position, SpecTypes, SeriesTypes } from '../utils/specs'; +import { ChartTypes } from '../..'; const nullDisplayValue = { formatted: { @@ -31,10 +32,12 @@ const colorValues2b = { colorValues: ['c', 'd'], }; const spec1: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: getSpecId('spec1'), name: 'Spec 1 title', groupId: getGroupId('group'), - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -44,9 +47,11 @@ const spec1: BasicSeriesSpec = { hideInLegend: false, }; const spec2: BasicSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: getSpecId('spec2'), groupId: getGroupId('group'), - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -56,8 +61,10 @@ const spec2: BasicSeriesSpec = { hideInLegend: false, }; -const axesSpecs = new Map<AxisId, AxisSpec>(); +const axesSpecs: AxisSpec[] = []; const axisSpec: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, id: getAxisId('axis1'), groupId: getGroupId('group1'), hide: false, @@ -70,14 +77,12 @@ const axisSpec: AxisSpec = { return `${value}`; }, }; -axesSpecs.set(axisSpec.id, axisSpec); +axesSpecs.push(axisSpec); describe('Legends', () => { const seriesColor = new Map<string, DataSeriesColorsValues>(); const seriesColorMap = new Map<string, string>(); - const specs = new Map<SpecId, BasicSeriesSpec>(); - specs.set(spec1.id, spec1); - specs.set(spec2.id, spec2); + const specs = [spec1, spec2]; seriesColorMap.set('colorSeries1a', 'red'); seriesColorMap.set('colorSeries1b', 'blue'); seriesColorMap.set('colorSeries2a', 'green'); @@ -182,9 +187,8 @@ describe('Legends', () => { seriesColor.set('colorSeries2b', colorValues2b); const emptyColorMap = new Map<string, string>(); - const deselectedDataSeries = null; - const legend = computeLegend(seriesColor, emptyColorMap, specs, 'violet', axesSpecs, deselectedDataSeries); + const legend = computeLegend(seriesColor, emptyColorMap, specs, 'violet', axesSpecs); const visibility = [...legend.values()].map((item) => item.isSeriesVisible); diff --git a/src/chart_types/xy_chart/legend/legend.ts b/src/chart_types/xy_chart/legend/legend.ts index d1153ff89b..48ede4e62c 100644 --- a/src/chart_types/xy_chart/legend/legend.ts +++ b/src/chart_types/xy_chart/legend/legend.ts @@ -1,15 +1,15 @@ -import { getAxesSpecForSpecId, LastValues } from '../store/utils'; +import { getAxesSpecForSpecId, LastValues, getSpecsById } from '../state/utils'; import { identity } from '../../../utils/commons'; -import { AxisId, SpecId } from '../../../utils/ids'; import { DataSeriesColorsValues, - findDataSeriesByColorValues, getSortedDataSeriesColorsValuesMap, + findDataSeriesByColorValues, } from '../utils/series'; import { AxisSpec, BasicSeriesSpec, Postfixes, isAreaSeriesSpec, isBarSeriesSpec } from '../utils/specs'; import { Y0_ACCESSOR_POSTFIX, Y1_ACCESSOR_POSTFIX } from '../tooltip/tooltip'; +import { AccessorType } from '../../../utils/geometry'; -export interface FormatedLastValues { +interface FormattedLastValues { y0: number | string | null; y1: number | string | null; } @@ -24,11 +24,11 @@ export type LegendItem = Postfixes & { isLegendItemVisible?: boolean; displayValue: { raw: LastValues; - formatted: FormatedLastValues; + formatted: FormattedLastValues; }; }; -export function getPostfix(spec: BasicSeriesSpec): Postfixes { +function getPostfix(spec: BasicSeriesSpec): Postfixes { if (isAreaSeriesSpec(spec) || isBarSeriesSpec(spec)) { const { y0AccessorFormat = Y0_ACCESSOR_POSTFIX, y1AccessorFormat = Y1_ACCESSOR_POSTFIX } = spec; return { @@ -40,20 +40,31 @@ export function getPostfix(spec: BasicSeriesSpec): Postfixes { return {}; } +export function getItemLabel( + { banded, label, y1AccessorFormat, y0AccessorFormat }: LegendItem, + yAccessor: AccessorType, +) { + if (!banded) { + return label; + } + + return yAccessor === AccessorType.Y1 ? `${label}${y1AccessorFormat}` : `${label}${y0AccessorFormat}`; +} + export function computeLegend( seriesColor: Map<string, DataSeriesColorsValues>, seriesColorMap: Map<string, string>, - specs: Map<SpecId, BasicSeriesSpec>, + specs: BasicSeriesSpec[], defaultColor: string, - axesSpecs: Map<AxisId, AxisSpec>, - deselectedDataSeries?: DataSeriesColorsValues[] | null, + axesSpecs: AxisSpec[], + deselectedDataSeries: DataSeriesColorsValues[] = [], ): Map<string, LegendItem> { const legendItems: Map<string, LegendItem> = new Map(); const sortedSeriesColors = getSortedDataSeriesColorsValuesMap(seriesColor); sortedSeriesColors.forEach((series, key) => { const { banded, specId, lastValue, colorValues } = series; - const spec = specs.get(specId); + const spec = getSpecsById<BasicSeriesSpec>(specs, specId); const color = seriesColorMap.get(key) || defaultColor; const hasSingleSeries = seriesColor.size === 1; const label = getSeriesColorLabel(colorValues, hasSingleSeries, spec); @@ -82,8 +93,8 @@ export function computeLegend( y1: lastValue && lastValue.y1 !== null ? lastValue.y1 : null, }, formatted: { - y0: isSeriesVisible && lastValue && lastValue.y0 !== null ? formatter(lastValue.y0) : null, - y1: isSeriesVisible && lastValue && lastValue.y1 !== null ? formatter(lastValue.y1) : null, + y0: lastValue && lastValue.y0 !== null ? formatter(lastValue.y0) : null, + y1: lastValue && lastValue.y1 !== null ? formatter(lastValue.y1) : null, }, }, ...getPostfix(spec), diff --git a/src/chart_types/xy_chart/renderer/_index.scss b/src/chart_types/xy_chart/renderer/_index.scss new file mode 100644 index 0000000000..57d9fadc19 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/_index.scss @@ -0,0 +1 @@ +@import 'dom/index'; diff --git a/src/components/react_canvas/area_geometries.tsx b/src/chart_types/xy_chart/renderer/canvas/area_geometries.tsx similarity index 92% rename from src/components/react_canvas/area_geometries.tsx rename to src/chart_types/xy_chart/renderer/canvas/area_geometries.tsx index 0ae752443c..e5d0f0bb24 100644 --- a/src/components/react_canvas/area_geometries.tsx +++ b/src/chart_types/xy_chart/renderer/canvas/area_geometries.tsx @@ -1,26 +1,19 @@ import React from 'react'; import { Group as KonvaGroup, PathConfig } from 'konva'; import { Circle, Group, Path } from 'react-konva'; - -import { LegendItem } from '../../chart_types/xy_chart/legend/legend'; -import { - AreaGeometry, - getGeometryStateStyle, - PointGeometry, - getGeometryIdKey, - GeometryId, -} from '../../chart_types/xy_chart/rendering/rendering'; -import { SharedGeometryStateStyle, PointStyle } from '../../utils/themes/theme'; import { buildAreaRenderProps, buildPointStyleProps, buildPointRenderProps, PointStyleProps, buildLineRenderProps, - Clippings, - clipRanges, } from './utils/rendering_props_utils'; -import { mergePartial } from '../../utils/commons'; +import { getGeometryIdKey, getGeometryStateStyle } from '../../rendering/rendering'; +import { mergePartial } from '../../../../utils/commons'; +import { AreaGeometry, PointGeometry, GeometryId } from '../../../../utils/geometry'; +import { PointStyle, SharedGeometryStateStyle } from '../../../../utils/themes/theme'; +import { LegendItem } from '../../legend/legend'; +import { Clippings, clipRanges } from './bar_values_utils'; interface AreaGeometriesDataProps { animated?: boolean; diff --git a/src/components/react_canvas/axis.tsx b/src/chart_types/xy_chart/renderer/canvas/axis.tsx similarity index 63% rename from src/components/react_canvas/axis.tsx rename to src/chart_types/xy_chart/renderer/canvas/axis.tsx index 54af603190..47d21d14c8 100644 --- a/src/components/react_canvas/axis.tsx +++ b/src/chart_types/xy_chart/renderer/canvas/axis.tsx @@ -9,13 +9,24 @@ import { getVerticalAxisTickLineProps, isHorizontalAxis, isVerticalAxis, -} from '../../chart_types/xy_chart/utils/axis_utils'; -import { AxisSpec, Position } from '../../chart_types/xy_chart/utils/specs'; -import { Theme } from '../../utils/themes/theme'; -import { Dimensions } from '../../utils/dimensions'; +} from '../../utils/axis_utils'; +import { AxisSpec, Position } from '../../utils/specs'; +import { Theme } from '../../../../utils/themes/theme'; +import { Dimensions } from '../../../../utils/dimensions'; +import { connect } from 'react-redux'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { computeAxisVisibleTicksSelector } from '../../state/selectors/compute_axis_visible_ticks'; +import { getAxisSpecsSelector } from '../../state/selectors/get_specs'; +import { AxisId } from '../../../../utils/ids'; +import { computeAxisTicksDimensionsSelector } from '../../state/selectors/compute_axis_ticks_dimensions'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; +import { LIGHT_THEME } from '../../../../utils/themes/light_theme'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getSpecsById } from '../../state/utils'; interface AxisProps { - chartTheme: Theme; + theme: Theme; axisSpec: AxisSpec; axisTicksDimensions: AxisTicksDimensions; axisPosition: Dimensions; @@ -25,70 +36,6 @@ interface AxisProps { } export class Axis extends React.PureComponent<AxisProps> { - render() { - return this.renderAxis(); - } - - private renderAxis = () => { - const { ticks, axisPosition, debug } = this.props; - return ( - <Group x={axisPosition.left} y={axisPosition.top}> - {debug && ( - <Rect - x={0} - y={0} - width={axisPosition.width} - height={axisPosition.height} - stroke="black" - strokeWidth={1} - fill="violet" - opacity={0.2} - /> - )} - <Group key="lines">{this.renderAxisLine()}</Group> - <Group key="tick-lines">{ticks.map(this.renderTickLine)}</Group> - <Group key="ticks">{ticks.filter((tick) => tick.label !== null).map(this.renderTickLabel)}</Group> - {this.renderAxisTitle()} - </Group> - ); - }; - private renderAxisLine = () => { - const { - axisSpec: { position }, - axisPosition, - chartTheme: { - axes: { axisLineStyle }, - }, - } = this.props; - const lineProps: number[] = []; - if (isVerticalAxis(position)) { - lineProps[0] = position === Position.Left ? axisPosition.width : 0; - lineProps[2] = position === Position.Left ? axisPosition.width : 0; - lineProps[1] = 0; - lineProps[3] = axisPosition.height; - } else { - lineProps[0] = 0; - lineProps[2] = axisPosition.width; - lineProps[1] = position === Position.Top ? axisPosition.height : 0; - lineProps[3] = position === Position.Top ? axisPosition.height : 0; - } - return <Line points={lineProps} {...axisLineStyle} />; - }; - private renderTickLine = (tick: AxisTick, i: number) => { - const { - axisSpec: { tickSize, position }, - axisPosition, - chartTheme: { - axes: { tickLineStyle }, - }, - } = this.props; - - const lineProps = isVerticalAxis(position) - ? getVerticalAxisTickLineProps(position, axisPosition.width, tickSize, tick.position) - : getHorizontalAxisTickLineProps(position, axisPosition.height, tickSize, tick.position); - - return <Line {...tickLineStyle} key={`tick-${i}`} points={lineProps} />; - }; private renderTickLabel = (tick: AxisTick, i: number) => { /** * padding is already computed through width @@ -96,7 +43,7 @@ export class Axis extends React.PureComponent<AxisProps> { * set padding to 0 to avoid conflict */ const labelStyle = { - ...this.props.chartTheme.axes.tickLabelStyle, + ...this.props.theme.axes.tickLabelStyle, padding: 0, }; @@ -141,6 +88,46 @@ export class Axis extends React.PureComponent<AxisProps> { </Group> ); }; + + private renderTickLine = (tick: AxisTick, i: number) => { + const { + axisSpec: { tickSize, position }, + axisPosition, + theme: { + axes: { tickLineStyle }, + }, + } = this.props; + + const lineProps = isVerticalAxis(position) + ? getVerticalAxisTickLineProps(position, axisPosition.width, tickSize, tick.position) + : getHorizontalAxisTickLineProps(position, axisPosition.height, tickSize, tick.position); + + return <Line {...tickLineStyle} key={`tick-${i}`} points={lineProps} />; + }; + + private renderAxisLine = () => { + const { + axisSpec: { position }, + axisPosition, + theme: { + axes: { axisLineStyle }, + }, + } = this.props; + const lineProps: number[] = []; + if (isVerticalAxis(position)) { + lineProps[0] = position === Position.Left ? axisPosition.width : 0; + lineProps[2] = position === Position.Left ? axisPosition.width : 0; + lineProps[1] = 0; + lineProps[3] = axisPosition.height; + } else { + lineProps[0] = 0; + lineProps[2] = axisPosition.width; + lineProps[1] = position === Position.Top ? axisPosition.height : 0; + lineProps[3] = position === Position.Top ? axisPosition.height : 0; + } + return <Line points={lineProps} {...axisLineStyle} />; + }; + private renderAxisTitle() { const { axisSpec: { title, position }, @@ -158,7 +145,7 @@ export class Axis extends React.PureComponent<AxisProps> { axisPosition: { height }, axisSpec: { title, position, tickSize, tickPadding }, axisTicksDimensions: { maxLabelBboxWidth }, - chartTheme: { + theme: { axes: { axisTitleStyle }, }, debug, @@ -194,7 +181,7 @@ export class Axis extends React.PureComponent<AxisProps> { axisPosition: { width, height }, axisSpec: { title, position, tickSize, tickPadding }, axisTicksDimensions: { maxLabelBboxHeight }, - chartTheme: { + theme: { axes: { axisTitleStyle: { padding, ...titleStyle }, }, @@ -227,4 +214,104 @@ export class Axis extends React.PureComponent<AxisProps> { </Group> ); } + render() { + const { ticks, axisPosition, debug } = this.props; + return ( + <Group x={axisPosition.left} y={axisPosition.top}> + {debug && ( + <Rect + x={0} + y={0} + width={axisPosition.width} + height={axisPosition.height} + stroke="black" + strokeWidth={1} + fill="violet" + opacity={0.2} + /> + )} + <Group key="lines">{this.renderAxisLine()}</Group> + <Group key="tick-lines">{ticks.map(this.renderTickLine)}</Group> + <Group key="ticks">{ticks.filter((tick) => tick.label !== null).map(this.renderTickLabel)}</Group> + {this.renderAxisTitle()} + </Group> + ); + } } + +interface AxesProps { + axesVisibleTicks: Map<AxisId, AxisTick[]>; + axesSpecs: AxisSpec[]; + axesTicksDimensions: Map<AxisId, AxisTicksDimensions>; + axesPositions: Map<string, Dimensions>; + theme: Theme; + debug: boolean; + chartDimensions: Dimensions; +} +class AxesComponent extends React.PureComponent<AxesProps> { + render() { + const { + axesVisibleTicks, + axesSpecs, + axesTicksDimensions, + axesPositions, + theme, + debug, + chartDimensions, + } = this.props; + const axesComponents: JSX.Element[] = []; + axesVisibleTicks.forEach((axisTicks, axisId) => { + const axisSpec = getSpecsById<AxisSpec>(axesSpecs, axisId); + const axisTicksDimensions = axesTicksDimensions.get(axisId); + const axisPosition = axesPositions.get(axisId); + const ticks = axesVisibleTicks.get(axisId); + if (!ticks || !axisSpec || !axisTicksDimensions || !axisPosition) { + return; + } + axesComponents.push( + <Axis + key={`axis-${axisId}`} + axisSpec={axisSpec} + axisTicksDimensions={axisTicksDimensions} + axisPosition={axisPosition} + ticks={ticks} + theme={theme} + debug={debug} + chartDimensions={chartDimensions} + />, + ); + }); + return axesComponents; + } +} + +const mapStateToProps = (state: GlobalChartState): AxesProps => { + if (!state.specsInitialized) { + return { + theme: LIGHT_THEME, + chartDimensions: { + width: 0, + left: 0, + top: 0, + height: 0, + }, + debug: false, + axesSpecs: [], + axesPositions: new Map(), + axesTicksDimensions: new Map(), + axesVisibleTicks: new Map(), + }; + } + const axisTickPositions = computeAxisVisibleTicksSelector(state); + return { + theme: getChartThemeSelector(state), + chartDimensions: computeChartDimensionsSelector(state).chartDimensions, + debug: getSettingsSpecSelector(state).debug, + axesPositions: axisTickPositions.axisPositions, + axesSpecs: getAxisSpecsSelector(state), + axesTicksDimensions: computeAxisTicksDimensionsSelector(state), + axesVisibleTicks: axisTickPositions.axisVisibleTicks, + }; +}; + +export const Axes = connect(mapStateToProps)(AxesComponent); diff --git a/src/components/react_canvas/bar_geometries.tsx b/src/chart_types/xy_chart/renderer/canvas/bar_geometries.tsx similarity index 89% rename from src/components/react_canvas/bar_geometries.tsx rename to src/chart_types/xy_chart/renderer/canvas/bar_geometries.tsx index 646decef6b..4fa7cd11c7 100644 --- a/src/components/react_canvas/bar_geometries.tsx +++ b/src/chart_types/xy_chart/renderer/canvas/bar_geometries.tsx @@ -2,10 +2,12 @@ import { Group as KonvaGroup } from 'konva'; import React from 'react'; import { Group, Rect } from 'react-konva'; import { animated, Spring } from 'react-spring/renderprops-konva.cjs'; -import { LegendItem } from '../../chart_types/xy_chart/legend/legend'; -import { BarGeometry, getGeometryStateStyle } from '../../chart_types/xy_chart/rendering/rendering'; -import { SharedGeometryStateStyle } from '../../utils/themes/theme'; -import { buildBarRenderProps, buildBarBorderRenderProps, Clippings } from './utils/rendering_props_utils'; +import { buildBarRenderProps, buildBarBorderRenderProps } from './utils/rendering_props_utils'; +import { BarGeometry } from '../../../../utils/geometry'; +import { LegendItem } from '../../../../chart_types/xy_chart/legend/legend'; +import { SharedGeometryStateStyle } from '../../../../utils/themes/theme'; +import { getGeometryStateStyle } from '../../rendering/rendering'; +import { Clippings } from './bar_values_utils'; interface BarGeometriesDataProps { animated?: boolean; diff --git a/src/chart_types/xy_chart/renderer/canvas/bar_values.tsx b/src/chart_types/xy_chart/renderer/canvas/bar_values.tsx new file mode 100644 index 0000000000..e515cf0ef3 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/canvas/bar_values.tsx @@ -0,0 +1,103 @@ +import React from 'react'; +import { Group, Rect, Text } from 'react-konva'; +import { Rotation } from '../../utils/specs'; +import { Theme } from '../../../../utils/themes/theme'; +import { Dimensions } from '../../../../utils/dimensions'; +import { BarGeometry } from '../../../../utils/geometry'; +import { buildBarValueProps } from './bar_values_utils'; +import { connect } from 'react-redux'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; +import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; +import { computeSeriesGeometriesSelector } from '../../state/selectors/compute_series_geometries'; +import { LIGHT_THEME } from '../../../../utils/themes/light_theme'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; + +interface BarValuesProps { + theme: Theme; + chartDimensions: Dimensions; + chartRotation: Rotation; + debug: boolean; + bars: BarGeometry[]; +} + +export class BarValuesComponent extends React.PureComponent<BarValuesProps> { + render() { + const { chartDimensions, bars } = this.props; + if (!bars) { + return; + } + + return ( + <Group x={chartDimensions.left} y={chartDimensions.top}> + {this.renderBarValues()} + </Group> + ); + } + + private renderBarValues = () => { + const { bars, debug, chartRotation, chartDimensions, theme } = this.props; + const displayValueStyle = theme.barSeriesStyle.displayValue; + + return bars.map((bar, index) => { + const { displayValue, x, y, height, width } = bar; + if (!displayValue) { + return; + } + + const key = `bar-value-${index}`; + const displayValueProps = buildBarValueProps({ + x, + y, + barHeight: height, + barWidth: width, + displayValueStyle, + displayValue, + chartRotation, + chartDimensions, + }); + + const debugProps = { + ...displayValueProps, + stroke: 'violet', + strokeWidth: 1, + fill: 'transparent', + }; + + return ( + <Group key={key}> + {debug && <Rect {...debugProps} />} + {displayValue && <Text {...displayValueProps} />} + </Group> + ); + }); + }; +} + +const mapStateToProps = (state: GlobalChartState): BarValuesProps => { + if (!state.specsInitialized) { + return { + theme: LIGHT_THEME, + chartDimensions: { + width: 0, + left: 0, + top: 0, + height: 0, + }, + chartRotation: 0, + debug: false, + bars: [], + }; + } + const geometries = computeSeriesGeometriesSelector(state); + return { + theme: getChartThemeSelector(state), + chartDimensions: computeChartDimensionsSelector(state).chartDimensions, + chartRotation: getChartRotationSelector(state), + debug: getSettingsSpecSelector(state).debug, + bars: geometries.geometries.bars, + }; +}; + +export const BarValues = connect(mapStateToProps)(BarValuesComponent); diff --git a/src/components/react_canvas/utils/rendering_props_utils.ts b/src/chart_types/xy_chart/renderer/canvas/bar_values_utils.ts similarity index 56% rename from src/components/react_canvas/utils/rendering_props_utils.ts rename to src/chart_types/xy_chart/renderer/canvas/bar_values_utils.ts index 0c320da9d2..7672b1da39 100644 --- a/src/components/react_canvas/utils/rendering_props_utils.ts +++ b/src/chart_types/xy_chart/renderer/canvas/bar_values_utils.ts @@ -1,19 +1,9 @@ -import { RectConfig, PathConfig, CircleConfig, ContainerConfig } from 'konva'; import { Required } from 'utility-types'; - -import { ClippedRanges } from '../../../chart_types/xy_chart/rendering/rendering'; -import { Rotation } from '../../../chart_types/xy_chart/utils/specs'; -import { - AreaStyle, - DisplayValueStyle, - LineStyle, - PointStyle, - RectBorderStyle, - RectStyle, - GeometryStateStyle, -} from '../../../utils/themes/theme'; -import { Dimensions } from '../../../utils/dimensions'; -import { GlobalKonvaElementProps } from '../globals'; +import { Rotation } from '../../utils/specs'; +import { Dimensions } from '../../../../utils/dimensions'; +import { DisplayValueStyle } from '../../../../utils/themes/theme'; +import { ContainerConfig } from 'konva'; +import { ClippedRanges } from '../../../../utils/geometry'; export interface PointStyleProps { radius: number; @@ -107,40 +97,6 @@ export function rotateBarValueProps( return props; } -export function getBarValueClipDimensions( - displayValue: { width: number; height: number; isValueContainedInElement?: boolean }, - computedDimensions: { width: number; height: number }, - barHeight: number, - chartRotation: Rotation, -): { width: number; height: number; offsetX: number; offsetY: number } { - const height = displayValue.isValueContainedInElement ? displayValue.height : computedDimensions.height; - const width = displayValue.isValueContainedInElement ? displayValue.width : computedDimensions.width; - - const offsetY = chartRotation === 180 ? barHeight - displayValue.height : 0; - const offsetX = chartRotation === 90 ? barHeight - displayValue.width : 0; - - return { height, width, offsetX, offsetY }; -} - -export function isBarValueOverflow( - chartDimensions: Dimensions, - clip: { width: number; height: number; offsetX: number; offsetY: number }, - valuePosition: { x: number; y: number; offsetX: number; offsetY: number }, - hideClippedValue?: boolean, -): boolean { - const chartHeight = chartDimensions.height; - const chartWidth = chartDimensions.width; - - const isOverflowX = - valuePosition.x + clip.width - valuePosition.offsetX > chartWidth || - valuePosition.x + clip.offsetX - valuePosition.offsetX < 0; - const isOverflowY = - valuePosition.y + clip.height - valuePosition.offsetY > chartHeight || - valuePosition.y + clip.offsetY - valuePosition.offsetY < 0; - - return !!hideClippedValue && (isOverflowX || isOverflowY); -} - export function buildBarValueProps({ x, y, @@ -240,186 +196,38 @@ export function buildBarValueProps({ return props; } -/** - * Return the style of a point. - * The color value is used for stroke or fill if they are undefind in the PointStyle - * @param color the series color - * @param pointStyle the merged point style - */ -export function buildPointStyleProps( - color: string, - pointStyle: PointStyle, - geometryStateStyle: GeometryStateStyle, -): PointStyleProps { - const { strokeWidth, opacity } = pointStyle; - const stroke = pointStyle.stroke || color; - const fill = pointStyle.fill || color; - return { - radius: pointStyle.radius, - stroke, - strokeWidth, - strokeEnabled: strokeWidth !== 0, - fill: fill, - ...geometryStateStyle, - opacity: opacity * geometryStateStyle.opacity, - }; -} - -/** - * Return the rendering props for a point - * @param x the x position of the point - * @param y the y position of the point - * @param pointStyleProps the style props of the point - */ -export function buildPointRenderProps(x: number, y: number, pointStyleProps: PointStyleProps): CircleConfig { - return { - x, - y, - ...pointStyleProps, - ...GlobalKonvaElementProps, - }; -} +export function getBarValueClipDimensions( + displayValue: { width: number; height: number; isValueContainedInElement?: boolean }, + computedDimensions: { width: number; height: number }, + barHeight: number, + chartRotation: Rotation, +): { width: number; height: number; offsetX: number; offsetY: number } { + const height = displayValue.isValueContainedInElement ? displayValue.height : computedDimensions.height; + const width = displayValue.isValueContainedInElement ? displayValue.width : computedDimensions.width; -/** - * Return the rendering props for a line. The color of the line will be overwritten - * by the stroke color of the lineStyle parameter if present - * @param x the horizontal offset to place the line - * @param linePath the SVG line path - * @param color the computed color of the line for this series - * @param lineStyle the line style - * @param geometryStateStyle the highlight geometry style - */ -export function buildLineRenderProps( - x: number, - linePath: string, - color: string, - lineStyle: LineStyle, - geometryStateStyle: GeometryStateStyle, -): PathConfig { - const opacity = lineStyle.opacity * geometryStateStyle.opacity; - - return { - x, - data: linePath, - stroke: lineStyle.stroke || color, - strokeWidth: lineStyle.strokeWidth, - lineCap: 'round', - lineJoin: 'round', - ...geometryStateStyle, - opacity, // want to override opactiy of geometryStateStyle - ...GlobalKonvaElementProps, - }; -} + const offsetY = chartRotation === 180 ? barHeight - displayValue.height : 0; + const offsetX = chartRotation === 90 ? barHeight - displayValue.width : 0; -/** - * Return the rendering props for an area. The color of the area will be overwritten - * by the fill color of the areaStyle parameter if present - * @param areaPath the SVG area path - * @param x the horizontal offset to place the area - * @param color the computed color of the line for this series - * @param areaStyle the area style - * @param geometryStateStyle the highlight geometry style - */ -export function buildAreaRenderProps( - xTransform: number, - areaPath: string, - color: string, - areaStyle: AreaStyle, - geometryStateStyle: GeometryStateStyle, -): PathConfig { - const opacity = areaStyle.opacity * geometryStateStyle.opacity; - - return { - x: xTransform, - data: areaPath, - fill: areaStyle.fill || color, - lineCap: 'round', - lineJoin: 'round', - ...geometryStateStyle, - opacity, // want to override opactiy of geometryStateStyle - ...GlobalKonvaElementProps, - }; + return { height, width, offsetX, offsetY }; } -/** - * Return the rendering props for a bar. The color of the bar will be overwritten - * by the fill color of the rectStyle parameter if present - * @param x the x position of the rect - * @param y the y position of the rect - * @param width the width of the rect - * @param height the height of the rect - * @param color the computed color of the rect for this series - * @param rectStyle the rect style - * @param geometryStateStyle the highlight geometry style - */ -export function buildBarRenderProps( - x: number, - y: number, - width: number, - height: number, - color: string, - rectStyle: RectStyle, - borderStyle: RectBorderStyle, - geometryStateStyle: GeometryStateStyle, -): RectConfig { - const opacity = rectStyle.opacity * geometryStateStyle.opacity; - const { stroke, visible, strokeWidth, strokeOpacity = 0 } = borderStyle; - const offset = !visible || strokeWidth <= 0 || !stroke || strokeOpacity <= 0 || opacity <= 0 ? 0 : strokeWidth; - - return { - x: x + offset, - y: y + offset, - width: width - 2 * offset, - height: height - 2 * offset, - fill: rectStyle.fill || color, - strokeEnabled: false, - ...geometryStateStyle, - opacity, // want to override opactiy of geometryStateStyle - ...GlobalKonvaElementProps, - }; -} +export function isBarValueOverflow( + chartDimensions: Dimensions, + clip: { width: number; height: number; offsetX: number; offsetY: number }, + valuePosition: { x: number; y: number; offsetX: number; offsetY: number }, + hideClippedValue?: boolean, +): boolean { + const chartHeight = chartDimensions.height; + const chartWidth = chartDimensions.width; -/** - * Return the rendering props for a bar. The color of the bar will be overwritten - * by the fill color of the rectStyle parameter if present - * @param x the x position of the rect - * @param y the y position of the rect - * @param width the width of the rect - * @param height the height of the rect - * @param color the computed color of the rect for this series - * @param rectStyle the rect style - * @param borderStyle the border rect style - * @param geometryStateStyle the highlight geometry style - */ -export function buildBarBorderRenderProps( - x: number, - y: number, - width: number, - height: number, - rectStyle: RectStyle, - borderStyle: RectBorderStyle, - geometryStateStyle: GeometryStateStyle, -): RectConfig | null { - const { stroke, visible, strokeWidth, strokeOpacity = rectStyle.opacity } = borderStyle; - const opacity = strokeOpacity * geometryStateStyle.opacity; - - if (!visible || strokeWidth <= 0 || !stroke || opacity <= 0) { - return null; - } + const isOverflowX = + valuePosition.x + clip.width - valuePosition.offsetX > chartWidth || + valuePosition.x + clip.offsetX - valuePosition.offsetX < 0; + const isOverflowY = + valuePosition.y + clip.height - valuePosition.offsetY > chartHeight || + valuePosition.y + clip.offsetY - valuePosition.offsetY < 0; - return { - x: x + strokeWidth / 2, - y: y + strokeWidth / 2, - width: width - strokeWidth, - height: height - strokeWidth, - fillEnabled: false, - strokeEnabled: true, - strokeWidth, - stroke, - ...geometryStateStyle, - opacity, // want to override opactiy of geometryStateStyle - ...GlobalKonvaElementProps, - }; + return !!hideClippedValue && (isOverflowX || isOverflowY); } /** diff --git a/src/chart_types/xy_chart/renderer/canvas/grid.tsx b/src/chart_types/xy_chart/renderer/canvas/grid.tsx new file mode 100644 index 0000000000..5b4976fc86 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/canvas/grid.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { Group, Line } from 'react-konva'; +import { connect } from 'react-redux'; +import { AxisLinePosition, isVerticalGrid } from '../../utils/axis_utils'; +import { GridLineConfig, mergeGridLineConfigs, Theme } from '../../../../utils/themes/theme'; +import { Dimensions } from '../../../../utils/dimensions'; +import { AxisId } from '../../../../utils/ids'; +import { AxisSpec } from '../../../../chart_types/xy_chart/utils/specs'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; +import { getAxisSpecsSelector } from '../../state/selectors/get_specs'; +import { computeAxisVisibleTicksSelector } from '../../state/selectors/compute_axis_visible_ticks'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { LIGHT_THEME } from '../../../../utils/themes/light_theme'; +import { getSpecsById } from '../../state/utils'; + +interface GridProps { + chartTheme: Theme; + axesGridLinesPositions: Map<AxisId, AxisLinePosition[]>; + axesSpecs: AxisSpec[]; + chartDimensions: Dimensions; +} + +class GridComponent extends React.PureComponent<GridProps> { + render() { + const { axesGridLinesPositions, axesSpecs, chartDimensions, chartTheme } = this.props; + const gridComponents: JSX.Element[] = []; + axesGridLinesPositions.forEach((axisGridLinesPositions, axisId) => { + const axisSpec = getSpecsById<AxisSpec>(axesSpecs, axisId); + if (axisSpec && axisGridLinesPositions.length > 0) { + const themeConfig = isVerticalGrid(axisSpec.position) + ? chartTheme.axes.gridLineStyle.vertical + : chartTheme.axes.gridLineStyle.horizontal; + + const axisSpecConfig = axisSpec.gridLineStyle; + const gridLineStyle = axisSpecConfig ? mergeGridLineConfigs(axisSpecConfig, themeConfig) : themeConfig; + gridComponents.push( + <Group key={`axis-grid-${axisId}`} x={chartDimensions.left} y={chartDimensions.top}> + <Group key="grid-lines"> + {axisGridLinesPositions.map((linePosition, index) => { + return this.renderGridLine(linePosition, index, gridLineStyle); + })} + </Group> + </Group>, + ); + } + }); + + return gridComponents; + } + private renderGridLine = (linePosition: AxisLinePosition, i: number, gridLineStyle?: GridLineConfig) => { + return <Line {...gridLineStyle} key={`tick-${i}`} points={linePosition} />; + }; +} + +const mapStateToProps = (state: GlobalChartState): GridProps => { + if (!state.specsInitialized) { + return { + chartTheme: LIGHT_THEME, + chartDimensions: { + width: 0, + left: 0, + top: 0, + height: 0, + }, + axesSpecs: [], + axesGridLinesPositions: new Map(), + }; + } + return { + chartTheme: getChartThemeSelector(state), + chartDimensions: computeChartDimensionsSelector(state).chartDimensions, + axesSpecs: getAxisSpecsSelector(state), + axesGridLinesPositions: computeAxisVisibleTicksSelector(state).axisGridLinesPositions, + }; +}; + +export const Grid = connect(mapStateToProps)(GridComponent); diff --git a/src/components/react_canvas/line_annotation.tsx b/src/chart_types/xy_chart/renderer/canvas/line_annotation.tsx similarity index 61% rename from src/components/react_canvas/line_annotation.tsx rename to src/chart_types/xy_chart/renderer/canvas/line_annotation.tsx index 92540a68fa..1853e197bf 100644 --- a/src/components/react_canvas/line_annotation.tsx +++ b/src/chart_types/xy_chart/renderer/canvas/line_annotation.tsx @@ -1,21 +1,20 @@ import React from 'react'; import { Group, Line } from 'react-konva'; -import { LineAnnotationStyle } from '../../utils/themes/theme'; -import { Dimensions } from '../../utils/dimensions'; -import { AnnotationLineProps } from '../../chart_types/xy_chart/annotations/annotation_utils'; +import { LineAnnotationStyle } from '../../../../utils/themes/theme'; +import { AnnotationLineProps } from '../../annotations/line_annotation_tooltip'; interface LineAnnotationProps { - chartDimensions: Dimensions; - debug: boolean; lines: AnnotationLineProps[]; lineStyle: LineAnnotationStyle; } export class LineAnnotation extends React.PureComponent<LineAnnotationProps> { render() { - return this.renderAnnotation(); + const { lines } = this.props; + + return <Group>{lines.map(this.renderAnnotationLine)}</Group>; } - private renderAnnotationLine = (lineConfig: AnnotationLineProps, i: number) => { + private renderAnnotationLine = (lineConfig: AnnotationLineProps, index: number) => { const { line } = this.props.lineStyle; const { start: { x1, y1 }, @@ -25,13 +24,6 @@ export class LineAnnotation extends React.PureComponent<LineAnnotationProps> { points: [x1, y1, x2, y2], ...line, }; - - return <Line {...lineProps} key={`tick-${i}`} />; - }; - - private renderAnnotation = () => { - const { lines } = this.props; - - return <Group>{lines.map(this.renderAnnotationLine)}</Group>; + return <Line {...lineProps} key={`annotation-line-${index}`} />; }; } diff --git a/src/components/react_canvas/line_geometries.tsx b/src/chart_types/xy_chart/renderer/canvas/line_geometries.tsx similarity index 89% rename from src/components/react_canvas/line_geometries.tsx rename to src/chart_types/xy_chart/renderer/canvas/line_geometries.tsx index 20799e5207..f17e7c65d5 100644 --- a/src/components/react_canvas/line_geometries.tsx +++ b/src/chart_types/xy_chart/renderer/canvas/line_geometries.tsx @@ -1,23 +1,18 @@ -import { Group as KonvaGroup } from 'konva'; import React from 'react'; +import { Group as KonvaGroup } from 'konva'; import { Circle, Group, Path } from 'react-konva'; -import { LegendItem } from '../../chart_types/xy_chart/legend/legend'; -import { - getGeometryStateStyle, - LineGeometry, - PointGeometry, - getGeometryIdKey, -} from '../../chart_types/xy_chart/rendering/rendering'; -import { SharedGeometryStateStyle, PointStyle } from '../../utils/themes/theme'; import { buildLineRenderProps, buildPointStyleProps, PointStyleProps, buildPointRenderProps, - Clippings, - clipRanges, } from './utils/rendering_props_utils'; -import { mergePartial } from '../../utils/commons'; +import { getGeometryIdKey, getGeometryStateStyle } from '../../rendering/rendering'; +import { mergePartial } from '../../../../utils/commons'; +import { LineGeometry, PointGeometry } from '../../../../utils/geometry'; +import { PointStyle, SharedGeometryStateStyle } from '../../../../utils/themes/theme'; +import { LegendItem } from '../../../../chart_types/xy_chart/legend/legend'; +import { Clippings, clipRanges } from './bar_values_utils'; interface LineGeometriesDataProps { animated?: boolean; diff --git a/src/chart_types/xy_chart/renderer/canvas/reactive_chart.tsx b/src/chart_types/xy_chart/renderer/canvas/reactive_chart.tsx new file mode 100644 index 0000000000..c790d5b838 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/canvas/reactive_chart.tsx @@ -0,0 +1,359 @@ +import React, { RefObject } from 'react'; +import { bindActionCreators, Dispatch } from 'redux'; +import { connect, ReactReduxContext, Provider } from 'react-redux'; +import { Layer, Rect, Stage } from 'react-konva'; +import { AreaGeometries } from './area_geometries'; +import { BarGeometries } from './bar_geometries'; +import { LineGeometries } from './line_geometries'; +import { LineAnnotation } from './line_annotation'; +import { RectAnnotation } from './rect_annotation'; +import { Grid } from './grid'; +import { Axes } from './axis'; +import { BarValues } from './bar_values'; +import { AnnotationDimensions } from '../../annotations/annotation_utils'; +import { AnnotationLineProps } from '../../annotations/line_annotation_tooltip'; +import { AnnotationRectProps } from '../../annotations/rect_annotation_tooltip'; +import { computeAnnotationDimensionsSelector } from '../../state/selectors/compute_annotations'; +import { computeChartTransformSelector } from '../../state/selectors/compute_chart_transform'; +import { getAnnotationSpecsSelector } from '../../state/selectors/get_specs'; +import { getHighlightedSeriesSelector } from '../../state/selectors/get_highlighted_series'; +import { isChartEmptySelector } from '../../state/selectors/is_chart_empty'; +import { isChartAnimatableSelector } from '../../state/selectors/is_chart_animatable'; +import { isBrushAvailableSelector } from '../../state/selectors/is_brush_available'; +import { Transform, getSpecsById, Geometries } from '../../state/utils'; +import { Rotation, AnnotationSpec, isLineAnnotation, isRectAnnotation } from '../../utils/specs'; +import { onChartRendered } from '../../../../state/actions/chart'; +import { isInitialized } from '../../../../state/selectors/is_initialized'; +import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { Dimensions } from '../../../../utils/dimensions'; +import { AnnotationId } from '../../../../utils/ids'; +import { Theme, mergeWithDefaultAnnotationLine, mergeWithDefaultAnnotationRect } from '../../../../utils/themes/theme'; +import { LIGHT_THEME } from '../../../../utils/themes/light_theme'; +import { computeSeriesGeometriesSelector } from '../../state/selectors/compute_series_geometries'; +import { LegendItem } from '../../../../chart_types/xy_chart/legend/legend'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; +import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions'; +import { Clippings } from './bar_values_utils'; + +interface ReactiveChartStateProps { + initialized: boolean; + geometries: Geometries; + debug: boolean; + chartContainerDimensions: Dimensions; + chartRotation: Rotation; + chartDimensions: Dimensions; + chartTransform: Transform; + theme: Theme; + isChartAnimatable: boolean; + isChartEmpty: boolean; + annotationDimensions: Map<AnnotationId, AnnotationDimensions>; + annotationSpecs: AnnotationSpec[]; + isBrushAvailable: boolean; + highlightedLegendItem?: LegendItem; +} +interface ReactiveChartDispatchProps { + onChartRendered: typeof onChartRendered; +} +interface ReactiveChartOwnProps { + forwardStageRef: RefObject<Stage>; +} +interface ReactiveChartElementIndex { + element: JSX.Element; + zIndex: number; +} + +type ReactiveChartProps = ReactiveChartOwnProps & ReactiveChartStateProps & ReactiveChartDispatchProps; +class Chart extends React.Component<ReactiveChartProps> { + static displayName = 'ReactiveChart'; + firstRender = true; + + componentDidUpdate() { + if (this.props.initialized) { + this.props.onChartRendered(); + } + } + renderBarSeries = (clippings: Clippings): ReactiveChartElementIndex[] => { + const { geometries, theme, isChartAnimatable, highlightedLegendItem } = this.props; + if (geometries.bars.length === 0) { + return []; + } + + const element = ( + <BarGeometries + key={'bar-geometries'} + animated={isChartAnimatable} + bars={geometries.bars} + sharedStyle={theme.sharedStyle} + highlightedLegendItem={highlightedLegendItem} + clippings={clippings} + /> + ); + + return [ + { + element, + zIndex: 0, + }, + ]; + }; + + renderLineSeries = (clippings: Clippings): ReactiveChartElementIndex[] => { + const { geometries, theme, isChartAnimatable, highlightedLegendItem } = this.props; + if (geometries.lines.length === 0) { + return []; + } + + const element = ( + <LineGeometries + key={'line-geometries'} + animated={isChartAnimatable} + lines={geometries.lines} + sharedStyle={theme.sharedStyle} + highlightedLegendItem={highlightedLegendItem} + clippings={clippings} + /> + ); + + return [ + { + element, + zIndex: 0, + }, + ]; + }; + + renderAreaSeries = (clippings: Clippings): ReactiveChartElementIndex[] => { + const { geometries, theme, isChartAnimatable, highlightedLegendItem } = this.props; + if (geometries.areas.length === 0) { + return []; + } + const element = ( + <AreaGeometries + key={'area-geometries'} + animated={isChartAnimatable} + areas={geometries.areas} + sharedStyle={theme.sharedStyle} + highlightedLegendItem={highlightedLegendItem} + clippings={clippings} + /> + ); + + return [ + { + element, + zIndex: 0, + }, + ]; + }; + + renderAnnotations = (): ReactiveChartElementIndex[] => { + const { annotationDimensions, annotationSpecs } = this.props; + const annotationElements: ReactiveChartElementIndex[] = []; + + annotationDimensions.forEach((annotation: AnnotationDimensions, id: AnnotationId) => { + const spec = getSpecsById<AnnotationSpec>(annotationSpecs, id); + + if (!spec) { + return; + } + + if (isLineAnnotation(spec)) { + const lineStyle = mergeWithDefaultAnnotationLine(spec.style); + const element = ( + <LineAnnotation + key={`line-annotation-group-${id}`} + lines={annotation as AnnotationLineProps[]} + lineStyle={lineStyle} + /> + ); + annotationElements.push({ + element, + zIndex: spec.zIndex || 0, + }); + } else if (isRectAnnotation(spec)) { + const rectStyle = mergeWithDefaultAnnotationRect(spec.style); + const element = ( + <RectAnnotation + key={`rect-annotation-group-${id}`} + rects={annotation as AnnotationRectProps[]} + rectStyle={rectStyle} + /> + ); + annotationElements.push({ + element, + zIndex: spec.zIndex || 0, + }); + } + }); + return annotationElements; + }; + + sortAndRenderElements() { + const { chartDimensions, chartRotation } = this.props; + const clippings = { + clipX: 0, + clipY: 0, + clipWidth: [90, -90].includes(chartRotation) ? chartDimensions.height : chartDimensions.width, + clipHeight: [90, -90].includes(chartRotation) ? chartDimensions.width : chartDimensions.height, + }; + + const bars = this.renderBarSeries(clippings); + const areas = this.renderAreaSeries(clippings); + const lines = this.renderLineSeries(clippings); + const annotations: ReactiveChartElementIndex[] = this.renderAnnotations(); + return [...bars, ...areas, ...lines, ...annotations] + .sort((elemIdxA, elemIdxB) => elemIdxA.zIndex - elemIdxB.zIndex) + .map((elemIdx) => elemIdx.element); + } + + render() { + const { initialized, chartRotation, chartDimensions, isChartEmpty, debug, chartContainerDimensions } = this.props; + if (!initialized || chartDimensions.width === 0 || chartDimensions.height === 0) { + return null; + } + const { chartTransform } = this.props; + + if (isChartEmpty) { + return ( + <div className="echReactiveChart_unavailable"> + <p>No data to display</p> + </div> + ); + } + const brushProps = {}; + return ( + <ReactReduxContext.Consumer> + {({ store }) => { + return ( + <Stage + width={chartContainerDimensions.width} + height={chartContainerDimensions.height} + ref={this.props.forwardStageRef} + style={{ + width: '100%', + height: '100%', + }} + {...brushProps} + > + <Provider store={store}> + <Layer hitGraphEnabled={false} listening={false}> + <Grid /> + <Axes /> + </Layer> + </Provider> + <Layer + x={chartDimensions.left + chartTransform.x} + y={chartDimensions.top + chartTransform.y} + rotation={chartRotation} + hitGraphEnabled={false} + listening={false} + > + {this.sortAndRenderElements()} + </Layer> + <Provider store={store}> + <Layer hitGraphEnabled={false} listening={false}> + <BarValues /> + </Layer> + </Provider> + {debug && ( + <Layer hitGraphEnabled={false} listening={false}> + {this.renderDebugChartBorders()} + </Layer> + )} + </Stage> + ); + }} + </ReactReduxContext.Consumer> + ); + } + + private renderDebugChartBorders = () => { + const { chartDimensions } = this.props; + return ( + <Rect + x={chartDimensions.left} + y={chartDimensions.top} + width={chartDimensions.width} + height={chartDimensions.height} + stroke="red" + strokeWidth={4} + listening={false} + dash={[4, 4]} + /> + ); + }; +} + +const mapDispatchToProps = (dispatch: Dispatch): ReactiveChartDispatchProps => + bindActionCreators( + { + onChartRendered, + }, + dispatch, + ); + +const DEFAULT_PROPS: ReactiveChartStateProps = { + initialized: false, + theme: LIGHT_THEME, + geometries: { + areas: [], + bars: [], + lines: [], + points: [], + }, + debug: false, + chartContainerDimensions: { + width: 0, + height: 0, + left: 0, + top: 0, + }, + chartRotation: 0 as 0, + chartDimensions: { + width: 0, + height: 0, + left: 0, + top: 0, + }, + chartTransform: { + x: 0, + y: 0, + rotate: 0, + }, + isChartAnimatable: false, + isChartEmpty: true, + annotationDimensions: new Map(), + annotationSpecs: [], + isBrushAvailable: false, + highlightedLegendItem: undefined, +}; + +const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => { + if (!isInitialized(state)) { + return DEFAULT_PROPS; + } + return { + initialized: true, + theme: getChartThemeSelector(state), + geometries: computeSeriesGeometriesSelector(state).geometries, + chartContainerDimensions: getChartContainerDimensionsSelector(state), + debug: getSettingsSpecSelector(state).debug, + chartRotation: getChartRotationSelector(state), + chartDimensions: computeChartDimensionsSelector(state).chartDimensions, + chartTransform: computeChartTransformSelector(state), + isChartAnimatable: isChartAnimatableSelector(state), + isChartEmpty: isChartEmptySelector(state), + annotationDimensions: computeAnnotationDimensionsSelector(state), + annotationSpecs: getAnnotationSpecsSelector(state), + isBrushAvailable: isBrushAvailableSelector(state), + highlightedLegendItem: getHighlightedSeriesSelector(state), + }; +}; + +export const ReactiveChart = connect( + mapStateToProps, + mapDispatchToProps, +)(Chart); diff --git a/src/chart_types/xy_chart/renderer/canvas/rect_annotation.tsx b/src/chart_types/xy_chart/renderer/canvas/rect_annotation.tsx new file mode 100644 index 0000000000..ff7753afa8 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/canvas/rect_annotation.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Group, Rect } from 'react-konva'; +import { RectAnnotationStyle } from '../../../../utils/themes/theme'; +import { AnnotationRectProps } from '../../annotations/rect_annotation_tooltip'; + +interface Props { + rects: AnnotationRectProps[]; + rectStyle: RectAnnotationStyle; +} + +export class RectAnnotation extends React.PureComponent<Props> { + render() { + const { rects } = this.props; + return <Group>{rects.map(this.renderAnnotationRect)}</Group>; + } + private renderAnnotationRect = ({ rect }: AnnotationRectProps, index: number) => { + const { x, y, width, height } = rect; + + const rectProps = { + ...this.props.rectStyle, + x, + y, + width, + height, + }; + + return <Rect {...rectProps} key={`rect-annotation-${index}`} />; + }; +} diff --git a/src/components/react_canvas/utils/rendering_props_utils.test.ts b/src/chart_types/xy_chart/renderer/canvas/utils/rendering_props_utils.test.ts similarity index 98% rename from src/components/react_canvas/utils/rendering_props_utils.test.ts rename to src/chart_types/xy_chart/renderer/canvas/utils/rendering_props_utils.test.ts index 581fab3cd7..5bf10a1a52 100644 --- a/src/components/react_canvas/utils/rendering_props_utils.test.ts +++ b/src/chart_types/xy_chart/renderer/canvas/utils/rendering_props_utils.test.ts @@ -1,21 +1,23 @@ -import { Rotation } from '../../../chart_types/xy_chart/utils/specs'; +import { Rotation } from '../../../utils/specs'; import { buildAreaRenderProps, buildBarRenderProps, - buildBarValueProps, buildLineRenderProps, buildPointRenderProps, - getBarValueClipDimensions, - isBarValueOverflow, - rotateBarValueProps, buildPointStyleProps, buildBarBorderRenderProps, +} from './rendering_props_utils'; +import { RectBorderStyle, RectStyle } from '../../../../../utils/themes/theme'; +import { + buildBarValueProps, + isBarValueOverflow, + getBarValueClipDimensions, + rotateBarValueProps, Clippings, clipRanges, -} from './rendering_props_utils'; -import { RectBorderStyle, RectStyle } from '../../../utils/themes/theme'; -import { forcedType } from '../../../mocks/utils'; -import { ClippedRanges } from '../../../chart_types/xy_chart/rendering/rendering'; +} from '../bar_values_utils'; +import { ClippedRanges } from '../../../../../utils/geometry'; +import { forcedType } from '../../../../../mocks/utils'; describe('[canvas] Area Geometries props', () => { test('can build area point props', () => { diff --git a/src/chart_types/xy_chart/renderer/canvas/utils/rendering_props_utils.ts b/src/chart_types/xy_chart/renderer/canvas/utils/rendering_props_utils.ts new file mode 100644 index 0000000000..99b34e0e75 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/canvas/utils/rendering_props_utils.ts @@ -0,0 +1,201 @@ +import { RectConfig, PathConfig, CircleConfig } from 'konva'; +import { + AreaStyle, + LineStyle, + PointStyle, + RectBorderStyle, + RectStyle, + GeometryStateStyle, +} from '../../../../../utils/themes/theme'; +import { GlobalKonvaElementProps } from '../../../../../components/react_canvas/globals'; + +export interface PointStyleProps { + radius: number; + stroke: string; + strokeWidth: number; + strokeEnabled: boolean; + fill: string; + opacity: number; +} + +/** + * Return the style of a point. + * The color value is used for stroke or fill if they are undefind in the PointStyle + * @param color the series color + * @param pointStyle the merged point style + */ +export function buildPointStyleProps( + color: string, + pointStyle: PointStyle, + geometryStateStyle: GeometryStateStyle, +): PointStyleProps { + const { strokeWidth, opacity } = pointStyle; + const stroke = pointStyle.stroke || color; + const fill = pointStyle.fill || color; + return { + radius: pointStyle.radius, + stroke, + strokeWidth, + strokeEnabled: strokeWidth !== 0, + fill: fill, + ...geometryStateStyle, + opacity: opacity * geometryStateStyle.opacity, + }; +} + +/** + * Return the rendering props for a point + * @param x the x position of the point + * @param y the y position of the point + * @param pointStyleProps the style props of the point + */ +export function buildPointRenderProps(x: number, y: number, pointStyleProps: PointStyleProps): CircleConfig { + return { + x, + y, + ...pointStyleProps, + ...GlobalKonvaElementProps, + }; +} + +/** + * Return the rendering props for a line. The color of the line will be overwritten + * by the stroke color of the lineStyle parameter if present + * @param x the horizontal offset to place the line + * @param linePath the SVG line path + * @param color the computed color of the line for this series + * @param lineStyle the line style + * @param geometryStateStyle the highlight geometry style + */ +export function buildLineRenderProps( + x: number, + linePath: string, + color: string, + lineStyle: LineStyle, + geometryStateStyle: GeometryStateStyle, +): PathConfig { + const opacity = lineStyle.opacity * geometryStateStyle.opacity; + + return { + x, + data: linePath, + stroke: lineStyle.stroke || color, + strokeWidth: lineStyle.strokeWidth, + lineCap: 'round', + lineJoin: 'round', + ...geometryStateStyle, + opacity, // want to override opactiy of geometryStateStyle + ...GlobalKonvaElementProps, + }; +} + +/** + * Return the rendering props for an area. The color of the area will be overwritten + * by the fill color of the areaStyle parameter if present + * @param areaPath the SVG area path + * @param x the horizontal offset to place the area + * @param color the computed color of the line for this series + * @param areaStyle the area style + * @param geometryStateStyle the highlight geometry style + */ +export function buildAreaRenderProps( + xTransform: number, + areaPath: string, + color: string, + areaStyle: AreaStyle, + geometryStateStyle: GeometryStateStyle, +): PathConfig { + const opacity = areaStyle.opacity * geometryStateStyle.opacity; + + return { + x: xTransform, + data: areaPath, + fill: areaStyle.fill || color, + lineCap: 'round', + lineJoin: 'round', + ...geometryStateStyle, + opacity, // want to override opactiy of geometryStateStyle + ...GlobalKonvaElementProps, + }; +} + +/** + * Return the rendering props for a bar. The color of the bar will be overwritten + * by the fill color of the rectStyle parameter if present + * @param x the x position of the rect + * @param y the y position of the rect + * @param width the width of the rect + * @param height the height of the rect + * @param color the computed color of the rect for this series + * @param rectStyle the rect style + * @param geometryStateStyle the highlight geometry style + */ +export function buildBarRenderProps( + x: number, + y: number, + width: number, + height: number, + color: string, + rectStyle: RectStyle, + borderStyle: RectBorderStyle, + geometryStateStyle: GeometryStateStyle, +): RectConfig { + const opacity = rectStyle.opacity * geometryStateStyle.opacity; + const { stroke, visible, strokeWidth, strokeOpacity = 0 } = borderStyle; + const offset = !visible || strokeWidth <= 0 || !stroke || strokeOpacity <= 0 || opacity <= 0 ? 0 : strokeWidth; + + return { + x: x + offset, + y: y + offset, + width: width - 2 * offset, + height: height - 2 * offset, + fill: rectStyle.fill || color, + strokeEnabled: false, + ...geometryStateStyle, + opacity, // want to override opactiy of geometryStateStyle + ...GlobalKonvaElementProps, + }; +} + +/** + * Return the rendering props for a bar. The color of the bar will be overwritten + * by the fill color of the rectStyle parameter if present + * @param x the x position of the rect + * @param y the y position of the rect + * @param width the width of the rect + * @param height the height of the rect + * @param color the computed color of the rect for this series + * @param rectStyle the rect style + * @param borderStyle the border rect style + * @param geometryStyle the highlight geometry style + */ +export function buildBarBorderRenderProps( + x: number, + y: number, + width: number, + height: number, + rectStyle: RectStyle, + borderStyle: RectBorderStyle, + geometryStateStyle: GeometryStateStyle, +): RectConfig | null { + const { stroke, visible, strokeWidth, strokeOpacity = rectStyle.opacity } = borderStyle; + const opacity = strokeOpacity * geometryStateStyle.opacity; + + if (!visible || strokeWidth <= 0 || !stroke || opacity <= 0) { + return null; + } + + return { + x: x + strokeWidth / 2, + y: y + strokeWidth / 2, + width: width - strokeWidth, + height: height - strokeWidth, + fillEnabled: false, + strokeEnabled: true, + strokeWidth, + stroke, + ...geometryStateStyle, + opacity, // want to override opactiy of geometryStateStyle + ...GlobalKonvaElementProps, + }; +} diff --git a/src/chart_types/xy_chart/renderer/dom/_brush.scss b/src/chart_types/xy_chart/renderer/dom/_brush.scss new file mode 100644 index 0000000000..f6f6f8fc20 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/dom/_brush.scss @@ -0,0 +1,6 @@ +.echBrushTool { + position: absolute; + box-sizing: border-box; + overflow: hidden; + pointer-events: none; +} diff --git a/src/components/_crosshair.scss b/src/chart_types/xy_chart/renderer/dom/_crosshair.scss similarity index 100% rename from src/components/_crosshair.scss rename to src/chart_types/xy_chart/renderer/dom/_crosshair.scss diff --git a/src/components/_highlighter.scss b/src/chart_types/xy_chart/renderer/dom/_highlighter.scss similarity index 100% rename from src/components/_highlighter.scss rename to src/chart_types/xy_chart/renderer/dom/_highlighter.scss diff --git a/src/chart_types/xy_chart/renderer/dom/_index.scss b/src/chart_types/xy_chart/renderer/dom/_index.scss new file mode 100644 index 0000000000..7b4cbb2616 --- /dev/null +++ b/src/chart_types/xy_chart/renderer/dom/_index.scss @@ -0,0 +1,3 @@ +@import 'highlighter'; +@import 'crosshair'; +@import 'brush'; diff --git a/src/components/annotation_tooltips.tsx b/src/chart_types/xy_chart/renderer/dom/annotation_tooltips.tsx similarity index 65% rename from src/components/annotation_tooltips.tsx rename to src/chart_types/xy_chart/renderer/dom/annotation_tooltips.tsx index fb7a758cd2..8efce018dc 100644 --- a/src/components/annotation_tooltips.tsx +++ b/src/chart_types/xy_chart/renderer/dom/annotation_tooltips.tsx @@ -1,20 +1,39 @@ -import { inject, observer } from 'mobx-react'; import React from 'react'; -import { isLineAnnotation } from '../chart_types/xy_chart/utils/specs'; -import { AnnotationId } from '../utils/ids'; +import { isLineAnnotation, AnnotationSpec, AnnotationTypes } from '../../utils/specs'; +import { AnnotationId } from '../../../../utils/ids'; import { AnnotationDimensions, - AnnotationLineProps, + AnnotationTooltipState, AnnotationTooltipFormatter, -} from '../chart_types/xy_chart/annotations/annotation_utils'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; +} from '../../annotations/annotation_utils'; +import { connect } from 'react-redux'; +import { Dimensions } from '../../../../utils/dimensions'; +import { GlobalChartState, BackwardRef } from '../../../../state/chart_state'; +import { isInitialized } from '../../../../state/selectors/is_initialized'; +import { computeAnnotationDimensionsSelector } from '../../state/selectors/compute_annotations'; +import { getAnnotationSpecsSelector } from '../../state/selectors/get_specs'; +import { getAnnotationTooltipStateSelector } from '../../state/selectors/get_annotation_tooltip_state'; +import { isChartEmptySelector } from '../../state/selectors/is_chart_empty'; +import { AnnotationLineProps } from '../../annotations/line_annotation_tooltip'; +import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; import { createPortal } from 'react-dom'; -import { getFinalAnnotationTooltipPosition } from '../chart_types/xy_chart/annotations/annotation_tooltip'; +import { getFinalAnnotationTooltipPosition } from '../../annotations/annotation_tooltip'; +import { getSpecsById } from '../../state/utils'; + +interface AnnotationTooltipStateProps { + isChartEmpty: boolean; + tooltipState: AnnotationTooltipState | null; + chartDimensions: Dimensions; + annotationDimensions: Map<AnnotationId, AnnotationDimensions>; + annotationSpecs: AnnotationSpec[]; +} -interface AnnotationTooltipProps { - chartStore?: ChartStore; - getChartContainerRef: () => React.RefObject<HTMLDivElement>; +interface AnnotationTooltipOwnProps { + getChartContainerRef: BackwardRef; } + +type AnnotationTooltipProps = AnnotationTooltipStateProps & AnnotationTooltipOwnProps; + const ANNOTATION_CONTAINER_ID = 'echAnnotationContainerPortal'; class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> { @@ -52,8 +71,8 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> if (!chartContainerRef.current) { return; } - const { annotationTooltipState, chartDimensions } = this.props.chartStore!; - const tooltipState = annotationTooltipState.get(); + + const { tooltipState, chartDimensions } = this.props; if (!tooltipState || !tooltipState.isVisible || !this.portalNode) { return null; } @@ -67,8 +86,12 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> tooltipState.anchor, ); - this.portalNode.style.left = tooltipStyle.left; - this.portalNode.style.top = tooltipStyle.top; + if (tooltipStyle.left) { + this.portalNode.style.left = tooltipStyle.left; + } + if (tooltipStyle.top) { + this.portalNode.style.top = tooltipStyle.top; + } } componentWillUnmount() { @@ -78,8 +101,7 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> } renderTooltip = () => { - const { annotationTooltipState } = this.props.chartStore!; - const tooltipState = annotationTooltipState.get(); + const { tooltipState } = this.props; if (!this.portalNode) { return null; } @@ -90,11 +112,11 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> const { details, header } = tooltipState; switch (tooltipState.annotationType) { - case 'line': { + case AnnotationTypes.Line: { const props = { details, header }; return createPortal(<LineAnnotationTooltip {...props} ref={this.tooltipRef} />, this.portalNode); } - case 'rectangle': { + case AnnotationTypes.Rectangle: { const props = { details, customTooltip: tooltipState.renderTooltip }; return createPortal(<RectAnnotationTooltip {...props} ref={this.tooltipRef} />, this.portalNode); } @@ -104,7 +126,7 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> }; renderAnnotationLineMarkers(annotationLines: AnnotationLineProps[], id: AnnotationId): JSX.Element[] { - const { chartDimensions } = this.props.chartStore!; + const { chartDimensions } = this.props; const markers: JSX.Element[] = []; @@ -134,11 +156,11 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> } renderAnnotationMarkers(): JSX.Element[] { - const { annotationDimensions, annotationSpecs } = this.props.chartStore!; + const { annotationDimensions, annotationSpecs } = this.props; const markers: JSX.Element[] = []; annotationDimensions.forEach((dimensions: AnnotationDimensions, id: AnnotationId) => { - const annotationSpec = annotationSpecs.get(id); + const annotationSpec = getSpecsById<AnnotationSpec>(annotationSpecs, id); if (!annotationSpec) { return; } @@ -154,9 +176,9 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> } render() { - const { chartStore } = this.props; + const { isChartEmpty } = this.props; - if (chartStore!.isChartEmpty.get()) { + if (isChartEmpty) { return null; } @@ -169,8 +191,6 @@ class AnnotationTooltipComponent extends React.Component<AnnotationTooltipProps> } } -export const AnnotationTooltip = inject('chartStore')(observer(AnnotationTooltipComponent)); - interface RectAnnotationTooltipProps { details?: string; customTooltip?: AnnotationTooltipFormatter; @@ -208,3 +228,24 @@ function LineAnnotationTooltipRender(props: LineAnnotationTooltipProps, ref: Rea ); } const LineAnnotationTooltip = React.forwardRef(LineAnnotationTooltipRender); + +const mapStateToProps = (state: GlobalChartState): AnnotationTooltipStateProps => { + if (!isInitialized(state)) { + return { + isChartEmpty: true, + chartDimensions: { top: 0, left: 0, width: 0, height: 0 }, + annotationDimensions: new Map(), + annotationSpecs: [], + tooltipState: null, + }; + } + return { + isChartEmpty: isChartEmptySelector(state), + chartDimensions: computeChartDimensionsSelector(state).chartDimensions, + annotationDimensions: computeAnnotationDimensionsSelector(state), + annotationSpecs: getAnnotationSpecsSelector(state), + tooltipState: getAnnotationTooltipStateSelector(state), + }; +}; + +export const AnnotationTooltip = connect(mapStateToProps)(AnnotationTooltipComponent); diff --git a/src/chart_types/xy_chart/renderer/dom/brush.tsx b/src/chart_types/xy_chart/renderer/dom/brush.tsx new file mode 100644 index 0000000000..e2a01a47bf --- /dev/null +++ b/src/chart_types/xy_chart/renderer/dom/brush.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import { Layer, Rect, Stage } from 'react-konva'; +import { connect } from 'react-redux'; +import { Dimensions } from '../../../../utils/dimensions'; +import { isInitialized } from '../../../../state/selectors/is_initialized'; +import { computeChartTransformSelector } from '../../state/selectors/compute_chart_transform'; +import { Transform } from '../../state/utils'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { getBrushAreaSelector } from '../../state/selectors/get_brush_area'; +import { isBrushAvailableSelector } from '../../state/selectors/is_brush_available'; +import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; +import { isBrushingSelector } from '../../state/selectors/is_brushing'; + +interface Props { + initialized: boolean; + chartDimensions: Dimensions; + chartTransform: Transform; + isBrushing: boolean | undefined; + isBrushAvailable: boolean | undefined; + brushArea: Dimensions | null; +} + +class BrushToolComponent extends React.Component<Props> { + static displayName = 'BrushToolComponent'; + + renderBrushTool = (brushArea: Dimensions | null) => { + if (!brushArea) { + return null; + } + const { top, left, width, height } = brushArea; + return <Rect x={left} y={top} width={width} height={height} fill="gray" opacity={0.6} />; + }; + + render() { + const { initialized, isBrushAvailable, isBrushing, chartDimensions, chartTransform, brushArea } = this.props; + if (!initialized || !isBrushAvailable || !isBrushing) { + return null; + } + + return ( + <Stage + width={chartDimensions.width} + height={chartDimensions.height} + className="echBrushTool" + style={{ + top: chartDimensions.top + chartTransform.x, + left: chartDimensions.left + chartTransform.y, + width: chartDimensions.width, + height: chartDimensions.height, + }} + > + <Layer hitGraphEnabled={false} listening={false}> + {this.renderBrushTool(brushArea)} + </Layer> + </Stage> + ); + } +} + +const mapStateToProps = (state: GlobalChartState): Props => { + if (!isInitialized(state)) { + return { + initialized: false, + isBrushing: false, + isBrushAvailable: false, + brushArea: null, + chartDimensions: { + top: 0, + left: 0, + width: 0, + height: 0, + }, + chartTransform: { + x: 0, + y: 0, + rotate: 0, + }, + }; + } + return { + initialized: state.specsInitialized, + brushArea: getBrushAreaSelector(state), + isBrushAvailable: isBrushAvailableSelector(state), + chartDimensions: computeChartDimensionsSelector(state).chartDimensions, + chartTransform: computeChartTransformSelector(state), + isBrushing: isBrushingSelector(state), + }; +}; + +export const BrushTool = connect(mapStateToProps)(BrushToolComponent); diff --git a/src/chart_types/xy_chart/renderer/dom/crosshair.tsx b/src/chart_types/xy_chart/renderer/dom/crosshair.tsx new file mode 100644 index 0000000000..fc70dac82f --- /dev/null +++ b/src/chart_types/xy_chart/renderer/dom/crosshair.tsx @@ -0,0 +1,117 @@ +import React, { CSSProperties } from 'react'; +import { connect } from 'react-redux'; +import { TooltipType } from '../../utils/interactions'; +import { isHorizontalRotation } from '../../state/utils'; +import { Dimensions } from '../../../../utils/dimensions'; +import { Theme } from '../../../../utils/themes/theme'; +import { Rotation } from '../../../../chart_types/xy_chart/utils/specs'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { isInitialized } from '../../../../state/selectors/is_initialized'; +import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; +import { getCursorBandPositionSelector } from '../../state/selectors/get_cursor_band'; +import { getCursorLinePositionSelector } from '../../state/selectors/get_cursor_line'; +import { getTooltipTypeSelector } from '../../state/selectors/get_tooltip_type'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { LIGHT_THEME } from '../../../../utils/themes/light_theme'; + +interface CrosshairProps { + theme: Theme; + chartRotation: Rotation; + cursorBandPosition?: Dimensions; + cursorLinePosition: Dimensions; + tooltipType: TooltipType; +} + +function canRenderBand(type: TooltipType, visible: boolean) { + return visible && (type === TooltipType.Crosshairs || type === TooltipType.VerticalCursor); +} +function canRenderHelpLine(type: TooltipType, visible: boolean) { + return visible && type === TooltipType.Crosshairs; +} + +class CrosshairComponent extends React.Component<CrosshairProps> { + static displayName = 'Crosshair'; + + render() { + return ( + <div className="echCrosshair"> + {this.renderBand()} + {this.renderLine()} + </div> + ); + } + + renderBand() { + const { + theme: { + crosshair: { band }, + }, + cursorBandPosition, + tooltipType, + } = this.props; + + if (!cursorBandPosition || !canRenderBand(tooltipType, band.visible)) { + return null; + } + const style: CSSProperties = { + ...cursorBandPosition, + background: band.fill, + }; + + return <div className="echCrosshair__band" style={style} />; + } + + renderLine() { + const { + theme: { + crosshair: { line }, + }, + cursorLinePosition, + tooltipType, + chartRotation, + } = this.props; + + if (!cursorLinePosition || !canRenderHelpLine(tooltipType, line.visible)) { + return null; + } + const isHorizontalRotated = isHorizontalRotation(chartRotation); + let style: CSSProperties; + if (isHorizontalRotated) { + style = { + ...cursorLinePosition, + borderTopWidth: line.strokeWidth, + borderTopColor: line.stroke, + borderTopStyle: line.dash ? 'dashed' : 'solid', + }; + } else { + style = { + ...cursorLinePosition, + borderLeftWidth: line.strokeWidth, + borderLeftColor: line.stroke, + borderLeftStyle: line.dash ? 'dashed' : 'solid', + }; + } + return <div className="echCrosshair__line" style={style} />; + } +} + +const mapStateToProps = (state: GlobalChartState): CrosshairProps => { + if (!isInitialized(state)) { + return { + theme: LIGHT_THEME, + chartRotation: 0, + cursorBandPosition: { top: 0, left: 0, width: 0, height: 0 }, + cursorLinePosition: { top: 0, left: 0, width: 0, height: 0 }, + tooltipType: TooltipType.None, + }; + } + return { + theme: getChartThemeSelector(state), + chartRotation: getChartRotationSelector(state), + cursorBandPosition: getCursorBandPositionSelector(state), + cursorLinePosition: getCursorLinePositionSelector(state), + tooltipType: getTooltipTypeSelector(state), + }; +}; + +export const Crosshair = connect(mapStateToProps)(CrosshairComponent); diff --git a/src/chart_types/xy_chart/renderer/dom/highlighter.tsx b/src/chart_types/xy_chart/renderer/dom/highlighter.tsx new file mode 100644 index 0000000000..bff9fe9d1e --- /dev/null +++ b/src/chart_types/xy_chart/renderer/dom/highlighter.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { isPointGeometry, IndexedGeometry } from '../../../../utils/geometry'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { isInitialized } from '../../../../state/selectors/is_initialized'; +import { computeChartTransformSelector } from '../../state/selectors/compute_chart_transform'; +import { getHighlightedGeomsSelector } from '../../state/selectors/get_tooltip_values_highlighted_geoms'; +import { Dimensions } from '../../../../utils/dimensions'; +import { Rotation } from '../../../../chart_types/xy_chart/utils/specs'; +import { Transform } from '../../state/utils'; +import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; +import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions'; + +interface HighlighterProps { + highlightedGeometries: IndexedGeometry[]; + initialized: boolean; + chartTransform: Transform; + chartDimensions: Dimensions; + chartRotation: Rotation; +} + +class HighlighterComponent extends React.Component<HighlighterProps> { + static displayName = 'Highlighter'; + + render() { + const { highlightedGeometries, chartTransform, chartDimensions, chartRotation } = this.props; + const left = chartDimensions.left + chartTransform.x; + const top = chartDimensions.top + chartTransform.y; + const clipWidth = [90, -90].includes(chartRotation) ? chartDimensions.height : chartDimensions.width; + const clipHeight = [90, -90].includes(chartRotation) ? chartDimensions.width : chartDimensions.height; + return ( + <svg className="echHighlighter"> + <defs> + <clipPath id="echHighlighterClipPath"> + <rect x="0" y="0" width={clipWidth} height={clipHeight} /> + </clipPath> + </defs> + <g transform={`translate(${left}, ${top}) rotate(${chartRotation})`}> + {highlightedGeometries.map((geom, i) => { + const { color, x, y } = geom; + if (isPointGeometry(geom)) { + return ( + <circle + key={i} + cx={x + geom.transform.x} + cy={y} + r={geom.radius} + stroke={color} + strokeWidth={4} + fill="transparent" + /> + ); + } + return ( + <rect + key={i} + x={x} + y={y} + width={geom.width} + height={geom.height} + className="echHighlighter__rect" + clipPath="url(#echHighlighterClipPath)" + /> + ); + })} + </g> + </svg> + ); + } +} + +const mapStateToProps = (state: GlobalChartState): HighlighterProps => { + if (!isInitialized(state)) { + return { + initialized: false, + highlightedGeometries: [], + chartTransform: { + x: 0, + y: 0, + rotate: 0, + }, + chartDimensions: { top: 0, left: 0, width: 0, height: 0 }, + chartRotation: 0, + }; + } + return { + initialized: true, + highlightedGeometries: getHighlightedGeomsSelector(state), + chartTransform: computeChartTransformSelector(state), + chartDimensions: computeChartDimensionsSelector(state).chartDimensions, + chartRotation: getChartRotationSelector(state), + }; +}; + +export const Highlighter = connect(mapStateToProps)(HighlighterComponent); diff --git a/src/components/tooltips.tsx b/src/chart_types/xy_chart/renderer/dom/tooltips.tsx similarity index 52% rename from src/components/tooltips.tsx rename to src/chart_types/xy_chart/renderer/dom/tooltips.tsx index cfc7addacb..e0a2799b12 100644 --- a/src/components/tooltips.tsx +++ b/src/chart_types/xy_chart/renderer/dom/tooltips.tsx @@ -1,15 +1,28 @@ import classNames from 'classnames'; -import { inject, observer } from 'mobx-react'; import React from 'react'; +import { connect } from 'react-redux'; +import { TooltipValue, TooltipValueFormatter } from '../../utils/interactions'; +import { GlobalChartState, BackwardRef } from '../../../../state/chart_state'; +import { isTooltipVisibleSelector } from '../../state/selectors/is_tooltip_visible'; +import { getTooltipHeaderFormatterSelector } from '../../state/selectors/get_tooltip_header_formatter'; +import { getTooltipPositionSelector } from '../../state/selectors/get_tooltip_position'; +import { getTooltipValuesSelector } from '../../state/selectors/get_tooltip_values_highlighted_geoms'; +import { isInitialized } from '../../../../state/selectors/is_initialized'; import { createPortal } from 'react-dom'; -import { TooltipValue, TooltipValueFormatter } from '../chart_types/xy_chart/utils/interactions'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; -import { getFinalTooltipPosition } from '../chart_types/xy_chart/crosshair/crosshair_utils'; +import { getFinalTooltipPosition, TooltipPosition } from '../../crosshair/crosshair_utils'; +import { isAnnotationTooltipVisibleSelector } from '../../state/selectors/is_annotation_tooltip_visible'; -interface TooltipProps { - chartStore?: ChartStore; - getChartContainerRef: () => React.RefObject<HTMLDivElement>; +interface TooltipStateProps { + isTooltipVisible: boolean; + isAnnotationTooltipVisible: boolean; + tooltipValues: TooltipValue[]; + tooltipPosition: TooltipPosition | null; + tooltipHeaderFormatter?: TooltipValueFormatter; } +interface TooltipOwnProps { + getChartContainerRef: BackwardRef; +} +type TooltipProps = TooltipStateProps & TooltipOwnProps; class TooltipsComponent extends React.Component<TooltipProps> { static displayName = 'Tooltips'; @@ -36,11 +49,10 @@ class TooltipsComponent extends React.Component<TooltipProps> { componentDidUpdate() { this.createPortalNode(); - const { getChartContainerRef } = this.props; - const { tooltipPosition } = this.props.chartStore!; + const { getChartContainerRef, tooltipPosition } = this.props; const chartContainerRef = getChartContainerRef(); - if (!this.tooltipRef.current || !chartContainerRef.current || !this.portalNode) { + if (!this.tooltipRef.current || !chartContainerRef.current || !this.portalNode || !tooltipPosition) { return; } @@ -48,8 +60,12 @@ class TooltipsComponent extends React.Component<TooltipProps> { const tooltipBBox = this.tooltipRef.current.getBoundingClientRect(); const tooltipStyle = getFinalTooltipPosition(chartContainerBBox, tooltipBBox, tooltipPosition); - this.portalNode.style.left = tooltipStyle.left; - this.portalNode.style.top = tooltipStyle.top; + if (tooltipStyle.left) { + this.portalNode.style.left = tooltipStyle.left; + } + if (tooltipStyle.top) { + this.portalNode.style.top = tooltipStyle.top; + } } componentWillUnmount() { @@ -67,22 +83,21 @@ class TooltipsComponent extends React.Component<TooltipProps> { } render() { - const { isTooltipVisible, tooltipData, tooltipHeaderFormatter } = this.props.chartStore!; - const isVisible = isTooltipVisible.get(); - let tooltip; + const { isTooltipVisible, tooltipValues, tooltipHeaderFormatter, isAnnotationTooltipVisible } = this.props; if (!this.portalNode) { return null; } const { getChartContainerRef } = this.props; const chartContainerRef = getChartContainerRef(); - if (chartContainerRef.current === null || !isVisible) { + let tooltip; + if (chartContainerRef.current === null || !isTooltipVisible || isAnnotationTooltipVisible) { return null; } else { tooltip = ( <div className="echTooltip" ref={this.tooltipRef}> - <div className="echTooltip__header">{this.renderHeader(tooltipData[0], tooltipHeaderFormatter)}</div> + <div className="echTooltip__header">{this.renderHeader(tooltipValues[0], tooltipHeaderFormatter)}</div> <div className="echTooltip__list"> - {tooltipData.slice(1).map(({ name, value, color, isHighlighted, seriesKey, yAccessor }) => { + {tooltipValues.slice(1).map(({ name, value, color, isHighlighted, seriesKey, yAccessor }) => { const classes = classNames('echTooltip__item', { /* eslint @typescript-eslint/camelcase:0 */ echTooltip__rowHighlighted: isHighlighted, @@ -108,4 +123,23 @@ class TooltipsComponent extends React.Component<TooltipProps> { } } -export const Tooltips = inject('chartStore')(observer(TooltipsComponent)); +const mapStateToProps = (state: GlobalChartState): TooltipStateProps => { + if (!isInitialized(state)) { + return { + isTooltipVisible: false, + isAnnotationTooltipVisible: false, + tooltipValues: [], + tooltipPosition: null, + tooltipHeaderFormatter: undefined, + }; + } + return { + isTooltipVisible: isTooltipVisibleSelector(state), + isAnnotationTooltipVisible: isAnnotationTooltipVisibleSelector(state), + tooltipValues: getTooltipValuesSelector(state), + tooltipPosition: getTooltipPositionSelector(state), + tooltipHeaderFormatter: getTooltipHeaderFormatterSelector(state), + }; +}; + +export const Tooltips = connect(mapStateToProps)(TooltipsComponent); diff --git a/src/chart_types/xy_chart/rendering/rendering.areas.test.ts b/src/chart_types/xy_chart/rendering/rendering.areas.test.ts index d3b8f12407..367266ec8b 100644 --- a/src/chart_types/xy_chart/rendering/rendering.areas.test.ts +++ b/src/chart_types/xy_chart/rendering/rendering.areas.test.ts @@ -1,22 +1,24 @@ -/* eslint @typescript-eslint/no-object-literal-type-assertion: off */ -import { computeSeriesDomains } from '../store/utils'; -import { getGroupId, getSpecId, SpecId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { CurveType } from '../../../utils/curves'; -import { AreaGeometry, IndexedGeometry, PointGeometry, renderArea } from './rendering'; -import { computeXScale, computeYScales } from '../utils/scales'; -import { AreaSeriesSpec } from '../utils/specs'; +import { IndexedGeometry, PointGeometry, AreaGeometry } from '../../../utils/geometry'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; +import { computeXScale, computeYScales } from '../utils/scales'; +import { AreaSeriesSpec, SpecTypes, SeriesTypes } from '../utils/specs'; +import { computeSeriesDomains } from '../state/utils'; +import { renderArea } from './rendering'; +import { ChartTypes } from '../..'; -const SPEC_ID = getSpecId('spec_1'); -const GROUP_ID = getGroupId('group_1'); +const SPEC_ID = 'spec_1'; +const GROUP_ID = 'group_1'; describe('Rendering points - areas', () => { describe('Empty line for missing data', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -24,12 +26,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ @@ -70,9 +71,11 @@ describe('Rendering points - areas', () => { }); describe('Single series area chart - ordinal', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -80,12 +83,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -170,12 +172,14 @@ describe('Rendering points - areas', () => { }); }); describe('Multi series area chart - ordinal', () => { - const spec1Id = getSpecId('point1'); - const spec2Id = getSpecId('point2'); + const spec1Id = 'point1'; + const spec2Id = 'point2'; const pointSeriesSpec1: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -184,9 +188,11 @@ describe('Rendering points - areas', () => { yScaleType: ScaleType.Linear, }; const pointSeriesSpec2: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 20], [1, 10]], xAccessor: 0, @@ -194,13 +200,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(spec1Id, pointSeriesSpec1); - pointSeriesMap.set(spec2Id, pointSeriesSpec2); + const pointSeriesMap = [pointSeriesSpec1, pointSeriesSpec2]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -353,9 +357,11 @@ describe('Rendering points - areas', () => { }); describe('Single series area chart - linear', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -363,12 +369,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -448,12 +453,14 @@ describe('Rendering points - areas', () => { }); }); describe('Multi series area chart - linear', () => { - const spec1Id = getSpecId('point1'); - const spec2Id = getSpecId('point2'); + const spec1Id = 'point1'; + const spec2Id = 'point2'; const pointSeriesSpec1: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -462,9 +469,11 @@ describe('Rendering points - areas', () => { yScaleType: ScaleType.Linear, }; const pointSeriesSpec2: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 20], [1, 10]], xAccessor: 0, @@ -472,13 +481,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(spec1Id, pointSeriesSpec1); - pointSeriesMap.set(spec2Id, pointSeriesSpec2); + const pointSeriesMap = [pointSeriesSpec1, pointSeriesSpec2]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -630,9 +637,11 @@ describe('Rendering points - areas', () => { }); describe('Single series area chart - time', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[1546300800000, 10], [1546387200000, 5]], xAccessor: 0, @@ -640,12 +649,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Time, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -725,12 +733,14 @@ describe('Rendering points - areas', () => { }); }); describe('Multi series area chart - time', () => { - const spec1Id = getSpecId('point1'); - const spec2Id = getSpecId('point2'); + const spec1Id = 'point1'; + const spec2Id = 'point2'; const pointSeriesSpec1: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[1546300800000, 10], [1546387200000, 5]], xAccessor: 0, @@ -739,9 +749,11 @@ describe('Rendering points - areas', () => { yScaleType: ScaleType.Linear, }; const pointSeriesSpec2: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[1546300800000, 20], [1546387200000, 10]], xAccessor: 0, @@ -749,13 +761,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Time, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(spec1Id, pointSeriesSpec1); - pointSeriesMap.set(spec2Id, pointSeriesSpec2); + const pointSeriesMap = [pointSeriesSpec1, pointSeriesSpec2]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -892,9 +902,11 @@ describe('Rendering points - areas', () => { }); describe('Single series area chart - y log', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 10], [1, 5], [2, null], [3, 5], [4, 5], [5, 0], [6, 10], [7, 10], [8, 10]], xAccessor: 0, @@ -902,12 +914,11 @@ describe('Rendering points - areas', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Log, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 90], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); diff --git a/src/chart_types/xy_chart/rendering/rendering.bands.test.ts b/src/chart_types/xy_chart/rendering/rendering.bands.test.ts index 3bbeca0b78..42a19c4441 100644 --- a/src/chart_types/xy_chart/rendering/rendering.bands.test.ts +++ b/src/chart_types/xy_chart/rendering/rendering.bands.test.ts @@ -1,22 +1,24 @@ -/* eslint @typescript-eslint/no-object-literal-type-assertion: off */ -import { computeSeriesDomains } from '../store/utils'; -import { getGroupId, getSpecId, SpecId } from '../../../utils/ids'; +import { computeSeriesDomains } from '../state/utils'; import { ScaleType } from '../../../utils/scales/scales'; import { CurveType } from '../../../utils/curves'; -import { AreaGeometry, IndexedGeometry, PointGeometry, renderArea, renderBars } from './rendering'; +import { renderArea, renderBars } from './rendering'; import { computeXScale, computeYScales } from '../utils/scales'; -import { AreaSeriesSpec, BarSeriesSpec } from '../utils/specs'; +import { AreaSeriesSpec, BarSeriesSpec, SpecTypes, SeriesTypes } from '../utils/specs'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; +import { AreaGeometry, IndexedGeometry, PointGeometry } from '../../../utils/geometry'; +import { ChartTypes } from '../..'; -const SPEC_ID = getSpecId('spec_1'); -const GROUP_ID = getGroupId('group_1'); +const SPEC_ID = 'spec_1'; +const GROUP_ID = 'group_1'; describe('Rendering bands - areas', () => { describe('Empty line for missing data', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 2, 10], [1, 3, 5]], xAccessor: 0, @@ -25,12 +27,11 @@ describe('Rendering bands - areas', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -68,9 +69,11 @@ describe('Rendering bands - areas', () => { }); describe('Single band area chart', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 2, 10], [1, 3, 5]], xAccessor: 0, @@ -79,12 +82,11 @@ describe('Rendering bands - areas', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -210,9 +212,11 @@ describe('Rendering bands - areas', () => { }); describe('Single band area chart with null values', () => { const pointSeriesSpec: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'area', + seriesType: SeriesTypes.Area, yScaleToDataExtent: false, data: [[0, 2, 10], [1, 2, null], [2, 3, 5], [3, 3, 5]], xAccessor: 0, @@ -221,12 +225,11 @@ describe('Rendering bands - areas', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, AreaSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -391,9 +394,11 @@ describe('Rendering bands - areas', () => { }); describe('Single series band bar chart - ordinal', () => { const barSeriesSpec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[0, 2, 10], [1, 3, null], [2, 3, 5], [3, 4, 8]], xAccessor: 0, @@ -402,12 +407,11 @@ describe('Rendering bands - areas', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(SPEC_ID, barSeriesSpec); + const barSeriesMap = [barSeriesSpec]; const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); diff --git a/src/chart_types/xy_chart/rendering/rendering.bars.test.ts b/src/chart_types/xy_chart/rendering/rendering.bars.test.ts index 2c950cbe79..ed3d915f75 100644 --- a/src/chart_types/xy_chart/rendering/rendering.bars.test.ts +++ b/src/chart_types/xy_chart/rendering/rendering.bars.test.ts @@ -1,21 +1,24 @@ -import { computeSeriesDomains } from '../store/utils'; +import { computeSeriesDomains } from '../state/utils'; import { identity } from '../../../utils/commons'; -import { getGroupId, getSpecId, SpecId, GroupId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { renderBars } from './rendering'; import { computeXScale, computeYScales } from '../utils/scales'; -import { BarSeriesSpec, DomainRange } from '../utils/specs'; +import { BarSeriesSpec, DomainRange, SpecTypes, SeriesTypes } from '../utils/specs'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; +import { GroupId } from '../../../utils/ids'; +import { ChartTypes } from '../..'; -const SPEC_ID = getSpecId('spec_1'); -const GROUP_ID = getGroupId('group_1'); +const SPEC_ID = 'spec_1'; +const GROUP_ID = 'group_1'; describe('Rendering bars', () => { describe('Single series bar chart - ordinal', () => { const barSeriesSpec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[-200, 0], [0, 10], [1, 5]], // first datum should be skipped as it's out of domain xAccessor: 0, @@ -23,13 +26,12 @@ describe('Rendering bars', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(SPEC_ID, barSeriesSpec); + const barSeriesMap = [barSeriesSpec]; const customDomain = [0, 1]; - const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map(), customDomain); + const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map(), [], customDomain); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); @@ -183,12 +185,14 @@ describe('Rendering bars', () => { }); }); describe('Multi series bar chart - ordinal', () => { - const spec1Id = getSpecId('bar1'); - const spec2Id = getSpecId('bar2'); + const spec1Id = 'bar1'; + const spec2Id = 'bar2'; const barSeriesSpec1: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -197,9 +201,11 @@ describe('Rendering bars', () => { yScaleType: ScaleType.Linear, }; const barSeriesSpec2: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[0, 20], [1, 10]], xAccessor: 0, @@ -207,13 +213,11 @@ describe('Rendering bars', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(spec1Id, barSeriesSpec1); - barSeriesMap.set(spec2Id, barSeriesSpec2); + const barSeriesMap = [barSeriesSpec1, barSeriesSpec2]; const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); @@ -387,9 +391,11 @@ describe('Rendering bars', () => { }); describe('Single series bar chart - linear', () => { const barSeriesSpec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -397,12 +403,11 @@ describe('Rendering bars', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(SPEC_ID, barSeriesSpec); + const barSeriesMap = [barSeriesSpec]; const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); @@ -492,9 +497,11 @@ describe('Rendering bars', () => { }); describe('Single series bar chart - log', () => { const barSeriesSpec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[1, 0], [2, 1], [3, 2], [4, 3], [5, 4], [6, 5]], xAccessor: 0, @@ -502,12 +509,10 @@ describe('Rendering bars', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Log, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(SPEC_ID, barSeriesSpec); - const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); + const barSeriesDomains = computeSeriesDomains([barSeriesSpec], new Map()); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: 1, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); @@ -531,12 +536,14 @@ describe('Rendering bars', () => { }); }); describe('Multi series bar chart - linear', () => { - const spec1Id = getSpecId('bar1'); - const spec2Id = getSpecId('bar2'); + const spec1Id = 'bar1'; + const spec2Id = 'bar2'; const barSeriesSpec1: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -545,9 +552,11 @@ describe('Rendering bars', () => { yScaleType: ScaleType.Linear, }; const barSeriesSpec2: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[0, 20], [1, 10]], xAccessor: 0, @@ -555,13 +564,11 @@ describe('Rendering bars', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(spec1Id, barSeriesSpec1); - barSeriesMap.set(spec2Id, barSeriesSpec2); + const barSeriesMap = [barSeriesSpec1, barSeriesSpec2]; const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); @@ -734,12 +741,14 @@ describe('Rendering bars', () => { }); }); describe('Multi series bar chart - time', () => { - const spec1Id = getSpecId('bar1'); - const spec2Id = getSpecId('bar2'); + const spec1Id = 'bar1'; + const spec2Id = 'bar2'; const barSeriesSpec1: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[1546300800000, 10], [1546387200000, 5]], xAccessor: 0, @@ -748,9 +757,11 @@ describe('Rendering bars', () => { yScaleType: ScaleType.Linear, }; const barSeriesSpec2: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[1546300800000, 20], [1546387200000, 10]], xAccessor: 0, @@ -758,13 +769,11 @@ describe('Rendering bars', () => { xScaleType: ScaleType.Time, yScaleType: ScaleType.Linear, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(spec1Id, barSeriesSpec1); - barSeriesMap.set(spec2Id, barSeriesSpec2); + const barSeriesMap = [barSeriesSpec1, barSeriesSpec2]; const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: barSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); @@ -938,9 +947,11 @@ describe('Rendering bars', () => { }); describe('Remove points datum is not in domain', () => { const barSeriesSpec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [[0, 0], [1, 1], [2, 10], [3, 3]], xAccessor: 0, @@ -948,18 +959,16 @@ describe('Rendering bars', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(SPEC_ID, barSeriesSpec); const customYDomain = new Map<GroupId, DomainRange>(); customYDomain.set(GROUP_ID, { max: 1, }); - const barSeriesDomains = computeSeriesDomains(barSeriesMap, customYDomain, { + const barSeriesDomains = computeSeriesDomains([barSeriesSpec], customYDomain, [], { max: 2, }); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: 1, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); @@ -1004,9 +1013,11 @@ describe('Rendering bars', () => { [18, 100000], ]; const barSeriesSpec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data, xAccessor: 0, @@ -1015,13 +1026,12 @@ describe('Rendering bars', () => { yScaleType: ScaleType.Linear, minBarHeight, }; - const barSeriesMap = new Map<SpecId, BarSeriesSpec>(); - barSeriesMap.set(SPEC_ID, barSeriesSpec); + const customYDomain = new Map<GroupId, DomainRange>(); - const barSeriesDomains = computeSeriesDomains(barSeriesMap, customYDomain); + const barSeriesDomains = computeSeriesDomains([barSeriesSpec], customYDomain); const xScale = computeXScale({ xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, + totalBarsInCluster: 1, range: [0, 100], }); const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [100, 0] }); diff --git a/src/chart_types/xy_chart/rendering/rendering.lines.test.ts b/src/chart_types/xy_chart/rendering/rendering.lines.test.ts index 2de21b9e8e..8eb35367fd 100644 --- a/src/chart_types/xy_chart/rendering/rendering.lines.test.ts +++ b/src/chart_types/xy_chart/rendering/rendering.lines.test.ts @@ -1,23 +1,25 @@ -/* eslint @typescript-eslint/no-object-literal-type-assertion: off */ - -import { computeSeriesDomains } from '../store/utils'; -import { getGroupId, getSpecId, SpecId, GroupId } from '../../../utils/ids'; +import { computeSeriesDomains } from '../state/utils'; import { ScaleType } from '../../../utils/scales/scales'; import { CurveType } from '../../../utils/curves'; -import { IndexedGeometry, LineGeometry, PointGeometry, renderLine } from './rendering'; +import { renderLine } from './rendering'; import { computeXScale, computeYScales } from '../utils/scales'; -import { LineSeriesSpec, DomainRange } from '../utils/specs'; +import { LineSeriesSpec, DomainRange, SpecTypes, SeriesTypes } from '../utils/specs'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; +import { LineGeometry, IndexedGeometry, PointGeometry } from '../../../utils/geometry'; +import { GroupId } from '../../../utils/ids'; +import { ChartTypes } from '../..'; -const SPEC_ID = getSpecId('spec_1'); -const GROUP_ID = getGroupId('group_1'); +const SPEC_ID = 'spec_1'; +const GROUP_ID = 'group_1'; describe('Rendering points - line', () => { describe('Empty line for missing data', () => { const pointSeriesSpec: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -25,12 +27,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -65,9 +66,11 @@ describe('Rendering points - line', () => { }); describe('Single series line chart - ordinal', () => { const pointSeriesSpec: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -75,12 +78,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -160,12 +162,14 @@ describe('Rendering points - line', () => { }); }); describe('Multi series line chart - ordinal', () => { - const spec1Id = getSpecId('point1'); - const spec2Id = getSpecId('point2'); + const spec1Id = 'point1'; + const spec2Id = 'point2'; const pointSeriesSpec1: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -174,9 +178,11 @@ describe('Rendering points - line', () => { yScaleType: ScaleType.Linear, }; const pointSeriesSpec2: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 20], [1, 10]], xAccessor: 0, @@ -184,13 +190,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(spec1Id, pointSeriesSpec1); - pointSeriesMap.set(spec2Id, pointSeriesSpec2); + const pointSeriesMap = [pointSeriesSpec1, pointSeriesSpec2]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -341,9 +345,11 @@ describe('Rendering points - line', () => { }); describe('Single series line chart - linear', () => { const pointSeriesSpec: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -351,12 +357,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -435,12 +440,14 @@ describe('Rendering points - line', () => { }); }); describe('Multi series line chart - linear', () => { - const spec1Id = getSpecId('point1'); - const spec2Id = getSpecId('point2'); + const spec1Id = 'point1'; + const spec2Id = 'point2'; const pointSeriesSpec1: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 10], [1, 5]], xAccessor: 0, @@ -449,9 +456,11 @@ describe('Rendering points - line', () => { yScaleType: ScaleType.Linear, }; const pointSeriesSpec2: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 20], [1, 10]], xAccessor: 0, @@ -459,13 +468,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(spec1Id, pointSeriesSpec1); - pointSeriesMap.set(spec2Id, pointSeriesSpec2); + const pointSeriesMap = [pointSeriesSpec1, pointSeriesSpec2]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -615,9 +622,11 @@ describe('Rendering points - line', () => { }); describe('Single series line chart - time', () => { const pointSeriesSpec: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[1546300800000, 10], [1546387200000, 5]], xAccessor: 0, @@ -625,12 +634,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Time, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -709,12 +717,14 @@ describe('Rendering points - line', () => { }); }); describe('Multi series line chart - time', () => { - const spec1Id = getSpecId('point1'); - const spec2Id = getSpecId('point2'); + const spec1Id = 'point1'; + const spec2Id = 'point2'; const pointSeriesSpec1: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec1Id, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[1546300800000, 10], [1546387200000, 5]], xAccessor: 0, @@ -723,9 +733,11 @@ describe('Rendering points - line', () => { yScaleType: ScaleType.Linear, }; const pointSeriesSpec2: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: spec2Id, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[1546300800000, 20], [1546387200000, 10]], xAccessor: 0, @@ -733,13 +745,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Time, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(spec1Id, pointSeriesSpec1); - pointSeriesMap.set(spec2Id, pointSeriesSpec2); + const pointSeriesMap = [pointSeriesSpec1, pointSeriesSpec2]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -876,9 +886,11 @@ describe('Rendering points - line', () => { }); describe('Single series line chart - y log', () => { const pointSeriesSpec: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 10], [1, 5], [2, null], [3, 5], [4, 5], [5, 0], [6, 10], [7, 10], [8, 10]], xAccessor: 0, @@ -886,12 +898,11 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Log, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); + const pointSeriesMap = [pointSeriesSpec]; const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, new Map()); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: pointSeriesMap.length, range: [0, 90], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); @@ -947,9 +958,11 @@ describe('Rendering points - line', () => { }); describe('Remove points datum is not in domain', () => { const pointSeriesSpec: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'line', + seriesType: SeriesTypes.Line, yScaleToDataExtent: false, data: [[0, 0], [1, 1], [2, 10], [3, 3]], xAccessor: 0, @@ -957,18 +970,16 @@ describe('Rendering points - line', () => { xScaleType: ScaleType.Linear, yScaleType: ScaleType.Linear, }; - const pointSeriesMap = new Map<SpecId, LineSeriesSpec>(); - pointSeriesMap.set(SPEC_ID, pointSeriesSpec); const customYDomain = new Map<GroupId, DomainRange>(); customYDomain.set(GROUP_ID, { max: 1, }); - const pointSeriesDomains = computeSeriesDomains(pointSeriesMap, customYDomain, { + const pointSeriesDomains = computeSeriesDomains([pointSeriesSpec], customYDomain, [], { max: 2, }); const xScale = computeXScale({ xDomain: pointSeriesDomains.xDomain, - totalBarsInCluster: pointSeriesMap.size, + totalBarsInCluster: 1, range: [0, 100], }); const yScales = computeYScales({ yDomains: pointSeriesDomains.yDomain, range: [100, 0] }); diff --git a/src/chart_types/xy_chart/rendering/rendering.test.ts b/src/chart_types/xy_chart/rendering/rendering.test.ts index 45b0997b5e..0c5f9c7a0e 100644 --- a/src/chart_types/xy_chart/rendering/rendering.test.ts +++ b/src/chart_types/xy_chart/rendering/rendering.test.ts @@ -1,17 +1,14 @@ -import { getSpecId } from '../../../utils/ids'; import { - BarGeometry, getGeometryStateStyle, isPointOnGeometry, - PointGeometry, getBarStyleOverrides, - GeometryId, getPointStyleOverrides, getClippedRanges, } from './rendering'; import { BarSeriesStyle, SharedGeometryStateStyle, PointStyle } from '../../../utils/themes/theme'; import { DataSeriesDatum } from '../utils/series'; -import { RecursivePartial, mergePartial } from '../../../utils/commons'; +import { mergePartial, RecursivePartial } from '../../../utils/commons'; +import { BarGeometry, PointGeometry, GeometryId } from '../../../utils/geometry'; import { MockDataSeries } from '../../../mocks'; import { MockScale } from '../../../mocks/scale'; @@ -39,7 +36,7 @@ describe('Rendering utils', () => { color: 'red', geometryId: { seriesKey: [], - specId: getSpecId('id'), + specId: 'id', }, value: { accessor: 'y1', @@ -65,7 +62,7 @@ describe('Rendering utils', () => { color: 'red', geometryId: { seriesKey: [], - specId: getSpecId('id'), + specId: 'id', }, value: { accessor: 'y1', @@ -93,7 +90,7 @@ describe('Rendering utils', () => { test('should get common geometry style dependent on legend item highlight state', () => { const geometryId = { seriesKey: [], - specId: getSpecId('id'), + specId: 'id', }; const highlightedLegendItem = { key: '', @@ -101,7 +98,7 @@ describe('Rendering utils', () => { label: '', value: { colorValues: [], - specId: getSpecId('id'), + specId: 'id', }, isSeriesVisible: true, isLegendItemVisible: true, @@ -121,7 +118,7 @@ describe('Rendering utils', () => { ...highlightedLegendItem, value: { colorValues: [], - specId: getSpecId('foo'), + specId: 'foo', }, }; @@ -207,7 +204,7 @@ describe('Rendering utils', () => { initialY0: 5, }; const geometryId: GeometryId = { - specId: getSpecId('test'), + specId: 'test', seriesKey: ['test'], }; @@ -296,7 +293,7 @@ describe('Rendering utils', () => { initialY0: 5, }; const geometryId: GeometryId = { - specId: getSpecId('test'), + specId: 'test', seriesKey: ['test'], }; diff --git a/src/chart_types/xy_chart/rendering/rendering.ts b/src/chart_types/xy_chart/rendering/rendering.ts index 7565f5b6c3..27e81945d7 100644 --- a/src/chart_types/xy_chart/rendering/rendering.ts +++ b/src/chart_types/xy_chart/rendering/rendering.ts @@ -1,12 +1,8 @@ import { area, line } from 'd3-shape'; -import { $Values } from 'utility-types'; - import { CanvasTextBBoxCalculator } from '../../../utils/bbox/canvas_text_bbox_calculator'; import { AreaSeriesStyle, - AreaStyle, LineSeriesStyle, - LineStyle, PointStyle, SharedGeometryStateStyle, BarSeriesStyle, @@ -16,114 +12,22 @@ import { SpecId } from '../../../utils/ids'; import { isLogarithmicScale } from '../../../utils/scales/scale_continuous'; import { Scale, ScaleType } from '../../../utils/scales/scales'; import { CurveType, getCurveFactory } from '../../../utils/curves'; -import { LegendItem } from '../legend/legend'; import { DataSeriesDatum } from '../utils/series'; import { belongsToDataSeries } from '../utils/series_utils'; -import { DisplayValueSpec, BarStyleAccessor, PointStyleAccessor } from '../utils/specs'; +import { DisplayValueSpec, PointStyleAccessor, BarStyleAccessor } from '../utils/specs'; +import { + IndexedGeometry, + PointGeometry, + BarGeometry, + AreaGeometry, + LineGeometry, + GeometryId, + isPointGeometry, + AccessorType, + ClippedRanges, +} from '../../../utils/geometry'; import { mergePartial } from '../../../utils/commons'; - -export interface GeometryId { - specId: SpecId; - seriesKey: any[]; -} - -/** - * The accessor type - */ -export const AccessorType = Object.freeze({ - Y0: 'y0' as 'y0', - Y1: 'y1' as 'y1', -}); - -export type AccessorType = $Values<typeof AccessorType>; - -export interface GeometryValue { - y: any; - x: any; - accessor: AccessorType; -} - -export type IndexedGeometry = PointGeometry | BarGeometry; - -/** - * Array of **range** clippings [x1, x2] to be excluded during rendering - * - * Note: Must be scaled **range** values (i.e. pixel coordinates) **NOT** domain values - */ -export type ClippedRanges = [number, number][]; - -export interface PointGeometry { - x: number; - y: number; - radius: number; - color: string; - transform: { - x: number; - y: number; - }; - geometryId: GeometryId; - value: GeometryValue; - styleOverrides?: Partial<PointStyle>; -} -export interface BarGeometry { - x: number; - y: number; - width: number; - height: number; - color: string; - displayValue?: { - text: any; - width: number; - height: number; - hideClippedValue?: boolean; - isValueContainedInElement?: boolean; - }; - geometryId: GeometryId; - value: GeometryValue; - seriesStyle: BarSeriesStyle; -} -export interface LineGeometry { - line: string; - points: PointGeometry[]; - color: string; - transform: { - x: number; - y: number; - }; - geometryId: GeometryId; - seriesLineStyle: LineStyle; - seriesPointStyle: PointStyle; - /** - * Ranges of `[x0, x1]` pairs to clip from series - */ - clippedRanges: ClippedRanges; -} -export interface AreaGeometry { - area: string; - lines: string[]; - points: PointGeometry[]; - color: string; - transform: { - x: number; - y: number; - }; - geometryId: GeometryId; - seriesAreaStyle: AreaStyle; - seriesAreaLineStyle: LineStyle; - seriesPointStyle: PointStyle; - isStacked: boolean; - /** - * Ranges of `[x0, x1]` pairs to clip from series - */ - clippedRanges: ClippedRanges; -} - -export function isPointGeometry(ig: IndexedGeometry): ig is PointGeometry { - return ig.hasOwnProperty('radius'); -} -export function isBarGeometry(ig: IndexedGeometry): ig is BarGeometry { - return ig.hasOwnProperty('width') && ig.hasOwnProperty('height'); -} +import { LegendItem } from '../legend/legend'; export function mutableIndexedGeometryMapUpsert( mutableGeometriesIndex: Map<any, IndexedGeometry[]>, @@ -186,7 +90,7 @@ export function getBarStyleOverrides( }); } -export function renderPoints( +function renderPoints( shift: number, dataset: DataSeriesDatum[], xScale: Scale, @@ -354,12 +258,8 @@ export function renderBars( : undefined : formattedDisplayValue; - const computedDisplayValueWidth = bboxCalculator - .compute(displayValueText || '', padding, fontSize, fontFamily) - .getOrElse({ - width: 0, - height: 0, - }).width; + const computedDisplayValueWidth = bboxCalculator.compute(displayValueText || '', padding, fontSize, fontFamily) + .width; const displayValueWidth = displayValueSettings && displayValueSettings.isValueContainedInElement ? width : computedDisplayValueWidth; diff --git a/src/chart_types/xy_chart/specs/area_series.tsx b/src/chart_types/xy_chart/specs/area_series.tsx index 5151a27917..5f16d672e0 100644 --- a/src/chart_types/xy_chart/specs/area_series.tsx +++ b/src/chart_types/xy_chart/specs/area_series.tsx @@ -1,42 +1,36 @@ -import { inject } from 'mobx-react'; -import { PureComponent } from 'react'; -import { AreaSeriesSpec, HistogramModeAlignments, DEFAULT_GLOBAL_ID } from '../utils/specs'; -import { getGroupId } from '../../../utils/ids'; +import { AreaSeriesSpec, HistogramModeAlignments, DEFAULT_GLOBAL_ID, SpecTypes, SeriesTypes } from '../utils/specs'; import { ScaleType } from '../../../utils/scales/scales'; -import { SpecProps } from '../../../specs/specs_parser'; +import { specComponentFactory, getConnect } from '../../../state/spec_factory'; +import { ChartTypes } from '../../../chart_types'; -type AreaSpecProps = SpecProps & AreaSeriesSpec; +const defaultProps = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + seriesType: SeriesTypes.Area, + groupId: DEFAULT_GLOBAL_ID, + xScaleType: ScaleType.Ordinal, + yScaleType: ScaleType.Linear, + xAccessor: 'x', + yAccessors: ['y'], + yScaleToDataExtent: false, + hideInLegend: false, + histogramModeAlignment: HistogramModeAlignments.Center, +}; -export class AreaSeriesSpecComponent extends PureComponent<AreaSpecProps> { - static defaultProps: Partial<AreaSpecProps> = { - seriesType: 'area', - groupId: getGroupId(DEFAULT_GLOBAL_ID), - xScaleType: ScaleType.Ordinal, - yScaleType: ScaleType.Linear, - xAccessor: 'x', - yAccessors: ['y'], - yScaleToDataExtent: false, - hideInLegend: false, - histogramModeAlignment: HistogramModeAlignments.Center, - }; - componentDidMount() { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - } - componentDidUpdate(prevProps: AreaSpecProps) { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - if (prevProps.id !== this.props.id) { - chartStore!.removeSeriesSpec(prevProps.id); - } - } - componentWillUnmount() { - const { chartStore, id } = this.props; - chartStore!.removeSeriesSpec(id); - } - render() { - return null; - } -} +type SpecRequiredProps = Pick<AreaSeriesSpec, 'id' | 'data'>; +type SpecOptionalProps = Partial<Omit<AreaSeriesSpec, 'chartType' | 'specType' | 'seriesType' | 'id' | 'data'>>; -export const AreaSeries = inject('chartStore')(AreaSeriesSpecComponent); +export const AreaSeries: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = getConnect()( + specComponentFactory< + AreaSeriesSpec, + | 'seriesType' + | 'groupId' + | 'xScaleType' + | 'yScaleType' + | 'xAccessor' + | 'yAccessors' + | 'yScaleToDataExtent' + | 'hideInLegend' + | 'histogramModeAlignment' + >(defaultProps), +); diff --git a/src/chart_types/xy_chart/specs/axis.tsx b/src/chart_types/xy_chart/specs/axis.tsx index d195bb0e7a..ca6ad98409 100644 --- a/src/chart_types/xy_chart/specs/axis.tsx +++ b/src/chart_types/xy_chart/specs/axis.tsx @@ -1,38 +1,35 @@ -import { inject } from 'mobx-react'; -import { PureComponent } from 'react'; -import { AxisSpec as AxisSpecType, Position, DEFAULT_GLOBAL_ID } from '../utils/specs'; -import { getGroupId } from '../../../utils/ids'; -import { SpecProps } from '../../../specs/specs_parser'; +import { AxisSpec, Position, DEFAULT_GLOBAL_ID, SpecTypes } from '../utils/specs'; +import { ChartTypes } from '../../../chart_types'; +import { specComponentFactory, getConnect } from '../../../state/spec_factory'; -type AxisSpecProps = SpecProps & AxisSpecType; +const defaultProps = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + groupId: DEFAULT_GLOBAL_ID, + hide: false, + showOverlappingTicks: false, + showOverlappingLabels: false, + position: Position.Left, + tickSize: 10, + tickPadding: 10, + tickFormat: (tick: any) => `${tick}`, + tickLabelRotation: 0, +}; -class AxisSpec extends PureComponent<AxisSpecProps> { - static defaultProps: Partial<AxisSpecProps> = { - groupId: getGroupId(DEFAULT_GLOBAL_ID), - hide: false, - showOverlappingTicks: false, - showOverlappingLabels: false, - position: Position.Left, - tickSize: 10, - tickPadding: 10, - tickFormat: (tick: any) => `${tick}`, - tickLabelRotation: 0, - }; - componentDidMount() { - const { chartStore, children, ...spec } = this.props; - chartStore!.addAxisSpec({ ...spec }); - } - componentDidUpdate() { - const { chartStore, children, ...spec } = this.props; - chartStore!.addAxisSpec({ ...spec }); - } - componentWillUnmount() { - const { id } = this.props; - this.props.chartStore!.removeAxisSpec(id); - } - render() { - return null; - } -} +type SpecRequired = Pick<AxisSpec, 'id'>; +type SpecOptionals = Partial<Omit<AxisSpec, 'chartType' | 'specType' | 'seriesType' | 'id'>>; -export const Axis = inject('chartStore')(AxisSpec); +export const Axis: React.FunctionComponent<SpecRequired & SpecOptionals> = getConnect()( + specComponentFactory< + AxisSpec, + | 'groupId' + | 'hide' + | 'showOverlappingTicks' + | 'showOverlappingLabels' + | 'position' + | 'tickSize' + | 'tickPadding' + | 'tickFormat' + | 'tickLabelRotation' + >(defaultProps), +); diff --git a/src/chart_types/xy_chart/specs/bar_series.tsx b/src/chart_types/xy_chart/specs/bar_series.tsx index 91c81ad013..d7f5e5d4a0 100644 --- a/src/chart_types/xy_chart/specs/bar_series.tsx +++ b/src/chart_types/xy_chart/specs/bar_series.tsx @@ -1,43 +1,38 @@ -import { inject } from 'mobx-react'; -import { PureComponent } from 'react'; -import { BarSeriesSpec, DEFAULT_GLOBAL_ID } from '../utils/specs'; -import { getGroupId } from '../../../utils/ids'; +import { BarSeriesSpec, DEFAULT_GLOBAL_ID, SpecTypes, SeriesTypes } from '../utils/specs'; import { ScaleType } from '../../../utils/scales/scales'; -import { SpecProps } from '../../../specs/specs_parser'; +import { ChartTypes } from '../../../chart_types'; +import { specComponentFactory, getConnect } from '../../../state/spec_factory'; -type BarSpecProps = SpecProps & BarSeriesSpec; +const defaultProps = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + seriesType: SeriesTypes.Bar, + groupId: DEFAULT_GLOBAL_ID, + xScaleType: ScaleType.Ordinal, + yScaleType: ScaleType.Linear, + xAccessor: 'x', + yAccessors: ['y'], + yScaleToDataExtent: false, + hideInLegend: false, + enableHistogramMode: false, + stackAsPercentage: false, +}; -export class BarSeriesSpecComponent extends PureComponent<BarSpecProps> { - static defaultProps: Partial<BarSpecProps> = { - seriesType: 'bar', - groupId: getGroupId(DEFAULT_GLOBAL_ID), - xScaleType: ScaleType.Ordinal, - yScaleType: ScaleType.Linear, - xAccessor: 'x', - yAccessors: ['y'], - yScaleToDataExtent: false, - hideInLegend: false, - enableHistogramMode: false, - stackAsPercentage: false, - }; - componentDidMount() { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - } - componentDidUpdate(prevProps: BarSpecProps) { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - if (prevProps.id !== this.props.id) { - chartStore!.removeSeriesSpec(prevProps.id); - } - } - componentWillUnmount() { - const { chartStore, id } = this.props; - chartStore!.removeSeriesSpec(id); - } - render() { - return null; - } -} +type SpecRequiredProps = Pick<BarSeriesSpec, 'id' | 'data'>; +type SpecOptionalProps = Partial<Omit<BarSeriesSpec, 'chartType' | 'specType' | 'seriesType' | 'id' | 'data'>>; -export const BarSeries = inject('chartStore')(BarSeriesSpecComponent); +export const BarSeries: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = getConnect()( + specComponentFactory< + BarSeriesSpec, + | 'seriesType' + | 'groupId' + | 'xScaleType' + | 'yScaleType' + | 'xAccessor' + | 'yAccessors' + | 'yScaleToDataExtent' + | 'hideInLegend' + | 'enableHistogramMode' + | 'stackAsPercentage' + >(defaultProps), +); diff --git a/src/chart_types/xy_chart/specs/histogram_bar_series.tsx b/src/chart_types/xy_chart/specs/histogram_bar_series.tsx index 70f5621a6c..733226d822 100644 --- a/src/chart_types/xy_chart/specs/histogram_bar_series.tsx +++ b/src/chart_types/xy_chart/specs/histogram_bar_series.tsx @@ -1,42 +1,36 @@ -import { inject } from 'mobx-react'; -import { PureComponent } from 'react'; -import { HistogramBarSeriesSpec, DEFAULT_GLOBAL_ID } from '../utils/specs'; -import { getGroupId } from '../../../utils/ids'; +import { HistogramBarSeriesSpec, DEFAULT_GLOBAL_ID, SpecTypes, SeriesTypes } from '../utils/specs'; import { ScaleType } from '../../../utils/scales/scales'; -import { SpecProps } from '../../../specs/specs_parser'; +import { specComponentFactory, getConnect } from '../../../state/spec_factory'; +import { ChartTypes } from '../../../chart_types'; -type HistogramBarSpecProps = SpecProps & HistogramBarSeriesSpec; +const defaultProps = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + seriesType: SeriesTypes.Bar, + groupId: DEFAULT_GLOBAL_ID, + xScaleType: ScaleType.Linear, + yScaleType: ScaleType.Linear, + xAccessor: 'x', + yAccessors: ['y'], + yScaleToDataExtent: false, + hideInLegend: false, + enableHistogramMode: true as true, +}; -export class HistogramBarSeriesSpecComponent extends PureComponent<HistogramBarSpecProps> { - static defaultProps: Partial<HistogramBarSpecProps> = { - seriesType: 'bar', - groupId: getGroupId(DEFAULT_GLOBAL_ID), - xScaleType: ScaleType.Ordinal, - yScaleType: ScaleType.Linear, - xAccessor: 'x', - yAccessors: ['y'], - yScaleToDataExtent: false, - hideInLegend: false, - enableHistogramMode: true, - }; - componentDidMount() { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - } - componentDidUpdate(prevProps: HistogramBarSpecProps) { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - if (prevProps.id !== this.props.id) { - chartStore!.removeSeriesSpec(prevProps.id); - } - } - componentWillUnmount() { - const { chartStore, id } = this.props; - chartStore!.removeSeriesSpec(id); - } - render() { - return null; - } -} +type SpecRequiredProps = Pick<HistogramBarSeriesSpec, 'id' | 'data'>; +type SpecOptionalProps = Partial<Omit<HistogramBarSeriesSpec, 'chartType' | 'specType' | 'seriesType' | 'id' | 'data'>>; -export const HistogramBarSeries = inject('chartStore')(HistogramBarSeriesSpecComponent); +export const HistogramBarSeries: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = getConnect()( + specComponentFactory< + HistogramBarSeriesSpec, + | 'seriesType' + | 'groupId' + | 'xScaleType' + | 'yScaleType' + | 'xAccessor' + | 'yAccessors' + | 'yScaleToDataExtent' + | 'hideInLegend' + | 'enableHistogramMode' + >(defaultProps), +); diff --git a/src/chart_types/xy_chart/specs/line_annotation.tsx b/src/chart_types/xy_chart/specs/line_annotation.tsx index 7ad35481c7..96c965aabf 100644 --- a/src/chart_types/xy_chart/specs/line_annotation.tsx +++ b/src/chart_types/xy_chart/specs/line_annotation.tsx @@ -1,16 +1,23 @@ -import { inject } from 'mobx-react'; import React, { createRef, CSSProperties, PureComponent } from 'react'; -import { LineAnnotationSpec, DEFAULT_GLOBAL_ID } from '../utils/specs'; +import { LineAnnotationSpec, DEFAULT_GLOBAL_ID, SpecTypes, AnnotationTypes } from '../utils/specs'; import { DEFAULT_ANNOTATION_LINE_STYLE } from '../../../utils/themes/theme'; -import { getGroupId } from '../../../utils/ids'; -import { SpecProps } from '../../../specs/specs_parser'; +import { bindActionCreators, Dispatch } from 'redux'; +import { connect } from 'react-redux'; +import { upsertSpec, removeSpec } from '../../../state/actions/specs'; +import { Spec } from '../../../specs'; +import { ChartTypes } from '../..'; -type LineAnnotationProps = SpecProps & LineAnnotationSpec; - -export class LineAnnotationSpecComponent extends PureComponent<LineAnnotationProps> { - static defaultProps: Partial<LineAnnotationProps> = { - groupId: getGroupId(DEFAULT_GLOBAL_ID), - annotationType: 'line', +type InjectedProps = LineAnnotationSpec & + DispatchProps & + Readonly<{ + children?: React.ReactNode; + }>; +export class LineAnnotationSpecComponent extends PureComponent<LineAnnotationSpec> { + static defaultProps: Partial<LineAnnotationSpec> = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + groupId: DEFAULT_GLOBAL_ID, + annotationType: AnnotationTypes.Line, style: DEFAULT_ANNOTATION_LINE_STYLE, hideLines: false, hideTooltips: false, @@ -21,7 +28,7 @@ export class LineAnnotationSpecComponent extends PureComponent<LineAnnotationPro private markerRef = createRef<HTMLDivElement>(); componentDidMount() { - const { chartStore, children, ...config } = this.props; + const { children, upsertSpec, removeSpec, ...config } = this.props as InjectedProps; if (this.markerRef.current) { const { offsetWidth, offsetHeight } = this.markerRef.current; config.markerDimensions = { @@ -29,10 +36,10 @@ export class LineAnnotationSpecComponent extends PureComponent<LineAnnotationPro height: offsetHeight, }; } - chartStore!.addAnnotationSpec({ ...config }); + upsertSpec({ ...config }); } componentDidUpdate() { - const { chartStore, children, ...config } = this.props; + const { upsertSpec, removeSpec, children, ...config } = this.props as InjectedProps; if (this.markerRef.current) { const { offsetWidth, offsetHeight } = this.markerRef.current; config.markerDimensions = { @@ -40,11 +47,11 @@ export class LineAnnotationSpecComponent extends PureComponent<LineAnnotationPro height: offsetHeight, }; } - chartStore!.addAnnotationSpec({ ...config }); + upsertSpec({ ...config }); } componentWillUnmount() { - const { chartStore, annotationId } = this.props; - chartStore!.removeAnnotationSpec(annotationId); + const { removeSpec, id } = this.props as InjectedProps; + removeSpec(id); } render() { if (!this.props.marker) { @@ -68,4 +75,32 @@ export class LineAnnotationSpecComponent extends PureComponent<LineAnnotationPro } } -export const LineAnnotation = inject('chartStore')(LineAnnotationSpecComponent); +interface DispatchProps { + upsertSpec: (spec: Spec) => void; + removeSpec: (id: string) => void; +} +const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => + bindActionCreators( + { + upsertSpec, + removeSpec, + }, + dispatch, + ); + +type SpecRequiredProps = Pick<LineAnnotationSpec, 'id' | 'dataValues' | 'domainType'>; +type SpecOptionalProps = Partial< + Omit< + LineAnnotationSpec, + 'chartType' | 'specType' | 'seriesType' | 'id' | 'dataValues' | 'domainType' | 'annotationType' + > +>; + +export const LineAnnotation: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = connect< + {}, + DispatchProps, + LineAnnotationSpec +>( + null, + mapDispatchToProps, +)(LineAnnotationSpecComponent); diff --git a/src/chart_types/xy_chart/specs/line_series.tsx b/src/chart_types/xy_chart/specs/line_series.tsx index acf5023080..86b48265c8 100644 --- a/src/chart_types/xy_chart/specs/line_series.tsx +++ b/src/chart_types/xy_chart/specs/line_series.tsx @@ -1,42 +1,35 @@ -import { inject } from 'mobx-react'; -import { PureComponent } from 'react'; -import { HistogramModeAlignments, LineSeriesSpec, DEFAULT_GLOBAL_ID } from '../utils/specs'; -import { getGroupId } from '../../../utils/ids'; +import { LineSeriesSpec, DEFAULT_GLOBAL_ID, HistogramModeAlignments, SpecTypes, SeriesTypes } from '../utils/specs'; import { ScaleType } from '../../../utils/scales/scales'; -import { SpecProps } from '../../../specs/specs_parser'; +import { ChartTypes } from '../../../chart_types'; +import { specComponentFactory, getConnect } from '../../../state/spec_factory'; -type LineSpecProps = SpecProps & LineSeriesSpec; +const defaultProps = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + seriesType: SeriesTypes.Line, + groupId: DEFAULT_GLOBAL_ID, + xScaleType: ScaleType.Ordinal, + yScaleType: ScaleType.Linear, + xAccessor: 'x', + yAccessors: ['y'], + yScaleToDataExtent: false, + hideInLegend: false, + histogramModeAlignment: HistogramModeAlignments.Center, +}; +type SpecRequiredProps = Pick<LineSeriesSpec, 'id' | 'data'>; +type SpecOptionalProps = Partial<Omit<LineSeriesSpec, 'chartType' | 'specType' | 'seriesType' | 'id' | 'data'>>; -export class LineSeriesSpecComponent extends PureComponent<LineSpecProps> { - static defaultProps: Partial<LineSpecProps> = { - seriesType: 'line', - groupId: getGroupId(DEFAULT_GLOBAL_ID), - xScaleType: ScaleType.Ordinal, - yScaleType: ScaleType.Linear, - xAccessor: 'x', - yAccessors: ['y'], - yScaleToDataExtent: false, - hideInLegend: false, - histogramModeAlignment: HistogramModeAlignments.Center, - }; - componentDidMount() { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - } - componentDidUpdate(prevProps: LineSpecProps) { - const { chartStore, children, ...config } = this.props; - chartStore!.addSeriesSpec({ ...config }); - if (prevProps.id !== this.props.id) { - chartStore!.removeSeriesSpec(prevProps.id); - } - } - componentWillUnmount() { - const { chartStore, id } = this.props; - chartStore!.removeSeriesSpec(id); - } - render() { - return null; - } -} - -export const LineSeries = inject('chartStore')(LineSeriesSpecComponent); +export const LineSeries: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = getConnect()( + specComponentFactory< + LineSeriesSpec, + | 'seriesType' + | 'groupId' + | 'xScaleType' + | 'yScaleType' + | 'xAccessor' + | 'yAccessors' + | 'yScaleToDataExtent' + | 'hideInLegend' + | 'histogramModeAlignment' + >(defaultProps), +); diff --git a/src/chart_types/xy_chart/specs/rect_annotation.tsx b/src/chart_types/xy_chart/specs/rect_annotation.tsx index f31788fc7b..7d3655d257 100644 --- a/src/chart_types/xy_chart/specs/rect_annotation.tsx +++ b/src/chart_types/xy_chart/specs/rect_annotation.tsx @@ -1,33 +1,24 @@ -import { inject } from 'mobx-react'; -import { PureComponent } from 'react'; -import { RectAnnotationSpec, DEFAULT_GLOBAL_ID } from '../utils/specs'; -import { getGroupId } from '../../../utils/ids'; -import { SpecProps } from '../../../specs/specs_parser'; +import { RectAnnotationSpec, DEFAULT_GLOBAL_ID, SpecTypes, AnnotationTypes } from '../utils/specs'; +import { specComponentFactory, getConnect } from '../../../state/spec_factory'; +import { DEFAULT_ANNOTATION_RECT_STYLE } from '../../../utils/themes/theme'; +import { ChartTypes } from '../../index'; -type RectAnnotationProps = SpecProps & RectAnnotationSpec; +const defaultProps = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + groupId: DEFAULT_GLOBAL_ID, + annotationType: AnnotationTypes.Rectangle, + zIndex: -1, + style: DEFAULT_ANNOTATION_RECT_STYLE, +}; -export class RectAnnotationSpecComponent extends PureComponent<RectAnnotationProps> { - static defaultProps: Partial<RectAnnotationProps> = { - groupId: getGroupId(DEFAULT_GLOBAL_ID), - annotationType: 'rectangle', - zIndex: -1, - }; - - componentDidMount() { - const { chartStore, children, ...config } = this.props; - chartStore!.addAnnotationSpec({ ...config }); - } - componentDidUpdate() { - const { chartStore, children, ...config } = this.props; - chartStore!.addAnnotationSpec({ ...config }); - } - componentWillUnmount() { - const { chartStore, annotationId } = this.props; - chartStore!.removeAnnotationSpec(annotationId); - } - render() { - return null; - } -} - -export const RectAnnotation = inject('chartStore')(RectAnnotationSpecComponent); +type SpecRequiredProps = Pick<RectAnnotationSpec, 'id' | 'dataValues'>; +type SpecOptionalProps = Partial< + Omit< + RectAnnotationSpec, + 'chartType' | 'specType' | 'seriesType' | 'id' | 'dataValues' | 'domainType' | 'annotationType' + > +>; +export const RectAnnotation: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = getConnect()( + specComponentFactory<RectAnnotationSpec, 'groupId' | 'annotationType' | 'zIndex' | 'style'>(defaultProps), +); diff --git a/src/chart_types/xy_chart/store/__snapshots__/utils.test.ts.snap b/src/chart_types/xy_chart/state/__snapshots__/utils.test.ts.snap similarity index 100% rename from src/chart_types/xy_chart/store/__snapshots__/utils.test.ts.snap rename to src/chart_types/xy_chart/state/__snapshots__/utils.test.ts.snap diff --git a/src/chart_types/xy_chart/state/chart_state.interactions.test.ts b/src/chart_types/xy_chart/state/chart_state.interactions.test.ts new file mode 100644 index 0000000000..2d7bb31c4c --- /dev/null +++ b/src/chart_types/xy_chart/state/chart_state.interactions.test.ts @@ -0,0 +1,655 @@ +import { createStore, Store } from 'redux'; +import { BarSeriesSpec, BasicSeriesSpec, AxisSpec, Position, SpecTypes, SeriesTypes } from '../utils/specs'; +import { TooltipType } from '../utils/interactions'; +import { ScaleType } from '../../../utils/scales/scales'; +import { chartStoreReducer, GlobalChartState } from '../../../state/chart_state'; +import { SettingsSpec, DEFAULT_SETTINGS_SPEC } from '../../../specs'; +import { computeSeriesGeometriesSelector } from './selectors/compute_series_geometries'; +import { getProjectedPointerPositionSelector } from './selectors/get_projected_pointer_position'; +import { + getHighlightedGeomsSelector, + getTooltipValuesAndGeometriesSelector, +} from './selectors/get_tooltip_values_highlighted_geoms'; +import { isTooltipVisibleSelector } from './selectors/is_tooltip_visible'; +import { createOnElementOutCaller } from './selectors/on_element_out_caller'; +import { createOnElementOverCaller } from './selectors/on_element_over_caller'; +import { getCursorBandPositionSelector } from './selectors/get_cursor_band'; +import { getSettingsSpecSelector } from '../../../state/selectors/get_settings_specs'; +import { upsertSpec, specParsed } from '../../../state/actions/specs'; +import { updateParentDimensions } from '../../../state/actions/chart_settings'; +import { onPointerMove } from '../../../state/actions/mouse'; +import { ChartTypes } from '../..'; + +const SPEC_ID = 'spec_1'; +const GROUP_ID = 'group_1'; + +const ordinalBarSeries: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: SPEC_ID, + groupId: GROUP_ID, + seriesType: SeriesTypes.Bar, + yScaleToDataExtent: false, + data: [[0, 10], [1, 5]], + xAccessor: 0, + yAccessors: [1], + xScaleType: ScaleType.Ordinal, + yScaleType: ScaleType.Linear, + hideInLegend: false, +}; +const linearBarSeries: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: SPEC_ID, + groupId: GROUP_ID, + seriesType: SeriesTypes.Bar, + yScaleToDataExtent: false, + data: [[0, 10], [1, 5]], + xAccessor: 0, + yAccessors: [1], + xScaleType: ScaleType.Linear, + yScaleType: ScaleType.Linear, + hideInLegend: false, +}; +const chartTop = 10; +const chartLeft = 10; +const settingSpec: SettingsSpec = { + ...DEFAULT_SETTINGS_SPEC, + tooltip: { + type: TooltipType.VerticalCursor, + }, + hideDuplicateAxes: false, + theme: { + chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, + chartMargins: { top: 10, left: 10, bottom: 0, right: 0 }, + scales: { + barsPadding: 0, + }, + }, +}; + +function initStore(spec: BasicSeriesSpec) { + const storeReducer = chartStoreReducer('chartId'); + const store = createStore(storeReducer); + + store.dispatch(upsertSpec(settingSpec)); + store.dispatch(upsertSpec(spec)); + store.dispatch(specParsed()); + store.dispatch(updateParentDimensions({ width: 100, height: 100, top: chartTop, left: chartLeft })); + + return store; +} + +// const barStyle = { +// rect: { +// opacity: 1, +// }, +// rectBorder: { +// strokeWidth: 1, +// visible: false, +// }, +// displayValue: { +// fill: 'black', +// fontFamily: '', +// fontSize: 2, +// offsetX: 0, +// offsetY: 0, +// padding: 2, +// }, +// }; +// const indexedGeom1Red: BarGeometry = { +// color: 'red', +// x: 0, +// y: 0, +// width: 50, +// height: 100, +// value: { +// x: 0, +// y: 10, +// accessor: 'y1', +// }, +// geometryId: { +// specId: SPEC_ID, +// seriesKey: [], +// }, +// seriesStyle: barStyle, +// }; +// const indexedGeom2Blue: BarGeometry = { +// color: 'blue', +// x: 50, +// y: 50, +// width: 50, +// height: 50, +// value: { +// x: 1, +// y: 5, +// accessor: 'y1', +// }, +// geometryId: { +// specId: SPEC_ID, +// seriesKey: [], +// }, +// seriesStyle: barStyle, +// }; + +describe('Chart state pointer interactions', () => { + let store: Store<GlobalChartState>; + const onElementOutCaller = createOnElementOutCaller(); + const onElementOverCaller = createOnElementOverCaller(); + beforeEach(() => { + store = initStore(ordinalBarSeries); + }); + test('check initial geoms', () => { + const { geometries } = computeSeriesGeometriesSelector(store.getState()); + expect(geometries).toBeDefined(); + expect(geometries.bars).toBeDefined(); + expect(geometries.bars.length).toBe(2); + }); + + test('can convert/limit mouse pointer positions relative to chart projection', () => { + store.dispatch(onPointerMove({ x: 20, y: 20 }, 0)); + let projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition.x).toBe(10); + expect(projectedPointerPosition.y).toBe(10); + + store.dispatch(onPointerMove({ x: 10, y: 10 }, 1)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition.x).toBe(0); + expect(projectedPointerPosition.y).toBe(0); + store.dispatch(onPointerMove({ x: 5, y: 5 }, 2)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition.x).toBe(-1); + expect(projectedPointerPosition.y).toBe(-1); + store.dispatch(onPointerMove({ x: 200, y: 20 }, 3)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition.x).toBe(-1); + expect(projectedPointerPosition.y).toBe(10); + store.dispatch(onPointerMove({ x: 20, y: 200 }, 4)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition.x).toBe(10); + expect(projectedPointerPosition.y).toBe(-1); + store.dispatch(onPointerMove({ x: 200, y: 200 }, 5)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition.x).toBe(-1); + expect(projectedPointerPosition.y).toBe(-1); + store.dispatch(onPointerMove({ x: -20, y: -20 }, 6)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition.x).toBe(-1); + expect(projectedPointerPosition.y).toBe(-1); + }); + + test('call onElementOut if moving the mouse out from the chart', () => { + const onOutListener = jest.fn((): undefined => undefined); + const settingsWithListeners: SettingsSpec = { + ...settingSpec, + onElementOut: onOutListener, + }; + store.dispatch(upsertSpec(settingsWithListeners)); + store.dispatch(specParsed()); + // registering the out/over listener caller + store.subscribe(() => { + onElementOutCaller(store.getState()); + onElementOverCaller(store.getState()); + }); + store.dispatch(onPointerMove({ x: 20, y: 20 }, 0)); + expect(onOutListener).toBeCalledTimes(0); + + // no more calls after the first out one outside chart + store.dispatch(onPointerMove({ x: 5, y: 5 }, 1)); + expect(onOutListener).toBeCalledTimes(1); + store.dispatch(onPointerMove({ x: 3, y: 3 }, 2)); + expect(onOutListener).toBeCalledTimes(1); + }); + + test('can respond to tooltip types changes', () => { + let updatedSettings: SettingsSpec = { + ...settingSpec, + tooltip: { + type: TooltipType.None, + }, + }; + store.dispatch(upsertSpec(updatedSettings)); + store.dispatch(specParsed()); + store.dispatch(onPointerMove({ x: 10, y: 10 + 70 }, 0)); + const tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues.length).toBe(2); + expect(tooltipData.tooltipValues[0].isXValue).toBe(true); + expect(tooltipData.tooltipValues[1].isXValue).toBe(false); + expect(tooltipData.tooltipValues[1].isHighlighted).toBe(true); + let isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(false); + + updatedSettings = { + ...settingSpec, + tooltip: { + type: TooltipType.Follow, + }, + }; + store.dispatch(upsertSpec(updatedSettings)); + store.dispatch(specParsed()); + store.dispatch(onPointerMove({ x: 10, y: 10 + 70 }, 1)); + const { geometriesIndex } = computeSeriesGeometriesSelector(store.getState()); + expect(geometriesIndex.size).toBe(2); + const highlightedGeometries = getHighlightedGeomsSelector(store.getState()); + expect(highlightedGeometries.length).toBe(1); + isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + }); + + describe('mouse over with Ordinal scale', () => { + mouseOverTestSuite(ScaleType.Ordinal); + }); + describe('mouse over with Linear scale', () => { + mouseOverTestSuite(ScaleType.Linear); + }); + + // TODO add test for point series + // TODO add test for mixed series + // TODO add test for clicks +}); + +function mouseOverTestSuite(scaleType: ScaleType) { + let store: Store<GlobalChartState>; + let onOverListener: jest.Mock<undefined>; + let onOutListener: jest.Mock<undefined>; + const spec = scaleType === ScaleType.Ordinal ? ordinalBarSeries : linearBarSeries; + beforeEach(() => { + store = initStore(spec); + onOverListener = jest.fn((): undefined => undefined); + onOutListener = jest.fn((): undefined => undefined); + const settingsWithListeners: SettingsSpec = { + ...settingSpec, + onElementOver: onOverListener, + onElementOut: onOutListener, + }; + store.dispatch(upsertSpec(settingsWithListeners)); + store.dispatch(specParsed()); + const onElementOutCaller = createOnElementOutCaller(); + const onElementOverCaller = createOnElementOverCaller(); + store.subscribe(() => { + onElementOutCaller(store.getState()); + onElementOverCaller(store.getState()); + }); + const tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues).toEqual([]); + }); + + test('store is correctly configured', () => { + // checking this to avoid broken tests due to nested describe and before + const seriesGeoms = computeSeriesGeometriesSelector(store.getState()); + expect(seriesGeoms.scales.xScale).not.toBeUndefined(); + expect(seriesGeoms.scales.yScales).not.toBeUndefined(); + }); + + test.skip('set cursor from external source', () => { + // store.setCursorValue(0); + // expect(store.externalCursorShown.get()).toBe(true); + // expect(store.cursorBandPosition).toEqual({ + // height: 100, + // left: 10, + // top: 10, + // visible: true, + // width: 50, + // }); + // store.setCursorValue(1); + // expect(store.externalCursorShown.get()).toBe(true); + // expect(store.cursorBandPosition).toEqual({ + // height: 100, + // left: 60, + // top: 10, + // visible: true, + // width: 50, + // }); + // store.setCursorValue(2); + // expect(store.externalCursorShown.get()).toBe(true); + // // equal to the latest except the visiblility + // expect(store.cursorBandPosition).toEqual({ + // height: 100, + // left: 60, + // top: 10, + // visible: false, + // width: 50, + // }); + }); + test.skip('can determine which tooltip to display if chart & annotation tooltips possible', () => { + // const annotationDimensions = [{ rect: { x: 49, y: -1, width: 3, height: 99 } }]; + // const rectAnnotationSpec: RectAnnotationSpec = { + // id: 'rect', + // groupId: GROUP_ID, + // annotationType: 'rectangle', + // dataValues: [{ coordinates: { x0: 1, x1: 1.5, y0: 0.5, y1: 10 } }], + // }; + // store.annotationSpecs.set(rectAnnotationSpec.annotationId, rectAnnotationSpec); + // store.annotationDimensions.set(rectAnnotationSpec.annotationId, annotationDimensions); + // debugger; + // // isHighlighted false, chart tooltip true; should show annotationTooltip only + // store.setCursorPosition(chartLeft + 51, chartTop + 1); + // expect(store.isTooltipVisible.get()).toBe(false); + }); + + test('can hover top-left corner of the first bar', () => { + let tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues).toEqual([]); + store.dispatch(onPointerMove({ x: chartLeft + 0, y: chartTop + 0 }, 0)); + let projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: 0, y: 0 }); + const cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 0); + expect(cursorBandPosition!.width).toBe(45); + let isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues.length).toBe(2); // x value + 1 y value + expect(tooltipData.highlightedGeometries.length).toBe(1); + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(0); + expect(onOverListener.mock.calls[0][0]).toEqual([ + { + x: 0, + y: 10, + accessor: 'y1', + }, + ]); + + store.dispatch(onPointerMove({ x: chartLeft - 1, y: chartTop - 1 }, 1)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: -1, y: -1 }); + isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(false); + tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues.length).toBe(0); + expect(tooltipData.highlightedGeometries.length).toBe(0); + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(1); + }); + + test('can hover bottom-left corner of the first bar', () => { + store.dispatch(onPointerMove({ x: chartLeft + 0, y: chartTop + 89 }, 0)); + let projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: 0, y: 89 }); + const cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 0); + expect(cursorBandPosition!.width).toBe(45); + let isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + let tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.highlightedGeometries.length).toBe(1); + expect(tooltipData.tooltipValues.length).toBe(2); // x value + 1 y value + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(0); + expect(onOverListener.mock.calls[0][0]).toEqual([ + { + x: 0, + y: 10, + accessor: 'y1', + }, + ]); + store.dispatch(onPointerMove({ x: chartLeft - 1, y: chartTop + 89 }, 1)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: -1, y: 89 }); + isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(false); + tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues.length).toBe(0); + expect(tooltipData.highlightedGeometries.length).toBe(0); + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(1); + }); + + test('can hover top-right corner of the first bar', () => { + let scaleOffset = 0; + if (scaleType !== ScaleType.Ordinal) { + scaleOffset = 1; + } + store.dispatch(onPointerMove({ x: chartLeft + 44 + scaleOffset, y: chartTop + 0 }, 0)); + let projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: 44 + scaleOffset, y: 0 }); + let cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 0); + expect(cursorBandPosition!.width).toBe(45); + let isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + let tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.highlightedGeometries.length).toBe(1); + expect(tooltipData.tooltipValues.length).toBe(2); + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(0); + expect(onOverListener.mock.calls[0][0]).toEqual([ + { + x: 0, + y: 10, + accessor: 'y1', + }, + ]); + + store.dispatch(onPointerMove({ x: chartLeft + 45 + scaleOffset, y: chartTop + 0 }, 1)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: 45 + scaleOffset, y: 0 }); + cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 45); + expect(cursorBandPosition!.width).toBe(45); + isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues.length).toBe(2); + expect(tooltipData.highlightedGeometries.length).toBe(0); + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(1); + }); + + test('can hover bottom-right corner of the first bar', () => { + let scaleOffset = 0; + if (scaleType !== ScaleType.Ordinal) { + scaleOffset = 1; + } + store.dispatch(onPointerMove({ x: chartLeft + 44 + scaleOffset, y: chartTop + 89 }, 0)); + let projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: 44 + scaleOffset, y: 89 }); + let cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 0); + expect(cursorBandPosition!.width).toBe(45); + let isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + let tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.highlightedGeometries.length).toBe(1); + expect(tooltipData.tooltipValues.length).toBe(2); + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(0); + expect(onOverListener.mock.calls[0][0]).toEqual([ + { + x: spec.data[0][0], + y: spec.data[0][1], + accessor: 'y1', + }, + ]); + + store.dispatch(onPointerMove({ x: chartLeft + 45 + scaleOffset, y: chartTop + 89 }, 1)); + projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: 45 + scaleOffset, y: 89 }); + cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 45); + expect(cursorBandPosition!.width).toBe(45); + isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues.length).toBe(2); + // we are over the second bar here + expect(tooltipData.highlightedGeometries.length).toBe(1); + expect(onOverListener).toBeCalledTimes(2); + expect(onOverListener.mock.calls[1][0]).toEqual([ + { + x: spec.data[1][0], + y: spec.data[1][1], + accessor: 'y1', + }, + ]); + + expect(onOutListener).toBeCalledTimes(0); + + store.dispatch(onPointerMove({ x: chartLeft + 47 + scaleOffset, y: chartTop + 89 }, 2)); + }); + + test('can hover top-right corner of the chart', () => { + expect(onOverListener).toBeCalledTimes(0); + expect(onOutListener).toBeCalledTimes(0); + let tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.highlightedGeometries.length).toBe(0); + expect(tooltipData.tooltipValues.length).toBe(0); + + store.dispatch(onPointerMove({ x: chartLeft + 89, y: chartTop + 0 }, 0)); + const projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + expect(projectedPointerPosition).toEqual({ x: 89, y: 0 }); + const cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 45); + expect(cursorBandPosition!.width).toBe(45); + + const isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.highlightedGeometries.length).toBe(0); + expect(tooltipData.tooltipValues.length).toBe(2); + expect(onOverListener).toBeCalledTimes(0); + expect(onOutListener).toBeCalledTimes(0); + }); + + test('will call only one time the listener with the same values', () => { + expect(onOverListener).toBeCalledTimes(0); + expect(onOutListener).toBeCalledTimes(0); + let halfWidth = 45; + if (scaleType !== ScaleType.Ordinal) { + halfWidth = 46; + } + let timeCounter = 0; + for (let i = 0; i < halfWidth; i++) { + store.dispatch(onPointerMove({ x: chartLeft + i, y: chartTop + 89 }, timeCounter)); + expect(onOverListener).toBeCalledTimes(1); + expect(onOutListener).toBeCalledTimes(0); + timeCounter++; + } + for (let i = halfWidth; i < 90; i++) { + store.dispatch(onPointerMove({ x: chartLeft + i, y: chartTop + 89 }, timeCounter)); + expect(onOverListener).toBeCalledTimes(2); + expect(onOutListener).toBeCalledTimes(0); + timeCounter++; + } + for (let i = 0; i < halfWidth; i++) { + store.dispatch(onPointerMove({ x: chartLeft + i, y: chartTop + 0 }, timeCounter)); + expect(onOverListener).toBeCalledTimes(3); + expect(onOutListener).toBeCalledTimes(0); + timeCounter++; + } + for (let i = halfWidth; i < 90; i++) { + store.dispatch(onPointerMove({ x: chartLeft + i, y: chartTop + 0 }, timeCounter)); + expect(onOverListener).toBeCalledTimes(3); + expect(onOutListener).toBeCalledTimes(1); + timeCounter++; + } + }); + + test('can hover bottom-right corner of the chart', () => { + store.dispatch(onPointerMove({ x: chartLeft + 89, y: chartTop + 89 }, 0)); + const projectedPointerPosition = getProjectedPointerPositionSelector(store.getState()); + // store.setCursorPosition(chartLeft + 99, chartTop + 99); + expect(projectedPointerPosition).toEqual({ x: 89, y: 89 }); + const cursorBandPosition = getCursorBandPositionSelector(store.getState()); + expect(cursorBandPosition).toBeDefined(); + expect(cursorBandPosition!.left).toBe(chartLeft + 45); + expect(cursorBandPosition!.width).toBe(45); + const isTooltipVisible = isTooltipVisibleSelector(store.getState()); + expect(isTooltipVisible).toBe(true); + const tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.highlightedGeometries.length).toBe(1); + expect(tooltipData.tooltipValues.length).toBe(2); + expect(onOverListener).toBeCalledTimes(1); + expect(onOverListener.mock.calls[0][0]).toEqual([ + { + x: 1, + y: 5, + accessor: 'y1', + }, + ]); + expect(onOutListener).toBeCalledTimes(0); + }); + + describe.skip('can position tooltip within chart when xScale is a single value scale', () => { + beforeEach(() => { + // const singleValueScale = + // store.xScale!.type === ScaleType.Ordinal + // ? new ScaleBand(['a'], [0, 0]) + // : new ScaleContinuous({ type: ScaleType.Linear, domain: [1, 1], range: [0, 0] }); + // store.xScale = singleValueScale; + }); + test.skip('horizontal chart rotation', () => { + // store.setCursorPosition(chartLeft + 99, chartTop + 99); + // const expectedTransform = `translateX(${chartLeft}px) translateX(-0%) translateY(109px) translateY(-100%)`; + // expect(store.tooltipPosition.transform).toBe(expectedTransform); + }); + + test.skip('vertical chart rotation', () => { + // store.chartRotation = 90; + // store.setCursorPosition(chartLeft + 99, chartTop + 99); + // const expectedTransform = `translateX(109px) translateX(-100%) translateY(${chartTop}px) translateY(-0%)`; + // expect(store.tooltipPosition.transform).toBe(expectedTransform); + }); + }); + describe('can format tooltip values on rotated chart', () => { + beforeEach(() => { + const leftAxis: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + hide: true, + id: 'yaxis', + groupId: GROUP_ID, + position: Position.Left, + tickFormat: (value) => `left ${Number(value)}`, + showOverlappingLabels: false, + showOverlappingTicks: false, + tickPadding: 0, + tickSize: 0, + }; + const bottomAxis: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + hide: true, + id: 'xaxis', + groupId: GROUP_ID, + position: Position.Bottom, + tickFormat: (value) => `bottom ${Number(value)}`, + showOverlappingLabels: false, + showOverlappingTicks: false, + tickPadding: 0, + tickSize: 0, + }; + store.dispatch(upsertSpec(leftAxis)); + store.dispatch(upsertSpec(bottomAxis)); + store.dispatch(specParsed()); + }); + test('chart 0 rotation', () => { + store.dispatch(onPointerMove({ x: chartLeft + 0, y: chartTop + 89 }, 0)); + const tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues[0].value).toBe('bottom 0'); + expect(tooltipData.tooltipValues[1].value).toBe('left 10'); + }); + + test('chart 90 deg rotated', () => { + const settings = getSettingsSpecSelector(store.getState()); + const updatedSettings: SettingsSpec = { + ...settings, + rotation: 90, + }; + store.dispatch(upsertSpec(updatedSettings)); + store.dispatch(specParsed()); + store.dispatch(onPointerMove({ x: chartLeft + 0, y: chartTop + 89 }, 0)); + const tooltipData = getTooltipValuesAndGeometriesSelector(store.getState()); + expect(tooltipData.tooltipValues[0].value).toBe('left 1'); + expect(tooltipData.tooltipValues[1].value).toBe('bottom 5'); + }); + }); +} diff --git a/src/chart_types/xy_chart/store/chart_state.test.ts b/src/chart_types/xy_chart/state/chart_state.test.ts similarity index 85% rename from src/chart_types/xy_chart/store/chart_state.test.ts rename to src/chart_types/xy_chart/state/chart_state.test.ts index 7d640d9b3e..b9d103517e 100644 --- a/src/chart_types/xy_chart/store/chart_state.test.ts +++ b/src/chart_types/xy_chart/state/chart_state.test.ts @@ -1,5 +1,3 @@ -import { LegendItem } from '../legend/legend'; -import { GeometryValue, IndexedGeometry, AccessorType } from '../rendering/rendering'; import { AnnotationDomainTypes, AnnotationSpec, @@ -8,28 +6,35 @@ import { BarSeriesSpec, Position, RectAnnotationSpec, + SpecTypes, + SeriesTypes, } from '../utils/specs'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; import { mergeWithDefaultTheme } from '../../../utils/themes/theme'; -import { getAnnotationId, getAxisId, getGroupId, getSpecId, AxisId } from '../../../utils/ids'; import { TooltipType, TooltipValue } from '../utils/interactions'; import { ScaleBand } from '../../../utils/scales/scale_band'; import { ScaleContinuous } from '../../../utils/scales/scale_continuous'; import { ScaleType } from '../../../utils/scales/scales'; -import { ChartStore, isDuplicateAxis } from './chart_state'; -import { AxisTicksDimensions } from '../utils/axis_utils'; +// import { ChartStore } from './chart_state'; +import { IndexedGeometry, GeometryValue, AccessorType } from '../../../utils/geometry'; +import { AxisTicksDimensions, isDuplicateAxis } from '../utils/axis_utils'; +import { AxisId } from '../../../utils/ids'; +import { LegendItem } from '../legend/legend'; +import { ChartTypes } from '../..'; -describe('Chart Store', () => { - let store = new ChartStore(); +describe.skip('Chart Store', () => { + let store: any = null; // - const SPEC_ID = getSpecId('spec_1'); - const AXIS_ID = getAxisId('axis_1'); - const GROUP_ID = getGroupId('group_1'); + const SPEC_ID = 'spec_1'; + const AXIS_ID = 'axis_1'; + const GROUP_ID = 'group_1'; const spec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [{ x: 1, y: 1, g: 0 }, { x: 2, y: 2, g: 1 }, { x: 3, y: 3, g: 3 }], xAccessor: 'x', @@ -79,17 +84,19 @@ describe('Chart Store', () => { }, }; beforeEach(() => { - store = new ChartStore(); + store = null; // new ChartStore(); store.updateParentDimensions(600, 600, 0, 0); store.computeChart(); }); describe('isDuplicateAxis', () => { - const AXIS_1_ID = getAxisId('spec_1'); - const AXIS_2_ID = getAxisId('spec_1'); + const AXIS_1_ID = 'spec_1'; + const AXIS_2_ID = 'spec_1'; const axis1: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, id: AXIS_1_ID, - groupId: getGroupId('group_1'), + groupId: 'group_1', hide: false, showOverlappingTicks: false, showOverlappingLabels: false, @@ -101,7 +108,7 @@ describe('Chart Store', () => { const axis2: AxisSpec = { ...axis1, id: AXIS_2_ID, - groupId: getGroupId('group_2'), + groupId: 'group_2', }; const axisTicksDimensions: AxisTicksDimensions = { tickValues: [], @@ -112,16 +119,16 @@ describe('Chart Store', () => { maxLabelTextHeight: 1, }; let tickMap: Map<AxisId, AxisTicksDimensions>; - let specMap: Map<AxisId, AxisSpec>; + let specMap: AxisSpec[]; beforeEach(() => { tickMap = new Map<AxisId, AxisTicksDimensions>(); - specMap = new Map<AxisId, AxisSpec>(); + specMap = []; }); it('should return true if axisSpecs and ticks match', () => { tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.set(AXIS_2_ID, axis2); + specMap.push(axis2); const result = isDuplicateAxis(axis1, axisTicksDimensions, tickMap, specMap); expect(result).toBe(true); @@ -129,7 +136,7 @@ describe('Chart Store', () => { it('should return false if axisSpecs, ticks AND title match', () => { tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.set(AXIS_2_ID, { + specMap.push({ ...axis2, title: 'TESTING', }); @@ -152,7 +159,7 @@ describe('Chart Store', () => { tickLabels: ['10'], }; tickMap.set(AXIS_2_ID, newAxisTicksDimensions); - specMap.set(AXIS_2_ID, axis2); + specMap.push(axis2); const result = isDuplicateAxis(axis1, newAxisTicksDimensions, tickMap, specMap); @@ -161,7 +168,7 @@ describe('Chart Store', () => { it('should return false if axisSpecs and ticks match but title is different', () => { tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.set(AXIS_2_ID, { + specMap.push({ ...axis2, title: 'TESTING', }); @@ -180,7 +187,7 @@ describe('Chart Store', () => { it('should return false if axisSpecs and ticks match but position is different', () => { tickMap.set(AXIS_2_ID, axisTicksDimensions); - specMap.set(AXIS_2_ID, axis2); + specMap.push(axis2); const result = isDuplicateAxis( { ...axis1, @@ -199,7 +206,7 @@ describe('Chart Store', () => { ...axisTicksDimensions, tickLabels: ['10%', '20%', '30%'], }); - specMap.set(AXIS_2_ID, axis2); + specMap.push(axis2); const result = isDuplicateAxis(axis1, axisTicksDimensions, tickMap, specMap); @@ -211,7 +218,7 @@ describe('Chart Store', () => { ...axisTicksDimensions, tickLabels: ['10', '20', '25', '30'], }); - specMap.set(AXIS_2_ID, axis2); + specMap.push(axis2); const result = isDuplicateAxis(axis1, axisTicksDimensions, tickMap, specMap); @@ -226,7 +233,7 @@ describe('Chart Store', () => { }); }); - test('can add a single spec', () => { + test.skip('can add a single spec', () => { store.addSeriesSpec(spec); store.updateParentDimensions(600, 600, 0, 0); store.computeChart(); @@ -234,15 +241,17 @@ describe('Chart Store', () => { expect(seriesDomainsAndData).not.toBeUndefined(); }); - test('can initialize deselectedDataSeries depending on previous state', () => { + test.skip('can initialize deselectedDataSeries depending on previous state', () => { store.specsInitialized.set(false); store.computeChart(); expect(store.deselectedDataSeries).toEqual(null); }); - test('can add an axis', () => { + test.skip('can add an axis', () => { store.addSeriesSpec(spec); const axisSpec: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, id: AXIS_ID, groupId: GROUP_ID, hide: false, @@ -263,14 +272,14 @@ describe('Chart Store', () => { expect(axesTicks.get(AXIS_ID)).not.toBeUndefined(); }); - test('can set legend visibility', () => { + test.skip('can set legend visibility', () => { store.showLegend.set(false); store.setShowLegend(true); expect(store.showLegend.get()).toEqual(true); }); - test('can get highlighted legend item', () => { + test.skip('can get highlighted legend item', () => { store.legendItems = new Map([[firstLegendItem.key, firstLegendItem], [secondLegendItem.key, secondLegendItem]]); store.highlightedLegendItemKey.set(null); @@ -280,7 +289,7 @@ describe('Chart Store', () => { expect(store.highlightedLegendItem.get()).toEqual(secondLegendItem); }); - test('can respond to legend item mouseover event', () => { + test.skip('can respond to legend item mouseover event', () => { const legendListener = jest.fn( (): void => { return; @@ -304,7 +313,7 @@ describe('Chart Store', () => { expect(legendListener).toBeCalledWith(null); }); - test('can respond to legend item mouseout event', () => { + test.skip('can respond to legend item mouseout event', () => { const outListener = jest.fn((): undefined => undefined); store.highlightedLegendItemKey.set(firstLegendItem.key); @@ -321,7 +330,7 @@ describe('Chart Store', () => { expect(outListener.mock.calls.length).toBe(1); }); - test('do nothing when mouseover an hidden series', () => { + test.skip('do nothing when mouseover an hidden series', () => { const legendListener = jest.fn( (): void => { return; @@ -349,7 +358,7 @@ describe('Chart Store', () => { store.removeOnLegendItemOutListener(); }); - test('can respond to legend item click event', () => { + test.skip('can respond to legend item click event', () => { const legendListener = jest.fn( (): void => { return; @@ -377,7 +386,7 @@ describe('Chart Store', () => { expect(legendListener).toBeCalledWith(secondLegendItem.value); }); - test('can respond to a legend item plus click event', () => { + test.skip('can respond to a legend item plus click event', () => { const legendListener = jest.fn( (): void => { return; @@ -400,7 +409,7 @@ describe('Chart Store', () => { expect(legendListener).toBeCalledWith(firstLegendItem.value); }); - test('can respond to a legend item minus click event', () => { + test.skip('can respond to a legend item minus click event', () => { const legendListener = jest.fn( (): void => { return; @@ -423,7 +432,7 @@ describe('Chart Store', () => { expect(legendListener).toBeCalledWith(firstLegendItem.value); }); - test('can toggle series visibility', () => { + test.skip('can toggle series visibility', () => { const computeChart = jest.fn( (): void => { return; @@ -448,7 +457,7 @@ describe('Chart Store', () => { expect(store.deselectedDataSeries).toEqual([]); }); - test('can toggle single series visibility', () => { + test.skip('can toggle single series visibility', () => { const computeChart = jest.fn( (): void => { return; @@ -470,7 +479,7 @@ describe('Chart Store', () => { expect(store.deselectedDataSeries).toEqual([secondLegendItem.value]); }); - test('can set an element click listener', () => { + test.skip('can set an element click listener', () => { const clickListener = (): void => { return; }; @@ -479,7 +488,7 @@ describe('Chart Store', () => { expect(store.onElementClickListener).toEqual(clickListener); }); - test('can set a brush end listener', () => { + test.skip('can set a brush end listener', () => { const brushEndListener = (): void => { return; }; @@ -488,7 +497,7 @@ describe('Chart Store', () => { expect(store.onBrushEndListener).toEqual(brushEndListener); }); - test('can set a cursor hover listener', () => { + test.skip('can set a cursor hover listener', () => { const listener = (): void => { return; }; @@ -497,7 +506,7 @@ describe('Chart Store', () => { expect(store.onCursorUpdateListener).toEqual(listener); }); - test('can set a render change listener', () => { + test.skip('can set a render change listener', () => { const listener = (): void => { return; }; @@ -506,7 +515,7 @@ describe('Chart Store', () => { expect(store.onRenderChangeListener).toEqual(listener); }); - test('should observe chartInitialized value', () => { + test.skip('should observe chartInitialized value', () => { const listener = jest.fn(); store.chartInitialized.set(false); store.setOnRenderChangeListener(listener); @@ -515,7 +524,7 @@ describe('Chart Store', () => { expect(listener).toBeCalledWith(true); }); - test('should observe chartInitialized value only on change', () => { + test.skip('should observe chartInitialized value only on change', () => { const listener = jest.fn(); store.chartInitialized.set(false); store.setOnRenderChangeListener(listener); @@ -524,7 +533,7 @@ describe('Chart Store', () => { expect(listener).not.toBeCalled(); }); - test('can remove listeners', () => { + test.skip('can remove listeners', () => { store.removeElementClickListener(); expect(store.onElementClickListener).toBeUndefined(); @@ -550,7 +559,7 @@ describe('Chart Store', () => { expect(store.onRenderChangeListener).toBeUndefined(); }); - test('can respond to a brush end event', () => { + test.skip('can respond to a brush end event', () => { const brushEndListener = jest.fn<void, [number, number]>( (): void => { return; @@ -595,7 +604,7 @@ describe('Chart Store', () => { expect(brushEndListener.mock.calls[1][1]).toBe(2.5); }); - test('can update parent dimensions', () => { + test.skip('can update parent dimensions', () => { const computeChart = jest.fn( (): void => { return; @@ -629,14 +638,16 @@ describe('Chart Store', () => { expect(computeChart).toBeCalled(); }); - test('can remove a series spec', () => { + test.skip('can remove a series spec', () => { store.addSeriesSpec(spec); store.removeSeriesSpec(SPEC_ID); expect(store.seriesSpecs.get(SPEC_ID)).toBe(undefined); }); - test('can remove an axis spec', () => { + test.skip('can remove an axis spec', () => { const axisSpec: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, id: AXIS_ID, groupId: GROUP_ID, hide: false, @@ -654,8 +665,8 @@ describe('Chart Store', () => { }); test('can add and remove an annotation spec', () => { - const annotationId = getAnnotationId('annotation'); - const groupId = getGroupId('group'); + const annotationId = 'annotation'; + const groupId = 'group'; const customStyle = { line: { @@ -673,8 +684,10 @@ describe('Chart Store', () => { }; const lineAnnotation: AnnotationSpec = { - annotationType: 'line', - annotationId, + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + annotationType: AnnotationTypes.Line, + id: annotationId, domainType: AnnotationDomainTypes.YDomain, dataValues: [{ dataValue: 2, details: 'foo' }], groupId, @@ -692,19 +705,21 @@ describe('Chart Store', () => { expect(store.annotationSpecs).toEqual(new Map()); const rectAnnotation: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId: GROUP_ID, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [{ coordinates: { x0: 1, x1: 2, y0: 3, y1: 5 } }], }; store.addAnnotationSpec(rectAnnotation); expectedAnnotationSpecs.clear(); - expectedAnnotationSpecs.set(rectAnnotation.annotationId, rectAnnotation); + expectedAnnotationSpecs.set(rectAnnotation.id, rectAnnotation); expect(store.annotationSpecs).toEqual(expectedAnnotationSpecs); }); - test('only computes chart if parent dimensions are computed', () => { - const localStore = new ChartStore(); + test.skip('only computes chart if parent dimensions are computed', () => { + const localStore: any = null; //new ChartStore(); localStore.parentDimensions = { width: 0, @@ -717,8 +732,8 @@ describe('Chart Store', () => { expect(localStore.chartInitialized.get()).toBe(false); }); - test('only computes chart if series specs exist', () => { - const localStore = new ChartStore(); + test.skip('only computes chart if series specs exist', () => { + const localStore: any = null; //new ChartStore(); localStore.parentDimensions = { width: 100, @@ -732,7 +747,7 @@ describe('Chart Store', () => { expect(localStore.chartInitialized.get()).toBe(false); }); - test('can set the color for a series', () => { + test.skip('can set the color for a series', () => { const computeChart = jest.fn( (): void => { return; @@ -760,12 +775,12 @@ describe('Chart Store', () => { expect(spec.customSeriesColors).toEqual(expectedSpecCustomColorSeries); }); - test('can reset selectedDataSeries', () => { + test.skip('can reset selectedDataSeries', () => { store.deselectedDataSeries = [firstLegendItem.value]; store.resetDeselectedDataSeries(); expect(store.deselectedDataSeries).toBe(null); }); - test('can update the crosshair visibility', () => { + test.skip('can update the crosshair visibility', () => { store.cursorPosition.x = -1; store.cursorPosition.y = 1; store.tooltipType.set(TooltipType.Crosshairs); @@ -787,7 +802,7 @@ describe('Chart Store', () => { expect(store.isCrosshairVisible.get()).toBe(true); }); - test('can update the tooltip visibility', () => { + test.skip('can update the tooltip visibility', () => { const tooltipValue: TooltipValue = { name: 'a', value: 'a', @@ -834,6 +849,8 @@ describe('Chart Store', () => { beforeEach(() => { const axisSpec: AxisSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, id: AXIS_ID, groupId: spec.groupId, hide: true, @@ -851,19 +868,19 @@ describe('Chart Store', () => { store.computeChart(); }); - test('with no tooltipHeaderFormatter defined, should return value formatted using xAxis tickFormatter', () => { + test.skip('with no tooltipHeaderFormatter defined, should return value formatted using xAxis tickFormatter', () => { store.tooltipHeaderFormatter = undefined; store.setCursorPosition(10, 10); expect(store.tooltipData[0].value).toBe('foo 1'); }); - test('with tooltipHeaderFormatter defined, should return value formatted', () => { + test.skip('with tooltipHeaderFormatter defined, should return value formatted', () => { store.tooltipHeaderFormatter = (value: TooltipValue) => `${value}`; store.setCursorPosition(10, 10); expect(store.tooltipData[0].value).toBe(1); }); - test('should update cursor postion with hover event', () => { + test.skip('should update cursor postion with hover event', () => { const legendListener = jest.fn( (): void => { return; @@ -883,7 +900,7 @@ describe('Chart Store', () => { }); }); - test('can disable brush based on scale and listener', () => { + test.skip('can disable brush based on scale and listener', () => { store.xScale = undefined; expect(store.isBrushEnabled()).toBe(false); store.xScale = new ScaleContinuous({ type: ScaleType.Linear, domain: [0, 100], range: [0, 100] }); @@ -895,7 +912,7 @@ describe('Chart Store', () => { expect(store.isBrushEnabled()).toBe(false); }); - test('can disable tooltip on brushing', () => { + test.skip('can disable tooltip on brushing', () => { store.addSeriesSpec(spec); store.setOnBrushEndListener(() => ({})); const tooltipValue: TooltipValue = { @@ -924,7 +941,7 @@ describe('Chart Store', () => { expect(store.isBrushing.get()).toBe(false); expect(store.isTooltipVisible.get()).toBe(true); }); - test('handle click on chart', () => { + test.skip('handle click on chart', () => { const barStyle = { rect: { opacity: 1, @@ -945,7 +962,7 @@ describe('Chart Store', () => { const geom1: IndexedGeometry = { color: 'red', geometryId: { - specId: getSpecId('specId1'), + specId: 'specId1', seriesKey: [2], }, value: { @@ -962,7 +979,7 @@ describe('Chart Store', () => { const geom2: IndexedGeometry = { color: 'blue', geometryId: { - specId: getSpecId('specId2'), + specId: 'specId2', seriesKey: [2], }, value: { @@ -997,11 +1014,11 @@ describe('Chart Store', () => { expect(clickListener).toBeCalledTimes(2); expect(clickListener.mock.calls[1][0]).toEqual([geom1.value, geom2.value]); }); - test('can compute annotation tooltip state', () => { + test.skip('can compute annotation tooltip state', () => { const scale = new ScaleContinuous({ type: ScaleType.Linear, domain: [0, 100], range: [0, 100] }); - store.rawCursorPosition.x = -1; - store.rawCursorPosition.y = 0; + store.currentPointerPosition.x = -1; + store.currentPointerPosition.y = 0; expect(store.annotationTooltipState.get()).toBe(null); @@ -1016,24 +1033,26 @@ describe('Chart Store', () => { store.yScales = new Map(); store.yScales.set(GROUP_ID, scale); - store.rawCursorPosition.x = 0; + store.currentPointerPosition.x = 0; expect(store.annotationTooltipState.get()).toBe(null); // If there's a rect annotation & there's also a highlight chart element tooltip, ignore annotation tooltip - store.rawCursorPosition.x = 18; - store.rawCursorPosition.y = 9; + store.currentPointerPosition.x = 18; + store.currentPointerPosition.y = 9; store.chartDimensions = { width: 10, height: 20, top: 5, left: 15 }; const annotationDimensions = [{ rect: { x: 2, y: 3, width: 3, height: 5 } }]; const rectAnnotationSpec: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Annotation, + id: 'rect', groupId: GROUP_ID, - annotationType: 'rectangle', + annotationType: AnnotationTypes.Rectangle, dataValues: [{ coordinates: { x0: 1, x1: 2, y0: 3, y1: 5 } }], }; - store.annotationSpecs.set(rectAnnotationSpec.annotationId, rectAnnotationSpec); - store.annotationDimensions.set(rectAnnotationSpec.annotationId, annotationDimensions); + store.annotationSpecs.set(rectAnnotationSpec.id, rectAnnotationSpec); + store.annotationDimensions.set(rectAnnotationSpec.id, annotationDimensions); const highlightedTooltipValue = { name: 'foo', @@ -1058,8 +1077,8 @@ describe('Chart Store', () => { isVisible: true, annotationType: AnnotationTypes.Rectangle, anchor: { - top: store.rawCursorPosition.y - store.chartDimensions.top, - left: store.rawCursorPosition.x - store.chartDimensions.left, + top: store.currentPointerPosition.y - store.chartDimensions.top, + left: store.currentPointerPosition.x - store.chartDimensions.left, }, }; store.tooltipData.push(unhighlightedTooltipValue); @@ -1068,7 +1087,7 @@ describe('Chart Store', () => { store.tooltipData.push(highlightedTooltipValue); expect(store.annotationTooltipState.get()).toBe(null); }); - test('can get tooltipValues by seriesKeys', () => { + test.skip('can get tooltipValues by seriesKeys', () => { store.tooltipData.clear(); expect(store.legendItemTooltipValues.get()).toEqual(new Map()); @@ -1114,34 +1133,34 @@ describe('Chart Store', () => { store.xScale = new ScaleContinuous({ type: ScaleType.Linear, domain: [0, 100], range: [0, 100] }); }); - test('when cursor is outside of chart bounds', () => { + test.skip('when cursor is outside of chart bounds', () => { store.cursorPosition.x = -1; store.cursorPosition.y = -1; store.onBrushEndListener = brushEndListener; expect(store.chartCursor.get()).toBe('default'); }); - test('when cursor is within chart bounds and brush enabled', () => { + test.skip('when cursor is within chart bounds and brush enabled', () => { store.cursorPosition.x = 10; store.cursorPosition.y = 10; store.onBrushEndListener = brushEndListener; expect(store.chartCursor.get()).toBe('crosshair'); }); - test('when cursor is within chart bounds and brush disabled', () => { + test.skip('when cursor is within chart bounds and brush disabled', () => { store.cursorPosition.x = 10; store.cursorPosition.y = 10; store.onBrushEndListener = undefined; expect(store.chartCursor.get()).toBe('default'); }); - test('when cursor is within chart bounds and brush enabled but over one geom', () => { + test.skip('when cursor is within chart bounds and brush enabled but over one geom', () => { store.cursorPosition.x = 10; store.cursorPosition.y = 10; store.onBrushEndListener = brushEndListener; const geom1: IndexedGeometry = { color: 'red', geometryId: { - specId: getSpecId('specId1'), + specId: 'specId1', seriesKey: [2], }, value: { @@ -1177,11 +1196,13 @@ describe('Chart Store', () => { expect(store.chartCursor.get()).toBe('pointer'); }); }); - test('should set tooltip type to follow when single value x scale', () => { + test.skip('should set tooltip type to follow when single value x scale', () => { const singleValueSpec: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID, groupId: GROUP_ID, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, yScaleToDataExtent: false, data: [{ x: 1, y: 1, g: 0 }], xAccessor: 'x', @@ -1196,7 +1217,7 @@ describe('Chart Store', () => { expect(store.tooltipType.get()).toBe(TooltipType.Follow); }); - describe('isActiveChart', () => { + describe.skip('isActiveChart', () => { it('should return true if no activeChartId is defined', () => { store.activeChartId = undefined; expect(store.isActiveChart.get()).toBe(true); @@ -1213,7 +1234,7 @@ describe('Chart Store', () => { }); }); - describe('setActiveChartId', () => { + describe.skip('setActiveChartId', () => { it('should set activeChartId with value', () => { store.activeChartId = undefined; store.setActiveChartId('test-id'); diff --git a/src/chart_types/xy_chart/state/chart_state.timescales.test.ts b/src/chart_types/xy_chart/state/chart_state.timescales.test.ts new file mode 100644 index 0000000000..a6fbc1368c --- /dev/null +++ b/src/chart_types/xy_chart/state/chart_state.timescales.test.ts @@ -0,0 +1,232 @@ +import { LineSeriesSpec, SpecTypes, SeriesTypes } from '../utils/specs'; +import { ScaleType } from '../../../utils/scales/scales'; +import { createStore, Store } from 'redux'; +import { chartStoreReducer, GlobalChartState } from '../../../state/chart_state'; +import { upsertSpec, specParsed } from '../../../state/actions/specs'; +import { SettingsSpec, DEFAULT_SETTINGS_SPEC } from '../../../specs'; +import { mergeWithDefaultTheme } from '../../../utils/themes/theme'; +import { LIGHT_THEME } from '../../../utils/themes/light_theme'; +import { updateParentDimensions } from '../../../state/actions/chart_settings'; +import { computeSeriesGeometriesSelector } from './selectors/compute_series_geometries'; +import { onPointerMove } from '../../../state/actions/mouse'; +import { getTooltipValuesSelector } from './selectors/get_tooltip_values_highlighted_geoms'; +import { DateTime } from 'luxon'; +import { getComputedScalesSelector } from './selectors/get_computed_scales'; +import { ChartTypes } from '../..'; + +describe('Render chart', () => { + describe('line, utc-time, day interval', () => { + let store: Store<GlobalChartState>; + const day1 = 1546300800000; // 2019-01-01T00:00:00.000Z + const day2 = day1 + 1000 * 60 * 60 * 24; + const day3 = day2 + 1000 * 60 * 60 * 24; + beforeEach(() => { + const storeReducer = chartStoreReducer('chartId'); + store = createStore(storeReducer); + + const lineSeries: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'lines', + groupId: 'line', + seriesType: SeriesTypes.Line, + xScaleType: ScaleType.Time, + yScaleType: ScaleType.Linear, + xAccessor: 0, + yAccessors: [1], + data: [[day1, 10], [day2, 22], [day3, 6]], + yScaleToDataExtent: false, + }; + store.dispatch(upsertSpec(lineSeries)); + + const settingSpec: SettingsSpec = { + ...DEFAULT_SETTINGS_SPEC, + theme: mergeWithDefaultTheme( + { + chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, + chartMargins: { top: 0, left: 0, bottom: 0, right: 0 }, + }, + LIGHT_THEME, + ), + }; + store.dispatch(upsertSpec(settingSpec)); + store.dispatch(specParsed()); + store.dispatch(updateParentDimensions({ width: 100, height: 100, top: 0, left: 0 })); + const state = store.getState(); + expect(state.specs['lines']).toBeDefined(); + expect(state.chartType).toBe(ChartTypes.XYAxis); + }); + test('check rendered geometries', () => { + const { geometries } = computeSeriesGeometriesSelector(store.getState()); + expect(geometries).toBeDefined(); + expect(geometries.lines).toBeDefined(); + expect(geometries.lines.length).toBe(1); + expect(geometries.lines[0].points.length).toBe(3); + }); + test('check mouse position correctly return inverted value', () => { + store.dispatch(onPointerMove({ x: 15, y: 10 }, 0)); // check first valid tooltip + let tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(day1); // x value + expect(tooltipData[1].value).toBe(10); // y value + store.dispatch(onPointerMove({ x: 35, y: 10 }, 1)); // check second valid tooltip + tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(day2); // x value + expect(tooltipData[1].value).toBe(22); // y value + store.dispatch(onPointerMove({ x: 76, y: 10 }, 2)); // check third valid tooltip + tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(day3); // x value + expect(tooltipData[1].value).toBe(6); // y value + }); + }); + describe('line, utc-time, 5m interval', () => { + let store: Store<GlobalChartState>; + const date1 = 1546300800000; // 2019-01-01T00:00:00.000Z + const date2 = date1 + 1000 * 60 * 5; + const date3 = date2 + 1000 * 60 * 5; + beforeEach(() => { + const storeReducer = chartStoreReducer('chartId'); + store = createStore(storeReducer); + + const lineSeries: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'lines', + groupId: 'line', + seriesType: SeriesTypes.Line, + xScaleType: ScaleType.Time, + yScaleType: ScaleType.Linear, + xAccessor: 0, + yAccessors: [1], + data: [[date1, 10], [date2, 22], [date3, 6]], + yScaleToDataExtent: false, + }; + store.dispatch(upsertSpec(lineSeries)); + const settingSpec: SettingsSpec = { + ...DEFAULT_SETTINGS_SPEC, + theme: mergeWithDefaultTheme( + { + chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, + chartMargins: { top: 0, left: 0, bottom: 0, right: 0 }, + }, + LIGHT_THEME, + ), + }; + store.dispatch(upsertSpec(settingSpec)); + store.dispatch(specParsed()); + store.dispatch(updateParentDimensions({ width: 100, height: 100, top: 0, left: 0 })); + const state = store.getState(); + expect(state.specs['lines']).toBeDefined(); + expect(state.chartType).toBe(ChartTypes.XYAxis); + }); + test('check rendered geometries', () => { + const { geometries } = computeSeriesGeometriesSelector(store.getState()); + expect(geometries).toBeDefined(); + expect(geometries.lines).toBeDefined(); + expect(geometries.lines.length).toBe(1); + expect(geometries.lines[0].points.length).toBe(3); + }); + test('check mouse position correctly return inverted value', () => { + store.dispatch(onPointerMove({ x: 15, y: 10 }, 0)); // check first valid tooltip + let tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(date1); // x value + expect(tooltipData[1].value).toBe(10); // y value + store.dispatch(onPointerMove({ x: 35, y: 10 }, 1)); // check second valid tooltip + tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(date2); // x value + expect(tooltipData[1].value).toBe(22); // y value + store.dispatch(onPointerMove({ x: 76, y: 10 }, 2)); // check third valid tooltip + tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(date3); // x value + expect(tooltipData[1].value).toBe(6); // y value + }); + }); + describe('line, non utc-time, 5m + 1s interval', () => { + let store: Store<GlobalChartState>; + const date1 = DateTime.fromISO('2019-01-01T00:00:01.000-0300', { setZone: true }).toMillis(); + const date2 = date1 + 1000 * 60 * 5; + const date3 = date2 + 1000 * 60 * 5; + beforeEach(() => { + const storeReducer = chartStoreReducer('chartId'); + store = createStore(storeReducer); + const lineSeries: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'lines', + groupId: 'line', + seriesType: SeriesTypes.Line, + xScaleType: ScaleType.Time, + yScaleType: ScaleType.Linear, + xAccessor: 0, + yAccessors: [1], + data: [[date1, 10], [date2, 22], [date3, 6]], + yScaleToDataExtent: false, + }; + store.dispatch(upsertSpec(lineSeries)); + const settingSpec: SettingsSpec = { + ...DEFAULT_SETTINGS_SPEC, + theme: mergeWithDefaultTheme( + { + chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, + chartMargins: { top: 0, left: 0, bottom: 0, right: 0 }, + }, + LIGHT_THEME, + ), + }; + store.dispatch(upsertSpec(settingSpec)); + store.dispatch(specParsed()); + store.dispatch(updateParentDimensions({ width: 100, height: 100, top: 0, left: 0 })); + const state = store.getState(); + expect(state.specs['lines']).toBeDefined(); + expect(state.chartType).toBe(ChartTypes.XYAxis); + }); + test('check rendered geometries', () => { + const { geometries } = computeSeriesGeometriesSelector(store.getState()); + expect(geometries).toBeDefined(); + expect(geometries.lines).toBeDefined(); + expect(geometries.lines.length).toBe(1); + expect(geometries.lines[0].points.length).toBe(3); + }); + test('check scale values', () => { + const xValues = [date1, date2, date3]; + const state = store.getState(); + const { xScale } = getComputedScalesSelector(state); + + expect(xScale.minInterval).toBe(1000 * 60 * 5); + expect(xScale.domain).toEqual([date1, date3]); + expect(xScale.range).toEqual([0, 100]); + expect(xScale.invert(0)).toBe(date1); + expect(xScale.invert(50)).toBe(date2); + expect(xScale.invert(100)).toBe(date3); + expect(xScale.invertWithStep(5, xValues)).toEqual({ value: date1, withinBandwidth: true }); + expect(xScale.invertWithStep(20, xValues)).toEqual({ value: date1, withinBandwidth: true }); + expect(xScale.invertWithStep(30, xValues)).toEqual({ value: date2, withinBandwidth: true }); + expect(xScale.invertWithStep(50, xValues)).toEqual({ value: date2, withinBandwidth: true }); + expect(xScale.invertWithStep(70, xValues)).toEqual({ value: date2, withinBandwidth: true }); + expect(xScale.invertWithStep(80, xValues)).toEqual({ value: date3, withinBandwidth: true }); + expect(xScale.invertWithStep(100, xValues)).toEqual({ value: date3, withinBandwidth: true }); + }); + test('check mouse position correctly return inverted value', () => { + store.dispatch(onPointerMove({ x: 15, y: 10 }, 0)); // check first valid tooltip + let tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(date1); // x value + expect(tooltipData[1].value).toBe(10); // y value + store.dispatch(onPointerMove({ x: 35, y: 10 }, 1)); // check second valid tooltip + tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(date2); // x value + expect(tooltipData[1].value).toBe(22); // y value + store.dispatch(onPointerMove({ x: 76, y: 10 }, 2)); // check third valid tooltip + tooltipData = getTooltipValuesSelector(store.getState()); + expect(tooltipData.length).toBe(2); // x value + y value + expect(tooltipData[0].value).toBe(date3); // x value + expect(tooltipData[1].value).toBe(6); // y value + }); + }); +}); diff --git a/src/chart_types/xy_chart/state/chart_state.tsx b/src/chart_types/xy_chart/state/chart_state.tsx new file mode 100644 index 0000000000..86ad9f7eb6 --- /dev/null +++ b/src/chart_types/xy_chart/state/chart_state.tsx @@ -0,0 +1,49 @@ +import React, { RefObject } from 'react'; +import { InternalChartState, GlobalChartState, BackwardRef } from '../../../state/chart_state'; +import { ChartTypes } from '../..'; +import { Tooltips } from '../renderer/dom/tooltips'; +import { htmlIdGenerator } from '../../../utils/commons'; +import { Highlighter } from '../renderer/dom/highlighter'; +import { Crosshair } from '../renderer/dom/crosshair'; +import { AnnotationTooltip } from '../renderer/dom/annotation_tooltips'; +import { isBrushAvailableSelector } from './selectors/is_brush_available'; +import { BrushTool } from '../renderer/dom/brush'; +import { isChartEmptySelector } from './selectors/is_chart_empty'; +import { ReactiveChart } from '../renderer/canvas/reactive_chart'; +import { computeLegendSelector } from './selectors/compute_legend'; +import { getLegendTooltipValuesSelector } from './selectors/get_legend_tooltip_values'; +import { TooltipLegendValue } from '../tooltip/tooltip'; +import { getPointerCursorSelector } from './selectors/get_cursor_pointer'; +import { Stage } from 'react-konva'; + +export class XYAxisChartState implements InternalChartState { + chartType = ChartTypes.XYAxis; + legendId: string = htmlIdGenerator()('legend'); + isBrushAvailable(globalState: GlobalChartState) { + return isBrushAvailableSelector(globalState); + } + isChartEmpty(globalState: GlobalChartState) { + return isChartEmptySelector(globalState); + } + getLegendItems(globalState: GlobalChartState) { + return computeLegendSelector(globalState); + } + getLegendItemsValues(globalState: GlobalChartState): Map<string, TooltipLegendValue> { + return getLegendTooltipValuesSelector(globalState); + } + chartRenderer(containerRef: BackwardRef, forwardStageRef: RefObject<Stage>) { + return ( + <React.Fragment> + <Crosshair /> + <ReactiveChart forwardStageRef={forwardStageRef} /> + <Tooltips getChartContainerRef={containerRef} /> + <AnnotationTooltip getChartContainerRef={containerRef} /> + <Highlighter /> + <BrushTool /> + </React.Fragment> + ); + } + getPointerCursor(globalState: GlobalChartState) { + return getPointerCursorSelector(globalState); + } +} diff --git a/src/chart_types/xy_chart/state/selectors/compute_annotations.ts b/src/chart_types/xy_chart/state/selectors/compute_annotations.ts new file mode 100644 index 0000000000..0e4ecd8073 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_annotations.ts @@ -0,0 +1,44 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getAxisSpecsSelector, getAnnotationSpecsSelector } from './get_specs'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { countBarsInClusterSelector } from './count_bars_in_cluster'; +import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +import { computeAnnotationDimensions, AnnotationDimensions } from '../../annotations/annotation_utils'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { AnnotationId } from '../../../../utils/ids'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const computeAnnotationDimensionsSelector = createCachedSelector( + [ + getAnnotationSpecsSelector, + computeChartDimensionsSelector, + getSettingsSpecSelector, + computeSeriesGeometriesSelector, + getAxisSpecsSelector, + countBarsInClusterSelector, + isHistogramModeEnabledSelector, + getAxisSpecsSelector, + ], + ( + annotationSpecs, + chartDimensions, + settingsSpec, + seriesGeometries, + axesSpecs, + totalBarsInCluster, + isHistogramMode, + ): Map<AnnotationId, AnnotationDimensions> => { + const { yScales, xScale } = seriesGeometries.scales; + return computeAnnotationDimensions( + annotationSpecs, + chartDimensions.chartDimensions, + settingsSpec.rotation, + yScales, + xScale, + axesSpecs, + totalBarsInCluster, + isHistogramMode, + ); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts b/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts new file mode 100644 index 0000000000..a791fe58bc --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_axis_ticks_dimensions.ts @@ -0,0 +1,60 @@ +import createCachedSelector from 're-reselect'; +import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +import { computeSeriesDomainsSelector } from './compute_series_domains'; +import { CanvasTextBBoxCalculator } from '../../../../utils/bbox/canvas_text_bbox_calculator'; +import { computeAxisTicksDimensions, AxisTicksDimensions, isDuplicateAxis } from '../../utils/axis_utils'; +import { countBarsInClusterSelector } from './count_bars_in_cluster'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { AxisId } from '../../../../utils/ids'; +import { getAxisSpecsSelector } from './get_specs'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getBarPaddingsSelector } from './get_bar_paddings'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const computeAxisTicksDimensionsSelector = createCachedSelector( + [ + getBarPaddingsSelector, + isHistogramModeEnabledSelector, + getAxisSpecsSelector, + getChartThemeSelector, + getSettingsSpecSelector, + computeSeriesDomainsSelector, + countBarsInClusterSelector, + ], + ( + barsPadding, + isHistogramMode, + axesSpecs, + chartTheme, + settingsSpec, + seriesDomainsAndData, + totalBarsInCluster, + ): Map<AxisId, AxisTicksDimensions> => { + const { xDomain, yDomain } = seriesDomainsAndData; + + const bboxCalculator = new CanvasTextBBoxCalculator(); + const axesTicksDimensions: Map<AxisId, AxisTicksDimensions> = new Map(); + axesSpecs.forEach((axisSpec) => { + const { id } = axisSpec; + const dimensions = computeAxisTicksDimensions( + axisSpec, + xDomain, + yDomain, + totalBarsInCluster, + bboxCalculator, + settingsSpec.rotation, + chartTheme.axes, + barsPadding, + isHistogramMode, + ); + if ( + dimensions && + (!settingsSpec.hideDuplicateAxes || !isDuplicateAxis(axisSpec, dimensions, axesTicksDimensions, axesSpecs)) + ) { + axesTicksDimensions.set(id, dimensions); + } + }); + bboxCalculator.destroy(); + return axesTicksDimensions; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/compute_axis_visible_ticks.ts b/src/chart_types/xy_chart/state/selectors/compute_axis_visible_ticks.ts new file mode 100644 index 0000000000..59bfa4358a --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_axis_visible_ticks.ts @@ -0,0 +1,59 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getAxisSpecsSelector } from './get_specs'; +import { getAxisTicksPositions, AxisTick, AxisLinePosition } from '../../utils/axis_utils'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { computeAxisTicksDimensionsSelector } from './compute_axis_ticks_dimensions'; +import { computeSeriesDomainsSelector } from './compute_series_domains'; +import { countBarsInClusterSelector } from './count_bars_in_cluster'; +import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +import { getBarPaddingsSelector } from './get_bar_paddings'; +import { AxisId } from '../../../../utils/ids'; +import { Dimensions } from '../../../../utils/dimensions'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +interface AxisVisibleTicks { + axisPositions: Map<AxisId, Dimensions>; + axisTicks: Map<AxisId, AxisTick[]>; + axisVisibleTicks: Map<AxisId, AxisTick[]>; + axisGridLinesPositions: Map<AxisId, AxisLinePosition[]>; +} +export const computeAxisVisibleTicksSelector = createCachedSelector( + [ + computeChartDimensionsSelector, + getChartThemeSelector, + getSettingsSpecSelector, + getAxisSpecsSelector, + computeAxisTicksDimensionsSelector, + computeSeriesDomainsSelector, + countBarsInClusterSelector, + isHistogramModeEnabledSelector, + getBarPaddingsSelector, + ], + ( + chartDimensions, + chartTheme, + settingsSpec, + axesSpecs, + axesTicksDimensions, + seriesDomainsAndData, + totalBarsInCluster, + isHistogramMode, + barsPadding, + ): AxisVisibleTicks => { + const { xDomain, yDomain } = seriesDomainsAndData; + return getAxisTicksPositions( + chartDimensions, + chartTheme, + settingsSpec.rotation, + axesSpecs, + axesTicksDimensions, + xDomain, + yDomain, + totalBarsInCluster, + isHistogramMode, + barsPadding, + ); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/compute_chart_dimensions.ts b/src/chart_types/xy_chart/state/selectors/compute_chart_dimensions.ts new file mode 100644 index 0000000000..145c554120 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_chart_dimensions.ts @@ -0,0 +1,28 @@ +import createCachedSelector from 're-reselect'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { getAxisSpecsSelector } from './get_specs'; +import { computeChartDimensions } from '../../utils/dimensions'; +import { computeAxisTicksDimensionsSelector } from './compute_axis_ticks_dimensions'; +import { Dimensions } from '../../../../utils/dimensions'; +import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const computeChartDimensionsSelector = createCachedSelector( + [ + getChartContainerDimensionsSelector, + getChartThemeSelector, + computeAxisTicksDimensionsSelector, + getAxisSpecsSelector, + ], + ( + chartContainerDimensions, + chartTheme, + axesTicksDimensions, + axesSpecs, + ): { + chartDimensions: Dimensions; + leftMargin: number; + } => { + return computeChartDimensions(chartContainerDimensions, chartTheme, axesTicksDimensions, axesSpecs); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/compute_chart_transform.ts b/src/chart_types/xy_chart/state/selectors/compute_chart_transform.ts new file mode 100644 index 0000000000..8acf6e023b --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_chart_transform.ts @@ -0,0 +1,12 @@ +import createCachedSelector from 're-reselect'; +import { computeChartTransform, Transform } from '../utils'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const computeChartTransformSelector = createCachedSelector( + [computeChartDimensionsSelector, getSettingsSpecSelector], + (chartDimensions, settingsSpecs): Transform => { + return computeChartTransform(chartDimensions.chartDimensions, settingsSpecs.rotation); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/compute_legend.ts b/src/chart_types/xy_chart/state/selectors/compute_legend.ts new file mode 100644 index 0000000000..1f54097f50 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_legend.ts @@ -0,0 +1,38 @@ +import createCachedSelector from 're-reselect'; +import { computeSeriesDomainsSelector } from './compute_series_domains'; +import { getSeriesSpecsSelector, getAxisSpecsSelector } from './get_specs'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { getSeriesColorMapSelector } from './get_series_color_map'; +import { computeLegend, LegendItem } from '../../legend/legend'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getDeselectedSeriesSelector = (state: GlobalChartState) => state.interactions.deselectedDataSeries; + +export const computeLegendSelector = createCachedSelector( + [ + getSeriesSpecsSelector, + computeSeriesDomainsSelector, + getChartThemeSelector, + getSeriesColorMapSelector, + getAxisSpecsSelector, + getDeselectedSeriesSelector, + ], + ( + seriesSpecs, + seriesDomainsAndData, + chartTheme, + seriesColorMap, + axesSpecs, + deselectedDataSeries, + ): Map<string, LegendItem> => { + return computeLegend( + seriesDomainsAndData.seriesColors, + seriesColorMap, + seriesSpecs, + chartTheme.colors.defaultVizColor, + axesSpecs, + deselectedDataSeries, + ); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/compute_series_domains.ts b/src/chart_types/xy_chart/state/selectors/compute_series_domains.ts new file mode 100644 index 0000000000..ca82793476 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_series_domains.ts @@ -0,0 +1,23 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getSeriesSpecsSelector } from './get_specs'; +import { mergeYCustomDomainsByGroupIdSelector } from './merge_y_custom_domains'; +import { computeSeriesDomains } from '../utils'; +import { SeriesDomainsAndData } from '../utils'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getDeselectedSeriesSelector = (state: GlobalChartState) => state.interactions.deselectedDataSeries; + +export const computeSeriesDomainsSelector = createCachedSelector( + [getSeriesSpecsSelector, mergeYCustomDomainsByGroupIdSelector, getDeselectedSeriesSelector, getSettingsSpecSelector], + (seriesSpecs, customYDomainsByGroupId, deselectedDataSeries, settingsSpec): SeriesDomainsAndData => { + const domains = computeSeriesDomains( + seriesSpecs, + customYDomainsByGroupId, + deselectedDataSeries, + settingsSpec.xDomain, + ); + return domains; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/compute_series_geometries.ts b/src/chart_types/xy_chart/state/selectors/compute_series_geometries.ts new file mode 100644 index 0000000000..db235a2b46 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/compute_series_geometries.ts @@ -0,0 +1,47 @@ +import createCachedSelector from 're-reselect'; +import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +import { computeSeriesDomainsSelector } from './compute_series_domains'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { getSeriesSpecsSelector, getAxisSpecsSelector } from './get_specs'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { computeSeriesGeometries, ComputedGeometries } from '../utils'; +import { getSeriesColorMapSelector } from './get_series_color_map'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const computeSeriesGeometriesSelector = createCachedSelector( + [ + getSettingsSpecSelector, + getSeriesSpecsSelector, + computeSeriesDomainsSelector, + getSeriesColorMapSelector, + getChartThemeSelector, + computeChartDimensionsSelector, + getAxisSpecsSelector, + isHistogramModeEnabledSelector, + ], + ( + settingsSpec, + seriesSpecs, + seriesDomainsAndData, + seriesColorMap, + chartTheme, + chartDimensions, + axesSpecs, + isHistogramMode, + ): ComputedGeometries => { + const { xDomain, yDomain, formattedDataSeries } = seriesDomainsAndData; + return computeSeriesGeometries( + seriesSpecs, + xDomain, + yDomain, + formattedDataSeries, + seriesColorMap, + chartTheme, + chartDimensions.chartDimensions, + settingsSpec.rotation, + axesSpecs, + isHistogramMode, + ); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/count_bars_in_cluster.ts b/src/chart_types/xy_chart/state/selectors/count_bars_in_cluster.ts new file mode 100644 index 0000000000..3349e8aceb --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/count_bars_in_cluster.ts @@ -0,0 +1,14 @@ +import createCachedSelector from 're-reselect'; +import { computeSeriesDomainsSelector } from './compute_series_domains'; +import { countBarsInCluster } from '../../utils/scales'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const countBarsInClusterSelector = createCachedSelector( + [computeSeriesDomainsSelector], + (seriesDomainsAndData): number => { + const { formattedDataSeries } = seriesDomainsAndData; + + const { totalBarsInCluster } = countBarsInCluster(formattedDataSeries.stacked, formattedDataSeries.nonStacked); + return totalBarsInCluster; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_annotation_tooltip_state.ts b/src/chart_types/xy_chart/state/selectors/get_annotation_tooltip_state.ts new file mode 100644 index 0000000000..5dbb58c6f5 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_annotation_tooltip_state.ts @@ -0,0 +1,84 @@ +import createCachedSelector from 're-reselect'; +import { Dimensions } from '../../../../utils/dimensions'; +import { Point } from '../../../../utils/point'; +import { TooltipValue } from '../../utils/interactions'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getAxisSpecsSelector, getAnnotationSpecsSelector } from './get_specs'; +import { AxisSpec, AnnotationSpec, Rotation, AnnotationTypes } from '../../utils/specs'; +import { + computeAnnotationTooltipState, + AnnotationTooltipState, + AnnotationDimensions, +} from '../../annotations/annotation_utils'; +import { computeAnnotationDimensionsSelector } from './compute_annotations'; +import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; +import { AnnotationId } from '../../../../utils/ids'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { ComputedGeometries } from '../utils'; +import { getTooltipValuesSelector } from './get_tooltip_values_highlighted_geoms'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; +import { GlobalChartState } from '../../../../state/chart_state'; + +const getCurrentPointerPosition = (state: GlobalChartState) => state.interactions.pointer.current.position; + +export const getAnnotationTooltipStateSelector = createCachedSelector( + [ + getCurrentPointerPosition, + computeChartDimensionsSelector, + computeSeriesGeometriesSelector, + getChartRotationSelector, + getAnnotationSpecsSelector, + getAxisSpecsSelector, + computeAnnotationDimensionsSelector, + getTooltipValuesSelector, + ], + getAnnotationTooltipState, +)(getChartIdSelector); + +function getAnnotationTooltipState( + { x, y }: Point, + { + chartDimensions, + }: { + chartDimensions: Dimensions; + }, + geometries: ComputedGeometries, + chartRotation: Rotation, + annotationSpecs: AnnotationSpec[], + axesSpecs: AxisSpec[], + annotationDimensions: Map<AnnotationId, AnnotationDimensions>, + tooltipValues: TooltipValue[], +): AnnotationTooltipState | null { + // get positions relative to chart + if (x < 0 || y < 0) { + return null; + } + const { xScale, yScales } = geometries.scales; + // only if we have a valid cursor position and the necessary scale + if (!xScale || !yScales) { + return null; + } + // use area chart projected coordinates of the pointer + const chartAreaProjectedPointer = { x: x - chartDimensions.left, y: y - chartDimensions.top }; + const tooltipState = computeAnnotationTooltipState( + chartAreaProjectedPointer, + annotationDimensions, + annotationSpecs, + chartRotation, + axesSpecs, + chartDimensions, + ); + + // If there's a highlighted chart element tooltip value, don't show annotation tooltip + const isChartTooltipDisplayed = tooltipValues.some(({ isHighlighted }) => isHighlighted); + if ( + tooltipState && + tooltipState.isVisible && + tooltipState.annotationType === AnnotationTypes.Rectangle && + isChartTooltipDisplayed + ) { + return null; + } + + return tooltipState; +} diff --git a/src/chart_types/xy_chart/state/selectors/get_bar_paddings.ts b/src/chart_types/xy_chart/state/selectors/get_bar_paddings.ts new file mode 100644 index 0000000000..08e461ec5c --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_bar_paddings.ts @@ -0,0 +1,11 @@ +import createCachedSelector from 're-reselect'; +import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getBarPaddingsSelector = createCachedSelector( + [isHistogramModeEnabledSelector, getChartThemeSelector], + (isHistogramMode, chartTheme): number => { + return isHistogramMode ? chartTheme.scales.histogramPadding : chartTheme.scales.barsPadding; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_brush_area.ts b/src/chart_types/xy_chart/state/selectors/get_brush_area.ts new file mode 100644 index 0000000000..2d97a0ee0e --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_brush_area.ts @@ -0,0 +1,47 @@ +import createCachedSelector from 're-reselect'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { Dimensions } from '../../../../utils/dimensions'; +import { computeChartTransformSelector } from './compute_chart_transform'; +import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getMouseDownPosition = (state: GlobalChartState) => state.interactions.pointer.down; +const getCurrentPointerPosition = (state: GlobalChartState) => { + return state.interactions.pointer.current.position; +}; + +export const getBrushAreaSelector = createCachedSelector( + [ + getMouseDownPosition, + getCurrentPointerPosition, + getChartRotationSelector, + computeChartDimensionsSelector, + computeChartTransformSelector, + ], + (mouseDownPosition, cursorPosition, chartRotation, { chartDimensions }, chartTransform): Dimensions | null => { + if (!mouseDownPosition) { + return null; + } + const brushStart = { + x: mouseDownPosition.position.x - chartDimensions.left, + y: mouseDownPosition.position.y - chartDimensions.top, + }; + if (chartRotation === 0 || chartRotation === 180) { + const area = { + left: brushStart.x, + top: 0, + width: cursorPosition.x - brushStart.x - chartDimensions.left, + height: chartDimensions.height, + }; + return area; + } else { + return { + left: chartDimensions.left + chartTransform.x, + top: brushStart.y - chartDimensions.top, + width: chartDimensions.width, + height: cursorPosition.y - brushStart.y - chartDimensions.top, + }; + } + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_computed_scales.ts b/src/chart_types/xy_chart/state/selectors/get_computed_scales.ts new file mode 100644 index 0000000000..e76c303706 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_computed_scales.ts @@ -0,0 +1,11 @@ +import createCachedSelector from 're-reselect'; +import { ComputedScales } from '../utils'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getComputedScalesSelector = createCachedSelector( + [computeSeriesGeometriesSelector], + (geometries): ComputedScales => { + return geometries.scales; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_cursor_band.ts b/src/chart_types/xy_chart/state/selectors/get_cursor_band.ts new file mode 100644 index 0000000000..58751e1077 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_cursor_band.ts @@ -0,0 +1,107 @@ +import { Dimensions } from '../../../../utils/dimensions'; +import createCachedSelector from 're-reselect'; +import { Point } from '../../../../utils/point'; +import { Scale } from '../../../../utils/scales/scales'; +import { isLineAreaOnlyChart } from '../utils'; +import { getCursorBandPosition } from '../../crosshair/crosshair_utils'; +import { SettingsSpec, CursorEvent } from '../../../../specs/settings'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { BasicSeriesSpec } from '../../utils/specs'; +import { countBarsInClusterSelector } from './count_bars_in_cluster'; +import { getSeriesSpecsSelector } from './get_specs'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { getOrientedProjectedPointerPositionSelector } from './get_oriented_projected_pointer_position'; +import { isTooltipSnapEnableSelector } from './is_tooltip_snap_enabled'; +import { getGeometriesIndexKeysSelector } from './get_geometries_index_keys'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { isValidExternalPointerEvent } from '../../../../utils/events'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getExternalPointerEventStateSelector = (state: GlobalChartState) => state.externalEvents.pointer; + +export const getCursorBandPositionSelector = createCachedSelector( + [ + getOrientedProjectedPointerPositionSelector, + getExternalPointerEventStateSelector, + computeChartDimensionsSelector, + getSettingsSpecSelector, + computeSeriesGeometriesSelector, + getSeriesSpecsSelector, + countBarsInClusterSelector, + isTooltipSnapEnableSelector, + getGeometriesIndexKeysSelector, + ], + ( + orientedProjectedPointerPosition, + externalPointerEvent, + chartDimensions, + settingsSpec, + seriesGeometries, + seriesSpec, + totalBarsInCluster, + isTooltipSnapEnabled, + geometriesIndexKeys, + ) => { + return getCursorBand( + orientedProjectedPointerPosition, + externalPointerEvent, + chartDimensions.chartDimensions, + settingsSpec, + seriesGeometries.scales.xScale, + seriesSpec, + totalBarsInCluster, + isTooltipSnapEnabled, + geometriesIndexKeys, + ); + }, +)(getChartIdSelector); + +function getCursorBand( + orientedProjectedPoinerPosition: Point, + externalPointerEvent: CursorEvent | null, + chartDimensions: Dimensions, + settingsSpec: SettingsSpec, + xScale: Scale | undefined, + seriesSpecs: BasicSeriesSpec[], + totalBarsInCluster: number, + isTooltipSnapEnabled: boolean, + geometriesIndexKeys: any[], +): Dimensions & { visible: boolean } | undefined { + // update che cursorBandPosition based on chart configuration + const isLineAreaOnly = isLineAreaOnlyChart(seriesSpecs); + if (!xScale) { + return; + } + let pointerPosition = orientedProjectedPoinerPosition; + let xValue; + if (externalPointerEvent && isValidExternalPointerEvent(externalPointerEvent, xScale)) { + const x = xScale.pureScale(externalPointerEvent.value); + + if (x == null || x > chartDimensions.width + chartDimensions.left) { + return; + } + pointerPosition = { x, y: 0 }; + xValue = { + value: externalPointerEvent.value, + withinBandwidth: true, + }; + } else { + xValue = xScale.invertWithStep(orientedProjectedPoinerPosition.x, geometriesIndexKeys); + if (!xValue) { + return; + } + } + return getCursorBandPosition( + settingsSpec.rotation, + chartDimensions, + pointerPosition, + { + value: xValue.value, + withinBandwidth: true, + }, + isTooltipSnapEnabled, + xScale, + isLineAreaOnly ? 1 : totalBarsInCluster, + ); +} diff --git a/src/chart_types/xy_chart/state/selectors/get_cursor_line.ts b/src/chart_types/xy_chart/state/selectors/get_cursor_line.ts new file mode 100644 index 0000000000..e727635af4 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_cursor_line.ts @@ -0,0 +1,13 @@ +import createCachedSelector from 're-reselect'; +import { getCursorLinePosition } from '../../crosshair/crosshair_utils'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getProjectedPointerPositionSelector } from './get_projected_pointer_position'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getCursorLinePositionSelector = createCachedSelector( + [computeChartDimensionsSelector, getSettingsSpecSelector, getProjectedPointerPositionSelector], + (chartDimensions, settingsSpec, projectedPointerPosition) => { + return getCursorLinePosition(settingsSpec.rotation, chartDimensions.chartDimensions, projectedPointerPosition); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_cursor_pointer.ts b/src/chart_types/xy_chart/state/selectors/get_cursor_pointer.ts new file mode 100644 index 0000000000..9c7848057c --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_cursor_pointer.ts @@ -0,0 +1,37 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getHighlightedGeomsSelector } from './get_tooltip_values_highlighted_geoms'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { isBrushAvailableSelector } from './is_brush_available'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getCurrentPointerPositionSelector = (state: GlobalChartState) => state.interactions.pointer.current.position; + +export const getPointerCursorSelector = createCachedSelector( + [ + getHighlightedGeomsSelector, + getSettingsSpecSelector, + getCurrentPointerPositionSelector, + computeChartDimensionsSelector, + isBrushAvailableSelector, + ], + (highlightedGeometries, settingsSpec, currentPointerPosition, { chartDimensions }, isBrushAvailable): string => { + const { x, y } = currentPointerPosition; + // get positions relative to chart + const xPos = x - chartDimensions.left; + const yPos = y - chartDimensions.top; + + // limit cursorPosition to chartDimensions + if (xPos < 0 || xPos >= chartDimensions.width) { + return 'default'; + } + if (yPos < 0 || yPos >= chartDimensions.height) { + return 'default'; + } + if (highlightedGeometries.length > 0 && (settingsSpec.onElementClick || settingsSpec.onElementOver)) { + return 'pointer'; + } + return isBrushAvailable ? 'crosshair' : 'default'; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_elements_at_cursor_pos.ts b/src/chart_types/xy_chart/state/selectors/get_elements_at_cursor_pos.ts new file mode 100644 index 0000000000..fb92a0175d --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_elements_at_cursor_pos.ts @@ -0,0 +1,56 @@ +import createCachedSelector from 're-reselect'; +import { Point } from '../../../../utils/point'; +import { getOrientedProjectedPointerPositionSelector } from './get_oriented_projected_pointer_position'; +import { ComputedScales } from '../utils'; +import { getComputedScalesSelector } from './get_computed_scales'; +import { getGeometriesIndexKeysSelector } from './get_geometries_index_keys'; +import { getGeometriesIndexSelector } from './get_geometries_index'; +import { IndexedGeometry } from '../../../../utils/geometry'; +import { CursorEvent } from '../../../../specs'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { Dimensions } from '../../../../utils/dimensions'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { isValidExternalPointerEvent } from '../../../../utils/events'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getExternalPointerEventStateSelector = (state: GlobalChartState) => state.externalEvents.pointer; + +export const getElementAtCursorPositionSelector = createCachedSelector( + [ + getOrientedProjectedPointerPositionSelector, + getComputedScalesSelector, + getGeometriesIndexKeysSelector, + getGeometriesIndexSelector, + getExternalPointerEventStateSelector, + computeChartDimensionsSelector, + ], + getElementAtCursorPosition, +)(getChartIdSelector); + +function getElementAtCursorPosition( + orientedProjectedPoinerPosition: Point, + scales: ComputedScales, + geometriesIndexKeys: any, + geometriesIndex: Map<any, IndexedGeometry[]>, + externalPointerEvent: CursorEvent | null, + { + chartDimensions, + }: { + chartDimensions: Dimensions; + }, +): IndexedGeometry[] { + if (externalPointerEvent && isValidExternalPointerEvent(externalPointerEvent, scales.xScale)) { + const x = scales.xScale.pureScale(externalPointerEvent.value); + + if (x == null || x > chartDimensions.width + chartDimensions.left) { + return []; + } + return geometriesIndex.get(externalPointerEvent.value) || []; + } + const xValue = scales.xScale.invertWithStep(orientedProjectedPoinerPosition.x, geometriesIndexKeys); + if (!xValue) { + return []; + } + // get the elements on at this cursor position + return geometriesIndex.get(xValue.value) || []; +} diff --git a/src/chart_types/xy_chart/state/selectors/get_geometries_index.ts b/src/chart_types/xy_chart/state/selectors/get_geometries_index.ts new file mode 100644 index 0000000000..05c77897ca --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_geometries_index.ts @@ -0,0 +1,11 @@ +import createCachedSelector from 're-reselect'; +import { IndexedGeometry } from '../../../../utils/geometry'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getGeometriesIndexSelector = createCachedSelector( + [computeSeriesGeometriesSelector], + (geometries): Map<any, IndexedGeometry[]> => { + return geometries.geometriesIndex; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_geometries_index_keys.ts b/src/chart_types/xy_chart/state/selectors/get_geometries_index_keys.ts new file mode 100644 index 0000000000..f18e8ddb20 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_geometries_index_keys.ts @@ -0,0 +1,11 @@ +import createCachedSelector from 're-reselect'; +import { compareByValueAsc } from '../../../../utils/commons'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getGeometriesIndexKeysSelector = createCachedSelector( + [computeSeriesGeometriesSelector], + (seriesGeometries): any[] => { + return [...seriesGeometries.geometriesIndex.keys()].sort(compareByValueAsc); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_highlighted_series.ts b/src/chart_types/xy_chart/state/selectors/get_highlighted_series.ts new file mode 100644 index 0000000000..ad2204ceb1 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_highlighted_series.ts @@ -0,0 +1,17 @@ +import createCachedSelector from 're-reselect'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { computeLegendSelector } from './compute_legend'; +import { LegendItem } from '../../../../chart_types/xy_chart/legend/legend'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getHighlightedLegendItemKey = (state: GlobalChartState) => state.interactions.highlightedLegendItemKey; + +export const getHighlightedSeriesSelector = createCachedSelector( + [getHighlightedLegendItemKey, computeLegendSelector], + (highlightedLegendItemKey, legendItems): LegendItem | undefined => { + if (!highlightedLegendItemKey) { + return undefined; + } + return legendItems.get(highlightedLegendItemKey); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_legend_tooltip_values.ts b/src/chart_types/xy_chart/state/selectors/get_legend_tooltip_values.ts new file mode 100644 index 0000000000..6c4e692ad4 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_legend_tooltip_values.ts @@ -0,0 +1,11 @@ +import createCachedSelector from 're-reselect'; +import { getSeriesTooltipValues, TooltipLegendValue } from '../../tooltip/tooltip'; +import { getTooltipValuesSelector } from './get_tooltip_values_highlighted_geoms'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getLegendTooltipValuesSelector = createCachedSelector( + [getTooltipValuesSelector], + (tooltipData): Map<string, TooltipLegendValue> => { + return getSeriesTooltipValues(tooltipData); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_oriented_projected_pointer_position.ts b/src/chart_types/xy_chart/state/selectors/get_oriented_projected_pointer_position.ts new file mode 100644 index 0000000000..6c9d2c938b --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_oriented_projected_pointer_position.ts @@ -0,0 +1,30 @@ +import { Dimensions } from '../../../../utils/dimensions'; +import createCachedSelector from 're-reselect'; +import { getProjectedPointerPositionSelector } from './get_projected_pointer_position'; +import { Point } from '../../../../utils/point'; +import { getOrientedXPosition, getOrientedYPosition } from '../../utils/interactions'; +import { SettingsSpec } from '../../../../specs/settings'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getOrientedProjectedPointerPositionSelector = createCachedSelector( + [getProjectedPointerPositionSelector, computeChartDimensionsSelector, getSettingsSpecSelector], + getOrientedProjectedPointerPosition, +)(getChartIdSelector); + +function getOrientedProjectedPointerPosition( + projectedPointerPosition: Point, + chartDimensions: { chartDimensions: Dimensions }, + settingsSpec: SettingsSpec, +): Point { + const xPos = projectedPointerPosition.x; + const yPos = projectedPointerPosition.y; + // get the oriented projected pointer position + const x = getOrientedXPosition(xPos, yPos, settingsSpec.rotation, chartDimensions.chartDimensions); + const y = getOrientedYPosition(xPos, yPos, settingsSpec.rotation, chartDimensions.chartDimensions); + return { + x, + y, + }; +} diff --git a/src/chart_types/xy_chart/state/selectors/get_projected_pointer_position.ts b/src/chart_types/xy_chart/state/selectors/get_projected_pointer_position.ts new file mode 100644 index 0000000000..4bc89b50e3 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_projected_pointer_position.ts @@ -0,0 +1,38 @@ +import createCachedSelector from 're-reselect'; +import { Dimensions } from '../../../../utils/dimensions'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { Point } from '../../../../utils/point'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getCurrentPointerPosition = (state: GlobalChartState) => state.interactions.pointer.current.position; + +export const getProjectedPointerPositionSelector = createCachedSelector( + [getCurrentPointerPosition, computeChartDimensionsSelector], + (currentPointerPosition, chartDimensions): Point => { + return getProjectedPointerPosition(currentPointerPosition, chartDimensions.chartDimensions); + }, +)(getChartIdSelector); + +/** + * Get the x and y pointer position relative to the chart projection area + * @param chartAreaPointerPosition the pointer position relative to the chart area + * @param chartAreaDimensions the chart dimensions + */ +function getProjectedPointerPosition(chartAreaPointerPosition: Point, chartAreaDimensions: Dimensions): Point { + const { x, y } = chartAreaPointerPosition; + // get positions relative to chart + let xPos = x - chartAreaDimensions.left; + let yPos = y - chartAreaDimensions.top; + // limit cursorPosition to the chart area + if (xPos < 0 || xPos >= chartAreaDimensions.width) { + xPos = -1; + } + if (yPos < 0 || yPos >= chartAreaDimensions.height) { + yPos = -1; + } + return { + x: xPos, + y: yPos, + }; +} diff --git a/src/chart_types/xy_chart/state/selectors/get_series_color_map.ts b/src/chart_types/xy_chart/state/selectors/get_series_color_map.ts new file mode 100644 index 0000000000..a109514788 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_series_color_map.ts @@ -0,0 +1,21 @@ +import createCachedSelector from 're-reselect'; +import { computeSeriesDomainsSelector } from './compute_series_domains'; +import { getSeriesSpecsSelector } from './get_specs'; +import { getUpdatedCustomSeriesColors } from '../utils'; +import { getSeriesColorMap } from '../../utils/series'; +import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getSeriesColorMapSelector = createCachedSelector( + [getSeriesSpecsSelector, computeSeriesDomainsSelector, getChartThemeSelector], + (seriesSpecs, seriesDomainsAndData, chartTheme): Map<string, string> => { + const updatedCustomSeriesColors = getUpdatedCustomSeriesColors(seriesSpecs); + + const seriesColorMap = getSeriesColorMap( + seriesDomainsAndData.seriesColors, + chartTheme.colors, + updatedCustomSeriesColors, + ); + return seriesColorMap; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_specs.test.ts b/src/chart_types/xy_chart/state/selectors/get_specs.test.ts new file mode 100644 index 0000000000..2f5092986a --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_specs.test.ts @@ -0,0 +1,28 @@ +import { getSeriesSpecsSelector } from './get_specs'; +import { getInitialState } from '../../../../state/chart_state'; +import { ChartTypes } from '../../..'; +import { SpecTypes } from '../../utils/specs'; + +describe('selector - get_specs', () => { + const state = getInitialState('chartId1'); + const barSpec1 = { + id: 'bars1', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + }; + const barSpec2 = { + id: 'bars2', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + }; + beforeEach(() => { + state.specs['bars1'] = barSpec1; + state.specs['bars2'] = barSpec2; + }); + it('shall return the same ref objects', () => { + const series = getSeriesSpecsSelector(state); + expect(series.length).toBe(2); + const seriesSecondCall = getSeriesSpecsSelector({ ...state, specsInitialized: true }); + expect(series).toBe(seriesSecondCall); + }); +}); diff --git a/src/chart_types/xy_chart/state/selectors/get_specs.ts b/src/chart_types/xy_chart/state/selectors/get_specs.ts new file mode 100644 index 0000000000..2d7eb779bc --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_specs.ts @@ -0,0 +1,24 @@ +import createCachedSelector from 're-reselect'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { getSpecsFromStore } from '../../../../state/utils'; +import { AxisSpec, BasicSeriesSpec, AnnotationSpec, SpecTypes } from '../../utils/specs'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; +import { ChartTypes } from '../../..'; + +const getSpecs = (state: GlobalChartState) => state.specs; + +export const getAxisSpecsSelector = createCachedSelector( + [getSpecs], + (specs): AxisSpec[] => { + return getSpecsFromStore<AxisSpec>(specs, ChartTypes.XYAxis, SpecTypes.Axis); + }, +)(getChartIdSelector); + +export const getSeriesSpecsSelector = createCachedSelector([getSpecs], (specs) => { + const seriesSpec = getSpecsFromStore<BasicSeriesSpec>(specs, ChartTypes.XYAxis, SpecTypes.Series); + return seriesSpec; +})(getChartIdSelector); + +export const getAnnotationSpecsSelector = createCachedSelector([getSpecs], (specs) => { + return getSpecsFromStore<AnnotationSpec>(specs, ChartTypes.XYAxis, SpecTypes.Annotation); +})(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_tooltip_header_formatter.ts b/src/chart_types/xy_chart/state/selectors/get_tooltip_header_formatter.ts new file mode 100644 index 0000000000..5f9f0cfff8 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_tooltip_header_formatter.ts @@ -0,0 +1,18 @@ +import createCachedSelector from 're-reselect'; +import { isTooltipProps, TooltipValueFormatter } from '../../utils/interactions'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { SettingsSpec } from '../../../../specs/settings'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getTooltipHeaderFormatterSelector = createCachedSelector( + [getSettingsSpecSelector], + getTooltipHeaderFormatter, +)(getChartIdSelector); + +function getTooltipHeaderFormatter(settings: SettingsSpec): TooltipValueFormatter | undefined { + const { tooltip } = settings; + if (tooltip && isTooltipProps(tooltip)) { + return tooltip.headerFormatter; + } + return undefined; +} diff --git a/src/chart_types/xy_chart/state/selectors/get_tooltip_position.ts b/src/chart_types/xy_chart/state/selectors/get_tooltip_position.ts new file mode 100644 index 0000000000..3e6364890d --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_tooltip_position.ts @@ -0,0 +1,30 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getTooltipPosition, TooltipPosition } from '../../crosshair/crosshair_utils'; +import { getProjectedPointerPositionSelector } from './get_projected_pointer_position'; +import { getComputedScalesSelector } from './get_computed_scales'; +import { getCursorBandPositionSelector } from './get_cursor_band'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getTooltipPositionSelector = createCachedSelector( + [ + computeChartDimensionsSelector, + getSettingsSpecSelector, + getCursorBandPositionSelector, + getProjectedPointerPositionSelector, + getComputedScalesSelector, + ], + ({ chartDimensions }, settings, cursorBandPosition, projectedPointerPosition, scales): TooltipPosition | null => { + if (!cursorBandPosition) { + return null; + } + return getTooltipPosition( + chartDimensions, + settings.rotation, + cursorBandPosition, + projectedPointerPosition, + scales.xScale.isSingleValue(), + ); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/get_tooltip_snap.ts b/src/chart_types/xy_chart/state/selectors/get_tooltip_snap.ts new file mode 100644 index 0000000000..341f27284c --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_tooltip_snap.ts @@ -0,0 +1,18 @@ +import createCachedSelector from 're-reselect'; +import { isTooltipProps } from '../../utils/interactions'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { SettingsSpec } from '../../../../specs/settings'; +import { DEFAULT_TOOLTIP_SNAP } from '../../../../specs/settings'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getTooltipSnapSelector = createCachedSelector([getSettingsSpecSelector], getTooltipSnap)( + getChartIdSelector, +); + +function getTooltipSnap(settings: SettingsSpec): boolean { + const { tooltip } = settings; + if (tooltip && isTooltipProps(tooltip)) { + return tooltip.snap || false; + } + return DEFAULT_TOOLTIP_SNAP; +} diff --git a/src/chart_types/xy_chart/state/selectors/get_tooltip_type.ts b/src/chart_types/xy_chart/state/selectors/get_tooltip_type.ts new file mode 100644 index 0000000000..4069cb0c83 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_tooltip_type.ts @@ -0,0 +1,23 @@ +import createCachedSelector from 're-reselect'; +import { TooltipType, isTooltipProps, isTooltipType } from '../../utils/interactions'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { SettingsSpec } from '../../../../specs/settings'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const getTooltipTypeSelector = createCachedSelector([getSettingsSpecSelector], getTooltipType)( + getChartIdSelector, +); + +function getTooltipType(settings: SettingsSpec): TooltipType { + const { tooltip } = settings; + if (tooltip === undefined || tooltip === null) { + return TooltipType.VerticalCursor; + } + if (isTooltipType(tooltip)) { + return tooltip; + } + if (isTooltipProps(tooltip)) { + return tooltip.type || TooltipType.VerticalCursor; + } + return TooltipType.VerticalCursor; +} diff --git a/src/chart_types/xy_chart/state/selectors/get_tooltip_values_highlighted_geoms.ts b/src/chart_types/xy_chart/state/selectors/get_tooltip_values_highlighted_geoms.ts new file mode 100644 index 0000000000..c0739b65c9 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_tooltip_values_highlighted_geoms.ts @@ -0,0 +1,150 @@ +import createCachedSelector from 're-reselect'; +import { TooltipValue, isFollowTooltipType, TooltipType, TooltipValueFormatter } from '../../utils/interactions'; +import { getProjectedPointerPositionSelector } from './get_projected_pointer_position'; +import { Point } from '../../../../utils/point'; +import { getOrientedProjectedPointerPositionSelector } from './get_oriented_projected_pointer_position'; +import { ComputedScales, getAxesSpecForSpecId, getSpecsById } from '../utils'; +import { getComputedScalesSelector } from './get_computed_scales'; +import { getElementAtCursorPositionSelector } from './get_elements_at_cursor_pos'; +import { IndexedGeometry } from '../../../../utils/geometry'; +import { getSeriesSpecsSelector, getAxisSpecsSelector } from './get_specs'; +import { BasicSeriesSpec, AxisSpec, Rotation } from '../../utils/specs'; +import { getTooltipTypeSelector } from './get_tooltip_type'; +import { formatTooltip } from '../../tooltip/tooltip'; +import { getTooltipHeaderFormatterSelector } from './get_tooltip_header_formatter'; +import { isPointOnGeometry } from '../../rendering/rendering'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { CursorEvent } from '../../../../specs'; +import { isValidExternalPointerEvent } from '../../../../utils/events'; +import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const EMPTY_VALUES = Object.freeze({ + tooltipValues: [], + highlightedGeometries: [], +}); + +export interface TooltipAndHighlightedGeoms { + tooltipValues: TooltipValue[]; + highlightedGeometries: IndexedGeometry[]; +} + +const getExternalPointerEventStateSelector = (state: GlobalChartState) => state.externalEvents.pointer; + +export const getTooltipValuesAndGeometriesSelector = createCachedSelector( + [ + getSeriesSpecsSelector, + getAxisSpecsSelector, + getProjectedPointerPositionSelector, + getOrientedProjectedPointerPositionSelector, + getChartRotationSelector, + getComputedScalesSelector, + getElementAtCursorPositionSelector, + getTooltipTypeSelector, + getExternalPointerEventStateSelector, + getTooltipHeaderFormatterSelector, + ], + getTooltipAndHighlightFromXValue, +)((state: GlobalChartState) => { + return state.chartId; +}); + +function getTooltipAndHighlightFromXValue( + seriesSpecs: BasicSeriesSpec[], + axesSpecs: AxisSpec[], + projectedPointerPosition: Point, + orientedProjectedPointerPosition: Point, + chartRotation: Rotation, + scales: ComputedScales, + xMatchingGeoms: IndexedGeometry[], + tooltipType: TooltipType, + externalPointerEvent: CursorEvent | null, + tooltipHeaderFormatter?: TooltipValueFormatter, +): TooltipAndHighlightedGeoms { + if (!scales.xScale || !scales.yScales) { + return EMPTY_VALUES; + } + let x = orientedProjectedPointerPosition.x; + let y = orientedProjectedPointerPosition.y; + if (externalPointerEvent && isValidExternalPointerEvent(externalPointerEvent, scales.xScale)) { + x = scales.xScale.pureScale(externalPointerEvent.value); + y = 0; + } else if (projectedPointerPosition.x === -1 || projectedPointerPosition.y === -1) { + return EMPTY_VALUES; + } + + if (xMatchingGeoms.length === 0) { + return EMPTY_VALUES; + } + + // build the tooltip value list + let xValueInfo: TooltipValue | null = null; + const highlightedGeometries: IndexedGeometry[] = []; + const tooltipValues = xMatchingGeoms + .filter(({ value: { y } }) => y !== null) + .reduce<TooltipValue[]>((acc, indexedGeometry) => { + const { + geometryId: { specId }, + } = indexedGeometry; + const spec = getSpecsById<BasicSeriesSpec>(seriesSpecs, specId); + + // safe guard check + if (!spec) { + return acc; + } + const { xAxis, yAxis } = getAxesSpecForSpecId(axesSpecs, spec.groupId); + + // yScales is ensured by the enclosing if + const yScale = scales.yScales.get(spec.groupId); + if (!yScale) { + return acc; + } + + // check if the pointer is on the geometry (avoid checking if using external pointer event) + let isHighlighted = false; + if (!externalPointerEvent && isPointOnGeometry(x, y, indexedGeometry)) { + isHighlighted = true; + highlightedGeometries.push(indexedGeometry); + } + + // if it's a follow tooltip, and no element is highlighted + // not add that element into the tooltip list + if (!isHighlighted && isFollowTooltipType(tooltipType)) { + return acc; + } + + // format the tooltip values + const yAxisFormatSpec = [0, 180].includes(chartRotation) ? yAxis : xAxis; + const formattedTooltip = formatTooltip(indexedGeometry, spec, false, isHighlighted, yAxisFormatSpec); + + // format only one time the x value + if (!xValueInfo) { + // if we have a tooltipHeaderFormatter, then don't pass in the xAxis as the user will define a formatter + const xAxisFormatSpec = [0, 180].includes(chartRotation) ? xAxis : yAxis; + const formatterAxis = tooltipHeaderFormatter ? undefined : xAxisFormatSpec; + xValueInfo = formatTooltip(indexedGeometry, spec, true, false, formatterAxis); + return [xValueInfo, ...acc, formattedTooltip]; + } + + return [...acc, formattedTooltip]; + }, []); + + return { + tooltipValues, + highlightedGeometries, + }; +} + +export const getTooltipValuesSelector = createCachedSelector( + [getTooltipValuesAndGeometriesSelector], + (values): TooltipValue[] => { + return values.tooltipValues; + }, +)(getChartIdSelector); + +export const getHighlightedGeomsSelector = createCachedSelector( + [getTooltipValuesAndGeometriesSelector], + (values): IndexedGeometry[] => { + return values.highlightedGeometries; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/is_annotation_tooltip_visible.ts b/src/chart_types/xy_chart/state/selectors/is_annotation_tooltip_visible.ts new file mode 100644 index 0000000000..27242608a3 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_annotation_tooltip_visible.ts @@ -0,0 +1,10 @@ +import { getAnnotationTooltipStateSelector } from './get_annotation_tooltip_state'; +import createCachedSelector from 're-reselect'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const isAnnotationTooltipVisibleSelector = createCachedSelector( + [getAnnotationTooltipStateSelector], + (annotationTooltipState): boolean => { + return annotationTooltipState !== null && annotationTooltipState.isVisible; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/is_brush_available.ts b/src/chart_types/xy_chart/state/selectors/is_brush_available.ts new file mode 100644 index 0000000000..4c36e69418 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_brush_available.ts @@ -0,0 +1,19 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getComputedScalesSelector } from './get_computed_scales'; +import { ScaleType } from '../../../../utils/scales/scales'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +/** + * The brush is available only for Ordinal xScales charts and + * if we have configured an onBrushEnd listener + */ +export const isBrushAvailableSelector = createCachedSelector( + [getSettingsSpecSelector, getComputedScalesSelector], + (settingsSpec, scales): boolean => { + if (!scales.xScale) { + return false; + } + return scales.xScale.type !== ScaleType.Ordinal && Boolean(settingsSpec.onBrushEnd); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/is_brushing.ts b/src/chart_types/xy_chart/state/selectors/is_brushing.ts new file mode 100644 index 0000000000..ed7521f05b --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_brushing.ts @@ -0,0 +1,17 @@ +import createCachedSelector from 're-reselect'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { isBrushAvailableSelector } from './is_brush_available'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getPointerSelector = (state: GlobalChartState) => state.interactions.pointer; + +export const isBrushingSelector = createCachedSelector( + [isBrushAvailableSelector, getPointerSelector], + (isBrushAvailable, pointer): boolean => { + if (!isBrushAvailable) { + return false; + } + + return pointer.dragging; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/is_chart_animatable.ts b/src/chart_types/xy_chart/state/selectors/is_chart_animatable.ts new file mode 100644 index 0000000000..eaf5cf9656 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_chart_animatable.ts @@ -0,0 +1,16 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; +// import { isChartAnimatable } from '../utils'; + +export const isChartAnimatableSelector = createCachedSelector( + [computeSeriesGeometriesSelector, getSettingsSpecSelector], + () => { + // const { geometriesCounts } = seriesGeometries; + // temporary disabled until + // https://github.com/elastic/elastic-charts/issues/89 and https://github.com/elastic/elastic-charts/issues/41 + // return isChartAnimatable(geometriesCounts, settingsSpec.animateData); + return false; + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/is_chart_empty.ts b/src/chart_types/xy_chart/state/selectors/is_chart_empty.ts new file mode 100644 index 0000000000..f77ad9a15f --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_chart_empty.ts @@ -0,0 +1,10 @@ +import createCachedSelector from 're-reselect'; +import { isAllSeriesDeselected } from '../utils'; +import { computeLegendSelector } from './compute_legend'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; +export const isChartEmptySelector = createCachedSelector( + [computeLegendSelector], + (legendItems): boolean => { + return isAllSeriesDeselected(legendItems); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/is_histogram_mode_enabled.ts b/src/chart_types/xy_chart/state/selectors/is_histogram_mode_enabled.ts new file mode 100644 index 0000000000..db92e8992e --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_histogram_mode_enabled.ts @@ -0,0 +1,11 @@ +import createCachedSelector from 're-reselect'; +import { getSeriesSpecsSelector } from './get_specs'; +import { isHistogramModeEnabled } from '../utils'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const isHistogramModeEnabledSelector = createCachedSelector( + [getSeriesSpecsSelector], + (seriesSpecs): boolean => { + return isHistogramModeEnabled(seriesSpecs); + }, +)(getChartIdSelector); diff --git a/src/chart_types/xy_chart/state/selectors/is_tooltip_snap_enabled.ts b/src/chart_types/xy_chart/state/selectors/is_tooltip_snap_enabled.ts new file mode 100644 index 0000000000..b1ef7e2ea2 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_tooltip_snap_enabled.ts @@ -0,0 +1,16 @@ +import createCachedSelector from 're-reselect'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { Scale } from '../../../../utils/scales/scales'; +import { getTooltipSnapSelector } from './get_tooltip_snap'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const isTooltipSnapEnableSelector = createCachedSelector( + [computeSeriesGeometriesSelector, getTooltipSnapSelector], + (seriesGeometries, snap) => { + return isTooltipSnapEnabled(seriesGeometries.scales.xScale, snap); + }, +)(getChartIdSelector); + +function isTooltipSnapEnabled(xScale: Scale, snap: boolean) { + return (xScale && xScale.bandwidth > 0) || snap; +} diff --git a/src/chart_types/xy_chart/state/selectors/is_tooltip_visible.ts b/src/chart_types/xy_chart/state/selectors/is_tooltip_visible.ts new file mode 100644 index 0000000000..931919ac5a --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/is_tooltip_visible.ts @@ -0,0 +1,42 @@ +import createCachedSelector from 're-reselect'; +import { TooltipType, TooltipValue, isTooltipType, isTooltipProps } from '../../utils/interactions'; +import { Point } from '../../../../utils/point'; +import { GlobalChartState, PointerStates } from '../../../../state/chart_state'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getProjectedPointerPositionSelector } from './get_projected_pointer_position'; +import { getTooltipValuesSelector } from './get_tooltip_values_highlighted_geoms'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getTooltipType = (state: GlobalChartState): TooltipType | undefined => { + const tooltip = getSettingsSpecSelector(state).tooltip; + if (!tooltip) { + return undefined; + } + if (isTooltipType(tooltip)) { + return tooltip; + } + if (isTooltipProps(tooltip)) { + return tooltip.type; + } +}; +const getPointerSelector = (state: GlobalChartState) => state.interactions.pointer; + +export const isTooltipVisibleSelector = createCachedSelector( + [getTooltipType, getPointerSelector, getProjectedPointerPositionSelector, getTooltipValuesSelector], + isTooltipVisible, +)(getChartIdSelector); + +function isTooltipVisible( + tooltipType: TooltipType | undefined, + pointer: PointerStates, + projectedPointerPosition: Point, + tooltipValues: TooltipValue[], +) { + return ( + tooltipType !== TooltipType.None && + pointer.down === null && + projectedPointerPosition.x > -1 && + projectedPointerPosition.y > -1 && + tooltipValues.length > 0 + ); +} diff --git a/src/chart_types/xy_chart/state/selectors/merge_y_custom_domains.ts b/src/chart_types/xy_chart/state/selectors/merge_y_custom_domains.ts new file mode 100644 index 0000000000..40ff022f8e --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/merge_y_custom_domains.ts @@ -0,0 +1,70 @@ +import createCachedSelector from 're-reselect'; +import { getAxisSpecsSelector } from './get_specs'; +import { isYDomain, isCompleteBound, isLowerBound, isUpperBound, isBounded } from '../../utils/axis_utils'; +import { AxisSpec, DomainRange, Rotation } from '../../utils/specs'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +export const mergeYCustomDomainsByGroupIdSelector = createCachedSelector( + [getAxisSpecsSelector, getSettingsSpecSelector], + (axisSpecs, settingsSpec): Map<string, DomainRange> => { + return mergeYCustomDomainsByGroupId(axisSpecs, settingsSpec ? settingsSpec.rotation : 0); + }, +)(getChartIdSelector); + +export function mergeYCustomDomainsByGroupId(axesSpecs: AxisSpec[], chartRotation: Rotation): Map<string, DomainRange> { + const domainsByGroupId = new Map<string, DomainRange>(); + + axesSpecs.forEach((spec: AxisSpec) => { + const { id, groupId, domain } = spec; + + if (!domain) { + return; + } + + const isAxisYDomain = isYDomain(spec.position, chartRotation); + + if (!isAxisYDomain) { + const errorMessage = `[Axis ${id}]: custom domain for xDomain should be defined in Settings`; + throw new Error(errorMessage); + } + + if (isCompleteBound(domain) && domain.min > domain.max) { + const errorMessage = `[Axis ${id}]: custom domain is invalid, min is greater than max`; + throw new Error(errorMessage); + } + + const prevGroupDomain = domainsByGroupId.get(groupId); + + if (prevGroupDomain) { + const prevDomain = prevGroupDomain as DomainRange; + + const prevMin = isLowerBound(prevDomain) ? prevDomain.min : undefined; + const prevMax = isUpperBound(prevDomain) ? prevDomain.max : undefined; + + let max = prevMax; + let min = prevMin; + + if (isCompleteBound(domain)) { + min = prevMin != null ? Math.min(domain.min, prevMin) : domain.min; + max = prevMax != null ? Math.max(domain.max, prevMax) : domain.max; + } else if (isLowerBound(domain)) { + min = prevMin != null ? Math.min(domain.min, prevMin) : domain.min; + } else if (isUpperBound(domain)) { + max = prevMax != null ? Math.max(domain.max, prevMax) : domain.max; + } + + const mergedDomain = { + min, + max, + }; + + if (isBounded(mergedDomain)) { + domainsByGroupId.set(groupId, mergedDomain); + } + } else { + domainsByGroupId.set(groupId, domain); + } + }); + return domainsByGroupId; +} diff --git a/src/chart_types/xy_chart/state/selectors/on_brush_end_caller.ts b/src/chart_types/xy_chart/state/selectors/on_brush_end_caller.ts new file mode 100644 index 0000000000..b2bb04e192 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/on_brush_end_caller.ts @@ -0,0 +1,93 @@ +import createCachedSelector from 're-reselect'; +import { Selector } from 'reselect'; +import { GlobalChartState, DragState } from '../../../../state/chart_state'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { SettingsSpec } from '../../../../specs'; +import { ChartTypes } from '../../../index'; +import { getComputedScalesSelector } from './get_computed_scales'; +import { computeChartDimensionsSelector } from './compute_chart_dimensions'; +import { isHistogramModeEnabledSelector } from './is_histogram_mode_enabled'; +import { isBrushAvailableSelector } from './is_brush_available'; + +const getLastDragSelector = (state: GlobalChartState) => state.interactions.pointer.lastDrag; + +interface Props { + settings: SettingsSpec | undefined; + lastDrag: DragState | null; +} + +function hasDragged(prevProps: Props | null, nextProps: Props | null) { + if (nextProps === null) { + return false; + } + if (!nextProps.settings || !nextProps.settings.onBrushEnd) { + return false; + } + const prevLastDrag = prevProps !== null ? prevProps.lastDrag : null; + const nextLastDrag = nextProps !== null ? nextProps.lastDrag : null; + + if (prevLastDrag === null && nextLastDrag !== null) { + return true; + } + if (prevLastDrag !== null && nextLastDrag !== null && prevLastDrag.end.time !== nextLastDrag.end.time) { + return true; + } + return false; +} + +/** + * Will call the onBrushEnd listener every time the following preconditions are met: + * - the onBrushEnd listener is available + * - we dragged the mouse pointer + */ +export function createOnBrushEndCaller(): (state: GlobalChartState) => void { + let prevProps: Props | null = null; + let selector: Selector<GlobalChartState, void> | null = null; + return (state: GlobalChartState) => { + if (selector === null && state.chartType === ChartTypes.XYAxis) { + if (!isBrushAvailableSelector(state)) { + selector = null; + prevProps = null; + return; + } + selector = createCachedSelector( + [ + getLastDragSelector, + getSettingsSpecSelector, + getComputedScalesSelector, + computeChartDimensionsSelector, + isHistogramModeEnabledSelector, + ], + (lastDrag, settings, computedScales, { chartDimensions }, histogramMode): void => { + const nextProps = { + lastDrag, + settings, + }; + + if (lastDrag !== null && hasDragged(prevProps, nextProps)) { + if (settings && settings.onBrushEnd) { + const minValue = Math.min(lastDrag.start.position.x, lastDrag.end.position.x); + const maxValue = Math.max(lastDrag.start.position.x, lastDrag.end.position.x); + if (maxValue === minValue) { + // if 0 size brush, avoid computing the value + return; + } + + const { xScale } = computedScales; + const offset = histogramMode ? 0 : -(xScale.bandwidth + xScale.bandwidthPadding) / 2; + const min = xScale.invert(minValue - chartDimensions.left + offset); + const max = xScale.invert(maxValue - chartDimensions.left + offset); + settings.onBrushEnd(min, max); + } + } + prevProps = nextProps; + }, + )({ + keySelector: (state: GlobalChartState) => state.chartId, + }); + } + if (selector) { + selector(state); + } + }; +} diff --git a/src/chart_types/xy_chart/state/selectors/on_element_click_caller.ts b/src/chart_types/xy_chart/state/selectors/on_element_click_caller.ts new file mode 100644 index 0000000000..fd6d9fe9b1 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/on_element_click_caller.ts @@ -0,0 +1,72 @@ +import createCachedSelector from 're-reselect'; +import { Selector } from 'reselect'; +import { GlobalChartState, PointerState } from '../../../../state/chart_state'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { getHighlightedGeomsSelector } from './get_tooltip_values_highlighted_geoms'; +import { SettingsSpec } from '../../../../specs'; +import { IndexedGeometry } from '../../../../utils/geometry'; +import { ChartTypes } from '../../../index'; + +const getLastClickSelector = (state: GlobalChartState) => state.interactions.pointer.lastClick; + +interface Props { + settings: SettingsSpec | undefined; + lastClick: PointerState | null; + indexedGeometries: IndexedGeometry[]; +} + +function isClicking(prevProps: Props | null, nextProps: Props | null) { + if (nextProps === null) { + return false; + } + if (!nextProps.settings || !nextProps.settings.onElementClick || nextProps.indexedGeometries.length === 0) { + return false; + } + const prevLastClick = prevProps !== null ? prevProps.lastClick : null; + const nextLastClick = nextProps !== null ? nextProps.lastClick : null; + + if (prevLastClick === null && nextLastClick !== null) { + return true; + } + if (prevLastClick !== null && nextLastClick !== null && prevLastClick.time !== nextLastClick.time) { + return true; + } + return false; +} + +/** + * Will call the onElementClick listener every time the following preconditions are met: + * - the onElementClick listener is available + * - we have at least one highlighted geometry + * - the pointer state goes from down state to up state + */ +export function createOnElementClickCaller(): (state: GlobalChartState) => void { + let prevProps: Props | null = null; + let selector: Selector<GlobalChartState, void> | null = null; + return (state: GlobalChartState) => { + if (selector === null && state.chartType === ChartTypes.XYAxis) { + selector = createCachedSelector( + [getLastClickSelector, getSettingsSpecSelector, getHighlightedGeomsSelector], + (lastClick: PointerState | null, settings: SettingsSpec, indexedGeometries: IndexedGeometry[]): void => { + const nextProps = { + lastClick, + settings, + indexedGeometries, + }; + + if (isClicking(prevProps, nextProps)) { + if (settings && settings.onElementClick) { + settings.onElementClick(indexedGeometries.map(({ value }) => value)); + } + } + prevProps = nextProps; + }, + )({ + keySelector: (state: GlobalChartState) => state.chartId, + }); + } + if (selector) { + selector(state); + } + }; +} diff --git a/src/chart_types/xy_chart/state/selectors/on_element_out_caller.ts b/src/chart_types/xy_chart/state/selectors/on_element_out_caller.ts new file mode 100644 index 0000000000..cf4042073b --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/on_element_out_caller.ts @@ -0,0 +1,63 @@ +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import createCachedSelector from 're-reselect'; +import { + getTooltipValuesAndGeometriesSelector, + TooltipAndHighlightedGeoms, +} from './get_tooltip_values_highlighted_geoms'; +import { SettingsSpec } from '../../../../specs'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { IndexedGeometry } from '../../../../utils/geometry'; +import { Selector } from 'react-redux'; +import { ChartTypes } from '../../../index'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +interface Props { + settings: SettingsSpec | undefined; + highlightedGeometries: IndexedGeometry[]; +} + +function isOutElement(prevProps: Props | null, nextProps: Props | null) { + if (!nextProps || !prevProps) { + return false; + } + if (!nextProps.settings || !nextProps.settings.onElementOut) { + return false; + } + if (prevProps.highlightedGeometries.length > 0 && nextProps.highlightedGeometries.length === 0) { + return true; + } + return false; +} + +/** + * Will call the onElementOut listener every time the following preconditions are met: + * - the onElementOut listener is available + * - the highlighted geometries list goes from a list of at least one object to an empty one + */ +export function createOnElementOutCaller(): (state: GlobalChartState) => void { + let prevProps: Props | null = null; + let selector: Selector<GlobalChartState, void> | null = null; + return (state: GlobalChartState) => { + if (selector === null && state.chartType === ChartTypes.XYAxis) { + selector = createCachedSelector( + [getTooltipValuesAndGeometriesSelector, getSettingsSpecSelector], + ({ highlightedGeometries }: TooltipAndHighlightedGeoms, settings: SettingsSpec): void => { + const nextProps = { + settings, + highlightedGeometries, + }; + + if (isOutElement(prevProps, nextProps) && settings.onElementOut) { + settings.onElementOut(); + } + prevProps = nextProps; + }, + )({ + keySelector: getChartIdSelector, + }); + } + if (selector) { + selector(state); + } + }; +} diff --git a/src/chart_types/xy_chart/state/selectors/on_element_over_caller.ts b/src/chart_types/xy_chart/state/selectors/on_element_over_caller.ts new file mode 100644 index 0000000000..ee6dea8ba0 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/on_element_over_caller.ts @@ -0,0 +1,72 @@ +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import createCachedSelector from 're-reselect'; +import { + getTooltipValuesAndGeometriesSelector, + TooltipAndHighlightedGeoms, +} from './get_tooltip_values_highlighted_geoms'; +import { SettingsSpec } from '../../../../specs'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { IndexedGeometry } from '../../../../utils/geometry'; +import { Selector } from 'react-redux'; +import { ChartTypes } from '../../../index'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +interface Props { + settings: SettingsSpec | undefined; + highlightedGeometries: IndexedGeometry[]; +} + +function isOverElement(prevProps: Props | null, nextProps: Props | null) { + if (!nextProps) { + return false; + } + if (!nextProps.settings || !nextProps.settings.onElementOver) { + return false; + } + const { highlightedGeometries: nextGeomValues } = nextProps; + const prevGeomValues = prevProps ? prevProps.highlightedGeometries : []; + if (nextGeomValues.length > 0) { + if (nextGeomValues.length !== prevGeomValues.length) { + return true; + } + return !nextGeomValues.every(({ value: next }, index) => { + const prev = prevGeomValues[index].value; + return prev && prev.x === next.x && prev.y === next.y && prev.accessor === next.accessor; + }); + } + + return false; +} + +/** + * Will call the onElementOver listener every time the following preconditions are met: + * - the onElementOver listener is available + * - we have a new set of highlighted geometries on our state + */ +export function createOnElementOverCaller(): (state: GlobalChartState) => void { + let prevProps: Props | null = null; + let selector: Selector<GlobalChartState, void> | null = null; + return (state: GlobalChartState) => { + if (selector === null && state.chartType === ChartTypes.XYAxis) { + selector = createCachedSelector( + [getTooltipValuesAndGeometriesSelector, getSettingsSpecSelector], + ({ highlightedGeometries }: TooltipAndHighlightedGeoms, settings: SettingsSpec): void => { + const nextProps = { + settings, + highlightedGeometries, + }; + + if (isOverElement(prevProps, nextProps) && settings.onElementOver) { + settings.onElementOver(highlightedGeometries.map(({ value }) => value)); + } + prevProps = nextProps; + }, + )({ + keySelector: getChartIdSelector, + }); + } + if (selector) { + selector(state); + } + }; +} diff --git a/src/chart_types/xy_chart/state/selectors/on_pointer_move_caller.ts b/src/chart_types/xy_chart/state/selectors/on_pointer_move_caller.ts new file mode 100644 index 0000000000..616cfe2154 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/on_pointer_move_caller.ts @@ -0,0 +1,118 @@ +import createCachedSelector from 're-reselect'; +import { Selector } from 'reselect'; +import { GlobalChartState } from '../../../../state/chart_state'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { SettingsSpec, CursorEvent } from '../../../../specs'; +import { ChartTypes } from '../../../index'; +import { Scale } from '../../../../utils/scales/scales'; +import { Point } from '../../../../utils/point'; +import { getOrientedProjectedPointerPositionSelector } from './get_oriented_projected_pointer_position'; +import { computeSeriesGeometriesSelector } from './compute_series_geometries'; +import { getGeometriesIndexKeysSelector } from './get_geometries_index_keys'; +import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; + +const getPointerEventSelector = createCachedSelector( + [ + getChartIdSelector, + getOrientedProjectedPointerPositionSelector, + computeSeriesGeometriesSelector, + getGeometriesIndexKeysSelector, + ], + (chartId, orientedProjectedPointerPosition, seriesGeometries, geometriesIndexKeys) => { + return getCursorBand( + chartId, + orientedProjectedPointerPosition, + seriesGeometries.scales.xScale, + geometriesIndexKeys, + ); + }, +)(getChartIdSelector); + +function getCursorBand( + chartId: string, + orientedProjectedPoinerPosition: Point, + xScale: Scale | undefined, + geometriesIndexKeys: any[], +): CursorEvent | null { + // update che cursorBandPosition based on chart configuration + if (!xScale) { + return null; + } + const { x, y } = orientedProjectedPoinerPosition; + if (x === -1 || y === -1) { + return null; + } + const xValue = xScale.invertWithStep(x, geometriesIndexKeys); + if (!xValue) { + return null; + } + return { + chartId, + scale: xScale.type, + unit: xScale.unit, + value: xValue.value, + }; +} +interface Props { + settings: SettingsSpec; + pointerEvent: CursorEvent | null; +} + +function hasPointerEventChanged(prevProps: Props, nextProps: Props | null) { + // new pointer event, pointer over + if (prevProps.pointerEvent === null && nextProps && nextProps.pointerEvent) { + return true; + } + + // new pointer event, pointer out + if (prevProps.pointerEvent !== null && nextProps && nextProps.pointerEvent === null) { + return true; + } + + const prevPointerEvent = prevProps.pointerEvent; + const nextPointerEvent = nextProps && nextProps.pointerEvent; + + // if something changed in the pointerEvent than recompute + if ( + prevPointerEvent !== null && + nextPointerEvent !== null && + (prevPointerEvent.value !== nextPointerEvent.value || + prevPointerEvent.scale !== nextPointerEvent.scale || + prevPointerEvent.unit !== nextPointerEvent.unit) + ) { + return true; + } + return false; +} + +export function createOnPointerMoveCaller(): (state: GlobalChartState) => void { + let prevProps: Props | null = null; + let selector: Selector<GlobalChartState, void> | null = null; + return (state: GlobalChartState) => { + if (selector === null && state.chartType === ChartTypes.XYAxis) { + selector = createCachedSelector( + [getSettingsSpecSelector, getPointerEventSelector], + (settings: SettingsSpec, pointerEvent: CursorEvent | null): void => { + const nextProps = { + settings, + pointerEvent, + }; + + if (prevProps === null && nextProps.pointerEvent === null) { + prevProps = nextProps; + return; + } + if (settings && settings.onCursorUpdate && hasPointerEventChanged(prevProps!, nextProps)) { + settings.onCursorUpdate(pointerEvent ? pointerEvent : undefined); + } + prevProps = nextProps; + }, + )({ + keySelector: getChartIdSelector, + }); + } + if (selector) { + selector(state); + } + }; +} diff --git a/src/chart_types/xy_chart/store/utils.test.ts b/src/chart_types/xy_chart/state/utils.test.ts similarity index 79% rename from src/chart_types/xy_chart/store/utils.test.ts rename to src/chart_types/xy_chart/state/utils.test.ts index 9cfb7d8e62..4d62ede289 100644 --- a/src/chart_types/xy_chart/store/utils.test.ts +++ b/src/chart_types/xy_chart/state/utils.test.ts @@ -1,5 +1,3 @@ -import { mergeYCustomDomainsByGroupId } from '../utils/axis_utils'; -import { IndexedGeometry, AccessorType } from '../rendering/rendering'; import { DataSeriesColorsValues, findDataSeriesByColorValues, getSeriesColorMap } from '../utils/series'; import { AreaSeriesSpec, @@ -8,10 +6,12 @@ import { BasicSeriesSpec, HistogramModeAlignments, LineSeriesSpec, + SpecTypes, + SeriesTypes, } from '../utils/specs'; import { BARCHART_1Y0G, BARCHART_1Y1G } from '../../../utils/data_samples/test_dataset'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; -import { AxisId, getGroupId, getSpecId, SpecId } from '../../../utils/ids'; +import { SpecId } from '../../../utils/ids'; import { ScaleContinuous } from '../../../utils/scales/scale_continuous'; import { ScaleType } from '../../../utils/scales/scales'; import { @@ -27,16 +27,21 @@ import { isVerticalRotation, mergeGeometriesIndexes, setBarSeriesAccessors, - updateDeselectedDataSeries, -} from '../store/utils'; +} from './utils'; +import { IndexedGeometry, AccessorType } from '../../../utils/geometry'; +import { mergeYCustomDomainsByGroupId } from './selectors/merge_y_custom_domains'; +import { updateDeselectedDataSeries } from './utils'; import { LegendItem } from '../legend/legend'; +import { ChartTypes } from '../..'; describe('Chart State utils', () => { it('should compute and format specifications for non stacked chart', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -45,9 +50,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y0G, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -55,10 +62,7 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y0G, }; - const specs = new Map<SpecId, BasicSeriesSpec>(); - specs.set(spec1.id, spec1); - specs.set(spec2.id, spec2); - const domains = computeSeriesDomains(specs, new Map(), undefined); + const domains = computeSeriesDomains([spec1, spec2], new Map(), undefined); expect(domains.xDomain).toEqual({ domain: [0, 3], isBandScale: false, @@ -87,9 +91,11 @@ describe('Chart State utils', () => { }); it('should compute and format specifications for stacked chart', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -99,9 +105,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -111,10 +119,7 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const specs = new Map<SpecId, BasicSeriesSpec>(); - specs.set(spec1.id, spec1); - specs.set(spec2.id, spec2); - const domains = computeSeriesDomains(specs, new Map(), undefined); + const domains = computeSeriesDomains([spec1, spec2], new Map(), undefined); expect(domains.xDomain).toEqual({ domain: [0, 3], isBandScale: false, @@ -143,17 +148,17 @@ describe('Chart State utils', () => { }); it('should check if a DataSeriesColorValues item exists in a list of DataSeriesColorValues', () => { const dataSeriesValuesA: DataSeriesColorsValues = { - specId: getSpecId('a'), + specId: 'a', colorValues: ['a', 'b', 'c'], }; const dataSeriesValuesB: DataSeriesColorsValues = { - specId: getSpecId('b'), + specId: 'b', colorValues: ['a', 'b', 'c'], }; const dataSeriesValuesC: DataSeriesColorsValues = { - specId: getSpecId('a'), + specId: 'a', colorValues: ['a', 'b', 'd'], }; @@ -165,17 +170,17 @@ describe('Chart State utils', () => { }); it('should update a list of DataSeriesColorsValues given a selected DataSeriesColorValues item', () => { const dataSeriesValuesA: DataSeriesColorsValues = { - specId: getSpecId('a'), + specId: 'a', colorValues: ['a', 'b', 'c'], }; const dataSeriesValuesB: DataSeriesColorsValues = { - specId: getSpecId('b'), + specId: 'b', colorValues: ['a', 'b', 'c'], }; const dataSeriesValuesC: DataSeriesColorsValues = { - specId: getSpecId('a'), + specId: 'a', colorValues: ['a', 'b', 'd'], }; @@ -189,9 +194,11 @@ describe('Chart State utils', () => { }); it('should get an updated customSeriesColor based on specs', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'spec1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -200,10 +207,7 @@ describe('Chart State utils', () => { data: BARCHART_1Y0G, }; - const specs = new Map<SpecId, BasicSeriesSpec>(); - specs.set(spec1.id, spec1); - - const emptyCustomSeriesColors = getUpdatedCustomSeriesColors(specs); + const emptyCustomSeriesColors = getUpdatedCustomSeriesColors([spec1]); expect(emptyCustomSeriesColors).toEqual(new Map()); const dataSeriesColorValues = { @@ -213,7 +217,7 @@ describe('Chart State utils', () => { spec1.customSeriesColors = new Map(); spec1.customSeriesColors.set(dataSeriesColorValues, 'custom_color'); - const updatedCustomSeriesColors = getUpdatedCustomSeriesColors(specs); + const updatedCustomSeriesColors = getUpdatedCustomSeriesColors([spec1]); const expectedCustomSeriesColors = new Map(); expectedCustomSeriesColors.set('specId:{spec1},colors:{bar}', 'custom_color'); @@ -239,9 +243,11 @@ describe('Chart State utils', () => { }); test('is an area or line only map', () => { const area: AreaSeriesSpec = { - id: getSpecId('area'), - groupId: getGroupId('group1'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area', + groupId: 'group1', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -251,9 +257,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line: LineSeriesSpec = { - id: getSpecId('line'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -264,9 +272,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const bar: BarSeriesSpec = { - id: getSpecId('bar'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bar', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -276,16 +286,16 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - let seriesMap = new Map<SpecId, BasicSeriesSpec>([[area.id, area], [line.id, line], [bar.id, bar]]); - expect(isLineAreaOnlyChart(seriesMap)).toBe(false); - seriesMap = new Map<SpecId, BasicSeriesSpec>([[area.id, area], [line.id, line]]); - expect(isLineAreaOnlyChart(seriesMap)).toBe(true); - seriesMap = new Map<SpecId, BasicSeriesSpec>([[area.id, area]]); - expect(isLineAreaOnlyChart(seriesMap)).toBe(true); - seriesMap = new Map<SpecId, BasicSeriesSpec>([[line.id, line]]); - expect(isLineAreaOnlyChart(seriesMap)).toBe(true); - seriesMap = new Map<SpecId, BasicSeriesSpec>([[bar.id, bar], [getSpecId('bar2'), bar]]); - expect(isLineAreaOnlyChart(seriesMap)).toBe(false); + let series = [area, line, bar]; + expect(isLineAreaOnlyChart(series)).toBe(false); + series = [area, line]; + expect(isLineAreaOnlyChart(series)).toBe(true); + series = [area]; + expect(isLineAreaOnlyChart(series)).toBe(true); + series = [line]; + expect(isLineAreaOnlyChart(series)).toBe(true); + series = [bar, { ...bar, id: 'bar2' }]; + expect(isLineAreaOnlyChart(series)).toBe(false); }); test('can enable the chart animation if we have a valid number of elements', () => { const geometriesCounts = { @@ -311,9 +321,11 @@ describe('Chart State utils', () => { describe('Geometries counts', () => { test('can compute stacked geometries counts', () => { const area: AreaSeriesSpec = { - id: getSpecId('area'), - groupId: getGroupId('group1'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area', + groupId: 'group1', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -323,9 +335,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line: LineSeriesSpec = { - id: getSpecId('line'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -336,9 +350,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const bar: BarSeriesSpec = { - id: getSpecId('bar'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bar', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -348,8 +364,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[area.id, area], [line.id, line], [bar.id, bar]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [area, line, bar]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -380,9 +396,11 @@ describe('Chart State utils', () => { }); test('can compute non stacked geometries indexes', () => { const line1: LineSeriesSpec = { - id: getSpecId('line1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Ordinal, xAccessor: 'x', @@ -391,9 +409,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y0G, }; const line2: LineSeriesSpec = { - id: getSpecId('line2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Ordinal, xAccessor: 'x', @@ -401,8 +421,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y0G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[line1.id, line1], [line2.id, line2]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [line1, line2]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -433,9 +453,11 @@ describe('Chart State utils', () => { }); test('can compute stacked geometries indexes', () => { const line1: LineSeriesSpec = { - id: getSpecId('line1'), - groupId: getGroupId('group1'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line1', + groupId: 'group1', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Ordinal, xAccessor: 'x', @@ -445,9 +467,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y0G, }; const line2: LineSeriesSpec = { - id: getSpecId('line2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Ordinal, xAccessor: 'x', @@ -456,8 +480,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y0G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[line1.id, line1], [line2.id, line2]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [line1, line2]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -488,9 +512,11 @@ describe('Chart State utils', () => { }); test('can compute non stacked geometries counts', () => { const area: AreaSeriesSpec = { - id: getSpecId('area'), - groupId: getGroupId('group1'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area', + groupId: 'group1', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -500,9 +526,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line: LineSeriesSpec = { - id: getSpecId('line'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -512,9 +540,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const bar: BarSeriesSpec = { - id: getSpecId('bar'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bar', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -536,8 +566,8 @@ describe('Chart State utils', () => { showValueLabel: true, }, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[area.id, area], [line.id, line], [bar.id, bar]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [area, line, bar]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -568,9 +598,11 @@ describe('Chart State utils', () => { }); test('can compute line geometries counts', () => { const line1: LineSeriesSpec = { - id: getSpecId('line1'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line1', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -580,9 +612,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line2: LineSeriesSpec = { - id: getSpecId('line2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -592,9 +626,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line3: LineSeriesSpec = { - id: getSpecId('line3'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line3', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -603,8 +639,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[line1.id, line1], [line2.id, line2], [line3.id, line3]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [line1, line2, line3]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -635,9 +671,11 @@ describe('Chart State utils', () => { }); test('can compute area geometries counts', () => { const area1: AreaSeriesSpec = { - id: getSpecId('area1'), - groupId: getGroupId('group2'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area1', + groupId: 'group2', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -647,9 +685,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const area2: AreaSeriesSpec = { - id: getSpecId('area2'), - groupId: getGroupId('group2'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area2', + groupId: 'group2', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -659,9 +699,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const area3: AreaSeriesSpec = { - id: getSpecId('area3'), - groupId: getGroupId('group2'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area3', + groupId: 'group2', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -670,8 +712,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[area1.id, area1], [area2.id, area2], [area3.id, area3]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [area1, area2, area3]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -702,9 +744,11 @@ describe('Chart State utils', () => { }); test('can compute line geometries with custom style', () => { const line1: LineSeriesSpec = { - id: getSpecId('line1'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line1', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -722,9 +766,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line2: LineSeriesSpec = { - id: getSpecId('line2'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -734,9 +780,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line3: LineSeriesSpec = { - id: getSpecId('line3'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line3', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -745,8 +793,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[line1.id, line1], [line2.id, line2], [line3.id, line3]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [line1, line2, line3]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -785,9 +833,11 @@ describe('Chart State utils', () => { }); test('can compute area geometries with custom style', () => { const area1: AreaSeriesSpec = { - id: getSpecId('area1'), - groupId: getGroupId('group2'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area1', + groupId: 'group2', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -809,9 +859,11 @@ describe('Chart State utils', () => { }, }; const area2: AreaSeriesSpec = { - id: getSpecId('area2'), - groupId: getGroupId('group2'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area2', + groupId: 'group2', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -821,9 +873,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const area3: AreaSeriesSpec = { - id: getSpecId('area3'), - groupId: getGroupId('group2'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area3', + groupId: 'group2', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -832,8 +886,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[area1.id, area1], [area2.id, area2], [area3.id, area3]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [area1, area2, area3]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -877,9 +931,11 @@ describe('Chart State utils', () => { }); test('can compute bars geometries counts', () => { const bars1: BarSeriesSpec = { - id: getSpecId('bars1'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bars1', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -889,9 +945,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const bars2: BarSeriesSpec = { - id: getSpecId('bars2'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bars2', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -901,9 +959,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const bars3: BarSeriesSpec = { - id: getSpecId('bars3'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bars3', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -912,8 +972,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[bars1.id, bars1], [bars2.id, bars2], [bars3.id, bars3]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [bars1, bars2, bars3]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -944,9 +1004,11 @@ describe('Chart State utils', () => { }); test('can compute the bar offset in mixed charts', () => { const line1: LineSeriesSpec = { - id: getSpecId('line1'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line1', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -957,9 +1019,11 @@ describe('Chart State utils', () => { }; const bar1: BarSeriesSpec = { - id: getSpecId('line3'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line3', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -968,8 +1032,8 @@ describe('Chart State utils', () => { yScaleToDataExtent: false, data: BARCHART_1Y1G, }; - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>([[line1.id, line1], [bar1.id, bar1]]); - const axesSpecs = new Map<AxisId, AxisSpec>(); + const seriesSpecs: BasicSeriesSpec[] = [line1, bar1]; + const axesSpecs: AxisSpec[] = []; const chartRotation = 0; const chartDimensions = { width: 100, height: 100, top: 0, left: 0 }; const chartColors = { @@ -1011,7 +1075,7 @@ describe('Chart State utils', () => { color: '#1EA593', value: { x: 0, y: 5, accessor: AccessorType.Y1 }, transform: { x: 0, y: 0 }, - geometryId: { specId: getSpecId('line1'), seriesKey: [] }, + geometryId: { specId: 'line1', seriesKey: [] }, }, ]); const map2 = new Map<string, IndexedGeometry[]>(); @@ -1023,7 +1087,7 @@ describe('Chart State utils', () => { color: '#2B70F7', value: { x: 0, y: 2, accessor: AccessorType.Y1 }, transform: { x: 0, y: 0 }, - geometryId: { specId: getSpecId('line2'), seriesKey: [] }, + geometryId: { specId: 'line2', seriesKey: [] }, }, ]); const merged = mergeGeometriesIndexes(map1, map2); @@ -1056,9 +1120,11 @@ describe('Chart State utils', () => { }); test('can determine if histogram mode is enabled', () => { const area: AreaSeriesSpec = { - id: getSpecId('area'), - groupId: getGroupId('group1'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area', + groupId: 'group1', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1068,9 +1134,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line: LineSeriesSpec = { - id: getSpecId('line'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1081,9 +1149,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const basicBar: BarSeriesSpec = { - id: getSpecId('bar'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bar', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1094,9 +1164,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const histogramBar: BarSeriesSpec = { - id: getSpecId('histo'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'histo', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1107,19 +1179,14 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, enableHistogramMode: true, }; - const seriesMap = new Map<SpecId, BasicSeriesSpec>([ - [area.id, area], - [line.id, line], - [basicBar.id, basicBar], - [histogramBar.id, histogramBar], - ]); + let seriesMap: BasicSeriesSpec[] = [area, line, basicBar, histogramBar]; expect(isHistogramModeEnabled(seriesMap)).toBe(true); - seriesMap.delete(histogramBar.id); + seriesMap = [area, line, basicBar]; expect(isHistogramModeEnabled(seriesMap)).toBe(false); - seriesMap.delete(basicBar.id); + seriesMap = [area, line]; expect(isHistogramModeEnabled(seriesMap)).toBe(false); }); test('can set the bar series accessors dependent on histogram mode', () => { @@ -1127,9 +1194,11 @@ describe('Chart State utils', () => { const isHistogramEnabled = true; const area: AreaSeriesSpec = { - id: getSpecId('area'), - groupId: getGroupId('group1'), - seriesType: 'area', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'area', + groupId: 'group1', + seriesType: SeriesTypes.Area, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1139,9 +1208,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const line: LineSeriesSpec = { - id: getSpecId('line'), - groupId: getGroupId('group2'), - seriesType: 'line', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'line', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1152,9 +1223,11 @@ describe('Chart State utils', () => { data: BARCHART_1Y1G, }; const bar: BarSeriesSpec = { - id: getSpecId('bar'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bar', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1181,9 +1254,11 @@ describe('Chart State utils', () => { // add another bar const bar2: BarSeriesSpec = { - id: getSpecId('bar2'), - groupId: getGroupId('group2'), - seriesType: 'bar', + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, + id: 'bar2', + groupId: 'group2', + seriesType: SeriesTypes.Bar, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -1203,7 +1278,7 @@ describe('Chart State utils', () => { key: 'specId:{bars},colors:{a}', color: '#1EA593', label: 'a', - value: { specId: getSpecId('bars'), colorValues: ['a'], lastValue: { y0: null, y1: 6 } }, + value: { specId: 'bars', colorValues: ['a'], lastValue: { y0: null, y1: 6 } }, displayValue: { raw: { y0: null, y1: 6 }, formatted: { y0: null, y1: '6.00' } }, isSeriesVisible: false, }); @@ -1211,7 +1286,7 @@ describe('Chart State utils', () => { key: 'specId:{bars},colors:{b}', color: '#2B70F7', label: 'b', - value: { specId: getSpecId('bars'), colorValues: ['b'], lastValue: { y0: null, y1: 2 } }, + value: { specId: 'bars', colorValues: ['b'], lastValue: { y0: null, y1: 2 } }, displayValue: { raw: { y0: null, y1: 2 }, formatted: { y0: null, y1: '2.00' } }, isSeriesVisible: false, }); @@ -1223,7 +1298,7 @@ describe('Chart State utils', () => { key: 'specId:{bars},colors:{a}', color: '#1EA593', label: 'a', - value: { specId: getSpecId('bars'), colorValues: ['a'], lastValue: { y0: null, y1: 6 } }, + value: { specId: 'bars', colorValues: ['a'], lastValue: { y0: null, y1: 6 } }, displayValue: { raw: { y0: null, y1: 6 }, formatted: { y0: null, y1: '6.00' } }, isSeriesVisible: true, }); @@ -1231,7 +1306,7 @@ describe('Chart State utils', () => { key: 'specId:{bars},colors:{b}', color: '#2B70F7', label: 'b', - value: { specId: getSpecId('bars'), colorValues: ['b'], lastValue: { y0: null, y1: 2 } }, + value: { specId: 'bars', colorValues: ['b'], lastValue: { y0: null, y1: 2 } }, displayValue: { raw: { y0: null, y1: 2 }, formatted: { y0: null, y1: '2.00' } }, isSeriesVisible: false, }); diff --git a/src/chart_types/xy_chart/store/utils.ts b/src/chart_types/xy_chart/state/utils.ts similarity index 88% rename from src/chart_types/xy_chart/store/utils.ts rename to src/chart_types/xy_chart/state/utils.ts index b4c3e2f637..56c4a79b54 100644 --- a/src/chart_types/xy_chart/store/utils.ts +++ b/src/chart_types/xy_chart/state/utils.ts @@ -2,26 +2,17 @@ import { isVerticalAxis } from '../utils/axis_utils'; import { CurveType } from '../../../utils/curves'; import { mergeXDomain, XDomain } from '../domains/x_domain'; import { mergeYDomain, YDomain } from '../domains/y_domain'; -import { - AreaGeometry, - BarGeometry, - IndexedGeometry, - LineGeometry, - mutableIndexedGeometryMapUpsert, - PointGeometry, - renderArea, - renderBars, - renderLine, -} from '../rendering/rendering'; +import { mutableIndexedGeometryMapUpsert, renderArea, renderBars, renderLine } from '../rendering/rendering'; import { computeXScale, computeYScales, countBarsInCluster } from '../utils/scales'; import { DataSeries, DataSeriesColorsValues, - findDataSeriesByColorValues, FormattedDataSeries, getColorValuesAsString, getFormattedDataseries, getSplittedSeries, + RawDataSeries, + findDataSeriesByColorValues, } from '../utils/series'; import { AreaSeriesSpec, @@ -38,15 +29,17 @@ import { isBandedSpec, Fit, FitConfig, + SeriesTypes, } from '../utils/specs'; import { ColorConfig, Theme } from '../../../utils/themes/theme'; import { identity, mergePartial } from '../../../utils/commons'; import { Dimensions } from '../../../utils/dimensions'; import { Domain } from '../../../utils/domain'; -import { AxisId, GroupId, SpecId } from '../../../utils/ids'; +import { GroupId, SpecId } from '../../../utils/ids'; import { Scale } from '../../../utils/scales/scales'; -import { SeriesDomainsAndData } from './chart_state'; +import { PointGeometry, BarGeometry, AreaGeometry, LineGeometry, IndexedGeometry } from '../../../utils/geometry'; import { LegendItem } from '../legend/legend'; +import { Spec } from '../../../specs'; const MAX_ANIMATABLE_BARS = 300; const MAX_ANIMATABLE_LINES_AREA_POINTS = 600; @@ -72,6 +65,35 @@ export interface GeometriesCounts { linePoints: number; } +export interface ComputedScales { + xScale: Scale; + yScales: Map<GroupId, Scale>; +} +export interface Geometries { + points: PointGeometry[]; + bars: BarGeometry[]; + areas: AreaGeometry[]; + lines: LineGeometry[]; +} + +export interface ComputedGeometries { + scales: ComputedScales; + geometries: Geometries; + geometriesIndex: Map<any, IndexedGeometry[]>; + geometriesCounts: GeometriesCounts; +} + +export interface SeriesDomainsAndData { + xDomain: XDomain; + yDomain: YDomain[]; + splittedDataSeries: RawDataSeries[][]; + formattedDataSeries: { + stacked: FormattedDataSeries[]; + nonStacked: FormattedDataSeries[]; + }; + seriesColors: Map<string, DataSeriesColorsValues>; +} + export function updateDeselectedDataSeries( series: DataSeriesColorsValues[] | null, value: DataSeriesColorsValues, @@ -87,7 +109,7 @@ export function updateDeselectedDataSeries( return updatedSeries; } -export function getUpdatedCustomSeriesColors(seriesSpecs: Map<SpecId, BasicSeriesSpec>): Map<string, string> { +export function getUpdatedCustomSeriesColors(seriesSpecs: BasicSeriesSpec[]): Map<string, string> { const updatedCustomSeriesColors = new Map(); seriesSpecs.forEach((spec: BasicSeriesSpec) => { if (spec.customSeriesColors) { @@ -106,7 +128,7 @@ export interface LastValues { y1: number | null; } -export function getLastValues(formattedDataSeries: { +function getLastValues(formattedDataSeries: { stacked: FormattedDataSeries[]; nonStacked: FormattedDataSeries[]; }): Map<string, LastValues> { @@ -154,10 +176,10 @@ export function getLastValues(formattedDataSeries: { * @returns `SeriesDomainsAndData` */ export function computeSeriesDomains( - seriesSpecs: Map<SpecId, BasicSeriesSpec>, - customYDomainsByGroupId: Map<GroupId, DomainRange>, + seriesSpecs: BasicSeriesSpec[], + customYDomainsByGroupId: Map<GroupId, DomainRange> = new Map(), + deselectedDataSeries: DataSeriesColorsValues[] = [], customXDomain?: DomainRange | Domain, - deselectedDataSeries?: DataSeriesColorsValues[] | null, ): SeriesDomainsAndData { const { splittedSeries, xValues, seriesColors } = getSplittedSeries(seriesSpecs, deselectedDataSeries); @@ -197,7 +219,7 @@ export function computeSeriesDomains( } export function computeSeriesGeometries( - seriesSpecs: Map<SpecId, BasicSeriesSpec>, + seriesSpecs: BasicSeriesSpec[], xDomain: XDomain, yDomain: YDomain[], formattedDataSeries: { @@ -208,22 +230,9 @@ export function computeSeriesGeometries( chartTheme: Theme, chartDims: Dimensions, chartRotation: Rotation, - axesSpecs: Map<AxisId, AxisSpec>, + axesSpecs: AxisSpec[], enableHistogramMode: boolean, -): { - scales: { - xScale: Scale; - yScales: Map<GroupId, Scale>; - }; - geometries: { - points: PointGeometry[]; - bars: BarGeometry[]; - areas: AreaGeometry[]; - lines: LineGeometry[]; - }; - geometriesIndex: Map<any, IndexedGeometry[]>; - geometriesCounts: GeometriesCounts; -} { +): ComputedGeometries { const chartColors: ColorConfig = chartTheme.colors; const barsPadding = enableHistogramMode ? chartTheme.scales.histogramPadding : chartTheme.scales.barsPadding; @@ -364,13 +373,10 @@ export function setBarSeriesAccessors(isHistogramMode: boolean, seriesSpecs: Map return; } -export function isHistogramModeEnabled(seriesSpecs: Map<SpecId, BasicSeriesSpec>): boolean { - for (const [, spec] of seriesSpecs) { - if (isBarSeriesSpec(spec) && spec.enableHistogramMode) { - return true; - } - } - return false; +export function isHistogramModeEnabled(seriesSpecs: BasicSeriesSpec[]): boolean { + return seriesSpecs.some((spec) => { + return isBarSeriesSpec(spec) && spec.enableHistogramMode; + }); } export function computeXScaleOffset( @@ -398,17 +404,17 @@ export function computeXScaleOffset( } } -export function renderGeometries( +function renderGeometries( indexOffset: number, clusteredCount: number, isStacked: boolean, dataSeries: DataSeries[], xScale: Scale, yScale: Scale, - seriesSpecs: Map<SpecId, BasicSeriesSpec>, + seriesSpecs: BasicSeriesSpec[], seriesColorsMap: Map<string, string>, defaultColor: string, - axesSpecs: Map<AxisId, AxisSpec>, + axesSpecs: AxisSpec[], chartTheme: Theme, enableHistogramMode: boolean, ): { @@ -440,7 +446,7 @@ export function renderGeometries( let barIndexOffset = 0; for (i = 0; i < len; i++) { const ds = dataSeries[i]; - const spec = getSpecById(seriesSpecs, ds.specId); + const spec = getSpecsById<BasicSeriesSpec>(seriesSpecs, ds.specId); if (spec === undefined) { continue; } @@ -553,14 +559,14 @@ export function renderGeometries( }; } -export function getSpecById(seriesSpecs: Map<SpecId, BasicSeriesSpec>, specId: SpecId) { - return seriesSpecs.get(specId); +export function getSpecsById<T extends Spec>(specs: T[], id: string): T | undefined { + return specs.find((spec) => spec.id === id); } -export function getAxesSpecForSpecId(axesSpecs: Map<AxisId, AxisSpec>, groupId: GroupId) { +export function getAxesSpecForSpecId(axesSpecs: AxisSpec[], groupId: GroupId) { let xAxis; let yAxis; - for (const axisSpec of axesSpecs.values()) { + for (const axisSpec of axesSpecs) { if (axisSpec.groupId !== groupId) { continue; } @@ -604,27 +610,6 @@ export function computeChartTransform(chartDimensions: Dimensions, chartRotation } } -export function computeBrushExtent( - chartDimensions: Dimensions, - chartRotation: Rotation, - chartTransform: Transform, -): BrushExtent { - const minX = [0, 180].includes(chartRotation) - ? chartDimensions.left + chartTransform.x - : chartDimensions.top + chartTransform.y; - const minY = [0, 180].includes(chartRotation) - ? chartDimensions.top + chartTransform.y - : chartDimensions.left + chartTransform.x; - const maxX = minX + chartDimensions.width; - const maxY = minY + chartDimensions.height; - return { - minX, - minY, - maxX, - maxY, - }; -} - /** * Merge multiple geometry indexes maps together. * @param iterables a set of maps to be merged @@ -654,9 +639,9 @@ export function isVerticalRotation(chartRotation: Rotation) { * Check if a specs map contains only line or area specs * @param specs Map<SpecId, BasicSeriesSpec> */ -export function isLineAreaOnlyChart(specs: Map<SpecId, BasicSeriesSpec>) { - return ![...specs.values()].some((spec) => { - return spec.seriesType === 'bar'; +export function isLineAreaOnlyChart(specs: BasicSeriesSpec[]) { + return !specs.some((spec) => { + return spec.seriesType === SeriesTypes.Bar; }); } diff --git a/src/chart_types/xy_chart/store/chart_state.interactions.test.ts b/src/chart_types/xy_chart/store/chart_state.interactions.test.ts deleted file mode 100644 index c957dd0c06..0000000000 --- a/src/chart_types/xy_chart/store/chart_state.interactions.test.ts +++ /dev/null @@ -1,483 +0,0 @@ -import { BarGeometry } from '../rendering/rendering'; -import { computeXScale, computeYScales } from '../utils/scales'; -import { DataSeriesColorsValues } from '../utils/series'; -import { BarSeriesSpec, BasicSeriesSpec, RectAnnotationSpec, Position } from '../utils/specs'; -import { getAnnotationId, getGroupId, getSpecId, getAxisId } from '../../../utils/ids'; -import { TooltipType } from '../utils/interactions'; -import { ScaleContinuous } from '../../../utils/scales/scale_continuous'; -import { ScaleType } from '../../../utils/scales/scales'; -import { ChartStore } from './chart_state'; -import { computeSeriesDomains } from './utils'; -import { ScaleBand } from '../../../utils/scales/scale_band'; - -const SPEC_ID = getSpecId('spec_1'); -const GROUP_ID = getGroupId('group_1'); - -const ordinalBarSeries: BarSeriesSpec = { - id: SPEC_ID, - groupId: GROUP_ID, - seriesType: 'bar', - yScaleToDataExtent: false, - data: [[0, 10], [1, 5]], - xAccessor: 0, - yAccessors: [1], - xScaleType: ScaleType.Ordinal, - yScaleType: ScaleType.Linear, - hideInLegend: false, -}; -const linearBarSeries: BarSeriesSpec = { - id: SPEC_ID, - groupId: GROUP_ID, - seriesType: 'bar', - yScaleToDataExtent: false, - data: [[0, 10], [1, 5]], - xAccessor: 0, - yAccessors: [1], - xScaleType: ScaleType.Linear, - yScaleType: ScaleType.Linear, - hideInLegend: false, -}; -const chartTop = 10; -const chartLeft = 10; - -function initStore(spec: BasicSeriesSpec) { - const store = new ChartStore(); - store.chartDimensions.width = 100; - store.chartDimensions.height = 100; - store.chartDimensions.top = chartTop; - store.chartDimensions.left = chartLeft; - store.chartRotation = 0; - store.seriesDomainsAndData = { - splittedDataSeries: [], - formattedDataSeries: { - stacked: [], - nonStacked: [], - }, - seriesColors: new Map<string, DataSeriesColorsValues>(), - xDomain: { - scaleType: spec.xScaleType, - domain: [0, 1], - isBandScale: true, - minInterval: 1, - type: 'xDomain', - }, - yDomain: [ - { - scaleType: spec.yScaleType, - domain: [0, 20], - isBandScale: false, - groupId: GROUP_ID, - type: 'yDomain', - }, - ], - }; - store.tooltipType.set(TooltipType.VerticalCursor); - store.seriesSpecs.set(spec.id, spec); - return store; -} - -const barStyle = { - rect: { - opacity: 1, - }, - rectBorder: { - strokeWidth: 1, - visible: false, - }, - displayValue: { - fill: 'black', - fontFamily: '', - fontSize: 2, - offsetX: 0, - offsetY: 0, - padding: 2, - }, -}; -const indexedGeom1Red: BarGeometry = { - color: 'red', - x: 0, - y: 0, - width: 50, - height: 100, - value: { - x: 0, - y: 10, - accessor: 'y1', - }, - geometryId: { - specId: SPEC_ID, - seriesKey: [], - }, - seriesStyle: barStyle, -}; -const indexedGeom2Blue: BarGeometry = { - color: 'blue', - x: 50, - y: 50, - width: 50, - height: 50, - value: { - x: 1, - y: 5, - accessor: 'y1', - }, - geometryId: { - specId: SPEC_ID, - seriesKey: [], - }, - seriesStyle: barStyle, -}; - -describe('Chart state pointer interactions', () => { - let store: ChartStore; - - beforeEach(() => { - store = initStore(ordinalBarSeries); - }); - - test('can convert/limit cursor positions relative to chart dimensions', () => { - store.setCursorPosition(20, 20); - expect(store.cursorPosition.x).toBe(10); - expect(store.cursorPosition.y).toBe(10); - store.setCursorPosition(10, 10); - expect(store.cursorPosition.x).toBe(0); - expect(store.cursorPosition.y).toBe(0); - store.setCursorPosition(5, 5); - expect(store.cursorPosition.x).toBe(-1); - expect(store.cursorPosition.y).toBe(-1); - store.setCursorPosition(200, 20); - expect(store.cursorPosition.x).toBe(-1); - expect(store.cursorPosition.y).toBe(10); - store.setCursorPosition(20, 200); - expect(store.cursorPosition.x).toBe(10); - expect(store.cursorPosition.y).toBe(-1); - store.setCursorPosition(200, 200); - expect(store.cursorPosition.x).toBe(-1); - expect(store.cursorPosition.y).toBe(-1); - store.setCursorPosition(-20, -20); - expect(store.cursorPosition.x).toBe(-1); - expect(store.cursorPosition.y).toBe(-1); - }); - - test('call onElementOut if moving the mouse out from the chart', () => { - store.highlightedGeometries.push(indexedGeom1Red); - const listener = jest.fn((): undefined => undefined); - store.setOnElementOutListener(listener); - store.setCursorPosition(5, 5); - expect(listener).toBeCalledTimes(1); - - // no more calls after the first out one outside chart - store.setCursorPosition(5, 5); - expect(listener).toBeCalledTimes(1); - store.setCursorPosition(3, 3); - expect(listener).toBeCalledTimes(1); - }); - - test('can respond to tooltip types changes', () => { - store.xScale = new ScaleContinuous( - { - type: ScaleType.Linear, - domain: [0, 1], - range: [0, 100], - }, - { bandwidth: 50, minInterval: 0.5 }, - ); - store.yScales = new Map(); - store.yScales.set(GROUP_ID, new ScaleContinuous({ type: ScaleType.Linear, domain: [0, 1], range: [0, 100] })); - store.geometriesIndex.set(0, [indexedGeom1Red]); - store.geometriesIndexKeys.push(0); - store.tooltipType.set(TooltipType.None); - store.setCursorPosition(10, 10 + 70); - expect(store.tooltipData).toEqual([]); - expect(store.isTooltipVisible.get()).toBe(false); - - store.tooltipType.set(TooltipType.Follow); - store.setCursorPosition(10, 10 + 70); - expect(store.geometriesIndexKeys.length).toBe(1); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.highlightedGeometries.length).toBe(1); - }); - - describe('mouse over with Ordinal scale', () => { - mouseOverTestSuite(ScaleType.Ordinal); - }); - describe('mouse over with Linear scale', () => { - mouseOverTestSuite(ScaleType.Linear); - }); - - // TODO add test for point series - // TODO add test for mixed series - // TODO add test for clicks -}); - -function mouseOverTestSuite(scaleType: ScaleType) { - let store: ChartStore; - let onOverListener: jest.Mock<undefined>; - let onOutListener: jest.Mock<undefined>; - - beforeEach(() => { - const spec = scaleType === ScaleType.Ordinal ? ordinalBarSeries : linearBarSeries; - store = initStore(spec); - const barSeriesMap = new Map(); - barSeriesMap.set(SPEC_ID, spec); - const barSeriesDomains = computeSeriesDomains(barSeriesMap, new Map()); - const barSeriesScale = computeXScale({ - xDomain: barSeriesDomains.xDomain, - totalBarsInCluster: barSeriesMap.size, - range: [0, 100], - }); - const yScales = computeYScales({ yDomains: barSeriesDomains.yDomain, range: [0, 100] }); - store.xScale = barSeriesScale; - store.yScales = yScales; - store.geometriesIndex.set(0, [indexedGeom1Red]); - store.geometriesIndex.set(1, [indexedGeom2Blue]); - store.geometriesIndexKeys.push(0); - store.geometriesIndexKeys.push(1); - onOverListener = jest.fn((): undefined => undefined); - onOutListener = jest.fn((): undefined => undefined); - store.setOnElementOverListener(onOverListener); - store.setOnElementOutListener(onOutListener); - expect(store.xScale).not.toBeUndefined(); - expect(store.tooltipData).toEqual([]); - }); - - test('store is correctly configured', () => { - // checking this to avoid broken tests due to nested describe and before - expect(store.xScale).not.toBeUndefined(); - expect(store.yScales).not.toBeUndefined(); - }); - - test('set cursor from external source', () => { - store.setCursorValue(0); - expect(store.externalCursorShown.get()).toBe(true); - expect(store.cursorBandPosition).toEqual({ - height: 100, - left: 10, - top: 10, - visible: true, - width: 50, - }); - - store.setCursorValue(1); - expect(store.externalCursorShown.get()).toBe(true); - expect(store.cursorBandPosition).toEqual({ - height: 100, - left: 60, - top: 10, - visible: true, - width: 50, - }); - - store.setCursorValue(2); - expect(store.externalCursorShown.get()).toBe(true); - // equal to the latest except the visiblility - expect(store.cursorBandPosition).toEqual({ - height: 100, - left: 60, - top: 10, - visible: false, - width: 50, - }); - }); - test('can determine which tooltip to display if chart & annotation tooltips possible', () => { - const annotationDimensions = [{ rect: { x: 49, y: -1, width: 3, height: 99 } }]; - const rectAnnotationSpec: RectAnnotationSpec = { - annotationId: getAnnotationId('rect'), - groupId: GROUP_ID, - annotationType: 'rectangle', - dataValues: [{ coordinates: { x0: 1, x1: 1.5, y0: 0.5, y1: 10 } }], - }; - - store.annotationSpecs.set(rectAnnotationSpec.annotationId, rectAnnotationSpec); - store.annotationDimensions.set(rectAnnotationSpec.annotationId, annotationDimensions); - // isHighlighted false, chart tooltip true; should show annotationTooltip only - store.setCursorPosition(chartLeft + 51, chartTop + 1); - expect(store.isTooltipVisible.get()).toBe(false); - }); - - test('can hover top-left corner of the first bar', () => { - expect(store.tooltipData).toEqual([]); - store.setCursorPosition(chartLeft + 0, chartTop + 0); - expect(store.cursorPosition).toEqual({ x: 0, y: 0 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 0); - expect(store.cursorBandPosition.width).toBe(50); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.tooltipData.length).toBe(2); // x value + 1 y value - expect(store.highlightedGeometries.length).toBe(1); - expect(onOverListener).toBeCalledTimes(1); - expect(onOutListener).toBeCalledTimes(0); - expect(onOverListener.mock.calls[0][0]).toEqual([indexedGeom1Red.value]); - - store.setCursorPosition(chartLeft - 1, chartTop - 1); - expect(store.cursorPosition).toEqual({ x: -1, y: -1 }); - expect(store.isTooltipVisible.get()).toBe(false); - expect(store.tooltipData.length).toBe(0); - expect(store.highlightedGeometries.length).toBe(0); - expect(onOverListener).toBeCalledTimes(1); - expect(onOutListener).toBeCalledTimes(1); - }); - - test('can hover bottom-left corner of the first bar', () => { - store.setCursorPosition(chartLeft + 0, chartTop + 99); - expect(store.cursorPosition).toEqual({ x: 0, y: 99 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 0); - expect(store.cursorBandPosition.width).toBe(50); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.highlightedGeometries.length).toBe(1); - expect(store.tooltipData.length).toBe(2); // x value + 1 y value - expect(onOverListener).toBeCalledTimes(1); - expect(onOutListener).toBeCalledTimes(0); - expect(onOverListener.mock.calls[0][0]).toEqual([indexedGeom1Red.value]); - - store.setCursorPosition(chartLeft - 1, chartTop + 99); - expect(store.cursorPosition).toEqual({ x: -1, y: 99 }); - expect(store.isTooltipVisible.get()).toBe(false); - expect(store.tooltipData.length).toBe(0); - expect(store.highlightedGeometries.length).toBe(0); - expect(onOverListener).toBeCalledTimes(1); - expect(onOutListener).toBeCalledTimes(1); - }); - - test('can hover top-right corner of the first bar', () => { - let scaleOffset = 0; - if (scaleType !== ScaleType.Ordinal) { - scaleOffset = 1; - } - store.setCursorPosition(chartLeft + 49 + scaleOffset, chartTop + 0); - expect(store.cursorPosition).toEqual({ x: 49 + scaleOffset, y: 0 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 0); - expect(store.cursorBandPosition.width).toBe(50); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.highlightedGeometries.length).toBe(1); - expect(store.tooltipData.length).toBe(2); - expect(onOverListener).toBeCalledTimes(1); - expect(onOutListener).toBeCalledTimes(0); - expect(onOverListener.mock.calls[0][0]).toEqual([indexedGeom1Red.value]); - - store.setCursorPosition(chartLeft + 50 + scaleOffset, chartTop + 0); - expect(store.cursorPosition).toEqual({ x: 50 + scaleOffset, y: 0 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 50); - expect(store.cursorBandPosition.width).toBe(50); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.tooltipData.length).toBe(2); - expect(store.highlightedGeometries.length).toBe(0); - expect(onOverListener).toBeCalledTimes(1); - expect(onOutListener).toBeCalledTimes(1); - }); - - test('can hover bottom-right corner of the first bar', () => { - let scaleOffset = 0; - if (scaleType !== ScaleType.Ordinal) { - scaleOffset = 1; - } - store.setCursorPosition(chartLeft + 49 + scaleOffset, chartTop + 99); - expect(store.cursorPosition).toEqual({ x: 49 + scaleOffset, y: 99 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 0); - expect(store.cursorBandPosition.width).toBe(50); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.highlightedGeometries.length).toBe(1); - expect(store.tooltipData.length).toBe(2); - expect(onOverListener).toBeCalledTimes(1); - expect(onOutListener).toBeCalledTimes(0); - expect(onOverListener.mock.calls[0][0]).toEqual([indexedGeom1Red.value]); - - store.setCursorPosition(chartLeft + 50 + scaleOffset, chartTop + 99); - expect(store.cursorPosition).toEqual({ x: 50 + scaleOffset, y: 99 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 50); - expect(store.cursorBandPosition.width).toBe(50); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.tooltipData.length).toBe(2); - // we are over the second bar here - expect(store.highlightedGeometries.length).toBe(1); - expect(onOverListener).toBeCalledTimes(2); - expect(onOverListener.mock.calls[1][0]).toEqual([indexedGeom2Blue.value]); - - expect(onOutListener).toBeCalledTimes(0); - }); - - test('can hover top-right corner of the chart', () => { - store.setCursorPosition(chartLeft + 99, chartTop + 0); - expect(store.cursorPosition).toEqual({ x: 99, y: 0 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 50); - expect(store.cursorBandPosition.width).toBe(50); - - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.highlightedGeometries.length).toBe(0); - expect(store.tooltipData.length).toBe(2); - expect(onOverListener).toBeCalledTimes(0); - expect(onOutListener).toBeCalledTimes(0); - }); - - test('can hover bottom-right corner of the chart', () => { - store.setCursorPosition(chartLeft + 99, chartTop + 99); - expect(store.cursorPosition).toEqual({ x: 99, y: 99 }); - expect(store.cursorBandPosition.left).toBe(chartLeft + 50); - expect(store.cursorBandPosition.width).toBe(50); - expect(store.isTooltipVisible.get()).toBe(true); - expect(store.highlightedGeometries.length).toBe(1); - expect(store.tooltipData.length).toBe(2); - expect(onOverListener).toBeCalledTimes(1); - expect(onOverListener.mock.calls[0][0]).toEqual([indexedGeom2Blue.value]); - expect(onOutListener).toBeCalledTimes(0); - }); - - describe('can position tooltip within chart when xScale is a single value scale', () => { - beforeEach(() => { - const singleValueScale = - store.xScale!.type === ScaleType.Ordinal - ? new ScaleBand(['a'], [0, 0]) - : new ScaleContinuous({ type: ScaleType.Linear, domain: [1, 1], range: [0, 0] }); - store.xScale = singleValueScale; - }); - test('horizontal chart rotation', () => { - store.setCursorPosition(chartLeft + 99, chartTop + 99); - expect(store.tooltipPosition.hPosition.bandLeft).toBe(chartLeft); - expect(store.tooltipPosition.vPosition.bandTop).toBe(109); - }); - - test('vertical chart rotation', () => { - store.chartRotation = 90; - store.setCursorPosition(chartLeft + 99, chartTop + 99); - expect(store.tooltipPosition.hPosition.bandLeft).toBe(109); - expect(store.tooltipPosition.vPosition.bandTop).toBe(chartTop); - }); - }); - describe('can format tooltip values on rotated chart', () => { - beforeEach(() => { - store.addAxisSpec({ - hide: true, - id: getAxisId('yaxis'), - groupId: GROUP_ID, - position: Position.Left, - tickFormat: (value) => `left ${Number(value)}`, - showOverlappingLabels: false, - showOverlappingTicks: false, - tickPadding: 0, - tickSize: 0, - }); - store.addAxisSpec({ - hide: true, - id: getAxisId('xaxis'), - groupId: GROUP_ID, - position: Position.Bottom, - tickFormat: (value) => `bottom ${Number(value)}`, - showOverlappingLabels: false, - showOverlappingTicks: false, - tickPadding: 0, - tickSize: 0, - }); - }); - test('chart 0 rotation', () => { - store.setCursorPosition(chartLeft + 0, chartTop + 99); - expect(store.tooltipData[0].value).toBe('bottom 0'); - expect(store.tooltipData[1].value).toBe('left 10'); - }); - - test('chart 90 deg rotated', () => { - store.chartRotation = 90; - store.setCursorPosition(chartLeft + 0, chartTop + 99); - expect(store.tooltipData[0].value).toBe('left 1'); - expect(store.tooltipData[1].value).toBe('bottom 5'); - }); - }); -} diff --git a/src/chart_types/xy_chart/store/chart_state.timescales.test.ts b/src/chart_types/xy_chart/store/chart_state.timescales.test.ts deleted file mode 100644 index c15125f172..0000000000 --- a/src/chart_types/xy_chart/store/chart_state.timescales.test.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { DateTime } from 'luxon'; -import { LineSeriesSpec } from '../utils/specs'; -import { LIGHT_THEME } from '../../../utils/themes/light_theme'; -import { mergeWithDefaultTheme } from '../../../utils/themes/theme'; -import { getGroupId, getSpecId } from '../../../utils/ids'; -import { ScaleType } from '../../../utils/scales/scales'; -import { ChartStore } from './chart_state'; - -describe('Render chart', () => { - describe('line, utc-time, day interval', () => { - let store: ChartStore; - const day1 = 1546300800000; // 2019-01-01T00:00:00.000Z - const day2 = day1 + 1000 * 60 * 60 * 24; - const day3 = day2 + 1000 * 60 * 60 * 24; - beforeEach(() => { - store = new ChartStore(); - - const lineSeries: LineSeriesSpec = { - id: getSpecId('lines'), - groupId: getGroupId('line'), - seriesType: 'line', - xScaleType: ScaleType.Time, - yScaleType: ScaleType.Linear, - xAccessor: 0, - yAccessors: [1], - data: [[day1, 10], [day2, 22], [day3, 6]], - yScaleToDataExtent: false, - }; - store.chartTheme = mergeWithDefaultTheme( - { - chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, - chartMargins: { top: 0, left: 0, bottom: 0, right: 0 }, - }, - LIGHT_THEME, - ); - - store.addSeriesSpec(lineSeries); - store.updateParentDimensions(100, 100, 0, 0); - }); - test('check rendered geometries', () => { - expect(store.geometries).toBeTruthy(); - expect(store.geometries!.lines).toBeDefined(); - expect(store.geometries!.lines.length).toBe(1); - expect(store.geometries!.lines[0].points.length).toBe(3); - }); - test('check mouse position correctly return inverted value', () => { - store.setCursorPosition(15, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(day1); // x value - expect(store.tooltipData[1].value).toBe(10); // y value - store.setCursorPosition(35, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(day2); // x value - expect(store.tooltipData[1].value).toBe(22); // y value - store.setCursorPosition(76, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(day3); // x value - expect(store.tooltipData[1].value).toBe(6); // y value - }); - }); - describe('line, utc-time, 5m interval', () => { - let store: ChartStore; - const date1 = 1546300800000; // 2019-01-01T00:00:00.000Z - const date2 = date1 + 1000 * 60 * 5; - const date3 = date2 + 1000 * 60 * 5; - beforeEach(() => { - store = new ChartStore(); - - const lineSeries: LineSeriesSpec = { - id: getSpecId('lines'), - groupId: getGroupId('line'), - seriesType: 'line', - xScaleType: ScaleType.Time, - yScaleType: ScaleType.Linear, - xAccessor: 0, - yAccessors: [1], - data: [[date1, 10], [date2, 22], [date3, 6]], - yScaleToDataExtent: false, - }; - store.chartTheme = mergeWithDefaultTheme( - { - chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, - chartMargins: { top: 0, left: 0, bottom: 0, right: 0 }, - }, - LIGHT_THEME, - ); - - store.addSeriesSpec(lineSeries); - store.updateParentDimensions(100, 100, 0, 0); - }); - test('check rendered geometries', () => { - expect(store.geometries).toBeTruthy(); - expect(store.geometries!.lines).toBeDefined(); - expect(store.geometries!.lines.length).toBe(1); - expect(store.geometries!.lines[0].points.length).toBe(3); - }); - test('check mouse position correctly return inverted value', () => { - store.setCursorPosition(15, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(date1); // x value - expect(store.tooltipData[1].value).toBe(10); // y value - store.setCursorPosition(35, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(date2); // x value - expect(store.tooltipData[1].value).toBe(22); // y value - store.setCursorPosition(76, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(date3); // x value - expect(store.tooltipData[1].value).toBe(6); // y value - }); - }); - describe('line, non utc-time, 5m + 1s interval', () => { - let store: ChartStore; - const date1 = DateTime.fromISO('2019-01-01T00:00:01.000-0300', { setZone: true }).toMillis(); - const date2 = date1 + 1000 * 60 * 5; - const date3 = date2 + 1000 * 60 * 5; - beforeEach(() => { - store = new ChartStore(); - - const lineSeries: LineSeriesSpec = { - id: getSpecId('lines'), - groupId: getGroupId('line'), - seriesType: 'line', - xScaleType: ScaleType.Time, - yScaleType: ScaleType.Linear, - xAccessor: 0, - yAccessors: [1], - data: [[date1, 10], [date2, 22], [date3, 6]], - yScaleToDataExtent: false, - }; - store.chartTheme = mergeWithDefaultTheme( - { - chartPaddings: { top: 0, left: 0, bottom: 0, right: 0 }, - chartMargins: { top: 0, left: 0, bottom: 0, right: 0 }, - }, - LIGHT_THEME, - ); - - store.addSeriesSpec(lineSeries); - store.updateParentDimensions(100, 100, 0, 0); - }); - test('check rendered geometries', () => { - expect(store.geometries).toBeTruthy(); - expect(store.geometries!.lines).toBeDefined(); - expect(store.geometries!.lines.length).toBe(1); - expect(store.geometries!.lines[0].points.length).toBe(3); - }); - test('check scale values', () => { - const xValues = [date1, date2, date3]; - expect(store.xScale!.minInterval).toBe(1000 * 60 * 5); - expect(store.xScale!.domain).toEqual([date1, date3]); - expect(store.xScale!.range).toEqual([0, 100]); - expect(store.xScale!.invert(0)).toBe(date1); - expect(store.xScale!.invert(50)).toBe(date2); - expect(store.xScale!.invert(100)).toBe(date3); - expect(store.xScale!.invertWithStep(5, xValues)).toEqual({ value: date1, withinBandwidth: true }); - expect(store.xScale!.invertWithStep(20, xValues)).toEqual({ value: date1, withinBandwidth: true }); - expect(store.xScale!.invertWithStep(30, xValues)).toEqual({ value: date2, withinBandwidth: true }); - expect(store.xScale!.invertWithStep(50, xValues)).toEqual({ value: date2, withinBandwidth: true }); - expect(store.xScale!.invertWithStep(70, xValues)).toEqual({ value: date2, withinBandwidth: true }); - expect(store.xScale!.invertWithStep(80, xValues)).toEqual({ value: date3, withinBandwidth: true }); - expect(store.xScale!.invertWithStep(100, xValues)).toEqual({ value: date3, withinBandwidth: true }); - }); - test('check mouse position correctly return inverted value', () => { - store.setCursorPosition(15, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(date1); // x value - expect(store.tooltipData[1].value).toBe(10); // y value - store.setCursorPosition(35, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(date2); // x value - expect(store.tooltipData[1].value).toBe(22); // y value - store.setCursorPosition(76, 10); // check first valid tooltip - expect(store.tooltipData.length).toBe(2); // x value + y value - expect(store.tooltipData[0].value).toBe(date3); // x value - expect(store.tooltipData[1].value).toBe(6); // y value - }); - }); -}); diff --git a/src/chart_types/xy_chart/store/chart_state.ts b/src/chart_types/xy_chart/store/chart_state.ts deleted file mode 100644 index 2b2daaaa01..0000000000 --- a/src/chart_types/xy_chart/store/chart_state.ts +++ /dev/null @@ -1,1081 +0,0 @@ -import { set, action, computed, IObservableValue, observable } from 'mobx'; -import * as uuid from 'uuid'; - -import { - AxisLinePosition, - AxisTick, - AxisTicksDimensions, - computeAxisTicksDimensions, - getAxisTicksPositions, - mergeYCustomDomainsByGroupId, -} from '../utils/axis_utils'; -import { CanvasTextBBoxCalculator } from '../../../utils/bbox/canvas_text_bbox_calculator'; -import { XDomain } from '../domains/x_domain'; -import { YDomain } from '../domains/y_domain'; -import { computeLegend, LegendItem } from '../legend/legend'; -import { - AreaGeometry, - BarGeometry, - GeometryValue, - IndexedGeometry, - LineGeometry, - PointGeometry, -} from '../rendering/rendering'; -import { countBarsInCluster } from '../utils/scales'; -import { - DataSeriesColorsValues, - findDataSeriesByColorValues, - FormattedDataSeries, - getSeriesColorMap, - RawDataSeries, -} from '../utils/series'; -import { - AnnotationSpec, - AnnotationTypes, - AreaSeriesSpec, - AxisSpec, - BarSeriesSpec, - BasicSeriesSpec, - DomainRange, - isLineAnnotation, - isRectAnnotation, - LineSeriesSpec, - Position, - Rendering, - Rotation, -} from '../utils/specs'; -import { getSeriesTooltipValues, getTooltipAndHighlightFromXValue } from '../tooltip/tooltip'; -import { mergeWithDefaultAnnotationLine, mergeWithDefaultAnnotationRect, Theme } from '../../../utils/themes/theme'; -import { compareByValueAsc } from '../../../utils/commons'; -import { computeChartDimensions } from '../utils/dimensions'; -import { Dimensions } from '../../../utils/dimensions'; -import { Domain } from '../../../utils/domain'; -import { AnnotationId, AxisId, GroupId, SpecId } from '../../../utils/ids'; -import { - areIndexedGeometryArraysEquals, - getValidXPosition, - getValidYPosition, - isCrosshairTooltipType, - isNoneTooltipType, - TooltipType, - TooltipValue, - TooltipValueFormatter, -} from '../utils/interactions'; -import { Scale, ScaleType } from '../../../utils/scales/scales'; -import { DEFAULT_TOOLTIP_SNAP, DEFAULT_TOOLTIP_TYPE, CursorEvent } from '../../../specs/settings'; -import { - AnnotationDimensions, - computeAnnotationDimensions, - computeAnnotationTooltipState, -} from '../annotations/annotation_utils'; -import { - getCursorBandPosition, - getCursorLinePosition, - getTooltipPosition, - TooltipPosition, -} from '../crosshair/crosshair_utils'; -import { - BrushExtent, - computeBrushExtent, - computeChartTransform, - computeSeriesDomains, - computeSeriesGeometries, - getUpdatedCustomSeriesColors, - isAllSeriesDeselected, - isChartAnimatable, - isHistogramModeEnabled, - isLineAreaOnlyChart, - setBarSeriesAccessors, - Transform, - updateDeselectedDataSeries, -} from './utils'; -import { LIGHT_THEME } from '../../../utils/themes/light_theme'; - -export interface Point { - x: number; - y: number; -} -export interface SeriesDomainsAndData { - xDomain: XDomain; - yDomain: YDomain[]; - splittedDataSeries: RawDataSeries[][]; - formattedDataSeries: { - stacked: FormattedDataSeries[]; - nonStacked: FormattedDataSeries[]; - }; - seriesColors: Map<string, DataSeriesColorsValues>; -} - -export type ElementClickListener = (values: GeometryValue[]) => void; -export type ElementOverListener = (values: GeometryValue[]) => void; -export type BrushEndListener = (min: number, max: number) => void; -export type LegendItemListener = (dataSeriesIdentifiers: DataSeriesColorsValues | null) => void; -export type CursorUpdateListener = (event?: CursorEvent) => void; -/** - * Listener to be called when chart render state changes - * - * `isRendered` value is `true` when rendering is complete and `false` otherwise - */ -export type RenderChangeListener = (isRendered: boolean) => void; -export type BasicListener = () => undefined | void; - -export const isDuplicateAxis = ( - { position, title }: AxisSpec, - { tickLabels }: AxisTicksDimensions, - tickMap: Map<AxisId, AxisTicksDimensions>, - specMap: Map<AxisId, AxisSpec>, -): boolean => { - const firstTickLabel = tickLabels[0]; - const lastTickLabel = tickLabels.slice(-1)[0]; - - let hasDuplicate = false; - tickMap.forEach(({ tickLabels: axisTickLabels }, axisId) => { - if ( - !hasDuplicate && - axisTickLabels && - tickLabels.length === axisTickLabels.length && - firstTickLabel === axisTickLabels[0] && - lastTickLabel === axisTickLabels.slice(-1)[0] - ) { - const spec = specMap.get(axisId); - - if (spec && spec.position === position && title === spec.title) { - hasDuplicate = true; - } - } - }); - - return hasDuplicate; -}; - -export class ChartStore { - constructor(id?: string) { - this.id = id || uuid.v4(); - } - debug = false; - id = uuid.v4(); - specsInitialized = observable.box(false); - chartInitialized = observable.box(false); - legendInitialized = observable.box(false); - enableHistogramMode = observable.box(false); - - parentDimensions: Dimensions = { - width: 0, - height: 0, - top: 0, - left: 0, - }; - chartDimensions: Dimensions = { - width: 0, - height: 0, - top: 0, - left: 0, - }; - chartTransform: Transform = { - x: 0, - y: 0, - rotate: 0, - }; - isBrushing = observable.box(false); - brushExtent: BrushExtent = { - minX: 0, - minY: 0, - maxX: 0, - maxY: 0, - }; - - resizeDebounce = 10; - - chartRotation: Rotation = 0; // updated from jsx - chartRendering: Rendering = 'canvas'; // updated from jsx - chartTheme: Theme = LIGHT_THEME; - hideDuplicateAxes = false; // updated from jsx - axesSpecs: Map<AxisId, AxisSpec> = new Map(); // readed from jsx - axesTicksDimensions: Map<AxisId, AxisTicksDimensions> = new Map(); // computed - axesPositions: Map<AxisId, Dimensions> = new Map(); // computed - axesVisibleTicks: Map<AxisId, AxisTick[]> = new Map(); // computed - axesTicks: Map<AxisId, AxisTick[]> = new Map(); // computed - axesGridLinesPositions: Map<AxisId, AxisLinePosition[]> = new Map(); // computed - - annotationSpecs = new Map<AnnotationId, AnnotationSpec>(); // read from jsx - - annotationDimensions = observable.map<AnnotationId, AnnotationDimensions>(new Map()); - - seriesSpecs: Map<SpecId, BasicSeriesSpec> = new Map(); // readed from jsx - isChartEmpty = observable.box(false); - activeChartId?: string; - seriesDomainsAndData?: SeriesDomainsAndData; // computed - xScale?: Scale; - yScales?: Map<GroupId, Scale>; - // custom X domain passed via <Settings /> - customXDomain?: Domain | DomainRange; - - legendItems: Map<string, LegendItem> = new Map(); - highlightedLegendItemKey: IObservableValue<string | null> = observable.box(null); - selectedLegendItemKey: IObservableValue<string | null> = observable.box(null); - // deselected/hidden data series from the legend - deselectedDataSeries: DataSeriesColorsValues[] | null = null; - customSeriesColors: Map<string, string> = new Map(); - seriesColorMap: Map<string, string> = new Map(); - totalBarsInCluster?: number; - - tooltipData = observable.array<TooltipValue>([], { deep: false }); - tooltipType = observable.box<TooltipType>(DEFAULT_TOOLTIP_TYPE); - tooltipSnap = observable.box<boolean>(DEFAULT_TOOLTIP_SNAP); - tooltipPosition = observable.object<TooltipPosition>({ - isRotatedHorizontal: true, - vPosition: { - bandTop: 0, - bandHeight: 0, - }, - hPosition: { - bandLeft: 0, - bandWidth: 0, - }, - }); - tooltipHeaderFormatter?: TooltipValueFormatter; - - /** cursorPosition is used by tooltip, so this is a way to expose the position for other uses */ - rawCursorPosition = observable.object<{ x: number; y: number }>({ x: 100, y: 100 }, undefined, { - deep: false, - }); - - /** position of the cursor relative to the chart */ - cursorPosition = observable.object<{ x: number; y: number }>({ x: -1, y: -1 }, undefined, { - deep: false, - }); - cursorBandPosition = observable.object<Dimensions & { visible: boolean }>( - { top: -1, left: -1, height: -1, width: -1, visible: false }, - undefined, - { - deep: false, - }, - ); - cursorLinePosition = observable.object<Dimensions>({ top: -1, left: -1, height: -1, width: -1 }, undefined, { - deep: false, - }); - externalCursorShown = observable.box(false); - - onElementClickListener?: ElementClickListener; - onElementOverListener?: ElementOverListener; - onElementOutListener?: BasicListener; - onBrushEndListener?: BrushEndListener; - onLegendItemOverListener?: LegendItemListener; - onLegendItemOutListener?: BasicListener; - onLegendItemClickListener?: LegendItemListener; - onLegendItemPlusClickListener?: LegendItemListener; - onLegendItemMinusClickListener?: LegendItemListener; - onLegendItemVisibilityToggleClickListener?: LegendItemListener; - onCursorUpdateListener?: CursorUpdateListener; - onRenderChangeListener?: RenderChangeListener; - - geometries: { - points: PointGeometry[]; - bars: BarGeometry[]; - areas: AreaGeometry[]; - lines: LineGeometry[]; - } | null = null; - - geometriesIndex: Map<any, IndexedGeometry[]> = new Map(); - geometriesIndexKeys: any[] = []; - highlightedGeometries = observable.array<IndexedGeometry>([], { deep: false }); - - animateData = false; - /** - * Define if the chart can be animated or not depending - * on the global configuration and on the number of elements per series - */ - canDataBeAnimated = false; - - showLegend = observable.box(false); - legendPosition = observable.box<Position>(Position.Right); - showLegendDisplayValue = observable.box(true); - isCursorOnChart = observable.box(false); - - chartCursor = computed(() => { - const { x: xPos, y: yPos } = this.cursorPosition; - if (yPos < 0 || xPos < 0) { - return 'default'; - } - if (this.highlightedGeometries.length > 0 && (this.onElementClickListener || this.onElementOverListener)) { - return 'pointer'; - } - return this.isBrushEnabled() ? 'crosshair' : 'default'; - }); - - /** - * determine if chart is currently active - */ - isActiveChart = computed(() => { - return !this.activeChartId ? true : this.activeChartId === this.id; - }); - - /** - * set activeChartId - */ - setActiveChartId = (chartId?: string) => { - this.activeChartId = chartId; - }; - - /** - * set the x value of the cursor - */ - setCursorValue = action((value: string | number) => { - this.externalCursorShown.set(true); - this.isCursorOnChart.set(true); - - if (!this.xScale) { - return; - } - - const xPosition = this.xScale.pureScale(value); - - if (xPosition == null || xPosition > this.chartDimensions.width + this.chartDimensions.left) { - this.clearTooltipAndHighlighted(); - return; - } - - const isLineAreaOnly = isLineAreaOnlyChart(this.seriesSpecs); - - const updatedCursorBand = getCursorBandPosition( - this.chartRotation, - this.chartDimensions, - { x: xPosition, y: 0 }, - { - value, - withinBandwidth: true, - }, - this.isTooltipSnapEnabled.get(), - this.xScale, - isLineAreaOnly ? 1 : this.totalBarsInCluster, - ); - - Object.assign(this.cursorBandPosition, updatedCursorBand); - - const tooltipAndHighlight = getTooltipAndHighlightFromXValue( - { x: xPosition, y: 0 }, - this.seriesSpecs, - this.axesSpecs, - this.geometriesIndex, - { - value, - withinBandwidth: true, - }, - this.isActiveChart.get(), - this.tooltipType.get(), - this.chartRotation, - this.yScales, - this.tooltipHeaderFormatter, - ); - if (!tooltipAndHighlight || tooltipAndHighlight.tooltipData.length === 0) { - this.clearTooltipAndHighlighted(false); - return; - } - // update tooltip visibility - if (tooltipAndHighlight.tooltipData.length === 0) { - this.tooltipData.clear(); - } else { - this.tooltipData.replace(tooltipAndHighlight.tooltipData); - } - }); - - /** - * x and y values are relative to the container. - */ - setCursorPosition = action((x: number, y: number, updateCursor: boolean = true) => { - this.isCursorOnChart.set(true); - this.rawCursorPosition.x = x; - this.rawCursorPosition.y = y; - - if (!this.seriesDomainsAndData || this.tooltipType.get() === TooltipType.None) { - return; - } - this.externalCursorShown.set(false); - - // get positions relative to chart - let xPos = x - this.chartDimensions.left; - let yPos = y - this.chartDimensions.top; - // limit cursorPosition to chartDimensions - // note: to debug and inspect tooltip html, just comment the following ifs - if (xPos < 0 || xPos >= this.chartDimensions.width) { - xPos = -1; - } - if (yPos < 0 || yPos >= this.chartDimensions.height) { - yPos = -1; - } - this.cursorPosition.x = xPos; - this.cursorPosition.y = yPos; - - // hide tooltip if outside chart dimensions - if (yPos === -1 || xPos === -1) { - this.isCursorOnChart.set(false); - if (this.onCursorUpdateListener && this.isActiveChart.get()) { - this.onCursorUpdateListener(); - } - this.clearTooltipAndHighlighted(); - return; - } - - // get the cursor position depending on the chart rotation - const xAxisCursorPosition = getValidXPosition(xPos, yPos, this.chartRotation, this.chartDimensions); - const yAxisCursorPosition = getValidYPosition(xPos, yPos, this.chartRotation, this.chartDimensions); - const axisCursorPosition = { x: xAxisCursorPosition, y: yAxisCursorPosition }; - - // only if we have a valid cursor position and the necessary scale - if (xAxisCursorPosition < 0 || !this.xScale || !this.yScales) { - this.clearTooltipAndHighlighted(); - return; - } - - // invert the cursor position to get the scale value - const xValue = this.xScale.invertWithStep(xAxisCursorPosition, this.geometriesIndexKeys); - if (updateCursor && this.onCursorUpdateListener) { - this.onCursorUpdateListener({ - chartId: this.id, - scale: this.xScale.type, - unit: this.xScale.unit, - value: xValue.value, - }); - } - - // update che cursorBandPosition based on chart configuration - const isLineAreaOnly = isLineAreaOnlyChart(this.seriesSpecs); - const updatedCursorBand = getCursorBandPosition( - this.chartRotation, - this.chartDimensions, - axisCursorPosition, - { - value: xValue.value, - withinBandwidth: true, - }, - this.isTooltipSnapEnabled.get(), - this.xScale, - isLineAreaOnly ? 1 : this.totalBarsInCluster, - ); - Object.assign(this.cursorBandPosition, updatedCursorBand); - - const updatedCursorLine = getCursorLinePosition(this.chartRotation, this.chartDimensions, this.cursorPosition); - Object.assign(this.cursorLinePosition, updatedCursorLine); - - const isSingleValueXScale = this.xScale.isSingleValue(); - - set( - this.tooltipPosition, - getTooltipPosition( - this.chartDimensions, - this.chartRotation, - this.cursorBandPosition, - this.cursorPosition, - isSingleValueXScale, - ), - ); - - const tooltipAndHighlight = getTooltipAndHighlightFromXValue( - axisCursorPosition, - this.seriesSpecs, - this.axesSpecs, - this.geometriesIndex, - xValue, - this.isActiveChart.get(), - this.tooltipType.get(), - this.chartRotation, - this.yScales, - this.tooltipHeaderFormatter, - ); - - // if no element, hide everything keep crosshair - if (!tooltipAndHighlight || tooltipAndHighlight.tooltipData.length === 0) { - this.clearTooltipAndHighlighted(false); - return; - } - const { highlightedGeometries, tooltipData } = tooltipAndHighlight; - - // if there's an annotation rect tooltip & there isn't a single highlighted element, hide - const annotationTooltip = this.annotationTooltipState.get(); - const hasRectAnnotationToolip = - annotationTooltip && - annotationTooltip.isVisible && - annotationTooltip.annotationType === AnnotationTypes.Rectangle; - if (hasRectAnnotationToolip && highlightedGeometries.length === 0) { - this.clearTooltipAndHighlighted(); - return; - } - - // check if we already have send out an over/out event on highlighted elements - if ( - this.onElementOverListener && - !areIndexedGeometryArraysEquals(highlightedGeometries, this.highlightedGeometries.toJS()) - ) { - if (highlightedGeometries.length > 0) { - this.onElementOverListener(highlightedGeometries.map(({ value }) => value)); - } else { - if (this.onElementOutListener) { - this.onElementOutListener(); - } - } - } - - // update highlighted geometries observer - this.highlightedGeometries.replace(highlightedGeometries); - - // update tooltip visibility - if (tooltipData.length === 0) { - this.tooltipData.clear(); - } else { - this.tooltipData.replace(tooltipData); - } - }); - - legendItemTooltipValues = computed(() => { - const xPos = this.rawCursorPosition.x - this.chartDimensions.left; - const yPos = this.rawCursorPosition.y - this.chartDimensions.top; - if (xPos > 0 && xPos <= this.chartDimensions.width && yPos > 0 && yPos <= this.chartDimensions.height) { - return getSeriesTooltipValues(this.tooltipData, ''); - } - // update legend items with value to display - return getSeriesTooltipValues(this.tooltipData); - }); - - annotationTooltipState = computed(() => { - // get positions relative to chart - const xPos = this.rawCursorPosition.x - this.chartDimensions.left; - const yPos = this.rawCursorPosition.y - this.chartDimensions.top; - - // only if we have a valid cursor position and the necessary scale - if (!this.xScale || !this.yScales) { - return null; - } - - const cursorPosition = { - x: xPos, - y: yPos, - }; - - const tooltipState = computeAnnotationTooltipState( - cursorPosition, - this.annotationDimensions, - this.annotationSpecs, - this.chartRotation, - this.axesSpecs, - this.chartDimensions, - ); - - // If there's a highlighted chart element tooltip value, don't show annotation tooltip - if (tooltipState && tooltipState.isVisible && tooltipState.annotationType === AnnotationTypes.Rectangle) { - for (const tooltipValue of this.tooltipData) { - if (tooltipValue.isHighlighted) { - return null; - } - } - } - - return tooltipState; - }); - - isTooltipVisible = computed(() => { - return ( - !this.isBrushing.get() && - this.tooltipType.get() !== TooltipType.None && - this.cursorPosition.x > -1 && - this.cursorPosition.y > -1 && - this.tooltipData.length > 0 && - this.isActiveChart.get() - ); - }); - - isCrosshairVisible = computed(() => { - return ( - !this.isBrushing.get() && - isCrosshairTooltipType(this.tooltipType.get()) && - !this.isChartEmpty.get() && - (this.externalCursorShown.get() || (this.cursorPosition.x > -1 && this.cursorPosition.y > -1)) - ); - }); - - isTooltipSnapEnabled = computed(() => { - return (this.xScale && this.xScale.bandwidth > 0) || this.tooltipSnap.get(); - }); - - clearTooltipAndHighlighted = action((clearCursorBand = true) => { - // if exist any highlighted geometry, send an out element event - if (this.onElementOutListener && this.highlightedGeometries.length > 0) { - this.onElementOutListener(); - } - // clear highlight geoms - this.highlightedGeometries.clear(); - this.tooltipData.clear(); - if (clearCursorBand) { - Object.assign(this.cursorBandPosition, { visible: false }); - } - }); - - setShowLegend = action((showLegend: boolean) => { - this.showLegend.set(showLegend); - }); - - highlightedLegendItem = computed(() => { - const key = this.highlightedLegendItemKey.get(); - return key == null ? null : this.legendItems.get(key); - }); - - selectedLegendItem = computed(() => { - const key = this.selectedLegendItemKey.get(); - return key == null ? null : this.legendItems.get(key); - }); - - onLegendItemOver = action((legendItemKey: string | null) => { - if (legendItemKey) { - const legendItem = this.legendItems.get(legendItemKey); - if (legendItem && findDataSeriesByColorValues(this.deselectedDataSeries, legendItem.value) > -1) { - return; - } - } - this.highlightedLegendItemKey.set(legendItemKey); - if (this.onLegendItemOverListener) { - const currentLegendItem = this.highlightedLegendItem.get(); - const listenerData = currentLegendItem ? currentLegendItem.value : null; - this.onLegendItemOverListener(listenerData); - } - }); - - onLegendItemOut = action(() => { - this.highlightedLegendItemKey.set(null); - if (this.onLegendItemOutListener) { - this.onLegendItemOutListener(); - } - }); - - onLegendItemClick = action((legendItemKey: string) => { - // Disabling the select until we implement the right contextual menu - // with extend possibility - // if (legendItemKey !== this.selectedLegendItemKey.get()) { - // this.selectedLegendItemKey.set(legendItemKey); - // } else { - // this.selectedLegendItemKey.set(null); - // } - if (this.onLegendItemClickListener) { - const currentLegendItem = legendItemKey == null ? null : this.legendItems.get(legendItemKey); - const listenerData = currentLegendItem ? currentLegendItem.value : null; - this.onLegendItemClickListener(listenerData); - } - }); - - onLegendItemPlusClick = action(() => { - if (this.onLegendItemPlusClickListener) { - const currentLegendItem = this.selectedLegendItem.get(); - const listenerData = currentLegendItem ? currentLegendItem.value : null; - this.onLegendItemPlusClickListener(listenerData); - } - }); - - onLegendItemMinusClick = action(() => { - if (this.onLegendItemMinusClickListener) { - const currentLegendItem = this.selectedLegendItem.get(); - const listenerData = currentLegendItem ? currentLegendItem.value : null; - this.onLegendItemMinusClickListener(listenerData); - } - }); - - toggleSingleSeries = action((legendItemKey: string) => { - const legendItem = this.legendItems.get(legendItemKey); - - if (legendItem) { - if (findDataSeriesByColorValues(this.deselectedDataSeries, legendItem.value) > -1) { - this.deselectedDataSeries = [...this.legendItems.values()] - .filter((item: LegendItem) => item.key !== legendItemKey) - .map((item: LegendItem) => item.value); - } else { - this.deselectedDataSeries = [legendItem.value]; - } - - this.computeChart(); - } - }); - - updateHighlightedLegendItemKey = action((legendItemKey: string, deselected: boolean) => { - if (deselected) { - this.highlightedLegendItemKey.set(null); - } else { - this.highlightedLegendItemKey.set(legendItemKey); - } - }); - - toggleSeriesVisibility = action((legendItemKey: string) => { - const legendItem = this.legendItems.get(legendItemKey); - - if (legendItem) { - this.deselectedDataSeries = updateDeselectedDataSeries(this.deselectedDataSeries, legendItem.value); - const deselected = findDataSeriesByColorValues(this.deselectedDataSeries, legendItem.value) > -1; - this.updateHighlightedLegendItemKey(legendItemKey, deselected); - this.computeChart(); - } - }); - - setSeriesColor = action((legendItemKey: string, color: string) => { - const legendItem = this.legendItems.get(legendItemKey); - - if (legendItem) { - const { specId } = legendItem.value; - - const spec = this.seriesSpecs.get(specId); - if (spec) { - if (spec.customSeriesColors) { - spec.customSeriesColors.set(legendItem.value, color); - } else { - const specCustomSeriesColors = new Map(); - spec.customSeriesColors = specCustomSeriesColors; - spec.customSeriesColors.set(legendItem.value, color); - } - } - - this.computeChart(); - } - }); - - onBrushStart = action(() => { - if (!this.onBrushEndListener) { - return; - } - this.isBrushing.set(true); - }); - - onBrushEnd = action((start: Point, end: Point) => { - if (!this.onBrushEndListener) { - return; - } - this.isBrushing.set(false); - const minValue = Math.min(start.x, end.x); - const maxValue = Math.max(start.x, end.x); - if (maxValue === minValue) { - // if 0 size brush, avoid computing the value - return; - } - const min = this.xScale!.invert(minValue - this.chartDimensions.left); - const max = this.xScale!.invert(maxValue - this.chartDimensions.left); - this.onBrushEndListener(min, max); - }); - - handleChartClick() { - if (this.highlightedGeometries.length > 0 && this.onElementClickListener) { - this.onElementClickListener(this.highlightedGeometries.toJS().map(({ value }) => value)); - } - } - - resetDeselectedDataSeries() { - this.deselectedDataSeries = null; - } - - setOnElementClickListener(listener: ElementClickListener) { - this.onElementClickListener = listener; - } - setOnElementOverListener(listener: ElementOverListener) { - this.onElementOverListener = listener; - } - setOnElementOutListener(listener: BasicListener) { - this.onElementOutListener = listener; - } - setOnBrushEndListener(listener: BrushEndListener) { - this.onBrushEndListener = listener; - } - setOnLegendItemOverListener(listener: LegendItemListener) { - this.onLegendItemOverListener = listener; - } - setOnLegendItemOutListener(listener: BasicListener) { - this.onLegendItemOutListener = listener; - } - setOnLegendItemClickListener(listener: LegendItemListener) { - this.onLegendItemClickListener = listener; - } - setOnLegendItemPlusClickListener(listener: LegendItemListener) { - this.onLegendItemPlusClickListener = listener; - } - setOnLegendItemMinusClickListener(listener: LegendItemListener) { - this.onLegendItemMinusClickListener = listener; - } - setOnCursorUpdateListener(listener: CursorUpdateListener) { - this.onCursorUpdateListener = listener; - } - setOnRenderChangeListener(listener: RenderChangeListener) { - this.onRenderChangeListener = listener; - - this.chartInitialized.observe(({ newValue, oldValue }) => { - if (this.onRenderChangeListener && newValue !== oldValue) { - this.onRenderChangeListener(newValue); - } - }); - } - removeElementClickListener() { - this.onElementClickListener = undefined; - } - removeElementOverListener() { - this.onElementOverListener = undefined; - } - removeElementOutListener() { - this.onElementOutListener = undefined; - } - removeOnLegendItemOverListener() { - this.onLegendItemOverListener = undefined; - } - removeOnLegendItemOutListener() { - this.onLegendItemOutListener = undefined; - } - removeOnLegendItemPlusClickListener() { - this.onLegendItemPlusClickListener = undefined; - } - removeOnLegendItemMinusClickListener() { - this.onLegendItemMinusClickListener = undefined; - } - removeOnCursorUpdateListener() { - this.onCursorUpdateListener = undefined; - } - removeOnRenderChangeListener() { - this.onRenderChangeListener = undefined; - } - - isBrushEnabled(): boolean { - if (!this.xScale) { - return false; - } - return this.xScale.type !== ScaleType.Ordinal && Boolean(this.onBrushEndListener); - } - - updateParentDimensions(width: number, height: number, top: number, left: number) { - let isChanged = false; - if (width !== this.parentDimensions.width) { - isChanged = true; - this.parentDimensions.width = width; - } - if (height !== this.parentDimensions.height) { - isChanged = true; - this.parentDimensions.height = height; - } - if (top !== this.parentDimensions.top) { - isChanged = true; - this.parentDimensions.top = top; - } - if (left !== this.parentDimensions.left) { - isChanged = true; - this.parentDimensions.left = left; - } - if (isChanged) { - this.computeChart(); - } - } - addSeriesSpec(seriesSpec: BasicSeriesSpec | LineSeriesSpec | AreaSeriesSpec | BarSeriesSpec) { - this.seriesSpecs.set(seriesSpec.id, seriesSpec); - - const isEnabled = isHistogramModeEnabled(this.seriesSpecs); - this.enableHistogramMode.set(isEnabled); - - setBarSeriesAccessors(isEnabled, this.seriesSpecs); - } - removeSeriesSpec(specId: SpecId) { - this.seriesSpecs.delete(specId); - - const isEnabled = isHistogramModeEnabled(this.seriesSpecs); - this.enableHistogramMode.set(isEnabled); - - setBarSeriesAccessors(isEnabled, this.seriesSpecs); - } - - /** - * Add an axis spec to the store - * @param axisSpec an axis spec - */ - addAxisSpec(axisSpec: AxisSpec) { - this.axesSpecs.set(axisSpec.id, axisSpec); - } - removeAxisSpec(axisId: AxisId) { - this.axesSpecs.delete(axisId); - } - - addAnnotationSpec(annotationSpec: AnnotationSpec) { - if (isLineAnnotation(annotationSpec)) { - const { style } = annotationSpec; - - const mergedLineStyle = mergeWithDefaultAnnotationLine(style); - annotationSpec.style = mergedLineStyle; - } - if (isRectAnnotation(annotationSpec)) { - const { style } = annotationSpec; - - const mergedRectStyle = mergeWithDefaultAnnotationRect(style); - annotationSpec.style = mergedRectStyle; - } - this.annotationSpecs.set(annotationSpec.annotationId, annotationSpec); - } - - removeAnnotationSpec(annotationId: AnnotationId) { - this.annotationSpecs.delete(annotationId); - } - - computeChart() { - this.chartInitialized.set(false); - // compute only if parent dimensions are computed - if (this.parentDimensions.width === 0 || this.parentDimensions.height === 0) { - return; - } - // avoid compute if no specs are specified - if (this.seriesSpecs.size === 0) { - return; - } - - // When specs are not initialized, reset selectedDataSeries to null - if (!this.specsInitialized.get()) { - this.deselectedDataSeries = null; - } - - // merge Y custom domains specified on the axis - const customYDomainsByGroupId = mergeYCustomDomainsByGroupId(this.axesSpecs, this.chartRotation); - - // compute general X and Y domains, split series based on split accessors - // process stacked and non-stacked values series formatting the data - this.seriesDomainsAndData = computeSeriesDomains( - this.seriesSpecs, - customYDomainsByGroupId, - this.customXDomain, - this.deselectedDataSeries, - ); - - // Merge all series spec custom colors with state custom colors map - const updatedCustomSeriesColors = getUpdatedCustomSeriesColors(this.seriesSpecs); - this.customSeriesColors = new Map([...this.customSeriesColors, ...updatedCustomSeriesColors]); - - this.seriesColorMap = getSeriesColorMap( - this.seriesDomainsAndData.seriesColors, - this.chartTheme.colors, - this.customSeriesColors, - ); - - this.legendItems = computeLegend( - this.seriesDomainsAndData.seriesColors, - this.seriesColorMap, - this.seriesSpecs, - this.chartTheme.colors.defaultVizColor, - this.axesSpecs, - this.deselectedDataSeries, - ); - - if (!this.legendInitialized.get()) { - this.legendInitialized.set(true); - - if (this.legendItems.size > 0 && this.showLegend.get()) { - return; - } - } - this.isChartEmpty.set(isAllSeriesDeselected(this.legendItems)); - - const { xDomain, yDomain, formattedDataSeries } = this.seriesDomainsAndData; - - // compute how many bar series are clustered - const { totalBarsInCluster } = countBarsInCluster(formattedDataSeries.stacked, formattedDataSeries.nonStacked); - this.totalBarsInCluster = totalBarsInCluster; - - // compute axis dimensions - const bboxCalculator = new CanvasTextBBoxCalculator(); - const barsPadding = this.enableHistogramMode.get() - ? this.chartTheme.scales.histogramPadding - : this.chartTheme.scales.barsPadding; - - this.axesTicksDimensions.clear(); - this.axesSpecs.forEach((axisSpec) => { - const { id } = axisSpec; - const dimensions = computeAxisTicksDimensions( - axisSpec, - xDomain, - yDomain, - totalBarsInCluster, - bboxCalculator, - this.chartRotation, - this.chartTheme.axes, - barsPadding, - this.enableHistogramMode.get(), - ); - - if ( - dimensions && - (!this.hideDuplicateAxes || !isDuplicateAxis(axisSpec, dimensions, this.axesTicksDimensions, this.axesSpecs)) - ) { - this.axesTicksDimensions.set(id, dimensions); - } - }); - bboxCalculator.destroy(); - - // compute chart dimensions - const computedChartDims = computeChartDimensions( - this.parentDimensions, - this.chartTheme, - this.axesTicksDimensions, - this.axesSpecs, - ); - this.chartDimensions = computedChartDims.chartDimensions; - - this.chartTransform = computeChartTransform(this.chartDimensions, this.chartRotation); - this.brushExtent = computeBrushExtent(this.chartDimensions, this.chartRotation, this.chartTransform); - - const seriesGeometries = computeSeriesGeometries( - this.seriesSpecs, - xDomain, - yDomain, - formattedDataSeries, - this.seriesColorMap, - this.chartTheme, - this.chartDimensions, - this.chartRotation, - this.axesSpecs, - this.enableHistogramMode.get(), - ); - - this.geometries = seriesGeometries.geometries; - this.xScale = seriesGeometries.scales.xScale; - - const isSingleValueXScale = this.xScale.isSingleValue(); - if (isSingleValueXScale && !isNoneTooltipType(this.tooltipType.get())) { - this.tooltipType.set(TooltipType.Follow); - } - - this.yScales = seriesGeometries.scales.yScales; - this.geometriesIndex = seriesGeometries.geometriesIndex; - this.geometriesIndexKeys = [...this.geometriesIndex.keys()].sort(compareByValueAsc); - - // compute visible ticks and their positions - const axisTicksPositions = getAxisTicksPositions( - computedChartDims, - this.chartTheme, - this.chartRotation, - this.axesSpecs, - this.axesTicksDimensions, - xDomain, - yDomain, - totalBarsInCluster, - this.enableHistogramMode.get(), - barsPadding, - ); - - this.axesPositions = axisTicksPositions.axisPositions; - this.axesTicks = axisTicksPositions.axisTicks; - this.axesVisibleTicks = axisTicksPositions.axisVisibleTicks; - this.axesGridLinesPositions = axisTicksPositions.axisGridLinesPositions; - - // annotation computations - const updatedAnnotationDimensions = computeAnnotationDimensions( - this.annotationSpecs, - this.chartDimensions, - this.chartRotation, - this.yScales, - this.xScale, - this.axesSpecs, - this.totalBarsInCluster, - this.enableHistogramMode.get(), - ); - - this.annotationDimensions.replace(updatedAnnotationDimensions); - - this.canDataBeAnimated = isChartAnimatable(seriesGeometries.geometriesCounts, this.animateData); - // temporary disabled until - // https://github.com/elastic/elastic-charts/issues/89 and https://github.com/elastic/elastic-charts/issues/41 - this.canDataBeAnimated = false; - this.chartInitialized.set(true); - // this.setCursorPosition(100, 100); - } -} diff --git a/src/chart_types/xy_chart/tooltip/tooltip.test.ts b/src/chart_types/xy_chart/tooltip/tooltip.test.ts index e648255312..dd79b82f80 100644 --- a/src/chart_types/xy_chart/tooltip/tooltip.test.ts +++ b/src/chart_types/xy_chart/tooltip/tooltip.test.ts @@ -1,16 +1,18 @@ -import { getAxisId, getGroupId, getSpecId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; -import { BarGeometry } from '../rendering/rendering'; -import { AxisSpec, BarSeriesSpec, Position } from '../utils/specs'; +import { AxisSpec, BarSeriesSpec, Position, SpecTypes, SeriesTypes } from '../utils/specs'; import { formatTooltip } from './tooltip'; +import { BarGeometry } from '../../../utils/geometry'; +import { ChartTypes } from '../..'; describe('Tooltip formatting', () => { - const SPEC_ID_1 = getSpecId('bar_1'); - const SPEC_GROUP_ID_1 = getGroupId('bar_group_1'); + const SPEC_ID_1 = 'bar_1'; + const SPEC_GROUP_ID_1 = 'bar_group_1'; const SPEC_1: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: SPEC_ID_1, groupId: SPEC_GROUP_ID_1, - seriesType: 'bar', + seriesType: SeriesTypes.Bar, data: [], xAccessor: 0, yAccessors: [1], @@ -23,7 +25,9 @@ describe('Tooltip formatting', () => { y0Accessors: [1], }; const YAXIS_SPEC: AxisSpec = { - id: getAxisId('axis_1'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + id: 'axis_1', groupId: SPEC_GROUP_ID_1, hide: false, position: Position.Left, diff --git a/src/chart_types/xy_chart/tooltip/tooltip.ts b/src/chart_types/xy_chart/tooltip/tooltip.ts index 607a51ecd2..45e2b0e32d 100644 --- a/src/chart_types/xy_chart/tooltip/tooltip.ts +++ b/src/chart_types/xy_chart/tooltip/tooltip.ts @@ -1,19 +1,14 @@ -import { TooltipValue, isFollowTooltipType, TooltipType, TooltipValueFormatter } from '../utils/interactions'; -import { IndexedGeometry, isPointOnGeometry, AccessorType } from '../rendering/rendering'; +import { TooltipValue } from '../utils/interactions'; import { getColorValuesAsString } from '../utils/series'; import { AxisSpec, BasicSeriesSpec, - Rotation, - isAreaSeriesSpec, isBandedSpec, + isAreaSeriesSpec, isBarSeriesSpec, TickFormatterOptions, } from '../utils/specs'; -import { SpecId, AxisId, GroupId } from '../../../utils/ids'; -import { getAxesSpecForSpecId } from '../store/utils'; -import { Scale } from '../../../utils/scales/scales'; -import { Point } from '../store/chart_state'; +import { IndexedGeometry, AccessorType } from '../../../utils/geometry'; import { getAccessorFormatLabel } from '../../../utils/accessor'; export interface TooltipLegendValue { @@ -85,90 +80,6 @@ export function formatTooltip( }; } -export function emptyFormatter<T>(value: T): T { +function emptyFormatter<T>(value: T): T { return value; } - -export function getTooltipAndHighlightFromXValue( - axisCursorPosition: Point, - seriesSpecs: Map<SpecId, BasicSeriesSpec>, - axesSpecs: Map<AxisId, AxisSpec>, - geometriesIndex: Map<any, IndexedGeometry[]>, - xValue: { - value: any; - withinBandwidth: boolean; - }, - isActiveChart: boolean, - tooltipType: TooltipType, - chartRotation: Rotation, - yScales?: Map<GroupId, Scale>, - tooltipHeaderFormatter?: TooltipValueFormatter, -): - | { - tooltipData: TooltipValue[]; - highlightedGeometries: IndexedGeometry[]; - } - | undefined { - // get the elements on at this cursor position - const elements = geometriesIndex.get(xValue.value); - - // if no element, hide everything - if (!elements || elements.length === 0) { - return; - } - - // build the tooltip value list - let xValueInfo: TooltipValue | null = null; - const highlightedGeometries: IndexedGeometry[] = []; - const tooltipData = elements - .filter(({ value: { y } }) => y !== null) - .reduce<TooltipValue[]>((acc, indexedGeometry) => { - const { - geometryId: { specId }, - } = indexedGeometry; - const spec = seriesSpecs.get(specId); - - // safe guard check - if (!spec) { - return acc; - } - const { xAxis, yAxis } = getAxesSpecForSpecId(axesSpecs, spec.groupId); - - // yScales is ensured by the enclosing if - const yScale = yScales!.get(spec.groupId); - if (!yScale) { - return acc; - } - - // check if the pointer is on the geometry - let isHighlighted = false; - if (isActiveChart && isPointOnGeometry(axisCursorPosition.x, axisCursorPosition.y, indexedGeometry)) { - isHighlighted = true; - highlightedGeometries.push(indexedGeometry); - } - - // if it's a follow tooltip, and no element is highlighted - // not add that element into the tooltip list - if (!isHighlighted && isFollowTooltipType(tooltipType)) { - return acc; - } - // format the tooltip values - const yAxisFormatSpec = [0, 180].includes(chartRotation) ? yAxis : xAxis; - const formattedTooltip = formatTooltip(indexedGeometry, spec, false, isHighlighted, yAxisFormatSpec); - // format only one time the x value - if (!xValueInfo) { - // if we have a tooltipHeaderFormatter, then don't pass in the xAxis as the user will define a formatter - const xAxisFormatSpec = [0, 180].includes(chartRotation) ? xAxis : yAxis; - const formatterAxis = tooltipHeaderFormatter ? undefined : xAxisFormatSpec; - xValueInfo = formatTooltip(indexedGeometry, spec, true, false, formatterAxis); - return [xValueInfo, ...acc, formattedTooltip]; - } - - return [...acc, formattedTooltip]; - }, []); - - return { - tooltipData, - highlightedGeometries, - }; -} diff --git a/src/chart_types/xy_chart/utils/axis_utils.test.ts b/src/chart_types/xy_chart/utils/axis_utils.test.ts index b2b57f2474..daed9569fc 100644 --- a/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -1,8 +1,8 @@ import { XDomain } from '../domains/x_domain'; import { YDomain } from '../domains/y_domain'; -import { AxisSpec, DomainRange, Position, AxisStyle } from './specs'; +import { AxisSpec, DomainRange, Position, AxisStyle, SpecTypes } from './specs'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; -import { AxisId, getAxisId, getGroupId, GroupId } from '../../../utils/ids'; +import { AxisId, GroupId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { AxisTick, @@ -28,13 +28,14 @@ import { isVerticalAxis, isYDomain, getAxisTickLabelPadding, - mergeYCustomDomainsByGroupId, isVerticalGrid, isHorizontalGrid, } from './axis_utils'; import { CanvasTextBBoxCalculator } from '../../../utils/bbox/canvas_text_bbox_calculator'; import { SvgTextBBoxCalculator } from '../../../utils/bbox/svg_text_bbox_calculator'; import { niceTimeFormatter } from '../../../utils/data/formatters'; +import { mergeYCustomDomainsByGroupId } from '../state/selectors/merge_y_custom_domains'; +import { ChartTypes } from '../..'; describe('Axis computational utils', () => { const mockedRect = { @@ -74,8 +75,10 @@ describe('Axis computational utils', () => { maxLabelTextHeight: 10, }; const verticalAxisSpec: AxisSpec = { - id: getAxisId('axis_1'), - groupId: getGroupId('group_1'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + id: 'axis_1', + groupId: 'group_1', hide: false, showOverlappingTicks: false, showOverlappingLabels: false, @@ -90,8 +93,10 @@ describe('Axis computational utils', () => { }; const horizontalAxisSpec: AxisSpec = { - id: getAxisId('axis_2'), - groupId: getGroupId('group_1'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + id: 'axis_2', + groupId: 'group_1', hide: false, showOverlappingTicks: false, showOverlappingLabels: false, @@ -105,8 +110,10 @@ describe('Axis computational utils', () => { }; const verticalAxisSpecWTitle: AxisSpec = { - id: getAxisId('axis_1'), - groupId: getGroupId('group_1'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + id: 'axis_1', + groupId: 'group_1', title: 'v axis', hide: false, showOverlappingTicks: false, @@ -121,8 +128,10 @@ describe('Axis computational utils', () => { integersOnly: false, }; const xAxisWithTime: AxisSpec = { - id: getAxisId('axis_1'), - groupId: getGroupId('group_1'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + id: 'axis_1', + groupId: 'group_1', title: 'v axis', hide: false, showOverlappingTicks: false, @@ -136,8 +145,8 @@ describe('Axis computational utils', () => { }; // const horizontalAxisSpecWTitle: AxisSpec = { - // id: getAxisId('axis_2'), - // groupId: getGroupId('group_1'), + // id: ('axis_2'), + // groupId: ('group_1'), // title: 'h axis', // hide: false, // showOverlappingTicks: false, @@ -160,7 +169,7 @@ describe('Axis computational utils', () => { const yDomain: YDomain = { scaleType: ScaleType.Linear, - groupId: getGroupId('group_1'), + groupId: 'group_1', type: 'yDomain', domain: [0, 1], isBandScale: false, @@ -177,7 +186,7 @@ describe('Axis computational utils', () => { computeAxisTicksDimensions(ungroupedAxisSpec, xDomain, [yDomain], 1, bboxCalculator, 0, axes); }; - const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: getGroupId('foo') }; + const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: 'foo' }; expect(computeScalelessSpec).toThrowError('Cannot compute scale for axis spec axis_1'); bboxCalculator.destroy(); @@ -263,7 +272,7 @@ describe('Axis computational utils', () => { expect(yScale!.range).toEqual([100, 0]); expect(yScale!.ticks()).toEqual([0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]); - const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: getGroupId('foo') }; + const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: 'foo' }; const nullYScale = getScaleForAxisSpec(ungroupedAxisSpec, xDomain, [yDomain], 0, 0, 100, 0); expect(nullYScale).toBe(null); @@ -843,8 +852,7 @@ describe('Axis computational utils', () => { // validate assumptions for test expect(verticalAxisSpec.id).toEqual(verticalAxisSpecWTitle.id); - const axisSpecs = new Map(); - axisSpecs.set(verticalAxisSpecWTitle.id, verticalAxisSpecWTitle); + const axisSpecs = [verticalAxisSpecWTitle]; const axisDims = new Map(); axisDims.set(verticalAxisSpecWTitle.id, axis1Dims); @@ -871,7 +879,7 @@ describe('Axis computational utils', () => { height: 100, }); - axisSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + axisSpecs[0] = verticalAxisSpec; axisDims.set(verticalAxisSpec.id, axis1Dims); @@ -1044,11 +1052,11 @@ describe('Axis computational utils', () => { test('should not compute axis ticks positions if missaligned specs', () => { const chartRotation = 0; - const axisSpecs = new Map<AxisId, AxisSpec>(); - axisSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + + const axisSpecs = [verticalAxisSpec]; const axisDims = new Map<AxisId, AxisTicksDimensions>(); - axisDims.set(getAxisId('not_a_mapped_one'), axis1Dims); + axisDims.set('not_a_mapped_one', axis1Dims); const axisTicksPosition = getAxisTicksPositions( { @@ -1072,8 +1080,8 @@ describe('Axis computational utils', () => { test('should compute axis ticks positions', () => { const chartRotation = 0; - const axisSpecs = new Map<AxisId, AxisSpec>(); - axisSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + + const axisSpecs = [verticalAxisSpec]; const axisDims = new Map<AxisId, AxisTicksDimensions>(); axisDims.set(verticalAxisSpec.id, axis1Dims); @@ -1133,9 +1141,8 @@ describe('Axis computational utils', () => { const verticalAxisWithTopLegendPosition = axisTicksPositionWithTopLegend.axisPositions.get(verticalAxisSpec.id); expect(verticalAxisWithTopLegendPosition).toEqual(expectedPositionWithTopLegend); - const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: getGroupId('foo') }; - const invalidSpecs = new Map<AxisId, AxisSpec>(); - invalidSpecs.set(verticalAxisSpec.id, ungroupedAxisSpec); + const ungroupedAxisSpec = { ...verticalAxisSpec, groupId: 'foo' }; + const invalidSpecs = [ungroupedAxisSpec]; const computeScalelessSpec = () => { getAxisTicksPositions( { @@ -1203,7 +1210,7 @@ describe('Axis computational utils', () => { }); test('should merge axis domains by group id', () => { - const groupId = getGroupId('group_1'); + const groupId = 'group_1'; const domainRange1 = { min: 2, max: 9, @@ -1211,8 +1218,7 @@ describe('Axis computational utils', () => { verticalAxisSpec.domain = domainRange1; - const axesSpecs = new Map<AxisId, AxisSpec>(); - axesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + const axesSpecs = [verticalAxisSpec]; // Base case const expectedSimpleMap = new Map<GroupId, DomainRange>(); @@ -1227,10 +1233,10 @@ describe('Axis computational utils', () => { max: 7, }; - const altVerticalAxisSpec = { ...verticalAxisSpec, id: getAxisId('axis2') }; + const altVerticalAxisSpec = { ...verticalAxisSpec, id: 'axis2' }; altVerticalAxisSpec.domain = domainRange2; - axesSpecs.set(altVerticalAxisSpec.id, altVerticalAxisSpec); + axesSpecs.push(altVerticalAxisSpec); const expectedMergedMap = new Map<GroupId, DomainRange>(); expectedMergedMap.set(groupId, { min: 0, max: 9 }); @@ -1243,7 +1249,7 @@ describe('Axis computational utils', () => { min: 5, max: 15, }; - axesSpecs.set(horizontalAxisSpec.id, horizontalAxisSpec); + axesSpecs.push(horizontalAxisSpec); const attemptToMerge = () => { mergeYCustomDomainsByGroupId(axesSpecs, 0); @@ -1253,7 +1259,7 @@ describe('Axis computational utils', () => { }); test('should merge axis domains by group id: partial upper bounded prevDomain with complete domain', () => { - const groupId = getGroupId('group_1'); + const groupId = 'group_1'; const domainRange1 = { max: 9, }; @@ -1265,13 +1271,10 @@ describe('Axis computational utils', () => { verticalAxisSpec.domain = domainRange1; - const axesSpecs = new Map<AxisId, AxisSpec>(); - axesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); - - const axis2 = { ...verticalAxisSpec, id: getAxisId('axis2') }; + const axis2 = { ...verticalAxisSpec, id: 'axis2' }; axis2.domain = domainRange2; - axesSpecs.set(axis2.id, axis2); + const axesSpecs = [verticalAxisSpec, axis2]; const expectedMergedMap = new Map<GroupId, DomainRange>(); expectedMergedMap.set(groupId, { min: 0, max: 9 }); @@ -1281,7 +1284,7 @@ describe('Axis computational utils', () => { }); test('should merge axis domains by group id: partial lower bounded prevDomain with complete domain', () => { - const groupId = getGroupId('group_1'); + const groupId = 'group_1'; const domainRange1 = { min: -1, }; @@ -1292,14 +1295,11 @@ describe('Axis computational utils', () => { }; verticalAxisSpec.domain = domainRange1; + const axis2 = { ...verticalAxisSpec, id: 'axis2' }; - const axesSpecs = new Map<AxisId, AxisSpec>(); - axesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); - - const axis2 = { ...verticalAxisSpec, id: getAxisId('axis2') }; + const axesSpecs = [verticalAxisSpec, axis2]; axis2.domain = domainRange2; - axesSpecs.set(axis2.id, axis2); const expectedMergedMap = new Map<GroupId, DomainRange>(); expectedMergedMap.set(groupId, { min: -1, max: 7 }); @@ -1309,7 +1309,7 @@ describe('Axis computational utils', () => { }); test('should merge axis domains by group id: partial upper bounded prevDomain with lower bounded domain', () => { - const groupId = getGroupId('group_1'); + const groupId = 'group_1'; const domainRange1 = { max: 9, }; @@ -1324,18 +1324,18 @@ describe('Axis computational utils', () => { verticalAxisSpec.domain = domainRange1; - const axesSpecs = new Map<AxisId, AxisSpec>(); - axesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + const axesSpecs = []; + axesSpecs.push(verticalAxisSpec); - const axis2 = { ...verticalAxisSpec, id: getAxisId('axis2') }; + const axis2 = { ...verticalAxisSpec, id: 'axis2' }; axis2.domain = domainRange2; - axesSpecs.set(axis2.id, axis2); + axesSpecs.push(axis2); - const axis3 = { ...verticalAxisSpec, id: getAxisId('axis3') }; + const axis3 = { ...verticalAxisSpec, id: 'axis3' }; axis3.domain = domainRange3; - axesSpecs.set(axis3.id, axis3); + axesSpecs.push(axis3); const expectedMergedMap = new Map<GroupId, DomainRange>(); expectedMergedMap.set(groupId, { min: -1, max: 9 }); @@ -1345,7 +1345,7 @@ describe('Axis computational utils', () => { }); test('should merge axis domains by group id: partial lower bounded prevDomain with upper bounded domain', () => { - const groupId = getGroupId('group_1'); + const groupId = 'group_1'; const domainRange1 = { min: 2, }; @@ -1360,18 +1360,18 @@ describe('Axis computational utils', () => { verticalAxisSpec.domain = domainRange1; - const axesSpecs = new Map<AxisId, AxisSpec>(); - axesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + const axesSpecs = []; + axesSpecs.push(verticalAxisSpec); - const axis2 = { ...verticalAxisSpec, id: getAxisId('axis2') }; + const axis2 = { ...verticalAxisSpec, id: 'axis2' }; axis2.domain = domainRange2; - axesSpecs.set(axis2.id, axis2); + axesSpecs.push(axis2); - const axis3 = { ...verticalAxisSpec, id: getAxisId('axis3') }; + const axis3 = { ...verticalAxisSpec, id: 'axis3' }; axis3.domain = domainRange3; - axesSpecs.set(axis3.id, axis3); + axesSpecs.push(axis3); const expectedMergedMap = new Map<GroupId, DomainRange>(); expectedMergedMap.set(groupId, { min: 2, max: 9 }); @@ -1388,8 +1388,7 @@ describe('Axis computational utils', () => { verticalAxisSpec.domain = domainRange1; - const axesSpecs = new Map<AxisId, AxisSpec>(); - axesSpecs.set(verticalAxisSpec.id, verticalAxisSpec); + const axesSpecs = [verticalAxisSpec]; const attemptToMerge = () => { mergeYCustomDomainsByGroupId(axesSpecs, 0); diff --git a/src/chart_types/xy_chart/utils/axis_utils.ts b/src/chart_types/xy_chart/utils/axis_utils.ts index eabff98bf2..37a1f78abf 100644 --- a/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/src/chart_types/xy_chart/utils/axis_utils.ts @@ -15,9 +15,10 @@ import { } from './specs'; import { AxisConfig, Theme } from '../../../utils/themes/theme'; import { Dimensions, Margins } from '../../../utils/dimensions'; -import { AxisId, GroupId } from '../../../utils/ids'; +import { AxisId } from '../../../utils/ids'; import { Scale } from '../../../utils/scales/scales'; import { BBox, BBoxCalculator } from '../../../utils/bbox/bbox_calculator'; +import { getSpecsById } from '../state/utils'; export type AxisLinePosition = [number, number, number, number]; @@ -184,10 +185,7 @@ export const getMaxBboxDimensions = ( maxLabelTextWidth: number; maxLabelTextHeight: number; } => { - const bbox = bboxCalculator.compute(tickLabel, tickLabelPadding, fontSize, fontFamily).getOrElse({ - width: 0, - height: 0, - }); + const bbox = bboxCalculator.compute(tickLabel, tickLabelPadding, fontSize, fontFamily); const rotatedBbox = computeRotatedLabelDimensions(bbox, tickLabelRotation); @@ -374,7 +372,7 @@ export function getMinMaxRange( } } -export function getBottomTopAxisMinMaxRange(chartRotation: Rotation, width: number) { +function getBottomTopAxisMinMaxRange(chartRotation: Rotation, width: number) { switch (chartRotation) { case 0: // dealing with x domain @@ -390,7 +388,7 @@ export function getBottomTopAxisMinMaxRange(chartRotation: Rotation, width: numb return { minRange: width, maxRange: 0 }; } } -export function getLeftAxisMinMaxRange(chartRotation: Rotation, height: number) { +function getLeftAxisMinMaxRange(chartRotation: Rotation, height: number) { switch (chartRotation) { case 0: // dealing with y domain @@ -430,7 +428,6 @@ export function getAvailableTicks( } } } - const shift = totalBarsInCluster > 0 ? totalBarsInCluster : 1; const band = scale.bandwidth / (1 - scale.barsPadding); @@ -569,14 +566,19 @@ export function getAxisTicksPositions( }, chartTheme: Theme, chartRotation: Rotation, - axisSpecs: Map<AxisId, AxisSpec>, + axisSpecs: AxisSpec[], axisDimensions: Map<AxisId, AxisTicksDimensions>, xDomain: XDomain, yDomain: YDomain[], totalGroupsCount: number, enableHistogramMode: boolean, barsPadding?: number, -) { +): { + axisPositions: Map<AxisId, Dimensions>; + axisTicks: Map<AxisId, AxisTick[]>; + axisVisibleTicks: Map<AxisId, AxisTick[]>; + axisGridLinesPositions: Map<AxisId, AxisLinePosition[]>; +} { const { chartPaddings, chartMargins } = chartTheme; const axisPositions: Map<AxisId, Dimensions> = new Map(); const axisVisibleTicks: Map<AxisId, AxisTick[]> = new Map(); @@ -589,7 +591,7 @@ export function getAxisTicksPositions( let cumRightSum = chartPaddings.right; axisDimensions.forEach((axisDim, id) => { - const axisSpec = axisSpecs.get(id); + const axisSpec = getSpecsById<AxisSpec>(axisSpecs, id); // Consider refactoring this so this condition can be tested // Given some of the values that get passed around, maybe re-write as a reduce instead of forEach? @@ -689,63 +691,31 @@ export function isBounded(domain: Partial<CompleteBoundedDomain>): domain is Dom return domain.max != null || domain.min != null; } -export function mergeYCustomDomainsByGroupId( - axesSpecs: Map<AxisId, AxisSpec>, - chartRotation: Rotation, -): Map<GroupId, DomainRange> { - const domainsByGroupId = new Map<GroupId, DomainRange>(); - - axesSpecs.forEach((spec: AxisSpec, id: AxisId) => { - const { groupId, domain } = spec; - - if (!domain) { - return; - } - - const isAxisYDomain = isYDomain(spec.position, chartRotation); - - if (!isAxisYDomain) { - const errorMessage = `[Axis ${id}]: custom domain for xDomain should be defined in Settings`; - throw new Error(errorMessage); - } - - if (isCompleteBound(domain) && domain.min > domain.max) { - const errorMessage = `[Axis ${id}]: custom domain is invalid, min is greater than max`; - throw new Error(errorMessage); - } - - const prevGroupDomain = domainsByGroupId.get(groupId); - - if (prevGroupDomain) { - const prevDomain = prevGroupDomain as DomainRange; - - const prevMin = isLowerBound(prevDomain) ? prevDomain.min : undefined; - const prevMax = isUpperBound(prevDomain) ? prevDomain.max : undefined; - - let max = prevMax; - let min = prevMin; - - if (isCompleteBound(domain)) { - min = prevMin != null ? Math.min(domain.min, prevMin) : domain.min; - max = prevMax != null ? Math.max(domain.max, prevMax) : domain.max; - } else if (isLowerBound(domain)) { - min = prevMin != null ? Math.min(domain.min, prevMin) : domain.min; - } else if (isUpperBound(domain)) { - max = prevMax != null ? Math.max(domain.max, prevMax) : domain.max; +export const isDuplicateAxis = ( + { position, title }: AxisSpec, + { tickLabels }: AxisTicksDimensions, + tickMap: Map<AxisId, AxisTicksDimensions>, + specs: AxisSpec[], +): boolean => { + const firstTickLabel = tickLabels[0]; + const lastTickLabel = tickLabels.slice(-1)[0]; + + let hasDuplicate = false; + tickMap.forEach(({ tickLabels: axisTickLabels }, axisId) => { + if ( + !hasDuplicate && + axisTickLabels && + tickLabels.length === axisTickLabels.length && + firstTickLabel === axisTickLabels[0] && + lastTickLabel === axisTickLabels.slice(-1)[0] + ) { + const spec = getSpecsById<AxisSpec>(specs, axisId); + + if (spec && spec.position === position && title === spec.title) { + hasDuplicate = true; } - - const mergedDomain = { - min, - max, - }; - - if (isBounded(mergedDomain)) { - domainsByGroupId.set(groupId, mergedDomain); - } - } else { - domainsByGroupId.set(groupId, domain); } }); - return domainsByGroupId; -} + return hasDuplicate; +}; diff --git a/src/chart_types/xy_chart/utils/dimensions.test.ts b/src/chart_types/xy_chart/utils/dimensions.test.ts index dbf7e330bb..88a3f061c7 100644 --- a/src/chart_types/xy_chart/utils/dimensions.test.ts +++ b/src/chart_types/xy_chart/utils/dimensions.test.ts @@ -1,10 +1,11 @@ import { AxisTicksDimensions } from './axis_utils'; -import { AxisSpec, Position } from './specs'; +import { AxisSpec, Position, SpecTypes } from './specs'; import { LIGHT_THEME } from '../../../utils/themes/light_theme'; import { LegendStyle } from '../../../utils/themes/theme'; import { computeChartDimensions } from './dimensions'; -import { AxisId, getAxisId, getGroupId } from '../../../utils/ids'; +import { AxisId } from '../../../utils/ids'; import { Margins } from '../../../utils/dimensions'; +import { ChartTypes } from '../..'; describe('Computed chart dimensions', () => { const parentDim = { @@ -35,8 +36,10 @@ describe('Computed chart dimensions', () => { maxLabelTextHeight: 10, }; const axisLeftSpec: AxisSpec = { - id: getAxisId('axis_1'), - groupId: getGroupId('group_1'), + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Axis, + id: 'axis_1', + groupId: 'group_1', hide: false, showOverlappingTicks: false, showOverlappingLabels: false, @@ -66,7 +69,7 @@ describe('Computed chart dimensions', () => { chartTheme.axes.axisTitleStyle.padding = 10; test('should be equal to parent dimension with no axis minus margins', () => { const axisDims = new Map<AxisId, AxisTicksDimensions>(); - const axisSpecs = new Map<AxisId, AxisSpec>(); + const axisSpecs: AxisSpec[] = []; const { chartDimensions } = computeChartDimensions(parentDim, chartTheme, axisDims, axisSpecs); expect(chartDimensions.left + chartDimensions.width).toBeLessThanOrEqual(parentDim.width); expect(chartDimensions.top + chartDimensions.height).toBeLessThanOrEqual(parentDim.height); @@ -76,9 +79,8 @@ describe('Computed chart dimensions', () => { // |margin|titleFontSize|titlePadding|maxLabelBboxWidth|tickPadding|tickSize|padding| // \10|10|10|10|10|10|10| = 70px from left const axisDims = new Map<AxisId, AxisTicksDimensions>(); - const axisSpecs = new Map<AxisId, AxisSpec>(); - axisDims.set(getAxisId('axis_1'), axis1Dims); - axisSpecs.set(getAxisId('axis_1'), axisLeftSpec); + const axisSpecs = [axisLeftSpec]; + axisDims.set('axis_1', axis1Dims); const { chartDimensions } = computeChartDimensions(parentDim, chartTheme, axisDims, axisSpecs); expect(chartDimensions.left + chartDimensions.width).toBeLessThanOrEqual(parentDim.width); expect(chartDimensions.top + chartDimensions.height).toBeLessThanOrEqual(parentDim.height); @@ -88,9 +90,8 @@ describe('Computed chart dimensions', () => { // |padding|tickSize|tickPadding|maxLabelBBoxWidth|titlePadding|titleFontSize\margin| // \10|10|10|10|10|10|10| = 70px from right const axisDims = new Map<AxisId, AxisTicksDimensions>(); - const axisSpecs = new Map<AxisId, AxisSpec>(); - axisDims.set(getAxisId('axis_1'), axis1Dims); - axisSpecs.set(getAxisId('axis_1'), { ...axisLeftSpec, position: Position.Right }); + const axisSpecs = [{ ...axisLeftSpec, position: Position.Right }]; + axisDims.set('axis_1', axis1Dims); const { chartDimensions } = computeChartDimensions(parentDim, chartTheme, axisDims, axisSpecs); expect(chartDimensions.left + chartDimensions.width).toBeLessThanOrEqual(parentDim.width); expect(chartDimensions.top + chartDimensions.height).toBeLessThanOrEqual(parentDim.height); @@ -100,12 +101,13 @@ describe('Computed chart dimensions', () => { // |margin|titleFontSize|titlePadding|maxLabelBboxHeight|tickPadding|tickSize|padding| // \10|10|10|10|10|10|10| = 70px from top const axisDims = new Map<AxisId, AxisTicksDimensions>(); - const axisSpecs = new Map<AxisId, AxisSpec>(); - axisDims.set(getAxisId('axis_1'), axis1Dims); - axisSpecs.set(getAxisId('axis_1'), { - ...axisLeftSpec, - position: Position.Top, - }); + const axisSpecs = [ + { + ...axisLeftSpec, + position: Position.Top, + }, + ]; + axisDims.set('axis_1', axis1Dims); const { chartDimensions } = computeChartDimensions(parentDim, chartTheme, axisDims, axisSpecs); expect(chartDimensions.left + chartDimensions.width).toBeLessThanOrEqual(parentDim.width); expect(chartDimensions.top + chartDimensions.height).toBeLessThanOrEqual(parentDim.height); @@ -115,12 +117,13 @@ describe('Computed chart dimensions', () => { // |margin|titleFontSize|titlePadding|maxLabelBboxHeight|tickPadding|tickSize|padding| // \10|10|10|10|10|10|10| = 70px from bottom const axisDims = new Map<AxisId, AxisTicksDimensions>(); - const axisSpecs = new Map<AxisId, AxisSpec>(); - axisDims.set(getAxisId('axis_1'), axis1Dims); - axisSpecs.set(getAxisId('axis_1'), { - ...axisLeftSpec, - position: Position.Bottom, - }); + const axisSpecs = [ + { + ...axisLeftSpec, + position: Position.Bottom, + }, + ]; + axisDims.set('axis_1', axis1Dims); const { chartDimensions } = computeChartDimensions(parentDim, chartTheme, axisDims, axisSpecs); expect(chartDimensions.left + chartDimensions.width).toBeLessThanOrEqual(parentDim.width); expect(chartDimensions.top + chartDimensions.height).toBeLessThanOrEqual(parentDim.height); @@ -128,12 +131,13 @@ describe('Computed chart dimensions', () => { }); test('should not add space for axis when no spec for axis dimensions or axis is hidden', () => { const axisDims = new Map<AxisId, AxisTicksDimensions>(); - const axisSpecs = new Map<AxisId, AxisSpec>(); - axisDims.set(getAxisId('foo'), axis1Dims); - axisSpecs.set(getAxisId('axis_1'), { - ...axisLeftSpec, - position: Position.Bottom, - }); + const axisSpecs = [ + { + ...axisLeftSpec, + position: Position.Bottom, + }, + ]; + axisDims.set('foo', axis1Dims); const chartDimensions = computeChartDimensions(parentDim, chartTheme, axisDims, axisSpecs); const expectedDims = { @@ -150,8 +154,8 @@ describe('Computed chart dimensions', () => { const hiddenAxisDims = new Map<AxisId, AxisTicksDimensions>(); const hiddenAxisSpecs = new Map<AxisId, AxisSpec>(); - hiddenAxisDims.set(getAxisId('axis_1'), axis1Dims); - hiddenAxisSpecs.set(getAxisId('axis_1'), { + hiddenAxisDims.set('axis_1', axis1Dims); + hiddenAxisSpecs.set('axis_1', { ...axisLeftSpec, hide: true, position: Position.Bottom, diff --git a/src/chart_types/xy_chart/utils/dimensions.ts b/src/chart_types/xy_chart/utils/dimensions.ts index 30b9588595..5a868a5171 100644 --- a/src/chart_types/xy_chart/utils/dimensions.ts +++ b/src/chart_types/xy_chart/utils/dimensions.ts @@ -3,6 +3,7 @@ import { AxisSpec, Position } from './specs'; import { Theme } from '../../../utils/themes/theme'; import { AxisId } from '../../../utils/ids'; import { Dimensions } from '../../../utils/dimensions'; +import { getSpecsById } from '../state/utils'; /** * Compute the chart dimensions. It's computed removing from the parent dimensions @@ -18,11 +19,22 @@ export function computeChartDimensions( parentDimensions: Dimensions, chartTheme: Theme, axisDimensions: Map<AxisId, AxisTicksDimensions>, - axisSpecs: Map<AxisId, AxisSpec>, + axisSpecs: AxisSpec[], ): { chartDimensions: Dimensions; leftMargin: number; } { + if (parentDimensions.width <= 0 || parentDimensions.height <= 0) { + return { + chartDimensions: { + width: 0, + height: 0, + left: 0, + top: 0, + }, + leftMargin: 0, + }; + } const { chartMargins, chartPaddings } = chartTheme; const { axisTitleStyle } = chartTheme.axes; @@ -35,7 +47,7 @@ export function computeChartDimensions( let horizontalEdgeLabelOverflow = 0; let verticalEdgeLabelOverflow = 0; axisDimensions.forEach(({ maxLabelBboxWidth = 0, maxLabelBboxHeight = 0 }, id) => { - const axisSpec = axisSpecs.get(id); + const axisSpec = getSpecsById<AxisSpec>(axisSpecs, id); if (!axisSpec || axisSpec.hide) { return; } diff --git a/src/chart_types/xy_chart/utils/interactions.test.ts b/src/chart_types/xy_chart/utils/interactions.test.ts index cbcbb661b1..e8e323dbbb 100644 --- a/src/chart_types/xy_chart/utils/interactions.test.ts +++ b/src/chart_types/xy_chart/utils/interactions.test.ts @@ -1,15 +1,14 @@ -import { IndexedGeometry, PointGeometry } from '../rendering/rendering'; import { Dimensions } from '../../../utils/dimensions'; -import { getSpecId } from '../../../utils/ids'; import { areIndexedGeometryArraysEquals, areIndexedGeomsEquals, - getValidXPosition, - getValidYPosition, + getOrientedXPosition, + getOrientedYPosition, isCrosshairTooltipType, isFollowTooltipType, TooltipType, } from './interactions'; +import { IndexedGeometry, PointGeometry } from '../../../utils/geometry'; const seriesStyle = { rect: { @@ -32,7 +31,7 @@ const seriesStyle = { const ig1: IndexedGeometry = { color: 'red', geometryId: { - specId: getSpecId('ig1'), + specId: 'ig1', seriesKey: [0, 1, 2], }, value: { @@ -48,7 +47,7 @@ const ig1: IndexedGeometry = { }; const ig2: IndexedGeometry = { geometryId: { - specId: getSpecId('ig1'), + specId: 'ig1', seriesKey: [0, 1, 2], }, value: { @@ -65,7 +64,7 @@ const ig2: IndexedGeometry = { }; const ig3: IndexedGeometry = { geometryId: { - specId: getSpecId('ig1'), + specId: 'ig1', seriesKey: [123, 123, 123], }, value: { @@ -83,7 +82,7 @@ const ig3: IndexedGeometry = { }; const ig4: IndexedGeometry = { geometryId: { - specId: getSpecId('ig4'), + specId: 'ig4', seriesKey: [123, 123, 123], }, value: { @@ -100,7 +99,7 @@ const ig4: IndexedGeometry = { }; const ig5: IndexedGeometry = { geometryId: { - specId: getSpecId('ig5'), + specId: 'ig5', seriesKey: [123, 123, 123], }, value: { @@ -117,7 +116,7 @@ const ig5: IndexedGeometry = { }; const ig6: PointGeometry = { geometryId: { - specId: getSpecId('ig5'), + specId: 'ig5', seriesKey: [123, 123, 123], }, value: { @@ -145,25 +144,25 @@ describe('Interaction utils', () => { test('limit x position with x already relative to chart', () => { const xPos = 30; const yPos = 50; - let validPosition = getValidXPosition(xPos, yPos, 0, chartDimensions); + let validPosition = getOrientedXPosition(xPos, yPos, 0, chartDimensions); expect(validPosition).toBe(xPos); - validPosition = getValidXPosition(xPos, yPos, 180, chartDimensions); + validPosition = getOrientedXPosition(xPos, yPos, 180, chartDimensions); expect(validPosition).toBe(chartDimensions.width - xPos); - validPosition = getValidXPosition(xPos, yPos, 90, chartDimensions); + validPosition = getOrientedXPosition(xPos, yPos, 90, chartDimensions); expect(validPosition).toBe(yPos); - validPosition = getValidXPosition(xPos, yPos, -90, chartDimensions); + validPosition = getOrientedXPosition(xPos, yPos, -90, chartDimensions); expect(validPosition).toBe(chartDimensions.height - yPos); }); test('limit y position with x already relative to chart', () => { const yPos = 30; const xPos = 50; - let validPosition = getValidYPosition(xPos, yPos, 0, chartDimensions); + let validPosition = getOrientedYPosition(xPos, yPos, 0, chartDimensions); expect(validPosition).toBe(yPos); - validPosition = getValidYPosition(xPos, yPos, 180, chartDimensions); + validPosition = getOrientedYPosition(xPos, yPos, 180, chartDimensions); expect(validPosition).toBe(chartDimensions.height - yPos); - validPosition = getValidYPosition(xPos, yPos, 90, chartDimensions); + validPosition = getOrientedYPosition(xPos, yPos, 90, chartDimensions); expect(validPosition).toBe(chartDimensions.width - xPos); - validPosition = getValidYPosition(xPos, yPos, -90, chartDimensions); + validPosition = getOrientedYPosition(xPos, yPos, -90, chartDimensions); expect(validPosition).toBe(xPos); }); test('checks tooltip type helpers', () => { diff --git a/src/chart_types/xy_chart/utils/interactions.ts b/src/chart_types/xy_chart/utils/interactions.ts index ec5ea633d8..39aac2294a 100644 --- a/src/chart_types/xy_chart/utils/interactions.ts +++ b/src/chart_types/xy_chart/utils/interactions.ts @@ -1,9 +1,8 @@ import { $Values } from 'utility-types'; - -import { BarGeometry, IndexedGeometry, isBarGeometry, isPointGeometry, PointGeometry } from '../rendering/rendering'; import { Datum, Rotation } from './specs'; import { Dimensions } from '../../../utils/dimensions'; import { Accessor } from '../../../utils/accessor'; +import { BarGeometry, PointGeometry, IndexedGeometry, isPointGeometry, isBarGeometry } from '../../../utils/geometry'; /** The type of tooltip to use */ export const TooltipType = Object.freeze({ @@ -29,6 +28,12 @@ export interface TooltipValue { yAccessor: Accessor; } +export interface TooltipProps { + type?: TooltipType; + snap?: boolean; + headerFormatter?: TooltipValueFormatter; +} + export type TooltipValueFormatter = (data: TooltipValue) => JSX.Element | string; export interface HighlightedElement { @@ -48,7 +53,7 @@ export interface HighlightedElement { * @param chartRotation the chart rotation * @param chartDimension the chart dimension */ -export function getValidXPosition(xPos: number, yPos: number, chartRotation: Rotation, chartDimension: Dimensions) { +export function getOrientedXPosition(xPos: number, yPos: number, chartRotation: Rotation, chartDimension: Dimensions) { switch (chartRotation) { case 0: return xPos; @@ -60,7 +65,7 @@ export function getValidXPosition(xPos: number, yPos: number, chartRotation: Rot return chartDimension.height - yPos; } } -export function getValidYPosition(xPos: number, yPos: number, chartRotation: Rotation, chartDimension: Dimensions) { +export function getOrientedYPosition(xPos: number, yPos: number, chartRotation: Rotation, chartDimension: Dimensions) { switch (chartRotation) { case 0: return yPos; @@ -79,9 +84,6 @@ export function isCrosshairTooltipType(type: TooltipType) { export function isFollowTooltipType(type: TooltipType) { return type === TooltipType.Follow; } -export function isNoneTooltipType(type: TooltipType) { - return type === TooltipType.None; -} export function areIndexedGeometryArraysEquals(arr1: IndexedGeometry[], arr2: IndexedGeometry[]) { if (arr1.length !== arr2.length) { @@ -103,7 +105,7 @@ export function areIndexedGeomsEquals(ig1: IndexedGeometry, ig2: IndexedGeometry return false; } -export function arePointsEqual(ig1: PointGeometry, ig2: PointGeometry) { +function arePointsEqual(ig1: PointGeometry, ig2: PointGeometry) { return ( ig1.geometryId.specId === ig2.geometryId.specId && ig1.color === ig2.color && @@ -114,7 +116,7 @@ export function arePointsEqual(ig1: PointGeometry, ig2: PointGeometry) { ig1.radius === ig2.radius ); } -export function areBarEqual(ig1: BarGeometry, ig2: BarGeometry) { +function areBarEqual(ig1: BarGeometry, ig2: BarGeometry) { return ( ig1.geometryId.specId === ig2.geometryId.specId && ig1.color === ig2.color && @@ -124,3 +126,11 @@ export function areBarEqual(ig1: BarGeometry, ig2: BarGeometry) { ig1.height === ig2.height ); } + +export function isTooltipProps(config: TooltipType | TooltipProps): config is TooltipProps { + return typeof config === 'object'; +} + +export function isTooltipType(config: TooltipType | TooltipProps): config is TooltipType { + return typeof config === 'string'; +} diff --git a/src/chart_types/xy_chart/utils/nonstacked_series_utils.test.ts b/src/chart_types/xy_chart/utils/nonstacked_series_utils.test.ts index d45235bab8..aa05e56385 100644 --- a/src/chart_types/xy_chart/utils/nonstacked_series_utils.test.ts +++ b/src/chart_types/xy_chart/utils/nonstacked_series_utils.test.ts @@ -1,4 +1,3 @@ -import { getSpecId } from '../../../utils/ids'; import { RawDataSeries } from './series'; import { ScaleType } from '../../../utils/scales/scales'; import { MockRawDataSeries, MockDataSeries } from '../../../mocks'; @@ -13,7 +12,7 @@ const EMPTY_DATA_SET: RawDataSeries[] = [ data: [], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, ]; const STANDARD_DATA_SET: RawDataSeries[] = [ @@ -26,7 +25,7 @@ const STANDARD_DATA_SET: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -37,7 +36,7 @@ const STANDARD_DATA_SET: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -48,7 +47,7 @@ const STANDARD_DATA_SET: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const WITH_NULL_DATASET: RawDataSeries[] = [ @@ -61,7 +60,7 @@ const WITH_NULL_DATASET: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -72,7 +71,7 @@ const WITH_NULL_DATASET: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -83,7 +82,7 @@ const WITH_NULL_DATASET: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const STANDARD_DATA_SET_WY0: RawDataSeries[] = [ @@ -97,7 +96,7 @@ const STANDARD_DATA_SET_WY0: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -109,7 +108,7 @@ const STANDARD_DATA_SET_WY0: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -121,7 +120,7 @@ const STANDARD_DATA_SET_WY0: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const WITH_NULL_DATASET_WY0: RawDataSeries[] = [ @@ -135,7 +134,7 @@ const WITH_NULL_DATASET_WY0: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -146,7 +145,7 @@ const WITH_NULL_DATASET_WY0: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -158,18 +157,18 @@ const WITH_NULL_DATASET_WY0: RawDataSeries[] = [ ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const DATA_SET_WITH_NULL_2: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 21 }, { x: 3, y1: 23 }], diff --git a/src/chart_types/xy_chart/utils/nonstacked_series_utils.ts b/src/chart_types/xy_chart/utils/nonstacked_series_utils.ts index 6b30fa3004..2c3980c8e2 100644 --- a/src/chart_types/xy_chart/utils/nonstacked_series_utils.ts +++ b/src/chart_types/xy_chart/utils/nonstacked_series_utils.ts @@ -1,7 +1,8 @@ import { DataSeries, DataSeriesDatum, RawDataSeries } from './series'; import { fitFunction } from './fit_function'; -import { isAreaSeriesSpec, isLineSeriesSpec, SeriesSpecs } from './specs'; +import { isAreaSeriesSpec, isLineSeriesSpec, SeriesSpecs, BasicSeriesSpec } from './specs'; import { ScaleType } from '../../../utils/scales/scales'; +import { getSpecsById } from '../state/utils'; export const formatNonStackedDataSeriesValues = ( dataseries: RawDataSeries[], @@ -13,7 +14,7 @@ export const formatNonStackedDataSeriesValues = ( const formattedValues: DataSeries[] = []; for (let i = 0; i < len; i++) { const formattedDataValue = formatNonStackedDataValues(dataseries[i], scaleToExtent); - const spec = seriesSpecs.get(formattedDataValue.specId); + const spec = getSpecsById<BasicSeriesSpec>(seriesSpecs, formattedDataValue.specId); if ( spec !== null && diff --git a/src/chart_types/xy_chart/utils/scales.test.ts b/src/chart_types/xy_chart/utils/scales.test.ts index d247a92c1b..576b7ac596 100644 --- a/src/chart_types/xy_chart/utils/scales.test.ts +++ b/src/chart_types/xy_chart/utils/scales.test.ts @@ -1,4 +1,3 @@ -import { getGroupId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { XDomain } from '../domains/x_domain'; import { computeXScale, countBarsInCluster } from './scales'; @@ -106,7 +105,7 @@ describe('Series scales', () => { test('count bars required on a cluster', () => { const stacked: FormattedDataSeries[] = [ { - groupId: getGroupId('g1'), + groupId: 'g1', dataSeries: [], counts: { areaSeries: 10, @@ -115,7 +114,7 @@ describe('Series scales', () => { }, }, { - groupId: getGroupId('g2'), + groupId: 'g2', dataSeries: [], counts: { areaSeries: 10, @@ -124,7 +123,7 @@ describe('Series scales', () => { }, }, { - groupId: getGroupId('g3'), + groupId: 'g3', dataSeries: [], counts: { areaSeries: 10, @@ -135,7 +134,7 @@ describe('Series scales', () => { ]; const nonStacked: FormattedDataSeries[] = [ { - groupId: getGroupId('g1'), + groupId: 'g1', dataSeries: [], counts: { areaSeries: 10, @@ -144,7 +143,7 @@ describe('Series scales', () => { }, }, { - groupId: getGroupId('g2'), + groupId: 'g2', dataSeries: [], counts: { areaSeries: 10, diff --git a/src/chart_types/xy_chart/utils/series.test.ts b/src/chart_types/xy_chart/utils/series.test.ts index ba284c5540..1185c058ca 100644 --- a/src/chart_types/xy_chart/utils/series.test.ts +++ b/src/chart_types/xy_chart/utils/series.test.ts @@ -1,5 +1,4 @@ import { ColorConfig } from '../../../utils/themes/theme'; -import { getGroupId, getSpecId, SpecId } from '../../../utils/ids'; import { ScaleType } from '../../../utils/scales/scales'; import { DataSeriesColorsValues, @@ -10,9 +9,10 @@ import { RawDataSeries, splitSeries, } from './series'; -import { BasicSeriesSpec } from './specs'; +import { BasicSeriesSpec, LineSeriesSpec, SpecTypes, SeriesTypes } from './specs'; import { formatStackedDataSeriesValues } from './stacked_series_utils'; import * as TestDataset from '../../../utils/data_samples/test_dataset'; +import { ChartTypes } from '../..'; describe('Series', () => { test('Can split dataset into 1Y0G series', () => { @@ -22,7 +22,7 @@ describe('Series', () => { xAccessor: 'x', yAccessors: ['y'], }, - getSpecId('spec1'), + 'spec1', ); expect(splittedSeries.rawDataSeries).toMatchSnapshot(); }); @@ -34,7 +34,7 @@ describe('Series', () => { yAccessors: ['y'], splitSeriesAccessors: ['g'], }, - getSpecId('spec1'), + 'spec1', ); expect(splittedSeries.rawDataSeries).toMatchSnapshot(); }); @@ -46,7 +46,7 @@ describe('Series', () => { yAccessors: ['y'], splitSeriesAccessors: ['g1', 'g2'], }, - getSpecId('spec1'), + 'spec1', ); expect(splittedSeries.rawDataSeries).toMatchSnapshot(); }); @@ -57,7 +57,7 @@ describe('Series', () => { xAccessor: 'x', yAccessors: ['y1', 'y2'], }, - getSpecId('spec1'), + 'spec1', ); expect(splittedSeries.rawDataSeries).toMatchSnapshot(); }); @@ -69,7 +69,7 @@ describe('Series', () => { yAccessors: ['y1', 'y2'], splitSeriesAccessors: ['g'], }, - getSpecId('spec1'), + 'spec1', ); expect(splittedSeries.rawDataSeries).toMatchSnapshot(); }); @@ -81,20 +81,20 @@ describe('Series', () => { yAccessors: ['y1', 'y2'], splitSeriesAccessors: ['g1', 'g2'], }, - getSpecId('spec1'), + 'spec1', ); expect(splittedSeries.rawDataSeries).toMatchSnapshot(); }); test('Can stack simple dataseries', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 21 }, { x: 3, y1: 23 }], @@ -107,25 +107,25 @@ describe('Series', () => { test('Can stack multiple dataseries', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], @@ -138,13 +138,13 @@ describe('Series', () => { test('Can stack unsorted dataseries', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 1 }, { x: 4, y1: 4 }, { x: 2, y1: 2 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 3, y1: 23 }, { x: 1, y1: 21 }], @@ -158,13 +158,13 @@ describe('Series', () => { const maxArrayItems = 1000; const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: new Array(maxArrayItems).fill(0).map((d, i) => ({ x: i, y1: i })), }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: new Array(maxArrayItems).fill(0).map((d, i) => ({ x: i, y1: i })), @@ -177,13 +177,13 @@ describe('Series', () => { test('Can stack simple dataseries with scale to extent', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 21 }, { x: 3, y1: 23 }], @@ -198,25 +198,25 @@ describe('Series', () => { test('Can stack multiple dataseries with scale to extent', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 3, y1: 3 }, { x: 4, y1: 4 }], @@ -231,13 +231,13 @@ describe('Series', () => { test('Can stack simple dataseries with y0', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 3, y0: 1 }, { x: 2, y1: 3, y0: 2 }, { x: 4, y1: 4, y0: 3 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 2, y0: 1 }, { x: 2, y1: 3, y0: 1 }, { x: 3, y1: 23, y0: 4 }, { x: 4, y1: 4, y0: 1 }], @@ -263,13 +263,13 @@ describe('Series', () => { test('Can stack simple dataseries with scale to extent with y0', () => { const dataSeries: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 3, y0: 1 }, { x: 2, y1: 3, y0: 2 }, { x: 4, y1: 4, y0: 3 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 2, y0: 1 }, { x: 2, y1: 3, y0: 1 }, { x: 3, y1: 23, y0: 4 }, { x: 4, y1: 4, y0: 1 }], @@ -292,11 +292,12 @@ describe('Series', () => { }); test('should split an array of specs into data series', () => { - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>(); - const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group'), - seriesType: 'line', + const spec1: LineSeriesSpec = { + specType: SpecTypes.Series, + chartType: ChartTypes.XYAxis, + id: 'spec1', + groupId: 'group', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -306,9 +307,11 @@ describe('Series', () => { hideInLegend: false, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group2'), - seriesType: 'line', + specType: SpecTypes.Series, + chartType: ChartTypes.XYAxis, + id: 'spec2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -318,18 +321,18 @@ describe('Series', () => { data: TestDataset.BARCHART_2Y0G, hideInLegend: false, }; - seriesSpecs.set(spec1.id, spec1); - seriesSpecs.set(spec2.id, spec2); - const splittedDataSeries = getSplittedSeries(seriesSpecs); - expect(splittedDataSeries.splittedSeries.get(getSpecId('spec1'))).toMatchSnapshot(); - expect(splittedDataSeries.splittedSeries.get(getSpecId('spec2'))).toMatchSnapshot(); + + const splittedDataSeries = getSplittedSeries([spec1, spec2]); + expect(splittedDataSeries.splittedSeries.get('spec1')).toMatchSnapshot(); + expect(splittedDataSeries.splittedSeries.get('spec2')).toMatchSnapshot(); }); test('should compute data series for stacked specs', () => { - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>(); const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group'), - seriesType: 'line', + specType: SpecTypes.Series, + chartType: ChartTypes.XYAxis, + id: 'spec1', + groupId: 'group', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -339,9 +342,11 @@ describe('Series', () => { hideInLegend: false, }; const spec2: BasicSeriesSpec = { - id: getSpecId('spec2'), - groupId: getGroupId('group2'), - seriesType: 'line', + specType: SpecTypes.Series, + chartType: ChartTypes.XYAxis, + id: 'spec2', + groupId: 'group2', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -352,23 +357,23 @@ describe('Series', () => { hideInLegend: false, }; const xValues = new Set([0, 1, 2, 3]); - seriesSpecs.set(spec1.id, spec1); - seriesSpecs.set(spec2.id, spec2); - const splittedDataSeries = getSplittedSeries(seriesSpecs); + const splittedDataSeries = getSplittedSeries([spec1, spec2]); const stackedDataSeries = getFormattedDataseries( [spec1, spec2], splittedDataSeries.splittedSeries, xValues, ScaleType.Linear, - new Map(), + [], ); expect(stackedDataSeries.stacked).toMatchSnapshot(); }); test('should get series color map', () => { const spec1: BasicSeriesSpec = { - id: getSpecId('spec1'), - groupId: getGroupId('group'), - seriesType: 'line', + specType: SpecTypes.Series, + chartType: ChartTypes.XYAxis, + id: 'spec1', + groupId: 'group', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -382,7 +387,7 @@ describe('Series', () => { specs.set(spec1.id, spec1); const dataSeriesValuesA: DataSeriesColorsValues = { - specId: getSpecId('spec1'), + specId: 'spec1', colorValues: ['a', 'b', 'c'], }; @@ -410,13 +415,14 @@ describe('Series', () => { expect(customizedColorMap).toEqual(expectedCustomizedColorMap); }); test('should only include deselectedDataSeries when splitting series if deselectedDataSeries is defined', () => { - const seriesSpecs = new Map<SpecId, BasicSeriesSpec>(); - const specId = getSpecId('splitSpec'); + const specId = 'splitSpec'; const splitSpec: BasicSeriesSpec = { + specType: SpecTypes.Series, + chartType: ChartTypes.XYAxis, id: specId, - groupId: getGroupId('group'), - seriesType: 'line', + groupId: 'group', + seriesType: SeriesTypes.Line, yScaleType: ScaleType.Log, xScaleType: ScaleType.Linear, xAccessor: 'x', @@ -427,12 +433,10 @@ describe('Series', () => { hideInLegend: false, }; - seriesSpecs.set(splitSpec.id, splitSpec); - - const allSeries = getSplittedSeries(seriesSpecs, null); + const allSeries = getSplittedSeries([splitSpec]); expect(allSeries.splittedSeries.get(specId)!.length).toBe(2); - const emptyDeselected = getSplittedSeries(seriesSpecs, []); + const emptyDeselected = getSplittedSeries([splitSpec]); expect(emptyDeselected.splittedSeries.get(specId)!.length).toBe(2); const deselectedDataSeries: DataSeriesColorsValues[] = [ @@ -441,14 +445,14 @@ describe('Series', () => { colorValues: ['y1'], }, ]; - const subsetSplit = getSplittedSeries(seriesSpecs, deselectedDataSeries); + const subsetSplit = getSplittedSeries([splitSpec], deselectedDataSeries); expect(subsetSplit.splittedSeries.get(specId)!.length).toBe(1); }); test('should sort series color by series spec sort index', () => { - const spec1Id = getSpecId('spec1'); - const spec2Id = getSpecId('spec2'); - const spec3Id = getSpecId('spec3'); + const spec1Id = 'spec1'; + const spec2Id = 'spec2'; + const spec3Id = 'spec3'; const colorValuesMap = new Map(); const dataSeriesValues1: DataSeriesColorsValues = { diff --git a/src/chart_types/xy_chart/utils/series.ts b/src/chart_types/xy_chart/utils/series.ts index 9a68fde443..379ac72883 100644 --- a/src/chart_types/xy_chart/utils/series.ts +++ b/src/chart_types/xy_chart/utils/series.ts @@ -4,10 +4,10 @@ import { GroupId, SpecId } from '../../../utils/ids'; import { splitSpecsByGroupId, YBasicSeriesSpec } from '../domains/y_domain'; import { formatNonStackedDataSeriesValues } from './nonstacked_series_utils'; import { isEqualSeriesKey } from './series_utils'; -import { BasicSeriesSpec, Datum, SeriesAccessors } from './specs'; +import { BasicSeriesSpec, Datum, SeriesAccessors, SeriesSpecs, SeriesTypes } from './specs'; import { formatStackedDataSeriesValues } from './stacked_series_utils'; -import { LastValues } from '../store/utils'; import { ScaleType } from '../../../utils/scales/scales'; +import { LastValues } from '../state/utils'; export interface FilledValues { /** the x value */ @@ -218,7 +218,7 @@ export function getFormattedDataseries( dataSeries: Map<SpecId, RawDataSeries[]>, xValues: Set<string | number>, xScaleType: ScaleType, - seriesSpecs: Map<SpecId, BasicSeriesSpec>, + seriesSpecs: SeriesSpecs, ): { stacked: FormattedDataSeries[]; nonStacked: FormattedDataSeries[]; @@ -268,7 +268,7 @@ export function getFormattedDataseries( }; } -export function getRawDataSeries( +function getRawDataSeries( seriesSpecs: YBasicSeriesSpec[], dataSeries: Map<SpecId, RawDataSeries[]>, ): { @@ -288,13 +288,13 @@ export function getRawDataSeries( const { id, seriesType } = spec; const ds = dataSeries.get(id); switch (seriesType) { - case 'bar': + case SeriesTypes.Bar: counts.barSeries += ds ? ds.length : 0; break; - case 'line': + case SeriesTypes.Line: counts.lineSeries += ds ? ds.length : 0; break; - case 'area': + case SeriesTypes.Area: counts.areaSeries += ds ? ds.length : 0; break; } @@ -314,8 +314,8 @@ export function getRawDataSeries( * @param deselectedDataSeries the array of deselected/hidden data series */ export function getSplittedSeries( - seriesSpecs: Map<SpecId, BasicSeriesSpec>, - deselectedDataSeries?: DataSeriesColorsValues[] | null, + seriesSpecs: BasicSeriesSpec[], + deselectedDataSeries: DataSeriesColorsValues[] = [], ): { splittedSeries: Map<SpecId, RawDataSeries[]>; seriesColors: Map<string, DataSeriesColorsValues>; @@ -325,17 +325,17 @@ export function getSplittedSeries( const seriesColors = new Map<string, DataSeriesColorsValues>(); let xValues: Set<string | number> = new Set(); let isOrdinalScale = false; - for (const [specId, spec] of seriesSpecs) { + for (const spec of seriesSpecs) { if (spec.xScaleType === ScaleType.Ordinal) { isOrdinalScale = true; } - const dataSeries = splitSeries(spec.data, spec, specId); + const dataSeries = splitSeries(spec.data, spec, spec.id); let currentRawDataSeries = dataSeries.rawDataSeries; - if (deselectedDataSeries) { + if (deselectedDataSeries.length > 0) { currentRawDataSeries = dataSeries.rawDataSeries.filter( (series): boolean => { const seriesValues = { - specId, + specId: spec.id, colorValues: series.key, }; @@ -344,13 +344,13 @@ export function getSplittedSeries( ); } - splittedSeries.set(specId, currentRawDataSeries); + splittedSeries.set(spec.id, currentRawDataSeries); const banded = spec.y0Accessors && spec.y0Accessors.length > 0; dataSeries.colorsValues.forEach((colorValues, key) => { seriesColors.set(key, { - specId, + specId: spec.id, specSortIndex: spec.sortIndex, banded, colorValues, @@ -372,7 +372,7 @@ export function getSplittedSeries( }; } -export function getSortIndex({ specSortIndex }: DataSeriesColorsValues, total: number): number { +function getSortIndex({ specSortIndex }: DataSeriesColorsValues, total: number): number { return specSortIndex != null ? specSortIndex : total; } diff --git a/src/chart_types/xy_chart/utils/series_utils.test.ts b/src/chart_types/xy_chart/utils/series_utils.test.ts index 8244bfc906..6c17e3f11a 100644 --- a/src/chart_types/xy_chart/utils/series_utils.test.ts +++ b/src/chart_types/xy_chart/utils/series_utils.test.ts @@ -1,7 +1,6 @@ -import { getSpecId } from '../../../utils/ids'; -import { GeometryId } from '../rendering/rendering'; import { DataSeriesColorsValues } from './series'; import { belongsToDataSeries, isEqualSeriesKey } from './series_utils'; +import { GeometryId } from '../../../utils/geometry'; describe('Series utility functions', () => { test('can compare series keys for identity', () => { @@ -20,22 +19,22 @@ describe('Series utility functions', () => { test('can determine if a geometry id belongs to a data series', () => { const geometryIdA: GeometryId = { - specId: getSpecId('a'), + specId: 'a', seriesKey: ['a', 'b', 'c'], }; const dataSeriesValuesA: DataSeriesColorsValues = { - specId: getSpecId('a'), + specId: 'a', colorValues: ['a', 'b', 'c'], }; const dataSeriesValuesB: DataSeriesColorsValues = { - specId: getSpecId('b'), + specId: 'b', colorValues: ['a', 'b', 'c'], }; const dataSeriesValuesC: DataSeriesColorsValues = { - specId: getSpecId('a'), + specId: 'a', colorValues: ['a', 'b', 'd'], }; diff --git a/src/chart_types/xy_chart/utils/series_utils.ts b/src/chart_types/xy_chart/utils/series_utils.ts index 69dcc2d722..aa77102942 100644 --- a/src/chart_types/xy_chart/utils/series_utils.ts +++ b/src/chart_types/xy_chart/utils/series_utils.ts @@ -1,5 +1,5 @@ -import { GeometryId } from '../rendering/rendering'; import { DataSeriesColorsValues } from './series'; +import { GeometryId } from '../../../utils/geometry'; export function isEqualSeriesKey(a: any[], b: any[]): boolean { if (a.length !== b.length) { diff --git a/src/chart_types/xy_chart/utils/specs.ts b/src/chart_types/xy_chart/utils/specs.ts index 999539b653..a7c73e494c 100644 --- a/src/chart_types/xy_chart/utils/specs.ts +++ b/src/chart_types/xy_chart/utils/specs.ts @@ -1,3 +1,4 @@ +import { $Values } from 'utility-types'; import { AreaSeriesStyle, GridLineConfig, @@ -9,13 +10,14 @@ import { } from '../../../utils/themes/theme'; import { Accessor, AccessorFormat } from '../../../utils/accessor'; import { RecursivePartial } from '../../../utils/commons'; -import { AnnotationId, AxisId, GroupId, SpecId } from '../../../utils/ids'; +import { AxisId, GroupId } from '../../../utils/ids'; import { ScaleContinuousType, ScaleType } from '../../../utils/scales/scales'; import { CurveType } from '../../../utils/curves'; -import { DataSeriesColorsValues, RawDataSeriesDatum } from './series'; -import { GeometryId } from '../rendering/rendering'; +import { RawDataSeriesDatum, DataSeriesColorsValues } from './series'; import { AnnotationTooltipFormatter } from '../annotations/annotation_utils'; -import { $Values } from 'utility-types'; +import { GeometryId } from '../../../utils/geometry'; +import { Spec } from '../../..'; +import { ChartTypes } from '../..'; export type Datum = any; export type Rotation = 0 | 90 | -90 | 180; @@ -23,6 +25,24 @@ export type Rendering = 'canvas' | 'svg'; export type Color = string; export type BarStyleOverride = RecursivePartial<BarSeriesStyle> | Color | null; export type PointStyleOverride = RecursivePartial<PointStyle> | Color | null; + +export const SeriesTypes = Object.freeze({ + Area: 'area' as 'area', + Bar: 'bar' as 'bar', + Line: 'line' as 'line', +}); + +export type SeriesTypes = $Values<typeof SeriesTypes>; + +export const SpecTypes = Object.freeze({ + Series: 'series' as 'series', + Axis: 'axis' as 'axis', + Annotation: 'annotation' as 'annotation', + Settings: 'settings' as 'settings', +}); + +export type SpecTypes = $Values<typeof SpecTypes>; + /** * Override for bar styles per datum * @@ -169,21 +189,21 @@ export interface DisplayValueSpec { hideClippedValue?: boolean; } -export interface SeriesSpec { - /** The ID of the spec, generated via getSpecId method */ - id: SpecId; +export interface SeriesSpec extends Spec { + specType: typeof SpecTypes.Series; + chartType: typeof ChartTypes.XYAxis; /** The name or label of the spec */ name?: string; /** The ID of the spec group, generated via getGroupId method * @default __global__ */ - groupId: GroupId; + groupId: string; /** when using a different groupId this option will allow compute in the same domain of the global domain */ useDefaultGroupDomain?: boolean; /** An array of data */ data: Datum[]; /** The type of series you are looking to render */ - seriesType: 'bar' | 'line' | 'area'; + seriesType: SeriesTypes; /** Custom colors for series */ customSeriesColors?: CustomSeriesColorsMap; /** If the series should appear in the legend @@ -264,7 +284,7 @@ export interface SeriesScales { export type BasicSeriesSpec = SeriesSpec & SeriesAccessors & SeriesScales; -export type SeriesSpecs<S extends BasicSeriesSpec = BasicSeriesSpec> = Map<SpecId, S>; +export type SeriesSpecs<S extends BasicSeriesSpec = BasicSeriesSpec> = Array<S>; /** * This spec describe the dataset configuration used to display a bar series. @@ -272,7 +292,7 @@ export type SeriesSpecs<S extends BasicSeriesSpec = BasicSeriesSpec> = Map<SpecI export type BarSeriesSpec = BasicSeriesSpec & Postfixes & { /** @default bar */ - seriesType: 'bar'; + seriesType: typeof SeriesTypes.Bar; /** If true, will stack all BarSeries and align bars to ticks (instead of centered on ticks) */ enableHistogramMode?: boolean; barSeriesStyle?: RecursivePartial<BarSeriesStyle>; @@ -327,7 +347,7 @@ export type FitConfig = { export type LineSeriesSpec = BasicSeriesSpec & HistogramConfig & { /** @default line */ - seriesType: 'line'; + seriesType: typeof SeriesTypes.Line; curve?: CurveType; lineSeriesStyle?: RecursivePartial<LineSeriesStyle>; /** @@ -347,7 +367,7 @@ export type AreaSeriesSpec = BasicSeriesSpec & HistogramConfig & Postfixes & { /** @default area */ - seriesType: 'area'; + seriesType: typeof SeriesTypes.Area; /** The type of interpolator to be used to interpolate values between points */ curve?: CurveType; areaSeriesStyle?: RecursivePartial<AreaSeriesStyle>; @@ -365,7 +385,7 @@ export type AreaSeriesSpec = BasicSeriesSpec & fit?: Exclude<Fit, 'explicit'> | FitConfig; }; -interface HistogramConfig { +export interface HistogramConfig { /** Determines how points in the series will align to bands in histogram mode * @default 'start' */ @@ -383,8 +403,10 @@ export type HistogramModeAlignment = 'start' | 'center' | 'end'; /** * This spec describe the configuration for a chart axis. */ -export interface AxisSpec { - /** The ID of the spec, generated via getSpecId method */ +export interface AxisSpec extends Spec { + specType: typeof SpecTypes.Axis; + chartType: typeof ChartTypes.XYAxis; + /** The ID of the spec */ id: AxisId; /** Style options for grid line */ gridLineStyle?: GridLineConfig; @@ -468,7 +490,7 @@ export interface LineAnnotationDatum { } export type LineAnnotationSpec = BaseAnnotationSpec & { - annotationType: 'line'; + annotationType: typeof AnnotationTypes.Line; domainType: AnnotationDomainType; /** Data values defined with value, details, and header */ dataValues: LineAnnotationDatum[]; @@ -507,7 +529,7 @@ export interface RectAnnotationDatum { } export type RectAnnotationSpec = BaseAnnotationSpec & { - annotationType: 'rectangle'; + annotationType: typeof AnnotationTypes.Rectangle; /** Custom rendering function for tooltip */ renderTooltip?: AnnotationTooltipFormatter; /** Data values defined with coordinates and details */ @@ -520,9 +542,9 @@ export type RectAnnotationSpec = BaseAnnotationSpec & { zIndex?: number; }; -export interface BaseAnnotationSpec { - /** The id of the annotation */ - annotationId: AnnotationId; +export interface BaseAnnotationSpec extends Spec { + chartType: ChartTypes; + specType: typeof SpecTypes.Annotation; /** Annotation type: line, rectangle, text */ annotationType: AnnotationType; /** The ID of the axis group, generated via getGroupId method @@ -556,15 +578,15 @@ export function isRectAnnotation(spec: AnnotationSpec): spec is RectAnnotationSp } export function isBarSeriesSpec(spec: BasicSeriesSpec): spec is BarSeriesSpec { - return spec.seriesType === 'bar'; + return spec.seriesType === SeriesTypes.Bar; } export function isLineSeriesSpec(spec: BasicSeriesSpec): spec is LineSeriesSpec { - return spec.seriesType === 'line'; + return spec.seriesType === SeriesTypes.Line; } export function isAreaSeriesSpec(spec: BasicSeriesSpec): spec is AreaSeriesSpec { - return spec.seriesType === 'area'; + return spec.seriesType === SeriesTypes.Area; } export function isBandedSpec(y0Accessors: SeriesAccessors['y0Accessors']): boolean { diff --git a/src/chart_types/xy_chart/utils/stacked_percent_series_utils.test.ts b/src/chart_types/xy_chart/utils/stacked_percent_series_utils.test.ts index 348c42645d..0e1c6559ba 100644 --- a/src/chart_types/xy_chart/utils/stacked_percent_series_utils.test.ts +++ b/src/chart_types/xy_chart/utils/stacked_percent_series_utils.test.ts @@ -1,4 +1,3 @@ -import { getSpecId } from '../../../utils/ids'; import { RawDataSeries } from './series'; import { formatStackedDataSeriesValues } from './stacked_series_utils'; import { ScaleType } from '../../../utils/scales/scales'; @@ -14,7 +13,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -25,7 +24,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -36,7 +35,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const WITH_NULL_DATASET: RawDataSeries[] = [ @@ -49,7 +48,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -60,7 +59,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -71,7 +70,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const STANDARD_DATA_SET_WY0: RawDataSeries[] = [ @@ -85,7 +84,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -97,7 +96,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -109,7 +108,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const WITH_NULL_DATASET_WY0: RawDataSeries[] = [ @@ -123,7 +122,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -134,7 +133,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -146,18 +145,18 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const DATA_SET_WITH_NULL_2: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 10 }, { x: 2, y1: 20 }, { x: 4, y1: 40 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 90 }, { x: 3, y1: 30 }], diff --git a/src/chart_types/xy_chart/utils/stacked_series_utils.test.ts b/src/chart_types/xy_chart/utils/stacked_series_utils.test.ts index 0747bc2921..fccc54907c 100644 --- a/src/chart_types/xy_chart/utils/stacked_series_utils.test.ts +++ b/src/chart_types/xy_chart/utils/stacked_series_utils.test.ts @@ -1,4 +1,3 @@ -import { getSpecId } from '../../../utils/ids'; import { RawDataSeries } from './series'; import { computeYStackedMapValues, formatStackedDataSeriesValues, getYValueStackMap } from './stacked_series_utils'; import { ScaleType } from '../../../utils/scales/scales'; @@ -9,7 +8,7 @@ describe('Stacked Series Utils', () => { data: [], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, ]; const STANDARD_DATA_SET: RawDataSeries[] = [ @@ -22,7 +21,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -33,7 +32,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -44,7 +43,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const WITH_NULL_DATASET: RawDataSeries[] = [ @@ -57,7 +56,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -68,7 +67,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -79,7 +78,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const STANDARD_DATA_SET_WY0: RawDataSeries[] = [ @@ -93,7 +92,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -105,7 +104,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -117,7 +116,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const WITH_NULL_DATASET_WY0: RawDataSeries[] = [ @@ -131,7 +130,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec1'), + specId: 'spec1', }, { data: [ @@ -142,7 +141,7 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec2'), + specId: 'spec2', }, { data: [ @@ -154,18 +153,18 @@ describe('Stacked Series Utils', () => { ], key: [], seriesColorKey: 'color-key', - specId: getSpecId('spec3'), + specId: 'spec3', }, ]; const DATA_SET_WITH_NULL_2: RawDataSeries[] = [ { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['a'], seriesColorKey: 'a', data: [{ x: 1, y1: 1 }, { x: 2, y1: 2 }, { x: 4, y1: 4 }], }, { - specId: getSpecId('spec1'), + specId: 'spec1', key: ['b'], seriesColorKey: 'b', data: [{ x: 1, y1: 21 }, { x: 3, y1: 23 }], diff --git a/src/components/_container.scss b/src/components/_container.scss index 4afb0d79cf..30f0eaf93a 100644 --- a/src/components/_container.scss +++ b/src/components/_container.scss @@ -1,22 +1,19 @@ -/** - * The Base Elastic-Charts container - */ - -.echContainer { - flex: 1; - position: relative; -} - .echChart { display: flex; height: 100%; + position: relative; &--column { flex-direction: column; } } -.echChartCursorContainer { +.echContainer { + flex: 1; + position: relative; +} + +.echChartPointerContainer { position: absolute; top: 0; bottom: 0; diff --git a/src/components/_global.scss b/src/components/_global.scss index 8099c94c55..b57fed5fa0 100644 --- a/src/components/_global.scss +++ b/src/components/_global.scss @@ -1,3 +1,12 @@ .invisible { visibility: hidden; } + +.echChartStatus { + visibility: hidden; + pointer-events: none; + z-index: -100000; + width: 0; + height: 0; + position: absolute; +} diff --git a/src/components/_index.scss b/src/components/_index.scss index de8ee6711d..74f4c59335 100644 --- a/src/components/_index.scss +++ b/src/components/_index.scss @@ -1,9 +1,9 @@ @import 'global'; @import 'container'; @import 'annotation'; -@import 'crosshair'; -@import 'highlighter'; @import 'tooltip'; @import 'icons/index'; @import 'legend/index'; @import 'unavailable_chart'; + +@import '../chart_types/xy_chart/renderer/index' \ No newline at end of file diff --git a/src/components/chart.tsx b/src/components/chart.tsx index c51426c25d..fc02f1ab62 100644 --- a/src/components/chart.tsx +++ b/src/components/chart.tsx @@ -1,22 +1,30 @@ import React, { CSSProperties, createRef } from 'react'; import classNames from 'classnames'; -import { Provider } from 'mobx-react'; - +import { Provider } from 'react-redux'; import { SpecsParser } from '../specs/specs_parser'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; -import { AnnotationTooltip } from './annotation_tooltips'; import { ChartResizer } from './chart_resizer'; -import { Crosshair } from './crosshair'; -import { Highlighter } from './highlighter'; import { Legend } from './legend/legend'; -import { ChartContainer } from './react_canvas/chart_container'; -import { Tooltips } from './tooltips'; +import { ChartContainer } from './chart_container'; import { isHorizontalAxis } from '../chart_types/xy_chart/utils/axis_utils'; import { Position } from '../chart_types/xy_chart/utils/specs'; -import { CursorEvent } from '../specs/settings'; import { ChartSize, getChartSize } from '../utils/chart_size'; -import { Stage } from 'react-konva'; +import { ChartStatus } from './chart_status'; +import { chartStoreReducer, GlobalChartState } from '../state/chart_state'; +import { createStore, Store } from 'redux'; +import uuid from 'uuid'; +import { devToolsEnhancer } from 'redux-devtools-extension'; +import { isInitialized } from '../state/selectors/is_initialized'; +import { createOnElementOutCaller } from '../chart_types/xy_chart/state/selectors/on_element_out_caller'; +import { createOnElementOverCaller } from '../chart_types/xy_chart/state/selectors/on_element_over_caller'; +import { createOnElementClickCaller } from '../chart_types/xy_chart/state/selectors/on_element_click_caller'; +import { ChartTypes } from '../chart_types/index'; +import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; +import { createOnBrushEndCaller } from '../chart_types/xy_chart/state/selectors/on_brush_end_caller'; +import { onExternalPointerEvent } from '../state/actions/events'; +import { CursorEvent } from '../specs'; +import { createOnPointerMoveCaller } from '../chart_types/xy_chart/state/selectors/on_pointer_move_caller'; import Konva from 'konva'; +import { Stage } from 'react-konva'; interface ChartProps { /** The type of rendered @@ -30,70 +38,70 @@ interface ChartProps { interface ChartState { legendPosition: Position; - renderComplete: boolean; - renderCount: number; +} + +function getContainerStyle(size: any): CSSProperties { + if (size) { + return { + position: 'relative', + ...getChartSize(size), + }; + } + return {}; } export class Chart extends React.Component<ChartProps, ChartState> { static defaultProps: ChartProps = { renderer: 'canvas', }; - private chartSpecStore: ChartStore; + private chartStore: Store<GlobalChartState>; private chartContainerRef: React.RefObject<HTMLDivElement>; private chartStageRef: React.RefObject<Stage>; constructor(props: any) { super(props); this.chartContainerRef = createRef(); this.chartStageRef = createRef(); - this.chartSpecStore = new ChartStore(props.id); + + const storeReducer = chartStoreReducer(uuid.v4()); + if (process.env.NODE_ENV !== 'production') { + this.chartStore = createStore(storeReducer, devToolsEnhancer({ trace: true })); + } else { + this.chartStore = createStore(storeReducer); + } this.state = { - legendPosition: this.chartSpecStore.legendPosition.get(), - renderComplete: false, - renderCount: 0, + legendPosition: Position.Right, }; - this.chartSpecStore.chartInitialized.observe(({ newValue, oldValue }) => { - if (newValue !== oldValue) { + const onElementClickCaller = createOnElementClickCaller(); + const onElementOverCaller = createOnElementOverCaller(); + const onElementOutCaller = createOnElementOutCaller(); + const onBrushEndCaller = createOnBrushEndCaller(); + const onPointerMoveCaller = createOnPointerMoveCaller(); + this.chartStore.subscribe(() => { + const state = this.chartStore.getState(); + if (!isInitialized(state)) { + return; + } + const settings = getSettingsSpecSelector(state); + if (this.state.legendPosition !== settings.legendPosition) { this.setState({ - renderComplete: newValue, - renderCount: newValue ? this.state.renderCount + 1 : this.state.renderCount, + legendPosition: settings.legendPosition, }); } - }); - // value is set to chart_store in settings so need to watch the value - this.chartSpecStore.legendPosition.observe(({ newValue: legendPosition }) => { - this.setState({ - legendPosition, - }); + + if (state.chartType !== ChartTypes.XYAxis) { + return; + } + onElementOverCaller(state); + onElementOutCaller(state); + onElementClickCaller(state); + onBrushEndCaller(state); + onPointerMoveCaller(state); }); } - static getContainerStyle = (size: any): CSSProperties => { - if (size) { - return { - position: 'relative', - ...getChartSize(size), - }; - } - return {}; - }; - dispatchExternalCursorEvent(event?: CursorEvent) { - this.chartSpecStore.setActiveChartId(event && event.chartId); - const isActiveChart = this.chartSpecStore.isActiveChart.get(); - - if (!event) { - this.chartSpecStore.externalCursorShown.set(false); - this.chartSpecStore.isCursorOnChart.set(false); - } else { - if ( - !isActiveChart && - this.chartSpecStore.xScale!.type === event.scale && - (event.unit === undefined || event.unit === this.chartSpecStore.xScale!.unit) - ) { - this.chartSpecStore.setCursorValue(event.value); - } - } + this.chartStore.dispatch(onExternalPointerEvent(event)); } getPNGSnapshot( @@ -150,34 +158,21 @@ export class Chart extends React.Component<ChartProps, ChartState> { }; render() { - const { renderer, size, className } = this.props; - const { renderComplete, renderCount } = this.state; - const containerStyle = Chart.getContainerStyle(size); + const { size, className } = this.props; + const containerStyle = getContainerStyle(size); const horizontal = isHorizontalAxis(this.state.legendPosition); const chartClassNames = classNames('echChart', className, { 'echChart--column': horizontal, }); - return ( - <Provider chartStore={this.chartSpecStore}> - <div - style={containerStyle} - className={chartClassNames} - data-ech-render-complete={renderComplete} - data-ech-render-count={renderCount} - ref={this.chartContainerRef} - > + <Provider store={this.chartStore}> + <div style={containerStyle} className={chartClassNames} ref={this.chartContainerRef}> + <ChartStatus /> + <ChartResizer /> <Legend /> <SpecsParser>{this.props.children}</SpecsParser> <div className="echContainer"> - <ChartResizer /> - <Crosshair /> - {// TODO reenable when SVG rendered is aligned with canvas one - renderer === 'svg' && <ChartContainer forwardRef={this.chartStageRef} />} - {renderer === 'canvas' && <ChartContainer forwardRef={this.chartStageRef} />} - <Tooltips getChartContainerRef={this.getChartContainerRef} /> - <AnnotationTooltip getChartContainerRef={this.getChartContainerRef} /> - <Highlighter /> + <ChartContainer getChartContainerRef={this.getChartContainerRef} forwardStageRef={this.chartStageRef} /> </div> </div> </Provider> diff --git a/src/components/chart_container.tsx b/src/components/chart_container.tsx new file mode 100644 index 0000000000..a477a32521 --- /dev/null +++ b/src/components/chart_container.tsx @@ -0,0 +1,173 @@ +import React from 'react'; +import { bindActionCreators, Dispatch } from 'redux'; +import { connect } from 'react-redux'; +import { GlobalChartState, BackwardRef } from '../state/chart_state'; +import { onMouseUp, onMouseDown, onPointerMove } from '../state/actions/mouse'; +import { getInternalChartRendererSelector } from '../state/selectors/get_chart_type_components'; +import { getInternalPointerCursor } from '../state/selectors/get_internal_cursor_pointer'; +import { getInternalIsBrushingAvailableSelector } from '../state/selectors/get_internal_is_brushing_available'; +import { isInternalChartEmptySelector } from '../state/selectors/is_chart_empty'; +import { isInitialized } from '../state/selectors/is_initialized'; +import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; +import { SettingsSpec } from '../specs'; +import { isBrushingSelector } from '../chart_types/xy_chart/state/selectors/is_brushing'; +import { Stage } from 'react-konva'; + +interface ReactiveChartStateProps { + initialized: boolean; + isChartEmpty?: boolean; + pointerCursor: string; + isBrushing: boolean; + isBrushingAvailable: boolean; + settings?: SettingsSpec; + internalChartRenderer: (containerRef: BackwardRef, forwardStageRef: React.RefObject<Stage>) => JSX.Element | null; +} +interface ReactiveChartDispatchProps { + onPointerMove: typeof onPointerMove; + onMouseUp: typeof onMouseUp; + onMouseDown: typeof onMouseDown; +} + +interface ReactiveChartOwnProps { + getChartContainerRef: BackwardRef; + forwardStageRef: React.RefObject<Stage>; +} + +type ReactiveChartProps = ReactiveChartStateProps & ReactiveChartDispatchProps & ReactiveChartOwnProps; + +class ChartContainerComponent extends React.Component<ReactiveChartProps> { + static displayName = 'ChartContainer'; + + shouldComponentUpdate(props: ReactiveChartProps) { + return props.initialized; + } + handleMouseMove = ({ + nativeEvent: { offsetX, offsetY, timeStamp }, + }: React.MouseEvent<HTMLDivElement, MouseEvent>) => { + const { isChartEmpty, onPointerMove } = this.props; + if (isChartEmpty) { + return; + } + onPointerMove( + { + x: offsetX, + y: offsetY, + }, + timeStamp, + ); + }; + handleMouseLeave = ({ nativeEvent: { timeStamp } }: React.MouseEvent<HTMLDivElement, MouseEvent>) => { + const { isChartEmpty, onPointerMove, isBrushing } = this.props; + if (isChartEmpty) { + return; + } + if (isBrushing) { + return; + } + onPointerMove({ x: -1, y: -1 }, timeStamp); + }; + handleMouseDown = ({ + nativeEvent: { offsetX, offsetY, timeStamp }, + }: React.MouseEvent<HTMLDivElement, MouseEvent>) => { + const { isChartEmpty, onMouseDown, isBrushingAvailable } = this.props; + if (isChartEmpty) { + return; + } + if (isBrushingAvailable) { + window.addEventListener('mouseup', this.handleBrushEnd); + } + onMouseDown( + { + x: offsetX, + y: offsetY, + }, + timeStamp, + ); + }; + handleMouseUp = ({ nativeEvent: { offsetX, offsetY, timeStamp } }: React.MouseEvent<HTMLDivElement, MouseEvent>) => { + const { isChartEmpty, onMouseUp } = this.props; + if (isChartEmpty) { + return; + } + onMouseUp( + { + x: offsetX, + y: offsetY, + }, + timeStamp, + ); + }; + handleBrushEnd = () => { + const { onMouseUp } = this.props; + + window.removeEventListener('mouseup', this.handleBrushEnd); + requestAnimationFrame(() => { + onMouseUp( + { + x: -1, + y: -1, + }, + Date.now(), + ); + }); + }; + + render() { + const { initialized } = this.props; + if (!initialized) { + return null; + } + const { pointerCursor, internalChartRenderer, getChartContainerRef, forwardStageRef } = this.props; + return ( + <div + className="echChartPointerContainer" + style={{ + cursor: pointerCursor, + }} + onMouseMove={this.handleMouseMove} + onMouseLeave={this.handleMouseLeave} + onMouseDown={this.handleMouseDown} + onMouseUp={this.handleMouseUp} + > + {internalChartRenderer(getChartContainerRef, forwardStageRef)} + </div> + ); + } +} + +const mapDispatchToProps = (dispatch: Dispatch): ReactiveChartDispatchProps => + bindActionCreators( + { + onPointerMove, + onMouseUp, + onMouseDown, + }, + dispatch, + ); +const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => { + if (!isInitialized(state)) { + return { + initialized: false, + isChartEmpty: true, + pointerCursor: 'default', + isBrushingAvailable: false, + isBrushing: false, + internalChartRenderer: () => null, + }; + } + + return { + initialized: true, + isChartEmpty: isInternalChartEmptySelector(state), + pointerCursor: getInternalPointerCursor(state), + isBrushingAvailable: getInternalIsBrushingAvailableSelector(state), + isBrushing: isBrushingSelector(state), + internalChartRenderer: getInternalChartRendererSelector(state), + settings: getSettingsSpecSelector(state), + }; +}; + +export const ChartContainer = connect( + mapStateToProps, + mapDispatchToProps, +)(ChartContainerComponent); diff --git a/src/components/chart_resizer.tsx b/src/components/chart_resizer.tsx index fbf90322a0..8a309f1420 100644 --- a/src/components/chart_resizer.tsx +++ b/src/components/chart_resizer.tsx @@ -1,12 +1,23 @@ -import { inject, observer } from 'mobx-react'; import React, { RefObject } from 'react'; import ResizeObserver from 'resize-observer-polyfill'; import { debounce } from 'ts-debounce'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; +import { Dimensions } from '../utils/dimensions'; +import { updateParentDimensions } from '../state/actions/chart_settings'; +import { Dispatch, bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; +import { GlobalChartState } from '../state/chart_state'; -interface ResizerProps { - chartStore?: ChartStore; +interface ResizerStateProps { + resizeDebounce: number; } + +interface ResizerDispatchProps { + updateParentDimensions(dimension: Dimensions): void; +} + +type ResizerProps = ResizerStateProps & ResizerDispatchProps; + class Resizer extends React.Component<ResizerProps> { private initialResizeComplete = false; private containerRef: RefObject<HTMLDivElement>; @@ -22,10 +33,12 @@ class Resizer extends React.Component<ResizerProps> { } componentDidMount() { - this.onResizeDebounced = debounce(this.onResize, this.props.chartStore!.resizeDebounce); + this.onResizeDebounced = debounce(this.onResize, this.props.resizeDebounce); if (this.containerRef.current) { - this.ro.observe(this.containerRef.current as Element); + const { clientWidth, clientHeight } = this.containerRef.current; + this.props.updateParentDimensions({ width: clientWidth, height: clientHeight, top: 0, left: 0 }); } + this.ro.observe(this.containerRef.current as Element); } componentWillUnmount() { @@ -44,7 +57,7 @@ class Resizer extends React.Component<ResizerProps> { } const { width, height } = entries[0].contentRect; this.animationFrameID = window.requestAnimationFrame(() => { - this.props.chartStore!.updateParentDimensions(width, height, 0, 0); + this.props.updateParentDimensions({ width, height, top: 0, left: 0 }); }); }; @@ -62,4 +75,24 @@ class Resizer extends React.Component<ResizerProps> { }; } -export const ChartResizer = inject('chartStore')(observer(Resizer)); +const mapDispatchToProps = (dispatch: Dispatch): ResizerDispatchProps => + bindActionCreators( + { + updateParentDimensions, + }, + dispatch, + ); + +const mapStateToProps = (state: GlobalChartState): ResizerStateProps => { + const settings = getSettingsSpecSelector(state); + const resizeDebounce = + settings.resizeDebounce === undefined || settings.resizeDebounce === null ? 200 : settings.resizeDebounce; + return { + resizeDebounce, + }; +}; + +export const ChartResizer = connect( + mapStateToProps, + mapDispatchToProps, +)(Resizer); diff --git a/src/components/chart_status.tsx b/src/components/chart_status.tsx new file mode 100644 index 0000000000..14624a3421 --- /dev/null +++ b/src/components/chart_status.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { GlobalChartState } from '../state/chart_state'; +import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; +import { RenderChangeListener } from '../specs'; + +interface ChartStatusStateProps { + rendered: boolean; + renderedCount: number; + onRenderChange?: RenderChangeListener; +} +class ChartStatusComponent extends React.Component<ChartStatusStateProps> { + componentDidMount() { + this.dispatchRenderChange(); + } + componentDidUpdate() { + this.dispatchRenderChange(); + } + dispatchRenderChange = () => { + const { onRenderChange, rendered } = this.props; + if (onRenderChange) { + onRenderChange(rendered); + } + }; + render() { + const { rendered, renderedCount } = this.props; + return <div className="echChartStatus" data-ech-render-complete={rendered} data-ech-render-count={renderedCount} />; + } +} + +const mapStateToProps = (state: GlobalChartState): ChartStatusStateProps => { + return { + rendered: state.chartRendered, + renderedCount: state.chartRenderedCount, + onRenderChange: getSettingsSpecSelector(state).onRenderChange, + }; +}; + +export const ChartStatus = connect(mapStateToProps)(ChartStatusComponent); diff --git a/src/components/crosshair.tsx b/src/components/crosshair.tsx deleted file mode 100644 index 3d28e2f228..0000000000 --- a/src/components/crosshair.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { inject, observer } from 'mobx-react'; -import React, { CSSProperties } from 'react'; -import { TooltipType } from '../chart_types/xy_chart/utils/interactions'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; -import { isHorizontalRotation } from '../chart_types/xy_chart/store/utils'; - -interface CrosshairProps { - chartStore?: ChartStore; -} - -function canRenderBand(type: TooltipType, visible: boolean) { - return visible && (type === TooltipType.Crosshairs || type === TooltipType.VerticalCursor); -} -function canRenderHelpLine(type: TooltipType, visible: boolean) { - return visible && type === TooltipType.Crosshairs; -} - -class CrosshairComponent extends React.Component<CrosshairProps> { - static displayName = 'Crosshair'; - - render() { - const { isCrosshairVisible } = this.props.chartStore!; - if (!isCrosshairVisible.get()) { - return <div className="echCrosshair" />; - } - return ( - <div className="echCrosshair"> - {this.renderBand()} - {this.renderLine()} - </div> - ); - } - - renderBand() { - const { - chartTheme: { - crosshair: { band }, - }, - cursorBandPosition: { top, left, width, height, visible }, - tooltipType, - } = this.props.chartStore!; - if (!visible || !canRenderBand(tooltipType.get(), band.visible)) { - return null; - } - - const style: CSSProperties = { - top, - left, - width, - height, - background: band.fill, - }; - - return <div className="echCrosshair__band" style={style} />; - } - - renderLine() { - const { - chartTheme: { - crosshair: { line }, - }, - cursorLinePosition, - tooltipType, - chartRotation, - } = this.props.chartStore!; - - if (!canRenderHelpLine(tooltipType.get(), line.visible)) { - return null; - } - const isHorizontalRotated = isHorizontalRotation(chartRotation); - let style: CSSProperties; - if (isHorizontalRotated) { - style = { - ...cursorLinePosition, - borderTopWidth: line.strokeWidth, - borderTopColor: line.stroke, - borderTopStyle: line.dash ? 'dashed' : 'solid', - }; - } else { - style = { - ...cursorLinePosition, - borderLeftWidth: line.strokeWidth, - borderLeftColor: line.stroke, - borderLeftStyle: line.dash ? 'dashed' : 'solid', - }; - } - return <div className="echCrosshair__line" style={style} />; - } -} - -export const Crosshair = inject('chartStore')(observer(CrosshairComponent)); diff --git a/src/components/highlighter.tsx b/src/components/highlighter.tsx deleted file mode 100644 index d19b8997aa..0000000000 --- a/src/components/highlighter.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { inject, observer } from 'mobx-react'; -import React from 'react'; -import { isPointGeometry } from '../chart_types/xy_chart/rendering/rendering'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; - -interface HighlighterProps { - chartStore?: ChartStore; -} - -class HighlighterComponent extends React.Component<HighlighterProps> { - static displayName = 'Highlighter'; - - render() { - const { highlightedGeometries, chartTransform, chartDimensions, chartRotation } = this.props.chartStore!; - const left = chartDimensions.left + chartTransform.x; - const top = chartDimensions.top + chartTransform.y; - const clipWidth = [90, -90].includes(chartRotation) ? chartDimensions.height : chartDimensions.width; - const clipHeight = [90, -90].includes(chartRotation) ? chartDimensions.width : chartDimensions.height; - return ( - <svg className="echHighlighter"> - <defs> - <clipPath id="echHighlighterClipPath"> - <rect x="0" y="0" width={clipWidth} height={clipHeight} /> - </clipPath> - </defs> - <g transform={`translate(${left}, ${top}) rotate(${chartRotation})`}> - {highlightedGeometries.map((geom, i) => { - const { color, x, y } = geom; - if (isPointGeometry(geom)) { - return ( - <circle - key={i} - cx={x + geom.transform.x} - cy={y} - r={geom.radius} - stroke={color} - strokeWidth={4} - fill="transparent" - /> - ); - } - return ( - <rect - key={i} - x={x} - y={y} - width={geom.width} - height={geom.height} - className="echHighlighter__rect" - clipPath="url(#echHighlighterClipPath)" - /> - ); - })} - </g> - </svg> - ); - } -} - -export const Highlighter = inject('chartStore')(observer(HighlighterComponent)); diff --git a/src/components/icons/assets/dot.tsx b/src/components/icons/assets/dot.tsx index 58921040ba..c50af6dcce 100644 --- a/src/components/icons/assets/dot.tsx +++ b/src/components/icons/assets/dot.tsx @@ -1,15 +1,17 @@ import React from 'react'; import { Props } from '../icon'; -export function DotIcon(extraProps: Props) { - return ( - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" {...extraProps}> - <defs> - <circle id="dot-a" cx="8" cy="8" r="4" /> - </defs> - <g> - <use xlinkHref="#dot-a" /> - </g> - </svg> - ); +export class DotIcon extends React.PureComponent<Props> { + render() { + return ( + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" {...this.props}> + <defs> + <circle id="dot-a" cx="8" cy="8" r="4" /> + </defs> + <g> + <use xlinkHref="#dot-a" /> + </g> + </svg> + ); + } } diff --git a/src/components/icons/icon.tsx b/src/components/icons/icon.tsx index 66b2686bc0..3d7de41eea 100644 --- a/src/components/icons/icon.tsx +++ b/src/components/icons/icon.tsx @@ -31,25 +31,27 @@ export interface IconProps { export type Props = Omit<SVGAttributes<SVGElement>, 'color' | 'type'> & IconProps; -export const Icon = (props: Props) => { - const { type, color, className, tabIndex, ...rest } = props; - let optionalCustomStyles = null; +export class Icon extends React.PureComponent<Props> { + render() { + const { type, color, className, tabIndex, ...rest } = this.props; + let optionalCustomStyles = null; - if (color) { - optionalCustomStyles = { color }; - } + if (color) { + optionalCustomStyles = { color }; + } - const classes = classNames('echIcon', className); + const classes = classNames('echIcon', className); - const Svg = (type && typeToIconMap[type]) || EmptyIcon; + const Svg = (type && typeToIconMap[type]) || EmptyIcon; - // This is a fix for IE and Edge, which ignores tabindex="-1" on an SVG, but respects - // focusable="false". - // - If there's no tab index specified, we'll default the icon to not be focusable, - // which is how SVGs behave in Chrome, Safari, and FF. - // - If tab index is -1, then the consumer wants the icon to not be focusable. - // - For all other values, the consumer wants the icon to be focusable. - const focusable = tabIndex == null || tabIndex === -1 ? 'false' : 'true'; + // This is a fix for IE and Edge, which ignores tabindex="-1" on an SVG, but respects + // focusable="false". + // - If there's no tab index specified, we'll default the icon to not be focusable, + // which is how SVGs behave in Chrome, Safari, and FF. + // - If tab index is -1, then the consumer wants the icon to not be focusable. + // - For all other values, the consumer wants the icon to be focusable. + const focusable = tabIndex == null || tabIndex === -1 ? 'false' : 'true'; - return <Svg className={classes} {...optionalCustomStyles} tabIndex={tabIndex} focusable={focusable} {...rest} />; -}; + return <Svg className={classes} {...optionalCustomStyles} tabIndex={tabIndex} focusable={focusable} {...rest} />; + } +} diff --git a/src/components/legend/legend.test.tsx b/src/components/legend/legend.test.tsx new file mode 100644 index 0000000000..348596e722 --- /dev/null +++ b/src/components/legend/legend.test.tsx @@ -0,0 +1,124 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import { Chart } from '../chart'; +import { Settings, BarSeries } from '../../specs'; +import { ScaleType } from '../../utils/scales/scales'; +import { DataGenerator } from '../../utils/data_generators/data_generator'; +import { Legend } from './legend'; +import { LegendListItem } from './legend_item'; + +describe('Legend', () => { + it('shall render the all the series names', () => { + const wrapper = mount( + <Chart> + <Settings showLegend /> + <BarSeries + id="areas" + name="area" + xScaleType={ScaleType.Linear} + yScaleType={ScaleType.Linear} + xAccessor={0} + yAccessors={[1]} + splitSeriesAccessors={[2]} + data={[[0, 123, 'group0'], [0, 123, 'group1'], [0, 123, 'group2'], [0, 123, 'group3']]} + /> + </Chart>, + ); + const legendWrapper = wrapper.find(Legend); + expect(legendWrapper.exists).toBeTruthy(); + const legendItems = legendWrapper.find(LegendListItem); + expect(legendItems.exists).toBeTruthy(); + expect(legendItems).toHaveLength(4); + legendItems.forEach((legendItem, i) => { + // the legend item shows also the value as default parameter + expect(legendItem.text()).toBe(`group${i}123`); + }); + }); + it('shall render the all the series names without the data value', () => { + const wrapper = mount( + <Chart> + <Settings showLegend showLegendDisplayValue={false} /> + <BarSeries + id="areas" + name="area" + xScaleType={ScaleType.Linear} + yScaleType={ScaleType.Linear} + xAccessor={0} + yAccessors={[1]} + splitSeriesAccessors={[2]} + data={[[0, 123, 'group0'], [0, 123, 'group1'], [0, 123, 'group2'], [0, 123, 'group3']]} + /> + </Chart>, + ); + const legendWrapper = wrapper.find(Legend); + expect(legendWrapper.exists).toBeTruthy(); + const legendItems = legendWrapper.find(LegendListItem); + expect(legendItems.exists).toBeTruthy(); + expect(legendItems).toHaveLength(4); + legendItems.forEach((legendItem, i) => { + // the legend item shows also the value as default parameter + expect(legendItem.text()).toBe(`group${i}`); + }); + }); + it('shall call the over and out listeners for every list item', () => { + const onLegendItemOver = jest.fn(); + const onLegendItemOut = jest.fn(); + const dg = new DataGenerator(); + const numberOfSeries = 4; + const data = dg.generateGroupedSeries(10, numberOfSeries, 'split'); + const wrapper = mount( + <Chart> + <Settings showLegend onLegendItemOver={onLegendItemOver} onLegendItemOut={onLegendItemOut} /> + <BarSeries + id="areas" + xScaleType={ScaleType.Linear} + yScaleType={ScaleType.Linear} + xAccessor={'x'} + yAccessors={['y']} + splitSeriesAccessors={['g']} + data={data} + /> + </Chart>, + ); + const legendWrapper = wrapper.find(Legend); + expect(legendWrapper.exists).toBeTruthy(); + const legendItems = legendWrapper.find(LegendListItem); + expect(legendItems.exists).toBeTruthy(); + legendItems.forEach((legendItem, i) => { + legendItem.simulate('mouseenter'); + expect(onLegendItemOver).toBeCalledTimes(i + 1); + legendItem.simulate('mouseleave'); + expect(onLegendItemOut).toBeCalledTimes(i + 1); + }); + }); + it('shall call click listener for every list item', () => { + const onLegendItemClick = jest.fn(); + const dg = new DataGenerator(); + const numberOfSeries = 4; + const data = dg.generateGroupedSeries(10, numberOfSeries, 'split'); + const wrapper = mount( + <Chart> + <Settings showLegend onLegendItemClick={onLegendItemClick} /> + <BarSeries + id="areas" + xScaleType={ScaleType.Linear} + yScaleType={ScaleType.Linear} + xAccessor={'x'} + yAccessors={['y']} + splitSeriesAccessors={['g']} + data={data} + /> + </Chart>, + ); + const legendWrapper = wrapper.find(Legend); + expect(legendWrapper.exists).toBeTruthy(); + const legendItems = legendWrapper.find(LegendListItem); + expect(legendItems.exists).toBeTruthy(); + expect(legendItems).toHaveLength(4); + legendItems.forEach((legendItem, i) => { + // the click is only enabled on the title + legendItem.find('.echLegendItem__title').simulate('click'); + expect(onLegendItemClick).toBeCalledTimes(i + 1); + }); + }); +}); diff --git a/src/components/legend/legend.tsx b/src/components/legend/legend.tsx index 93afc1409c..015aa46691 100644 --- a/src/components/legend/legend.tsx +++ b/src/components/legend/legend.tsx @@ -1,28 +1,54 @@ import React, { createRef } from 'react'; -import { inject, observer } from 'mobx-react'; import classNames from 'classnames'; - import { isVerticalAxis, isHorizontalAxis } from '../../chart_types/xy_chart/utils/axis_utils'; -import { LegendItem as SeriesLegendItem } from '../../chart_types/xy_chart/legend/legend'; -import { ChartStore } from '../../chart_types/xy_chart/store/chart_state'; +import { connect } from 'react-redux'; import { Position } from '../../chart_types/xy_chart/utils/specs'; -import { LegendItem } from './legend_item'; +import { GlobalChartState } from '../../state/chart_state'; +import { getLegendItemsSelector } from '../../state/selectors/get_legend_items'; +import { getSettingsSpecSelector } from '../../state/selectors/get_settings_specs'; +import { getChartThemeSelector } from '../../state/selectors/get_chart_theme'; +import { getLegendItemsValuesSelector } from '../../state/selectors/get_legend_items_values'; +import { getLegendSizeSelector } from '../../state/selectors/get_legend_size'; +import { onToggleLegend } from '../../state/actions/legend'; +import { Dispatch, bindActionCreators } from 'redux'; +import { LIGHT_THEME } from '../../utils/themes/light_theme'; +import { LegendListItem } from './legend_item'; import { Theme } from '../../utils/themes/theme'; import { TooltipLegendValue } from '../../chart_types/xy_chart/tooltip/tooltip'; -import { AccessorType } from '../../chart_types/xy_chart/rendering/rendering'; - -interface LegendProps { - chartStore?: ChartStore; // FIX until we find a better way on ts mobx +import { AccessorType } from '../../utils/geometry'; +import { LegendItem, getItemLabel } from '../../chart_types/xy_chart/legend/legend'; +import { BBox } from '../../utils/bbox/bbox_calculator'; +import { + onToggleDeselectSeriesAction, + onLegendItemOutAction, + onLegendItemOverAction, +} from '../../state/actions/legend'; +import { SettingsSpec } from '../../specs'; + +interface LegendStateProps { + legendItems: Map<string, LegendItem>; + legendPosition: Position; + legendItemTooltipValues: Map<string, TooltipLegendValue>; + showLegend: boolean; + legendCollapsed: boolean; + debug: boolean; + chartTheme: Theme; + legendSize: BBox; + settings?: SettingsSpec; } - -interface LegendState { - width?: number; +interface LegendDispatchProps { + onToggleLegend: typeof onToggleLegend; + onLegendItemOutAction: typeof onLegendItemOutAction; + onLegendItemOverAction: typeof onLegendItemOverAction; + onToggleDeselectSeriesAction: typeof onToggleDeselectSeriesAction; } +type LegendProps = LegendStateProps & LegendDispatchProps; interface LegendStyle { maxHeight?: string; maxWidth?: string; width?: string; + height?: string; } interface LegendListStyle { @@ -33,41 +59,21 @@ interface LegendListStyle { gridTemplateColumns?: string; } -class LegendComponent extends React.Component<LegendProps, LegendState> { +class LegendComponent extends React.Component<LegendProps> { static displayName = 'Legend'; legendItemCount = 0; - state = { - width: undefined, - }; - private echLegend = createRef<HTMLDivElement>(); - componentDidUpdate() { - this.tryLegendResize(); - } - render() { - const { - legendInitialized, - chartInitialized, - legendItems, - legendPosition, - showLegend, - debug, - chartTheme, - } = this.props.chartStore!; - const position = legendPosition.get(); - - if (!showLegend.get() || !legendInitialized.get() || legendItems.size === 0) { + const { legendItems, legendPosition, legendSize, showLegend, debug, chartTheme } = this.props; + if (!showLegend || legendItems.size === 0) { return null; } - - const legendContainerStyle = this.getLegendStyle(position, chartTheme); - const legendListStyle = this.getLegendListStyle(position, chartTheme); - const legendClasses = classNames('echLegend', `echLegend--${position}`, { + const legendContainerStyle = this.getLegendStyle(legendPosition, legendSize); + const legendListStyle = this.getLegendListStyle(legendPosition, chartTheme); + const legendClasses = classNames('echLegend', `echLegend--${legendPosition}`, { 'echLegend--debug': debug, - invisible: !chartInitialized.get(), }); return ( @@ -81,35 +87,6 @@ class LegendComponent extends React.Component<LegendProps, LegendState> { ); } - tryLegendResize = () => { - const { chartInitialized, chartTheme, legendPosition, legendItems } = this.props.chartStore!; - const { width } = this.state; - - if ( - this.echLegend.current && - isVerticalAxis(legendPosition.get()) && - !chartInitialized.get() && - width === undefined && - this.echLegend.current.offsetWidth > 0 - ) { - const buffer = chartTheme.legend.spacingBuffer; - this.legendItemCount = legendItems.size; - - return this.setState({ - width: this.echLegend.current.offsetWidth + buffer, - }); - } - - // Need to reset width to enable downsizing of width - if (width !== undefined && legendItems.size !== this.legendItemCount) { - this.legendItemCount = legendItems.size; - - this.setState({ - width: undefined, - }); - } - }; - getLegendListStyle = (position: Position, { chartMargins, legend }: Theme): LegendListStyle => { const { top: paddingTop, bottom: paddingBottom, left: paddingLeft, right: paddingRight } = chartMargins; @@ -127,36 +104,21 @@ class LegendComponent extends React.Component<LegendProps, LegendState> { }; }; - getLegendStyle = (position: Position, { legend }: Theme): LegendStyle => { + getLegendStyle = (position: Position, size: BBox): LegendStyle => { if (isVerticalAxis(position)) { - if (this.state.width !== undefined) { - const threshold = Math.min(this.state.width!, legend.verticalWidth); - const width = `${threshold}px`; - - return { - width, - maxWidth: width, - }; - } - + const width = `${size.width}px`; return { - maxWidth: `${legend.verticalWidth}px`, + width, + maxWidth: width, }; } - + const height = `${size.height}px`; return { - maxHeight: `${legend.horizontalHeight}px`, + height, + maxHeight: height, }; }; - onLegendItemMouseover = (legendItemKey: string) => () => { - this.props.chartStore!.onLegendItemOver(legendItemKey); - }; - - onLegendItemMouseout = () => { - this.props.chartStore!.onLegendItemOut(); - }; - private getLegendValues( tooltipValues: Map<string, TooltipLegendValue> | undefined, key: string, @@ -171,39 +133,89 @@ class LegendComponent extends React.Component<LegendProps, LegendState> { return banded ? [y1, y0] : [y1]; } - private getItemLabel( - { banded, label, y1AccessorFormat, y0AccessorFormat }: SeriesLegendItem, - yAccessor: AccessorType, - ) { - if (!banded) { - return label; + private renderLegendElement = (item: LegendItem) => { + if (!this.props.settings) { + return null; } - - return yAccessor === AccessorType.Y1 ? `${label}${y1AccessorFormat}` : `${label}${y0AccessorFormat}`; - } - - private renderLegendElement = (item: SeriesLegendItem) => { const { key, displayValue, banded } = item; - const { legendPosition, legendItemTooltipValues, isCursorOnChart } = this.props.chartStore!; - const tooltipValues = legendItemTooltipValues.get(); - const legendValues = this.getLegendValues(tooltipValues, key, banded); - + const { legendItemTooltipValues, settings } = this.props; + const { showLegendDisplayValue, legendPosition } = settings; + const legendValues = this.getLegendValues(legendItemTooltipValues, key, banded); return legendValues.map((value, index) => { const yAccessor: AccessorType = index === 0 ? AccessorType.Y1 : AccessorType.Y0; return ( - <LegendItem + <LegendListItem {...item} - label={this.getItemLabel(item, yAccessor)} + label={getItemLabel(item, yAccessor)} key={`${key}-${yAccessor}`} - legendItemKey={key} - legendPosition={legendPosition.get()} - displayValue={isCursorOnChart.get() ? value : displayValue.formatted[yAccessor]} - onMouseEnter={this.onLegendItemMouseover(key)} - onMouseLeave={this.onLegendItemMouseout} + legendItem={item} + displayValue={value !== '' ? value : displayValue.formatted[yAccessor]} + showLegendDisplayValue={showLegendDisplayValue} + legendPosition={legendPosition} + toggleDeselectSeriesAction={this.props.onToggleDeselectSeriesAction} + legendItemOutAction={this.props.onLegendItemOutAction} + legendItemOverAction={this.props.onLegendItemOverAction} + onLegendItemOverListener={settings.onLegendItemOver} + onLegendItemOutListener={settings.onLegendItemOut} + onLegendItemClickListener={settings.onLegendItemClick} /> ); }); }; } -export const Legend = inject('chartStore')(observer(LegendComponent)); +const mapDispatchToProps = (dispatch: Dispatch): LegendDispatchProps => + bindActionCreators( + { + onToggleLegend, + onToggleDeselectSeriesAction, + onLegendItemOutAction, + onLegendItemOverAction, + }, + dispatch, + ); + +const mapStateToProps = (state: GlobalChartState): LegendStateProps => { + if (!state.specsInitialized) { + return { + legendItems: new Map(), + legendPosition: Position.Right, + showLegend: false, + legendCollapsed: false, + legendItemTooltipValues: new Map(), + debug: false, + chartTheme: LIGHT_THEME, + legendSize: { width: 0, height: 0 }, + }; + } + const { legendPosition, showLegend, debug } = getSettingsSpecSelector(state); + if (!showLegend) { + return { + legendItems: new Map(), + legendPosition: Position.Right, + showLegend: false, + legendCollapsed: false, + legendItemTooltipValues: new Map(), + debug: false, + chartTheme: LIGHT_THEME, + legendSize: { width: 0, height: 0 }, + }; + } + const legendItems = getLegendItemsSelector(state); + return { + legendItems, + legendPosition, + showLegend, + legendCollapsed: state.interactions.legendCollapsed, + legendItemTooltipValues: getLegendItemsValuesSelector(state), + debug, + chartTheme: getChartThemeSelector(state), + legendSize: getLegendSizeSelector(state), + settings: getSettingsSpecSelector(state), + }; +}; + +export const Legend = connect( + mapStateToProps, + mapDispatchToProps, +)(LegendComponent); diff --git a/src/components/legend/legend_item.tsx b/src/components/legend/legend_item.tsx index dfa1ebd403..7e279fba1d 100644 --- a/src/components/legend/legend_item.tsx +++ b/src/components/legend/legend_item.tsx @@ -1,185 +1,151 @@ import classNames from 'classnames'; -import { inject, observer } from 'mobx-react'; import React from 'react'; import { Icon } from '../icons/icon'; - -import { ChartStore } from '../../chart_types/xy_chart/store/chart_state'; +import { LegendItemListener, BasicListener } from '../../specs/settings'; +import { isEqualSeriesKey } from '../../chart_types/xy_chart/utils/series_utils'; +import { DataSeriesColorsValues } from '../../chart_types/xy_chart/utils/series'; +import { LegendItem } from '../../chart_types/xy_chart/legend/legend'; +import { onLegendItemOutAction, onLegendItemOverAction } from '../../state/actions/legend'; import { Position } from '../../chart_types/xy_chart/utils/specs'; interface LegendItemProps { - chartStore?: ChartStore; // FIX until we find a better way on ts mobx - legendItemKey: string; - legendPosition: Position; - color: string | undefined; - label: string | undefined; - isSeriesVisible?: boolean; - isLegendItemVisible?: boolean; + selectedLegendItem?: LegendItem | null; + legendItem: LegendItem; displayValue: string; - onMouseEnter: (event: React.MouseEvent) => void; - onMouseLeave: () => void; + label?: string; + legendPosition: Position; + showLegendDisplayValue: boolean; + onLegendItemClickListener?: LegendItemListener; + onLegendItemOutListener?: BasicListener; + onLegendItemOverListener?: LegendItemListener; + legendItemOutAction: typeof onLegendItemOutAction; + legendItemOverAction: typeof onLegendItemOverAction; + toggleDeselectSeriesAction: (legendItemId: DataSeriesColorsValues) => void; } interface LegendItemState { isColorPickerOpen: boolean; } -class LegendItemComponent extends React.Component<LegendItemProps, LegendItemState> { - static displayName = 'LegendItem'; +/** + * Create a div for the the displayed value + * @param displayValue + * @param isSeriesVisible + */ +function renderDisplayValue(displayValue: string, isSeriesVisible: boolean | undefined) { + const displayValueClassNames = classNames('echLegendItem__displayValue', { + ['echLegendItem__displayValue--hidden']: !isSeriesVisible, + }); + return ( + <div className={displayValueClassNames} title={displayValue}> + {displayValue} + </div> + ); +} - constructor(props: LegendItemProps) { - super(props); - this.state = { - isColorPickerOpen: false, - }; - } +/** + * Create a div for the title + * @param title + * @param onTitleClick + * @param hasTitleClickListener + * @param isSelected + * @param showLegendDisplayValue + */ +function renderTitle( + title: string, + onTitleClick: (event: React.MouseEvent<Element, MouseEvent>) => void, + hasTitleClickListener: boolean, + isSelected: boolean, + showLegendDisplayValue: boolean, +) { + // TODO add contextual menu panel on click + const titleClassNames = classNames('echLegendItem__title', { + ['echLegendItem__title--hasClickListener']: hasTitleClickListener, + ['echLegendItem__title--selected']: isSelected, + ['echLegendItem__title--hasDisplayValue']: showLegendDisplayValue, + }); + return ( + <div className={titleClassNames} title={title} onClick={onTitleClick}> + {title} + </div> + ); +} - closeColorPicker = () => { - this.setState({ - isColorPickerOpen: false, - }); - }; +/** + * Create a div for the color/eye icon + * @param color + * @param isSeriesVisible + */ +function renderColor(color: string, isSeriesVisible = true) { + // TODO add color picker + if (isSeriesVisible) { + return ( + <div className="echLegendItem__color" aria-label="series color" title="series color"> + <Icon type="dot" color={color} /> + </div> + ); + } + // changing the default viewBox for the eyeClosed icon to keep the same dimensions + return ( + <div className="echLegendItem__color" aria-label="series hidden" title="series hidden"> + <Icon type="eyeClosed" viewBox="-3 -3 22 22" /> + </div> + ); +} - toggleColorPicker = () => { - this.setState({ - isColorPickerOpen: !this.state.isColorPickerOpen, - }); - }; +export class LegendListItem extends React.PureComponent<LegendItemProps, LegendItemState> { + static displayName = 'LegendItem'; render() { - const { - legendItemKey, - legendPosition, - chartStore, - color, - label, - isSeriesVisible, - isLegendItemVisible, - displayValue, - onMouseEnter, - onMouseLeave, - } = this.props; - const onTitleClick = this.onVisibilityClick(legendItemKey); - const showLegendDisplayValue = chartStore!.showLegendDisplayValue.get(); - const isSelected = legendItemKey === chartStore!.selectedLegendItemKey.get(); - const hasDisplayValue = chartStore!.showLegendDisplayValue.get(); - const hasTitleClickListener = Boolean(chartStore!.onLegendItemClickListener); - + const { displayValue, legendItem, legendPosition, label } = this.props; + const { color, isSeriesVisible, value, isLegendItemVisible } = legendItem; + const onTitleClick = this.onVisibilityClick(legendItem.value); + + const { showLegendDisplayValue, selectedLegendItem, onLegendItemClickListener } = this.props; + const isSelected = + selectedLegendItem == null + ? false + : isEqualSeriesKey(value.colorValues, selectedLegendItem.value.colorValues) && + value.specId === selectedLegendItem.value.specId; + const hasTitleClickListener = Boolean(onLegendItemClickListener); const itemClasses = classNames('echLegendItem', `echLegendItem--${legendPosition}`, { - 'echLegendItem--hidden': !isSeriesVisible, + 'echLegendItem-isHidden': !isSeriesVisible, 'echLegendItem__displayValue--hidden': !isLegendItemVisible, }); return ( - <div className={itemClasses} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}> - {this.renderColor(this.toggleColorPicker, color, isSeriesVisible)} - {this.renderTitle(label, onTitleClick, hasTitleClickListener, isSelected, hasDisplayValue)} - {this.renderDisplayValue(displayValue, showLegendDisplayValue, isSeriesVisible)} - </div> - ); - } - renderColor(colorClickAction: () => void, color?: string, isSeriesVisible = true) { - if (!color) { - return null; - } - // TODO add color picker - const iconType = isSeriesVisible ? 'dot' : 'eyeClosed'; - const iconColor = isSeriesVisible ? color : undefined; - const title = isSeriesVisible ? 'series color' : 'series hidden'; - const viewBox = isSeriesVisible ? undefined : '-3 -3 22 22'; - return ( - <div className="echLegendItem__color" aria-label={title} title={title}> - <Icon type={iconType} color={iconColor} onClick={colorClickAction} viewBox={viewBox} /> + <div className={itemClasses} onMouseEnter={this.onLegendItemMouseOver} onMouseLeave={this.onLegendItemMouseOut}> + {color && renderColor(color, isSeriesVisible)} + {label && renderTitle(label, onTitleClick, hasTitleClickListener, isSelected, showLegendDisplayValue)} + {showLegendDisplayValue && renderDisplayValue(displayValue, isSeriesVisible)} </div> ); } - renderVisibilityButton = (legendItemKey: string, isSeriesVisible = true) => { - const iconType = isSeriesVisible ? 'eye' : 'eyeClosed'; - return ( - <div className="echLegendItem__visibility"> - <Icon type={iconType} aria-label="toggle visibility" onClick={this.onVisibilityClick(legendItemKey)} /> - </div> - ); - }; - - renderTitle( - title: string | undefined, - onTitleClick: (event: React.MouseEvent<Element, MouseEvent>) => void, - hasTitleClickListener: boolean, - isSelected: boolean, - hasDisplayValue: boolean, - ) { - // TODO add contextual menu panel on click - if (!title) { - return null; + onLegendItemMouseOver = () => { + const { onLegendItemOverListener, legendItemOverAction, legendItem } = this.props; + // call the settings listener directly if available + if (onLegendItemOverListener) { + onLegendItemOverListener(legendItem.value); } - const titleClassNames = classNames('echLegendItem__title', { - ['echLegendItem__title--hasClickListener']: hasTitleClickListener, - ['echLegendItem__title--selected']: isSelected, - ['echLegendItem__title--hasDisplayValue']: hasDisplayValue, - }); - return ( - <div className={titleClassNames} title={title} onClick={onTitleClick}> - {title} - </div> - ); - } + legendItemOverAction(legendItem.key); + }; - renderDisplayValue(displayValue: string, show: boolean, isSeriesVisible: boolean | undefined) { - if (!show) { - return; + onLegendItemMouseOut = () => { + const { onLegendItemOutListener, legendItemOutAction } = this.props; + // call the settings listener directly if available + if (onLegendItemOutListener) { + onLegendItemOutListener(); } - const displayValueClassNames = classNames('echLegendItem__displayValue', { - ['echLegendItem__displayValue--hidden']: !isSeriesVisible, - }); - return ( - <div className={displayValueClassNames} title={displayValue}> - {displayValue} - </div> - ); - } - - onLegendTitleClick = (legendItemKey: string) => () => { - this.props.chartStore!.onLegendItemClick(legendItemKey); + legendItemOutAction(); }; - // Keeping these as reference when we have a contextual panel - // private onLegendItemPanelClose = () => { - // // tslint:disable-next-line:no-console - // console.log('close'); - // } - - // private onColorPickerChange = (legendItemKey: string) => (color: string) => { - // this.props.chartStore!.setSeriesColor(legendItemKey, color); - // } - - // private renderPlusButton = () => { - // return ( - // <EuiButtonIcon - // onClick={this.props.chartStore!.onLegendItemPlusClick} - // iconType="plusInCircle" - // aria-label="minus" - // /> - // ); - // } - - // private renderMinusButton = () => { - // return ( - // <EuiButtonIcon - // onClick={this.props.chartStore!.onLegendItemMinusClick} - // iconType="minusInCircle" - // aria-label="minus" - // /> - // ); - // } - - private onVisibilityClick = (legendItemKey: string) => (event: React.MouseEvent) => { - if (event.shiftKey) { - this.props.chartStore!.toggleSingleSeries(legendItemKey); - } else { - this.props.chartStore!.toggleSeriesVisibility(legendItemKey); + // TODO handle shift key + onVisibilityClick = (legendItemId: DataSeriesColorsValues) => () => { + const { onLegendItemClickListener, toggleDeselectSeriesAction } = this.props; + if (onLegendItemClickListener) { + onLegendItemClickListener(legendItemId); } + toggleDeselectSeriesAction(legendItemId); }; } - -export const LegendItem = inject('chartStore')(observer(LegendItemComponent)); diff --git a/src/components/react_canvas/bar_values.tsx b/src/components/react_canvas/bar_values.tsx deleted file mode 100644 index 327efb529e..0000000000 --- a/src/components/react_canvas/bar_values.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react'; -import { Group, Rect, Text } from 'react-konva'; -import { BarGeometry } from '../../chart_types/xy_chart/rendering/rendering'; -import { Rotation } from '../../chart_types/xy_chart/utils/specs'; -import { DisplayValueStyle } from '../../utils/themes/theme'; -import { Dimensions } from '../../utils/dimensions'; -import { buildBarValueProps } from './utils/rendering_props_utils'; - -interface BarValuesProps { - chartDimensions: Dimensions; - chartRotation: Rotation; - debug: boolean; - bars: BarGeometry[]; - displayValueStyle: DisplayValueStyle; -} - -export class BarValues extends React.PureComponent<BarValuesProps> { - render() { - const { chartDimensions } = this.props; - - return ( - <Group x={chartDimensions.left} y={chartDimensions.top}> - {this.renderBarValues()} - </Group> - ); - } - - private renderBarValues = () => { - const { bars, displayValueStyle, debug, chartRotation, chartDimensions } = this.props; - return bars.map((bar, index) => { - const { displayValue, x, y, height, width } = bar; - if (!displayValue) { - return; - } - - const key = `bar-value-${index}`; - const displayValueProps = buildBarValueProps({ - x, - y, - barHeight: height, - barWidth: width, - displayValueStyle, - displayValue, - chartRotation, - chartDimensions, - }); - - const debugProps = { - ...displayValueProps, - stroke: 'violet', - strokeWidth: 1, - fill: 'transparent', - }; - - return ( - <Group key={key}> - {debug && <Rect {...debugProps} />} - {displayValue && <Text {...displayValueProps} />} - </Group> - ); - }); - }; -} diff --git a/src/components/react_canvas/chart_container.tsx b/src/components/react_canvas/chart_container.tsx deleted file mode 100644 index c455eb89b8..0000000000 --- a/src/components/react_canvas/chart_container.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import { inject, observer } from 'mobx-react'; -import { ChartStore } from '../../chart_types/xy_chart/store/chart_state'; -import { ReactiveChart } from './reactive_chart'; -import { Stage } from 'react-konva'; -interface ReactiveChartProps { - chartStore?: ChartStore; // FIX until we find a better way on ts mobx - forwardRef: React.RefObject<Stage>; -} - -class ChartContainerComponent extends React.Component<ReactiveChartProps> { - static displayName = 'ChartContainer'; - - render() { - const { chartInitialized } = this.props.chartStore!; - if (!chartInitialized.get()) { - return null; - } - const { setCursorPosition, isChartEmpty } = this.props.chartStore!; - return ( - <div - className="echChartCursorContainer" - style={{ - cursor: this.props.chartStore!.chartCursor.get(), - }} - onMouseMove={({ nativeEvent: { offsetX, offsetY } }) => { - if (!isChartEmpty.get()) { - setCursorPosition(offsetX, offsetY); - } - }} - onMouseLeave={() => { - setCursorPosition(-1, -1); - }} - onMouseUp={() => { - if (this.props.chartStore!.isBrushing.get()) { - return; - } - this.props.chartStore!.handleChartClick(); - }} - > - <ReactiveChart forwardRef={this.props.forwardRef} /> - </div> - ); - } -} - -export const ChartContainer = inject('chartStore')(observer(ChartContainerComponent)); diff --git a/src/components/react_canvas/reactive_chart.tsx b/src/components/react_canvas/reactive_chart.tsx deleted file mode 100644 index 83ee14327b..0000000000 --- a/src/components/react_canvas/reactive_chart.tsx +++ /dev/null @@ -1,473 +0,0 @@ -import React from 'react'; -import { inject, observer } from 'mobx-react'; -import { Layer, Rect, Stage } from 'react-konva'; - -import { AnnotationId } from '../../utils/ids'; -import { isLineAnnotation, isRectAnnotation, AxisSpec } from '../../chart_types/xy_chart/utils/specs'; -import { LineAnnotationStyle, RectAnnotationStyle, mergeGridLineConfigs } from '../../utils/themes/theme'; -import { - AnnotationDimensions, - AnnotationLineProps, - AnnotationRectProps, -} from '../../chart_types/xy_chart/annotations/annotation_utils'; -import { ChartStore, Point } from '../../chart_types/xy_chart/store/chart_state'; -import { BrushExtent } from '../../chart_types/xy_chart/store/utils'; -import { AreaGeometries } from './area_geometries'; -import { Axis } from './axis'; -import { BarGeometries } from './bar_geometries'; -import { BarValues } from './bar_values'; -import { Grid } from './grid'; -import { LineAnnotation } from './line_annotation'; -import { LineGeometries } from './line_geometries'; -import { RectAnnotation } from './rect_annotation'; -import { AxisTick, AxisTicksDimensions, isVerticalGrid } from '../../chart_types/xy_chart/utils/axis_utils'; -import { Dimensions } from '../../utils/dimensions'; -import { Clippings } from './utils/rendering_props_utils'; - -interface ReactiveChartProps { - chartStore?: ChartStore; // FIX until we find a better way on ts mobx - forwardRef: React.RefObject<Stage>; -} -interface ReactiveChartState { - brushing: boolean; - brushStart: Point; - brushEnd: Point; - bbox: { - left: number; - top: number; - }; -} - -interface AxisProps { - key: string; - axisSpec: AxisSpec; - axisTicksDimensions: AxisTicksDimensions; - axisPosition: Dimensions; - ticks: AxisTick[]; -} - -interface ReactiveChartElementIndex { - element: JSX.Element; - zIndex: number; -} - -function limitPoint(value: number, min: number, max: number) { - if (value > max) { - return max; - } else if (value < min) { - return min; - } else { - return value; - } -} -function getPoint(event: MouseEvent, extent: BrushExtent): Point { - const point = { - x: limitPoint(event.offsetX, extent.minX, extent.maxX), - y: limitPoint(event.offsetY, extent.minY, extent.maxY), - }; - return point; -} -class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> { - static displayName = 'ReactiveChart'; - firstRender = true; - state = { - brushing: false, - brushStart: { - x: 0, - y: 0, - }, - brushEnd: { - x: 0, - y: 0, - }, - bbox: { - left: 0, - top: 0, - }, - }; - - componentWillUnmount() { - window.removeEventListener('mouseup', this.onEndBrushing); - } - - renderBarSeries = (clippings: Clippings): ReactiveChartElementIndex[] => { - const { geometries, canDataBeAnimated, chartTheme } = this.props.chartStore!; - if (!geometries) { - return []; - } - const highlightedLegendItem = this.getHighlightedLegendItem(); - const element = ( - <BarGeometries - key={'bar-geometries'} - animated={canDataBeAnimated} - bars={geometries.bars} - sharedStyle={chartTheme.sharedStyle} - highlightedLegendItem={highlightedLegendItem} - clippings={clippings} - /> - ); - - return [ - { - element, - zIndex: 0, - }, - ]; - }; - renderLineSeries = (clippings: Clippings): ReactiveChartElementIndex[] => { - const { geometries, canDataBeAnimated, chartTheme } = this.props.chartStore!; - if (!geometries) { - return []; - } - - const highlightedLegendItem = this.getHighlightedLegendItem(); - - const element = ( - <LineGeometries - key={'line-geometries'} - animated={canDataBeAnimated} - lines={geometries.lines} - sharedStyle={chartTheme.sharedStyle} - highlightedLegendItem={highlightedLegendItem} - clippings={clippings} - /> - ); - - return [ - { - element, - zIndex: 0, - }, - ]; - }; - renderAreaSeries = (clippings: Clippings): ReactiveChartElementIndex[] => { - const { geometries, canDataBeAnimated, chartTheme } = this.props.chartStore!; - if (!geometries) { - return []; - } - - const highlightedLegendItem = this.getHighlightedLegendItem(); - - const element = ( - <AreaGeometries - key={'area-geometries'} - animated={canDataBeAnimated} - areas={geometries.areas} - sharedStyle={chartTheme.sharedStyle} - highlightedLegendItem={highlightedLegendItem} - clippings={clippings} - /> - ); - - return [ - { - element, - zIndex: 0, - }, - ]; - }; - - getAxes = (): AxisProps[] => { - const { axesVisibleTicks, axesSpecs, axesTicksDimensions, axesPositions } = this.props.chartStore!; - const ids = [...axesVisibleTicks.keys()]; - - return ids - .map((id) => ({ - key: `axis-${id}`, - ticks: axesVisibleTicks.get(id), - axisSpec: axesSpecs.get(id), - axisTicksDimensions: axesTicksDimensions.get(id), - axisPosition: axesPositions.get(id), - })) - .filter( - (config: Partial<AxisProps>): config is AxisProps => { - const { ticks, axisSpec, axisTicksDimensions, axisPosition } = config; - - return Boolean(ticks && axisSpec && axisTicksDimensions && axisPosition); - }, - ); - }; - - renderAxes = (): JSX.Element[] => { - const { chartTheme, debug, chartDimensions } = this.props.chartStore!; - const axes = this.getAxes(); - - return axes.map(({ key, ...axisProps }) => ( - <Axis {...axisProps} key={key} chartTheme={chartTheme} debug={debug} chartDimensions={chartDimensions} /> - )); - }; - - renderGrids = () => { - const { axesGridLinesPositions, axesSpecs, chartDimensions, chartTheme, debug } = this.props.chartStore!; - - const gridComponents: JSX.Element[] = []; - axesGridLinesPositions.forEach((axisGridLinesPositions, axisId) => { - const axisSpec = axesSpecs.get(axisId); - - if (axisSpec && axisGridLinesPositions.length > 0) { - const themeConfig = isVerticalGrid(axisSpec.position) - ? chartTheme.axes.gridLineStyle.vertical - : chartTheme.axes.gridLineStyle.horizontal; - - const axisSpecConfig = axisSpec.gridLineStyle; - const gridLineStyle = axisSpecConfig ? mergeGridLineConfigs(axisSpecConfig, themeConfig) : themeConfig; - gridComponents.push( - <Grid - key={`axis-grid-${axisId}`} - chartDimensions={chartDimensions} - debug={debug} - gridLineStyle={gridLineStyle} - linesPositions={axisGridLinesPositions} - />, - ); - } - }); - return gridComponents; - }; - - renderAnnotations = (): ReactiveChartElementIndex[] => { - const { annotationDimensions, annotationSpecs, chartDimensions, debug } = this.props.chartStore!; - - const annotationElements: ReactiveChartElementIndex[] = []; - annotationDimensions.forEach((annotation: AnnotationDimensions, id: AnnotationId) => { - const spec = annotationSpecs.get(id); - - if (!spec) { - return; - } - - const zIndex = spec.zIndex || 0; - let element; - if (isLineAnnotation(spec)) { - const lineStyle = spec.style as LineAnnotationStyle; - - element = ( - <LineAnnotation - key={`annotation-${id}`} - chartDimensions={chartDimensions} - debug={debug} - lines={annotation as AnnotationLineProps[]} - lineStyle={lineStyle} - /> - ); - } else if (isRectAnnotation(spec)) { - const rectStyle = spec.style as RectAnnotationStyle; - element = ( - <RectAnnotation - key={`annotation-${id}`} - chartDimensions={chartDimensions} - debug={debug} - rects={annotation as AnnotationRectProps[]} - rectStyle={rectStyle} - /> - ); - } - - if (element) { - annotationElements.push({ - element, - zIndex, - }); - } - }); - return annotationElements; - }; - - renderBarValues = () => { - const { debug, chartDimensions, geometries, chartTheme, chartRotation } = this.props.chartStore!; - if (!geometries) { - return; - } - const props = { - debug, - chartDimensions, - chartRotation, - bars: geometries.bars, - // displayValue is guaranteed on style as part of the merged theme - displayValueStyle: chartTheme.barSeriesStyle.displayValue!, - }; - return <BarValues {...props} />; - }; - - renderBrushTool = () => { - const { brushing, brushStart, brushEnd } = this.state; - const { chartDimensions, chartRotation, chartTransform } = this.props.chartStore!; - if (!brushing) { - return null; - } - let x = 0; - let y = 0; - let width = 0; - let height = 0; - if (chartRotation === 0 || chartRotation === 180) { - x = brushStart.x; - y = chartDimensions.top + chartTransform.y; - width = brushEnd.x - brushStart.x; - height = chartDimensions.height; - } else { - x = chartDimensions.left + chartTransform.x; - y = brushStart.y; - width = chartDimensions.width; - height = brushEnd.y - brushStart.y; - } - return <Rect x={x} y={y} width={width} height={height} fill="gray" opacity={0.6} />; - }; - onStartBrusing = (event: { evt: MouseEvent }) => { - window.addEventListener('mouseup', this.onEndBrushing); - const { brushExtent } = this.props.chartStore!; - const point = getPoint(event.evt, brushExtent); - this.setState(() => ({ - brushing: true, - brushStart: point, - brushEnd: point, - })); - }; - onEndBrushing = () => { - window.removeEventListener('mouseup', this.onEndBrushing); - const { brushStart, brushEnd } = this.state; - - this.setState( - () => ({ - brushing: false, - brushStart: { x: 0, y: 0 }, - brushEnd: { x: 0, y: 0 }, - }), - () => { - this.props.chartStore!.onBrushEnd(brushStart, brushEnd); - }, - ); - }; - onBrushing = (event: { evt: MouseEvent }) => { - if (!this.state.brushing) { - return; - } - if (!this.props.chartStore!.isBrushing.get()) { - this.props.chartStore!.onBrushStart(); - } - const { brushExtent } = this.props.chartStore!; - const point = getPoint(event.evt, brushExtent); - this.setState(() => ({ - brushEnd: point, - })); - }; - - sortAndRenderElements() { - const { chartRotation, chartDimensions } = this.props.chartStore!; - const { height, width } = chartDimensions; - const clippings = { - clipX: 0, - clipY: 0, - clipWidth: [90, -90].includes(chartRotation) ? height : width, - clipHeight: [90, -90].includes(chartRotation) ? width : height, - }; - - const bars = this.renderBarSeries(clippings); - const areas = this.renderAreaSeries(clippings); - const lines = this.renderLineSeries(clippings); - const annotations = this.renderAnnotations(); - - return [...bars, ...areas, ...lines, ...annotations] - .sort((elemIdxA, elemIdxB) => elemIdxA.zIndex - elemIdxB.zIndex) - .map((elemIdx) => elemIdx.element); - } - - render() { - const { chartInitialized } = this.props.chartStore!; - if (!chartInitialized.get()) { - return null; - } - - const { - parentDimensions, - chartDimensions, - chartRotation, - chartTransform, - debug, - isChartEmpty, - } = this.props.chartStore!; - - if (isChartEmpty.get()) { - return ( - <div className="echReactiveChart_unavailable"> - <p>No data to display</p> - </div> - ); - } - - let brushProps = {}; - const isBrushEnabled = this.props.chartStore!.isBrushEnabled(); - if (isBrushEnabled) { - brushProps = { - onMouseDown: this.onStartBrusing, - onMouseMove: this.onBrushing, - }; - } - - return ( - <Stage - width={parentDimensions.width} - height={parentDimensions.height} - style={{ - width: '100%', - height: '100%', - }} - {...brushProps} - ref={this.props.forwardRef} - > - <Layer hitGraphEnabled={false} listening={false}> - {this.renderGrids()} - </Layer> - <Layer hitGraphEnabled={false} listening={false}> - {this.renderAxes()} - </Layer> - - <Layer - x={chartDimensions.left + chartTransform.x} - y={chartDimensions.top + chartTransform.y} - rotation={chartRotation} - hitGraphEnabled={false} - listening={false} - > - {this.sortAndRenderElements()} - </Layer> - - {debug && ( - <Layer hitGraphEnabled={false} listening={false}> - {this.renderDebugChartBorders()} - </Layer> - )} - {isBrushEnabled && ( - <Layer hitGraphEnabled={false} listening={false}> - {this.renderBrushTool()} - </Layer> - )} - - <Layer hitGraphEnabled={false} listening={false}> - {this.renderBarValues()} - </Layer> - </Stage> - ); - } - - private renderDebugChartBorders = () => { - const { chartDimensions } = this.props.chartStore!; - return ( - <Rect - x={chartDimensions.left} - y={chartDimensions.top} - width={chartDimensions.width} - height={chartDimensions.height} - stroke="red" - strokeWidth={4} - listening={false} - dash={[4, 4]} - /> - ); - }; - - private getHighlightedLegendItem = () => { - return this.props.chartStore!.highlightedLegendItem.get(); - }; -} - -export const ReactiveChart = inject('chartStore')(observer(Chart)); diff --git a/src/components/react_canvas/rect_annotation.tsx b/src/components/react_canvas/rect_annotation.tsx deleted file mode 100644 index 13f984e075..0000000000 --- a/src/components/react_canvas/rect_annotation.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { Group, Rect } from 'react-konva'; -import { RectAnnotationStyle } from '../../utils/themes/theme'; -import { Dimensions } from '../../utils/dimensions'; -import { AnnotationRectProps } from '../../chart_types/xy_chart/annotations/annotation_utils'; - -interface RectAnnotationProps { - chartDimensions: Dimensions; - debug: boolean; - rects: AnnotationRectProps[]; - rectStyle: RectAnnotationStyle; -} - -export class RectAnnotation extends React.PureComponent<RectAnnotationProps> { - render() { - return this.renderAnnotation(); - } - private renderAnnotationRect = (props: AnnotationRectProps, i: number) => { - const { x, y, width, height } = props.rect; - const rectProps = { - ...this.props.rectStyle, - x, - y, - width, - height, - }; - - return <Rect {...rectProps} key={`rect-${i}`} />; - }; - - private renderAnnotation = () => { - const { rects } = this.props; - - return <Group>{rects.map(this.renderAnnotationRect)}</Group>; - }; -} diff --git a/src/index.ts b/src/index.ts index 2a0ac16032..e231d32cda 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,8 @@ export * from './specs'; export { Chart } from './components/chart'; export { ChartSize, ChartSizeArray, ChartSizeObject } from './utils/chart_size'; -export { TooltipType, TooltipValue, TooltipValueFormatter } from './chart_types/xy_chart/utils/interactions'; export { SpecId, GroupId, AxisId, AnnotationId, getAxisId, getGroupId, getSpecId, getAnnotationId } from './utils/ids'; export { ScaleType } from './utils/scales/scales'; -export { Position, Rendering, Rotation, TickFormatter } from './chart_types/xy_chart/utils/specs'; export * from './utils/themes/theme'; export { LIGHT_THEME } from './utils/themes/light_theme'; export { DARK_THEME } from './utils/themes/dark_theme'; @@ -13,6 +11,9 @@ export { RecursivePartial } from './utils/commons'; export { CurveType } from './utils/curves'; export { timeFormatter, niceTimeFormatter, niceTimeFormatByDay } from './utils/data/formatters'; export { DataGenerator } from './utils/data_generators/data_generator'; +export { ChartTypes } from './chart_types'; +export { Position, Rendering, Rotation, TickFormatter } from './chart_types/xy_chart/utils/specs'; +export { TooltipType, TooltipValue, TooltipValueFormatter } from './chart_types/xy_chart/utils/interactions'; export { DataSeriesColorsValues } from './chart_types/xy_chart/utils/series'; export { AnnotationDomainType, @@ -24,16 +25,8 @@ export { LineAnnotationSpec, RectAnnotationDatum, RectAnnotationSpec, + SeriesTypes, + SpecTypes, } from './chart_types/xy_chart/utils/specs'; -export { GeometryValue } from './chart_types/xy_chart/rendering/rendering'; export { AnnotationTooltipFormatter } from './chart_types/xy_chart/annotations/annotation_utils'; -export { SettingSpecProps } from './specs/settings'; -export { - BrushEndListener, - ElementClickListener, - ElementOverListener, - LegendItemListener, - CursorUpdateListener, - RenderChangeListener, - BasicListener, -} from './chart_types/xy_chart/store/chart_state'; +export { GeometryValue } from './utils/geometry'; diff --git a/src/mocks/scale/scale.ts b/src/mocks/scale/scale.ts index 53384e29f1..386988db6a 100644 --- a/src/mocks/scale/scale.ts +++ b/src/mocks/scale/scale.ts @@ -6,6 +6,7 @@ export class MockScale { scale: jest.fn().mockImplementation((x) => x), type: ScaleType.Linear, bandwidth: 0, + bandwidthPadding: 0, minInterval: 0, barsPadding: 0, range: [0, 100], diff --git a/src/mocks/specs/specs.ts b/src/mocks/specs/specs.ts index c889979131..0a831adfec 100644 --- a/src/mocks/specs/specs.ts +++ b/src/mocks/specs/specs.ts @@ -8,14 +8,19 @@ import { HistogramBarSeriesSpec, LineSeriesSpec, BasicSeriesSpec, + SpecTypes, + SeriesTypes, } from '../../chart_types/xy_chart/utils/specs'; -import { getSpecId, getGroupId, SpecId } from '../../utils/ids'; +import { getSpecId, getGroupId } from '../../utils/ids'; import { ScaleType } from '../../utils/scales/scales'; +import { ChartTypes } from '../../chart_types'; export class MockSeriesSpec { private static readonly barBase: BarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: getSpecId('spec1'), - seriesType: 'bar', + seriesType: SeriesTypes.Bar, groupId: getGroupId(DEFAULT_GLOBAL_ID), xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, @@ -25,12 +30,14 @@ export class MockSeriesSpec { hideInLegend: false, enableHistogramMode: false, stackAsPercentage: false, - data: [], + data: [] as any[], }; private static readonly histogramBarBase: HistogramBarSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: getSpecId('spec1'), - seriesType: 'bar', + seriesType: SeriesTypes.Bar, groupId: getGroupId(DEFAULT_GLOBAL_ID), xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, @@ -43,8 +50,10 @@ export class MockSeriesSpec { }; private static readonly areaBase: AreaSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: getSpecId('spec1'), - seriesType: 'area', + seriesType: SeriesTypes.Area, groupId: getGroupId(DEFAULT_GLOBAL_ID), xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, @@ -57,8 +66,10 @@ export class MockSeriesSpec { }; private static readonly lineBase: LineSeriesSpec = { + chartType: ChartTypes.XYAxis, + specType: SpecTypes.Series, id: getSpecId('spec1'), - seriesType: 'line', + seriesType: SeriesTypes.Line, groupId: getGroupId(DEFAULT_GLOBAL_ID), xScaleType: ScaleType.Ordinal, yScaleType: ScaleType.Linear, @@ -91,11 +102,10 @@ export class MockSeriesSpec { export class MockSeriesSpecs { static fromSpecs(specs: BasicSeriesSpec[]): SeriesSpecs { - const specsMap: [SpecId, BasicSeriesSpec][] = specs.map((spec) => [spec.id, spec]); - return new Map(specsMap); + return specs; } static empty(): SeriesSpecs { - return new Map(); + return []; } } diff --git a/src/specs/index.ts b/src/specs/index.ts index aed77a90a9..29bbf5feaf 100644 --- a/src/specs/index.ts +++ b/src/specs/index.ts @@ -1,3 +1,13 @@ -export { Settings, CursorEvent } from './settings'; -// XY chart specs -export * from '../chart_types/xy_chart/specs'; +import { ChartTypes } from '../chart_types'; + +export interface Spec { + /** unique Spec identifier */ + id: string; + /** Chart type define the type of chart that use this spec */ + chartType: ChartTypes; + /** The type of spec, can be series, axis, annotation, settings etc*/ + specType: string; +} +export * from './settings'; + +export * from '../chart_types/specs'; diff --git a/src/specs/settings.test.tsx b/src/specs/settings.test.tsx index caa6cde14c..e3f43a4627 100644 --- a/src/specs/settings.test.tsx +++ b/src/specs/settings.test.tsx @@ -3,115 +3,105 @@ import * as React from 'react'; import { Position, Rendering, Rotation } from '../chart_types/xy_chart/utils/specs'; import { DARK_THEME } from '../utils/themes/dark_theme'; import { TooltipType } from '../chart_types/xy_chart/utils/interactions'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; -import { DEFAULT_TOOLTIP_SNAP, DEFAULT_TOOLTIP_TYPE, SettingsComponent, SettingSpecProps } from './settings'; +import { Settings, SettingsSpec } from './settings'; import { PartialTheme } from '../utils/themes/theme'; import { LIGHT_THEME } from '../utils/themes/light_theme'; - +import { chartStoreReducer, GlobalChartState } from '../state/chart_state'; +import { createStore, Store } from 'redux'; +import { SpecsParser } from './specs_parser'; +import { Provider } from 'react-redux'; +import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs'; +import { getChartThemeSelector } from '../state/selectors/get_chart_theme'; + +const getProxy = (chartStore: Store<GlobalChartState>) => { + return function SettingsProxy({ settings }: { settings?: Partial<SettingsSpec> }) { + return ( + <Provider store={chartStore}> + <SpecsParser> + <Settings {...settings} /> + </SpecsParser> + </Provider> + ); + }; +}; describe('Settings spec component', () => { + let chartStore: Store<GlobalChartState>; + let SettingsProxy: ({ settings }: { settings?: Partial<SettingsSpec> }) => JSX.Element; + beforeEach(() => { + const storeReducer = chartStoreReducer('chart_id'); + chartStore = createStore(storeReducer); + expect(chartStore.getState().specsInitialized).toBe(false); + SettingsProxy = getProxy(chartStore); + }); test('should update store on mount if spec has a chart store', () => { - const chartStore = new ChartStore(); - - // component without store - mount(<SettingsComponent rotation={90} />); - expect(chartStore.chartRotation).toBe(0); - - mount(<SettingsComponent rotation={90} chartStore={chartStore} />); - expect(chartStore.chartRotation).toBe(90); + mount( + <Provider store={chartStore}> + <SpecsParser /> + </Provider>, + ); + expect(getSettingsSpecSelector(chartStore.getState()).rotation).toBe(0); + + mount( + <Provider store={chartStore}> + <SpecsParser> + <Settings rotation={90} /> + </SpecsParser> + </Provider>, + ); + expect(getSettingsSpecSelector(chartStore.getState()).rotation).toBe(90); }); test('should update store on component update', () => { - const chartStore = new ChartStore(); - - const component = mount(<SettingsComponent chartStore={chartStore} />); + const component = mount(<SettingsProxy />); + let settingSpec = getSettingsSpecSelector(chartStore.getState()); + expect(settingSpec.theme).toEqual(LIGHT_THEME); + expect(settingSpec.rotation).toBe(0); component.setProps({ - theme: DARK_THEME, - rotation: 90 as Rotation, - rendering: 'svg' as Rendering, - animateData: true, - showLegend: true, - tooltip: { - type: TooltipType.None, - snap: false, + settings: { + theme: DARK_THEME, + rotation: 90 as Rotation, + rendering: 'svg' as Rendering, + animateData: true, + showLegend: true, + tooltip: { + type: TooltipType.None, + snap: false, + }, + legendPosition: Position.Bottom, + showLegendDisplayValue: false, + debug: true, + xDomain: { min: 0, max: 10 }, }, - legendPosition: Position.Bottom, - showLegendDisplayValue: false, - debug: true, - xDomain: { min: 0, max: 10 }, }); - - expect(chartStore.chartTheme).toEqual(DARK_THEME); - expect(chartStore.chartRotation).toBe(90); - expect(chartStore.chartRendering).toBe('svg'); - expect(chartStore.animateData).toBe(true); - expect(chartStore.showLegend.get()).toEqual(true); - expect(chartStore.tooltipType.get()).toEqual(TooltipType.None); - expect(chartStore.tooltipSnap.get()).toEqual(false); - expect(chartStore.legendPosition.get()).toBe(Position.Bottom); - expect(chartStore.showLegendDisplayValue.get()).toEqual(false); - expect(chartStore.debug).toBe(true); - expect(chartStore.customXDomain).toEqual({ min: 0, max: 10 }); - }); - - test('should set chart properties on chart store', () => { - const chartStore = new ChartStore(); - - expect(chartStore.chartTheme).toEqual(LIGHT_THEME); - expect(chartStore.chartRotation).toBe(0); - expect(chartStore.chartRendering).toBe('canvas'); - expect(chartStore.animateData).toBe(false); - expect(chartStore.showLegend.get()).toEqual(false); - expect(chartStore.tooltipType.get()).toEqual(DEFAULT_TOOLTIP_TYPE); - expect(chartStore.tooltipSnap.get()).toEqual(DEFAULT_TOOLTIP_SNAP); - expect(chartStore.showLegendDisplayValue.get()).toEqual(true); - expect(chartStore.legendPosition.get()).toBe(Position.Right); - expect(chartStore.debug).toBe(false); - expect(chartStore.customXDomain).toBeUndefined(); - - const updatedProps: SettingSpecProps = { - theme: DARK_THEME, - rotation: 90 as Rotation, - rendering: 'svg' as Rendering, - animateData: true, - showLegend: true, - tooltip: { - type: TooltipType.None, - snap: false, - }, - legendPosition: Position.Bottom, - hideDuplicateAxes: false, - showLegendDisplayValue: false, - debug: true, - xDomain: { min: 0, max: 10 }, - }; - - mount(<SettingsComponent chartStore={chartStore} {...updatedProps} />); - - expect(chartStore.chartTheme).toEqual(DARK_THEME); - expect(chartStore.chartRotation).toBe(90); - expect(chartStore.chartRendering).toBe('svg'); - expect(chartStore.animateData).toBe(true); - expect(chartStore.showLegend.get()).toEqual(true); - expect(chartStore.tooltipType.get()).toEqual(TooltipType.None); - expect(chartStore.tooltipSnap.get()).toEqual(false); - expect(chartStore.legendPosition.get()).toBe(Position.Bottom); - expect(chartStore.showLegendDisplayValue.get()).toEqual(false); - expect(chartStore.debug).toBe(true); - expect(chartStore.customXDomain).toEqual({ min: 0, max: 10 }); + settingSpec = getSettingsSpecSelector(chartStore.getState()); + expect(settingSpec.theme).toEqual(DARK_THEME); + expect(settingSpec.rotation).toBe(90); + expect(settingSpec.rendering).toBe('svg'); + expect(settingSpec.animateData).toBe(true); + expect(settingSpec.showLegend).toEqual(true); + expect(settingSpec.tooltip).toEqual({ + type: TooltipType.None, + snap: false, + }); + expect(settingSpec.legendPosition).toBe(Position.Bottom); + expect(settingSpec.showLegendDisplayValue).toEqual(false); + expect(settingSpec.debug).toBe(true); + expect(settingSpec.xDomain).toEqual({ min: 0, max: 10 }); }); test('should set event listeners on chart store', () => { - const chartStore = new ChartStore(); - - expect(chartStore.onElementClickListener).toBeUndefined(); - expect(chartStore.onElementOverListener).toBeUndefined(); - expect(chartStore.onElementOutListener).toBeUndefined(); - expect(chartStore.onBrushEndListener).toBeUndefined(); - expect(chartStore.onLegendItemOverListener).toBeUndefined(); - expect(chartStore.onLegendItemOutListener).toBeUndefined(); - expect(chartStore.onLegendItemClickListener).toBeUndefined(); - expect(chartStore.onLegendItemPlusClickListener).toBeUndefined(); - expect(chartStore.onLegendItemMinusClickListener).toBeUndefined(); + mount(<SettingsProxy />); + let settingSpec = getSettingsSpecSelector(chartStore.getState()); + + expect(settingSpec.onElementClick).toBeUndefined(); + expect(settingSpec.onElementOver).toBeUndefined(); + expect(settingSpec.onElementOut).toBeUndefined(); + expect(settingSpec.onBrushEnd).toBeUndefined(); + expect(settingSpec.onLegendItemOver).toBeUndefined(); + expect(settingSpec.onLegendItemOut).toBeUndefined(); + expect(settingSpec.onLegendItemClick).toBeUndefined(); + expect(settingSpec.onLegendItemPlusClick).toBeUndefined(); + expect(settingSpec.onLegendItemMinusClick).toBeUndefined(); const onElementClick = (): void => { return; @@ -133,7 +123,7 @@ describe('Settings spec component', () => { return; }; - const chartStoreListeners = { + const updatedProps: Partial<SettingsSpec> = { onElementClick, onElementOver, onElementOut: onOut, @@ -147,31 +137,34 @@ describe('Settings spec component', () => { onRenderChange: onRenderChangeEvent, }; - mount(<SettingsComponent chartStore={chartStore} {...chartStoreListeners} />); - expect(chartStore.onElementClickListener).toEqual(onElementClick); - expect(chartStore.onElementOverListener).toEqual(onElementOver); - expect(chartStore.onElementOutListener).toEqual(onOut); - expect(chartStore.onBrushEndListener).toEqual(onBrushEnd); - expect(chartStore.onLegendItemOverListener).toEqual(onLegendEvent); - expect(chartStore.onLegendItemOutListener).toEqual(onOut); - expect(chartStore.onLegendItemClickListener).toEqual(onLegendEvent); - expect(chartStore.onLegendItemPlusClickListener).toEqual(onLegendEvent); - expect(chartStore.onLegendItemMinusClickListener).toEqual(onLegendEvent); - expect(chartStore.onCursorUpdateListener).toEqual(onCursorUpdateEvent); - expect(chartStore.onRenderChangeListener).toEqual(onRenderChangeEvent); + mount(<SettingsProxy settings={updatedProps} />); + settingSpec = getSettingsSpecSelector(chartStore.getState()); + + expect(settingSpec.onElementClick).toEqual(onElementClick); + expect(settingSpec.onElementOver).toEqual(onElementOver); + expect(settingSpec.onElementOut).toEqual(onOut); + expect(settingSpec.onBrushEnd).toEqual(onBrushEnd); + expect(settingSpec.onLegendItemOver).toEqual(onLegendEvent); + expect(settingSpec.onLegendItemOut).toEqual(onOut); + expect(settingSpec.onLegendItemClick).toEqual(onLegendEvent); + expect(settingSpec.onLegendItemPlusClick).toEqual(onLegendEvent); + expect(settingSpec.onLegendItemMinusClick).toEqual(onLegendEvent); + expect(settingSpec.onCursorUpdate).toEqual(onCursorUpdateEvent); + expect(settingSpec.onRenderChange).toEqual(onRenderChangeEvent); }); test('should allow partial theme', () => { - const chartStore = new ChartStore(); + mount(<SettingsProxy />); + let settingSpec = getSettingsSpecSelector(chartStore.getState()); + expect(settingSpec.theme).toEqual(LIGHT_THEME); + const partialTheme: PartialTheme = { colors: { defaultVizColor: 'aquamarine', }, }; - expect(chartStore.chartTheme).toEqual(LIGHT_THEME); - - const updatedProps: SettingSpecProps = { + const updatedProps: Partial<SettingsSpec> = { theme: partialTheme, baseTheme: DARK_THEME, rotation: 90 as Rotation, @@ -189,9 +182,13 @@ describe('Settings spec component', () => { xDomain: { min: 0, max: 10 }, }; - mount(<SettingsComponent chartStore={chartStore} {...updatedProps} />); + mount(<SettingsProxy settings={updatedProps} />); - expect(chartStore.chartTheme).toEqual({ + settingSpec = getSettingsSpecSelector(chartStore.getState()); + // the theme is no longer stored into the setting spec. + // it's final theme object is computed through selectors + const theme = getChartThemeSelector(chartStore.getState()); + expect(theme).toEqual({ ...DARK_THEME, colors: { ...DARK_THEME.colors, diff --git a/src/specs/settings.tsx b/src/specs/settings.tsx index e3e9f1ab41..1d44143991 100644 --- a/src/specs/settings.tsx +++ b/src/specs/settings.tsx @@ -1,31 +1,27 @@ -import { PureComponent } from 'react'; -import { inject } from 'mobx-react'; - -import { DomainRange, Position, Rendering, Rotation } from '../chart_types/xy_chart/utils/specs'; -import { mergeWithDefaultTheme, PartialTheme, Theme } from '../utils/themes/theme'; +import { DomainRange, Position, Rendering, Rotation, SpecTypes } from '../chart_types/xy_chart/utils/specs'; +import { PartialTheme, Theme } from '../utils/themes/theme'; import { Domain } from '../utils/domain'; import { TooltipType, TooltipValueFormatter } from '../chart_types/xy_chart/utils/interactions'; -import { - BrushEndListener, - ChartStore, - ElementClickListener, - ElementOverListener, - LegendItemListener, - CursorUpdateListener, - RenderChangeListener, -} from '../chart_types/xy_chart/store/chart_state'; import { ScaleTypes } from '../utils/scales/scales'; +import { getConnect, specComponentFactory } from '../state/spec_factory'; +import { Spec } from '.'; import { LIGHT_THEME } from '../utils/themes/light_theme'; - -export const DEFAULT_TOOLTIP_TYPE = TooltipType.VerticalCursor; -export const DEFAULT_TOOLTIP_SNAP = true; - -interface TooltipProps { - type?: TooltipType; - snap?: boolean; - headerFormatter?: TooltipValueFormatter; -} - +import { ChartTypes } from '../chart_types'; +import { GeometryValue } from '../utils/geometry'; +import { DataSeriesColorsValues } from '../chart_types/xy_chart/utils/series'; + +export type ElementClickListener = (values: GeometryValue[]) => void; +export type ElementOverListener = (values: GeometryValue[]) => void; +export type BrushEndListener = (min: number, max: number) => void; +export type LegendItemListener = (dataSeriesIdentifiers: DataSeriesColorsValues | null) => void; +export type CursorUpdateListener = (event?: CursorEvent) => void; +/** + * Listener to be called when chart render state changes + * + * `isRendered` value is `true` when rendering is complete and `false` otherwise + */ +export type RenderChangeListener = (isRendered: boolean) => void; +export type BasicListener = () => undefined | void; /** * Event used to syncronize cursors between Charts. * @@ -42,16 +38,14 @@ export interface CursorEvent { value: number | string; } -function isTooltipProps(config: TooltipType | TooltipProps): config is TooltipProps { - return typeof config === 'object'; -} - -function isTooltipType(config: TooltipType | TooltipProps): config is TooltipType { - return typeof config === 'string'; +interface TooltipProps { + type?: TooltipType; + snap?: boolean; + headerFormatter?: TooltipValueFormatter; + unit?: string; } -export interface SettingSpecProps { - chartStore?: ChartStore; +export interface SettingsSpec extends Spec { /** * Partial theme to be merged with base * @@ -74,9 +68,9 @@ export interface SettingSpecProps { animateData: boolean; showLegend: boolean; /** Either a TooltipType or an object with configuration of type, snap, and/or headerFormatter */ - tooltip?: TooltipType | TooltipProps; + tooltip: TooltipType | TooltipProps; debug: boolean; - legendPosition?: Position; + legendPosition: Position; showLegendDisplayValue: boolean; /** * Removes duplicate axes @@ -86,10 +80,10 @@ export interface SettingSpecProps { hideDuplicateAxes: boolean; onElementClick?: ElementClickListener; onElementOver?: ElementOverListener; - onElementOut?: () => undefined | void; + onElementOut?: BasicListener; onBrushEnd?: BrushEndListener; onLegendItemOver?: LegendItemListener; - onLegendItemOut?: () => undefined | void; + onLegendItemOut?: BasicListener; onLegendItemClick?: LegendItemListener; onLegendItemPlusClick?: LegendItemListener; onLegendItemMinusClick?: LegendItemListener; @@ -99,135 +93,48 @@ export interface SettingSpecProps { resizeDebounce?: number; } -function getTheme(baseTheme?: Theme, theme?: PartialTheme | PartialTheme[]): Theme { - const base = baseTheme ? baseTheme : LIGHT_THEME; - - if (Array.isArray(theme)) { - const [firstTheme, ...axillaryThemes] = theme; - return mergeWithDefaultTheme(firstTheme, base, axillaryThemes); - } - - return theme ? mergeWithDefaultTheme(theme, base) : base; -} - -function updateChartStore(props: SettingSpecProps) { - const { - chartStore, - theme, - baseTheme, - rotation, - rendering, - animateData, - showLegend, - tooltip, - legendPosition, - showLegendDisplayValue, - onElementClick, - onElementOver, - onElementOut, - onBrushEnd, - onLegendItemOver, - onLegendItemOut, - onLegendItemClick, - onLegendItemMinusClick, - onLegendItemPlusClick, - onRenderChange, - onCursorUpdate, - debug, - xDomain, - resizeDebounce, - hideDuplicateAxes, - } = props; - - if (!chartStore) { - return; - } - - chartStore.chartTheme = getTheme(baseTheme, theme); - chartStore.chartRotation = rotation; - chartStore.chartRendering = rendering; - chartStore.animateData = animateData; - chartStore.debug = debug; - chartStore.resizeDebounce = resizeDebounce!; - chartStore.hideDuplicateAxes = hideDuplicateAxes; - - if (tooltip && isTooltipProps(tooltip)) { - const { type, snap, headerFormatter } = tooltip; - chartStore.tooltipType.set(type!); - chartStore.tooltipSnap.set(snap!); - chartStore.tooltipHeaderFormatter = headerFormatter; - } else if (tooltip && isTooltipType(tooltip)) { - chartStore.tooltipType.set(tooltip); - } - - chartStore.setShowLegend(showLegend); - - if (legendPosition) { - chartStore.legendPosition.set(legendPosition); - } - chartStore.showLegendDisplayValue.set(showLegendDisplayValue); - chartStore.customXDomain = xDomain; - - if (onElementOver) { - chartStore.setOnElementOverListener(onElementOver); - } - if (onElementClick) { - chartStore.setOnElementClickListener(onElementClick); - } - if (onElementOut) { - chartStore.setOnElementOutListener(onElementOut); - } - if (onBrushEnd) { - chartStore.setOnBrushEndListener(onBrushEnd); - } - if (onLegendItemOver) { - chartStore.setOnLegendItemOverListener(onLegendItemOver); - } - if (onLegendItemOut) { - chartStore.setOnLegendItemOutListener(onLegendItemOut); - } - if (onLegendItemClick) { - chartStore.setOnLegendItemClickListener(onLegendItemClick); - } - if (onLegendItemPlusClick) { - chartStore.setOnLegendItemPlusClickListener(onLegendItemPlusClick); - } - if (onLegendItemMinusClick) { - chartStore.setOnLegendItemMinusClickListener(onLegendItemMinusClick); - } - if (onCursorUpdate) { - chartStore.setOnCursorUpdateListener(onCursorUpdate); - } - if (onRenderChange) { - chartStore.setOnRenderChangeListener(onRenderChange); - } -} - -export class SettingsComponent extends PureComponent<SettingSpecProps> { - static defaultProps: Partial<SettingSpecProps> = { - rendering: 'canvas', - rotation: 0, - animateData: true, - showLegend: false, - resizeDebounce: 10, - debug: false, - hideDuplicateAxes: false, - tooltip: { - type: DEFAULT_TOOLTIP_TYPE, - snap: DEFAULT_TOOLTIP_SNAP, - }, - showLegendDisplayValue: true, - }; +export type DefaultSettingsProps = + | 'id' + | 'chartType' + | 'specType' + | 'rendering' + | 'rotation' + | 'resizeDebounce' + | 'animateData' + | 'showLegend' + | 'debug' + | 'tooltip' + | 'showLegendDisplayValue' + | 'theme' + | 'legendPosition' + | 'hideDuplicateAxes'; - componentDidMount() { - updateChartStore(this.props); - } - componentDidUpdate() { - updateChartStore(this.props); - } - render() { - return null; - } -} +export const DEFAULT_TOOLTIP_TYPE = TooltipType.VerticalCursor; +export const DEFAULT_TOOLTIP_SNAP = true; -export const Settings = inject('chartStore')(SettingsComponent); +export const DEFAULT_SETTINGS_SPEC = { + id: '__global__settings___', + chartType: ChartTypes.Global, + specType: SpecTypes.Settings, + rendering: 'canvas' as 'canvas', + rotation: 0 as 0, + animateData: true, + showLegend: false, + resizeDebounce: 10, + debug: false, + tooltip: { + type: DEFAULT_TOOLTIP_TYPE, + snap: DEFAULT_TOOLTIP_SNAP, + value: '', + }, + legendPosition: Position.Right, + showLegendDisplayValue: true, + hideDuplicateAxes: false, + theme: LIGHT_THEME, +}; + +type SpecProps = Partial<Omit<SettingsSpec, 'chartType' | 'specType' | 'id'>>; + +export const Settings: React.FunctionComponent<SpecProps> = getConnect()( + specComponentFactory<SettingsSpec, DefaultSettingsProps>(DEFAULT_SETTINGS_SPEC), +); diff --git a/src/specs/specs_parser.test.tsx b/src/specs/specs_parser.test.tsx index c68e8bdd1d..44a4c7a316 100644 --- a/src/specs/specs_parser.test.tsx +++ b/src/specs/specs_parser.test.tsx @@ -1,36 +1,81 @@ import { mount } from 'enzyme'; import * as React from 'react'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; -import { SpecsSpecRootComponent } from './specs_parser'; +import { createStore } from 'redux'; +import { Provider } from 'react-redux'; +import { SpecsParser } from './specs_parser'; +import { chartStoreReducer } from '../state/chart_state'; +import { BarSeries } from '../'; +import { DEFAULT_SETTINGS_SPEC } from './settings'; +import { BarSeriesSpec } from '../chart_types/xy_chart/utils/specs'; describe('Specs parser', () => { - test('Mount and parse specs', () => { - const chartStore = new ChartStore(); - expect(chartStore.specsInitialized.get()).toBe(false); - const component = <SpecsSpecRootComponent chartStore={chartStore} />; + test('can mount the spec parser', () => { + const storeReducer = chartStoreReducer('chart_id'); + const chartStore = createStore(storeReducer); + + expect(chartStore.getState().specsInitialized).toBe(false); + const component = ( + <Provider store={chartStore}> + <SpecsParser /> + </Provider> + ); + mount(component); + expect(chartStore.getState().specsInitialized).toBe(true); + }); + test('can parse few components', () => { + const storeReducer = chartStoreReducer('chart_id'); + const chartStore = createStore(storeReducer); + + expect(chartStore.getState().specsInitialized).toBe(false); + const component = ( + <Provider store={chartStore}> + <SpecsParser> + <BarSeries id={'bars'} xAccessor={0} yAccessors={[1]} data={[[0, 1], [1, 2]]} /> + <BarSeries id={'bars'} xAccessor={0} yAccessors={[1]} data={[[0, 1], [1, 2]]} /> + <BarSeries id={'bars2'} xAccessor={0} yAccessors={[1]} data={[[0, 1], [1, 2]]} /> + </SpecsParser> + </Provider> + ); mount(component); - expect(chartStore.specsInitialized.get()).toBe(true); + const state = chartStore.getState(); + expect(state.specsInitialized).toBe(true); + expect(Object.keys(state.specs)).toEqual([DEFAULT_SETTINGS_SPEC.id, 'bars', 'bars2']); + expect(state.specs['bars']).toBeDefined(); + expect(state.specs['bars2']).toBeDefined(); }); - test('chart store initialized and computeChart on component update', () => { - const chartStore = new ChartStore(); - const computeChart = jest.fn( - (): void => { - return; - }, + test('can update a component', () => { + const storeReducer = chartStoreReducer('chart_id'); + const chartStore = createStore(storeReducer); + + expect(chartStore.getState().specsInitialized).toBe(false); + const component = ( + <Provider store={chartStore}> + <SpecsParser> + <BarSeries id={'bars'} xAccessor={0} yAccessors={[1]} data={[[0, 1], [1, 2]]} /> + </SpecsParser> + </Provider> ); - chartStore.computeChart = computeChart; + const wrapper = mount(component); - const component = mount(<SpecsSpecRootComponent chartStore={chartStore} />); - component.update(); - component.setState({ foo: 'bar' }); - expect(chartStore.specsInitialized.get()).toBe(true); - expect(computeChart).toBeCalled(); + wrapper.setProps({ + children: ( + <SpecsParser> + <BarSeries id={'bars'} xAccessor={1} yAccessors={[1]} data={[[0, 1], [1, 2]]} /> + </SpecsParser> + ), + }); + const state = chartStore.getState(); + expect((state.specs['bars'] as BarSeriesSpec).xAccessor).toBe(1); }); - test('updates initialization state on unmount', () => { - const chartStore = new ChartStore(); - chartStore.chartInitialized.set(true); - const component = mount(<SpecsSpecRootComponent chartStore={chartStore} />); + test('set initialization to false on unmount', () => { + const storeReducer = chartStoreReducer('chart_id'); + const chartStore = createStore(storeReducer); + const component = mount( + <Provider store={chartStore}> + <SpecsParser /> + </Provider>, + ); component.unmount(); - expect(chartStore.chartInitialized.get()).toBe(false); + expect(chartStore.getState().specsInitialized).toBe(false); }); }); diff --git a/src/specs/specs_parser.tsx b/src/specs/specs_parser.tsx index aaa827e891..7fe38ede6b 100644 --- a/src/specs/specs_parser.tsx +++ b/src/specs/specs_parser.tsx @@ -1,26 +1,37 @@ -import { inject } from 'mobx-react'; -import { PureComponent } from 'react'; -import { ChartStore } from '../chart_types/xy_chart/store/chart_state'; +import React, { useEffect } from 'react'; +import { bindActionCreators, Dispatch } from 'redux'; +import { connect } from 'react-redux'; +import { specParsed, specUnmounted } from '../state/actions/specs'; -export interface SpecProps { - chartStore?: ChartStore; // FIX -} +export const SpecsParserComponent: React.FunctionComponent<{}> = (props) => { + const injected = props as DispatchProps; + useEffect(() => { + injected.specParsed(); + }); + useEffect( + () => () => { + injected.specUnmounted(); + }, + [], + ); + return props.children ? (props.children as React.ReactElement) : null; +}; -export class SpecsSpecRootComponent extends PureComponent<SpecProps> { - componentDidMount() { - this.props.chartStore!.specsInitialized.set(true); - this.props.chartStore!.computeChart(); - } - componentDidUpdate() { - this.props.chartStore!.specsInitialized.set(true); - this.props.chartStore!.computeChart(); - } - componentWillUnmount() { - this.props.chartStore!.chartInitialized.set(false); - } - render() { - return this.props.children || null; - } +interface DispatchProps { + specParsed: () => void; + specUnmounted: () => void; } -export const SpecsParser = inject('chartStore')(SpecsSpecRootComponent); +const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => + bindActionCreators( + { + specParsed, + specUnmounted, + }, + dispatch, + ); + +export const SpecsParser = connect( + null, + mapDispatchToProps, +)(SpecsParserComponent); diff --git a/src/state/actions/chart.ts b/src/state/actions/chart.ts new file mode 100644 index 0000000000..763f94f113 --- /dev/null +++ b/src/state/actions/chart.ts @@ -0,0 +1,11 @@ +export const CHART_RENDERED = 'CHART_RENDERED'; + +interface ChartRenderedAction { + type: typeof CHART_RENDERED; +} + +export function onChartRendered(): ChartRenderedAction { + return { type: CHART_RENDERED }; +} + +export type ChartActions = ChartRenderedAction; diff --git a/src/state/actions/chart_settings.ts b/src/state/actions/chart_settings.ts new file mode 100644 index 0000000000..e8bbfd7a69 --- /dev/null +++ b/src/state/actions/chart_settings.ts @@ -0,0 +1,14 @@ +import { Dimensions } from '../../utils/dimensions'; + +export const UPDATE_PARENT_DIMENSION = 'UPDATE_PARENT_DIMENSION'; + +interface UpdateParentDimensionAction { + type: typeof UPDATE_PARENT_DIMENSION; + dimensions: Dimensions; +} + +export function updateParentDimensions(dimensions: Dimensions): UpdateParentDimensionAction { + return { type: UPDATE_PARENT_DIMENSION, dimensions }; +} + +export type ChartSettingsActions = UpdateParentDimensionAction; diff --git a/src/state/actions/events.ts b/src/state/actions/events.ts new file mode 100644 index 0000000000..c51133b84d --- /dev/null +++ b/src/state/actions/events.ts @@ -0,0 +1,14 @@ +import { CursorEvent } from '../../specs/settings'; + +export const EXTERNAL_POINTER_EVENT = 'EXTERNAL_POINTER_EVENT'; + +interface ExternalPointerEvent { + type: typeof EXTERNAL_POINTER_EVENT; + event?: CursorEvent; +} + +export function onExternalPointerEvent(event?: CursorEvent): ExternalPointerEvent { + return { type: EXTERNAL_POINTER_EVENT, event }; +} + +export type EventsActions = ExternalPointerEvent; diff --git a/src/state/actions/index.ts b/src/state/actions/index.ts new file mode 100644 index 0000000000..7044bba8b6 --- /dev/null +++ b/src/state/actions/index.ts @@ -0,0 +1,14 @@ +import { SpecActions } from './specs'; +import { ChartActions } from './chart'; +import { ChartSettingsActions } from './chart_settings'; +import { LegendActions } from './legend'; +import { EventsActions } from './events'; +import { MouseActions } from './mouse'; + +export type StateActions = + | SpecActions + | ChartActions + | ChartSettingsActions + | LegendActions + | EventsActions + | MouseActions; diff --git a/src/state/actions/legend.ts b/src/state/actions/legend.ts new file mode 100644 index 0000000000..9884bda069 --- /dev/null +++ b/src/state/actions/legend.ts @@ -0,0 +1,44 @@ +import { DataSeriesColorsValues } from '../../chart_types/xy_chart/utils/series'; + +export const ON_TOGGLE_LEGEND = 'ON_TOGGLE_LEGEND'; +export const ON_LEGEND_ITEM_OVER = 'ON_LEGEND_ITEM_OVER'; +export const ON_LEGEND_ITEM_OUT = 'ON_LEGEND_ITEM_OUT'; +export const ON_TOGGLE_DESELECT_SERIES = 'ON_TOGGLE_DESELECT_SERIES'; + +interface ToggleLegendAction { + type: typeof ON_TOGGLE_LEGEND; +} +interface LegendItemOverAction { + type: typeof ON_LEGEND_ITEM_OVER; + legendItemKey: string | null; +} +interface LegendItemOutAction { + type: typeof ON_LEGEND_ITEM_OUT; +} + +interface ToggleDeselectSeriesAction { + type: typeof ON_TOGGLE_DESELECT_SERIES; + legendItemId: DataSeriesColorsValues; +} + +export function onToggleLegend(): ToggleLegendAction { + return { type: ON_TOGGLE_LEGEND }; +} + +export function onLegendItemOverAction(legendItemKey: string | null): LegendItemOverAction { + return { type: ON_LEGEND_ITEM_OVER, legendItemKey }; +} + +export function onLegendItemOutAction(): LegendItemOutAction { + return { type: ON_LEGEND_ITEM_OUT }; +} + +export function onToggleDeselectSeriesAction(legendItemId: DataSeriesColorsValues): ToggleDeselectSeriesAction { + return { type: ON_TOGGLE_DESELECT_SERIES, legendItemId }; +} + +export type LegendActions = + | ToggleLegendAction + | LegendItemOverAction + | LegendItemOutAction + | ToggleDeselectSeriesAction; diff --git a/src/state/actions/mouse.ts b/src/state/actions/mouse.ts new file mode 100644 index 0000000000..ab1f45c740 --- /dev/null +++ b/src/state/actions/mouse.ts @@ -0,0 +1,51 @@ +import { Point } from '../../utils/point'; + +export const ON_POINTER_MOVE = 'ON_POINTER_MOVE'; +export const ON_MOUSE_DOWN = 'ON_MOUSE_DOWN'; +export const ON_MOUSE_UP = 'ON_MOUSE_UP'; + +interface MouseDownAction { + type: typeof ON_MOUSE_DOWN; + position: Point; + time: number; +} +interface MouseUpAction { + type: typeof ON_MOUSE_UP; + position: Point; + time: number; +} + +interface PointerMoveAction { + type: typeof ON_POINTER_MOVE; + position: Point; + time: number; +} + +/** + * Action called on mouse button down event + * @param position the x and y position (native event offsetX, offsetY) + * @param time the timestamp of the event (native event timeStamp) + */ +export function onMouseDown(position: Point, time: number): MouseDownAction { + return { type: ON_MOUSE_DOWN, position, time }; +} + +/** + * Action called on mouse button up event + * @param position the x and y position (native event offsetX, offsetY) + * @param time the timestamp of the event (native event timeStamp) + */ +export function onMouseUp(position: Point, time: number): MouseUpAction { + return { type: ON_MOUSE_UP, position, time }; +} + +/** + * Action called with the mouse coordinates relatives to the chart container (exclude the legend) + * @param position the x and y position (native event offsetX, offsetY) + * @param time the timestamp of the event (native event timeStamp) + */ +export function onPointerMove(position: Point, time: number): PointerMoveAction { + return { type: ON_POINTER_MOVE, position, time }; +} + +export type MouseActions = MouseDownAction | MouseUpAction | PointerMoveAction; diff --git a/src/state/actions/specs.ts b/src/state/actions/specs.ts new file mode 100644 index 0000000000..0bf622a9ea --- /dev/null +++ b/src/state/actions/specs.ts @@ -0,0 +1,42 @@ +import { Spec } from '../../specs'; + +export const UPSERT_SPEC = 'UPSERT_SPEC'; +export const REMOVE_SPEC = 'REMOVE_SPEC'; +export const SPEC_PARSED = 'SPEC_PARSED'; +export const SPEC_UNMOUNTED = 'SPEC_UNMOUNTED'; + +interface SpecParsedAction { + type: typeof SPEC_PARSED; +} + +interface SpecUnmountedAction { + type: typeof SPEC_UNMOUNTED; +} + +interface UpsertSpecAction { + type: typeof UPSERT_SPEC; + spec: Spec; +} + +interface RemoveSpecAction { + type: typeof REMOVE_SPEC; + id: string; +} + +export function upsertSpec(spec: Spec): UpsertSpecAction { + return { type: UPSERT_SPEC, spec }; +} + +export function removeSpec(id: string): RemoveSpecAction { + return { type: REMOVE_SPEC, id }; +} + +export function specParsed(): SpecParsedAction { + return { type: SPEC_PARSED }; +} + +export function specUnmounted(): SpecUnmountedAction { + return { type: SPEC_UNMOUNTED }; +} + +export type SpecActions = SpecParsedAction | SpecUnmountedAction | UpsertSpecAction | RemoveSpecAction; diff --git a/src/state/chart_state.ts b/src/state/chart_state.ts new file mode 100644 index 0000000000..ec3a6ac4f1 --- /dev/null +++ b/src/state/chart_state.ts @@ -0,0 +1,271 @@ +import { SPEC_PARSED, SPEC_UNMOUNTED, UPSERT_SPEC, REMOVE_SPEC } from './actions/specs'; +import { interactionsReducer } from './reducers/interactions'; +import { ChartTypes } from '../chart_types'; +import { XYAxisChartState } from '../chart_types/xy_chart/state/chart_state'; +import { DataSeriesColorsValues } from '../chart_types/xy_chart/utils/series'; +import { Spec } from '../specs'; +import { DEFAULT_SETTINGS_SPEC, CursorEvent } from '../specs/settings'; +import { Dimensions } from '../utils/dimensions'; +import { Point } from '../utils/point'; +import { LegendItem } from '../chart_types/xy_chart/legend/legend'; +import { TooltipLegendValue } from '../chart_types/xy_chart/tooltip/tooltip'; +import { StateActions } from './actions'; +import { CHART_RENDERED } from './actions/chart'; +import { UPDATE_PARENT_DIMENSION } from './actions/chart_settings'; +import { EXTERNAL_POINTER_EVENT } from './actions/events'; +import { RefObject } from 'react'; +import { Stage } from 'react-konva'; + +export type BackwardRef = () => React.RefObject<HTMLDivElement>; + +/** + * A set of chart-type-dependant functions that are required and called + * globally by the <ChartContainer> and + */ +export interface InternalChartState { + // the chart type + chartType: ChartTypes; + // returns a JSX element with the chart rendered (lenged excluded) + chartRenderer(containerRef: BackwardRef, forwardStageRef: RefObject<Stage>): JSX.Element | null; + // true if the brush is available for this chart type + isBrushAvailable(globalState: GlobalChartState): boolean; + // true if the chart is empty (no data displayed) + isChartEmpty(globalState: GlobalChartState): boolean; + // return the list of legend items + getLegendItems(globalState: GlobalChartState): Map<string, LegendItem>; + // return the list of values for each legend item + getLegendItemsValues(globalState: GlobalChartState): Map<string, TooltipLegendValue>; + // return the CSS pointer cursor depending on the internal chart state + getPointerCursor(globalState: GlobalChartState): string; +} + +export interface SpecList { + [specId: string]: Spec; +} + +export interface PointerState { + position: Point; + time: number; +} +export interface DragState { + start: PointerState; + end: PointerState; +} +export interface PointerStates { + dragging: boolean; + current: PointerState; + down: PointerState | null; + up: PointerState | null; + lastDrag: DragState | null; + lastClick: PointerState | null; +} + +export interface InteractionsState { + pointer: PointerStates; + highlightedLegendItemKey: string | null; + legendCollapsed: boolean; + invertDeselect: boolean; + deselectedDataSeries: DataSeriesColorsValues[]; +} + +export interface ExternalEventsState { + pointer: CursorEvent | null; +} + +export interface GlobalChartState { + // an unique ID for each chart used by re-reselect to memoize selector per chart + chartId: string; + // true when all all the specs are parsed ad stored into the specs object + specsInitialized: boolean; + // true if the chart is rendered on dom + chartRendered: boolean; + // incremental count of the chart rendering + chartRenderedCount: number; + // the map of parsed specs + specs: SpecList; + // the chart type depending on the used specs + chartType: ChartTypes | null; + // a chart-type-dependant class that is used to render and share chart-type dependant functions + internalChartState: InternalChartState | null; + // the dimensions of the parent container, including the legend + parentDimensions: Dimensions; + // the state of the interactions + interactions: InteractionsState; + // external event state + externalEvents: ExternalEventsState; +} + +export const getInitialState = (chartId: string): GlobalChartState => ({ + chartId, + specsInitialized: false, + chartRendered: false, + chartRenderedCount: 0, + specs: { + [DEFAULT_SETTINGS_SPEC.id]: DEFAULT_SETTINGS_SPEC, + }, + chartType: null, + internalChartState: null, + interactions: { + pointer: { + dragging: false, + current: { + position: { + x: -1, + y: -1, + }, + time: 0, + }, + down: null, + up: null, + lastDrag: null, + lastClick: null, + }, + legendCollapsed: false, + highlightedLegendItemKey: null, + deselectedDataSeries: [], + invertDeselect: false, + }, + externalEvents: { + pointer: null, + }, + parentDimensions: { + height: 0, + width: 0, + left: 0, + top: 0, + }, +}); + +export const chartStoreReducer = (chartId: string) => { + const initialState = getInitialState(chartId); + return (state = initialState, action: StateActions): GlobalChartState => { + switch (action.type) { + case SPEC_PARSED: + const chartType = findMainChartType(state.specs); + + if (isChartTypeChanged(state, chartType)) { + const internalChartState = initInternalChartState(chartType); + return { + ...state, + specsInitialized: true, + chartRendered: false, + chartType, + internalChartState, + }; + } else { + return { + ...state, + specsInitialized: true, + chartRendered: false, + chartType, + }; + } + case SPEC_UNMOUNTED: + return { + ...state, + specsInitialized: false, + chartRendered: false, + }; + case UPSERT_SPEC: + return { + ...state, + specsInitialized: false, + chartRendered: false, + specs: { + ...state.specs, + [action.spec.id]: action.spec, + }, + }; + case REMOVE_SPEC: + const { [action.id]: specToRemove, ...rest } = state.specs; + return { + ...state, + specsInitialized: false, + chartRendered: false, + specs: { + ...rest, + }, + }; + case CHART_RENDERED: + const count = state.chartRendered ? state.chartRenderedCount : state.chartRenderedCount + 1; + return { + ...state, + chartRendered: true, + chartRenderedCount: count, + }; + case UPDATE_PARENT_DIMENSION: + return { + ...state, + parentDimensions: { + ...action.dimensions, + }, + }; + case EXTERNAL_POINTER_EVENT: + // discard events from self if any + if (!action.event || action.event.chartId === state.chartId) { + return { + ...state, + externalEvents: { + ...state.externalEvents, + pointer: null, + }, + }; + } + return { + ...state, + externalEvents: { + ...state.externalEvents, + pointer: { + ...action.event, + }, + }, + }; + default: + return { + ...state, + interactions: interactionsReducer(state.interactions, action), + }; + } + }; +}; + +function findMainChartType(specs: SpecList): ChartTypes | null { + const types: Partial<Record<ChartTypes, number>> = Object.keys(specs).reduce<Partial<Record<ChartTypes, number>>>( + (acc, specId) => { + const { chartType } = specs[specId]; + let accumulator = acc[chartType]; + if (accumulator === undefined) { + accumulator = 0; + } else { + accumulator += 1; + } + acc[chartType] = accumulator; + return acc; + }, + {}, + ); + // https://stackoverflow.com/questions/55012174/why-doesnt-object-keys-return-a-keyof-type-in-typescript + const chartTypes = Object.keys(types).filter((type) => type !== ChartTypes.Global); + if (chartTypes.length > 1) { + // eslint-disable-next-line no-console + console.warn('Multiple chart type on the same configuration'); + return null; + } else { + return chartTypes[0] as ChartTypes; + } +} + +function initInternalChartState(chartType: ChartTypes | null): InternalChartState | null { + switch (chartType) { + case ChartTypes.Pie: + return null; // TODO add pie chart state + case ChartTypes.XYAxis: + return new XYAxisChartState(); + default: + return null; + } +} + +function isChartTypeChanged(state: GlobalChartState, newChartType: ChartTypes | null) { + return state.chartType !== newChartType; +} diff --git a/src/state/reducers/interactions.ts b/src/state/reducers/interactions.ts new file mode 100644 index 0000000000..64b1542737 --- /dev/null +++ b/src/state/reducers/interactions.ts @@ -0,0 +1,120 @@ +import { InteractionsState } from '../chart_state'; +import { + ON_TOGGLE_LEGEND, + ON_LEGEND_ITEM_OUT, + ON_LEGEND_ITEM_OVER, + ON_TOGGLE_DESELECT_SERIES, + LegendActions, +} from '../actions/legend'; +import { ON_MOUSE_DOWN, ON_MOUSE_UP, ON_POINTER_MOVE, MouseActions } from '../actions/mouse'; +import { DataSeriesColorsValues, findDataSeriesByColorValues } from '../../chart_types/xy_chart/utils/series'; + +export function interactionsReducer(state: InteractionsState, action: LegendActions | MouseActions): InteractionsState { + switch (action.type) { + case ON_POINTER_MOVE: + return { + ...state, + pointer: { + ...state.pointer, + dragging: state.pointer.down && state.pointer.down.time < action.time ? true : false, + current: { + position: { + ...action.position, + }, + time: action.time, + }, + }, + }; + case ON_MOUSE_DOWN: + return { + ...state, + pointer: { + ...state.pointer, + dragging: false, + up: null, + down: { + position: { + ...action.position, + }, + time: action.time, + }, + }, + }; + case ON_MOUSE_UP: { + return { + ...state, + pointer: { + ...state.pointer, + lastDrag: + state.pointer.down && state.pointer.dragging + ? { + start: { + position: { + ...state.pointer.down.position, + }, + time: state.pointer.down.time, + }, + end: { + position: { + ...action.position, + }, + time: action.time, + }, + } + : null, + lastClick: + state.pointer.down && !state.pointer.dragging + ? { + position: { + ...action.position, + }, + time: action.time, + } + : null, + dragging: false, + down: null, + up: { + position: { + ...action.position, + }, + time: action.time, + }, + }, + }; + } + case ON_TOGGLE_LEGEND: + return { + ...state, + legendCollapsed: !state.legendCollapsed, + }; + case ON_LEGEND_ITEM_OUT: + return { + ...state, + highlightedLegendItemKey: null, + }; + case ON_LEGEND_ITEM_OVER: + return { + ...state, + highlightedLegendItemKey: action.legendItemKey, + }; + case ON_TOGGLE_DESELECT_SERIES: + return { + ...state, + deselectedDataSeries: toggleDeselectedDataSeries(action.legendItemId, state.deselectedDataSeries), + }; + default: + return state; + } +} + +function toggleDeselectedDataSeries( + legendItem: DataSeriesColorsValues, + deselectedDataSeries: DataSeriesColorsValues[], +) { + const index = findDataSeriesByColorValues(deselectedDataSeries, legendItem); + if (index > -1) { + return [...deselectedDataSeries.slice(0, index), ...deselectedDataSeries.slice(index + 1)]; + } else { + return [...deselectedDataSeries, legendItem]; + } +} diff --git a/src/state/selectors/get_chart_container_dimensions.ts b/src/state/selectors/get_chart_container_dimensions.ts new file mode 100644 index 0000000000..29288e7055 --- /dev/null +++ b/src/state/selectors/get_chart_container_dimensions.ts @@ -0,0 +1,33 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from './get_settings_specs'; +import { getLegendSizeSelector } from './get_legend_size'; +import { GlobalChartState } from '../chart_state'; +import { Dimensions } from '../../utils/dimensions'; +import { isVerticalAxis } from '../../chart_types/xy_chart/utils/axis_utils'; +import { getChartIdSelector } from './get_chart_id'; + +const getParentDimension = (state: GlobalChartState) => state.parentDimensions; + +export const getChartContainerDimensionsSelector = createCachedSelector( + [getSettingsSpecSelector, getLegendSizeSelector, getParentDimension], + (settings, legendSize, parentDimensions): Dimensions => { + if (!settings.showLegend) { + return parentDimensions; + } + if (isVerticalAxis(settings.legendPosition)) { + return { + left: 0, + top: 0, + width: parentDimensions.width - legendSize.width, + height: parentDimensions.height, + }; + } else { + return { + left: 0, + top: 0, + width: parentDimensions.width, + height: parentDimensions.height - legendSize.height, + }; + } + }, +)(getChartIdSelector); diff --git a/src/state/selectors/get_chart_id.ts b/src/state/selectors/get_chart_id.ts new file mode 100644 index 0000000000..e0177ae7b4 --- /dev/null +++ b/src/state/selectors/get_chart_id.ts @@ -0,0 +1,3 @@ +import { GlobalChartState } from '../chart_state'; + +export const getChartIdSelector = (state: GlobalChartState) => state.chartId; diff --git a/src/state/selectors/get_chart_rotation.ts b/src/state/selectors/get_chart_rotation.ts new file mode 100644 index 0000000000..219d72e48c --- /dev/null +++ b/src/state/selectors/get_chart_rotation.ts @@ -0,0 +1,12 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from './get_settings_specs'; + +import { Rotation } from '../../chart_types/xy_chart/utils/specs'; +import { getChartIdSelector } from './get_chart_id'; + +export const getChartRotationSelector = createCachedSelector( + [getSettingsSpecSelector], + (settingsSpec): Rotation => { + return settingsSpec.rotation; + }, +)(getChartIdSelector); diff --git a/src/state/selectors/get_chart_theme.ts b/src/state/selectors/get_chart_theme.ts new file mode 100644 index 0000000000..9a4b739452 --- /dev/null +++ b/src/state/selectors/get_chart_theme.ts @@ -0,0 +1,23 @@ +import createCachedSelector from 're-reselect'; +import { getSettingsSpecSelector } from './get_settings_specs'; +import { PartialTheme, Theme, mergeWithDefaultTheme } from '../../utils/themes/theme'; +import { LIGHT_THEME } from '../../utils/themes/light_theme'; +import { getChartIdSelector } from './get_chart_id'; + +export const getChartThemeSelector = createCachedSelector( + [getSettingsSpecSelector], + (settingsSpec): Theme => { + return getTheme(settingsSpec.baseTheme, settingsSpec.theme); + }, +)(getChartIdSelector); + +function getTheme(baseTheme?: Theme, theme?: PartialTheme | PartialTheme[]): Theme { + const base = baseTheme ? baseTheme : LIGHT_THEME; + + if (Array.isArray(theme)) { + const [firstTheme, ...axillaryThemes] = theme; + return mergeWithDefaultTheme(firstTheme, base, axillaryThemes); + } + + return theme ? mergeWithDefaultTheme(theme, base) : base; +} diff --git a/src/state/selectors/get_chart_type_components.ts b/src/state/selectors/get_chart_type_components.ts new file mode 100644 index 0000000000..0f87771481 --- /dev/null +++ b/src/state/selectors/get_chart_type_components.ts @@ -0,0 +1,12 @@ +import { GlobalChartState, BackwardRef } from '../chart_state'; +import { Stage } from 'react-konva'; + +type ChartRendererFn = (containerRef: BackwardRef, forwardStageRef: React.RefObject<Stage>) => JSX.Element | null; + +export const getInternalChartRendererSelector = (state: GlobalChartState): ChartRendererFn => { + if (state.internalChartState) { + return state.internalChartState.chartRenderer; + } else { + return () => null; + } +}; diff --git a/src/state/selectors/get_internal_cursor_pointer.ts b/src/state/selectors/get_internal_cursor_pointer.ts new file mode 100644 index 0000000000..21f43ef9bd --- /dev/null +++ b/src/state/selectors/get_internal_cursor_pointer.ts @@ -0,0 +1,9 @@ +import { GlobalChartState } from '../chart_state'; + +export const getInternalPointerCursor = (state: GlobalChartState): string => { + if (state.internalChartState) { + return state.internalChartState.getPointerCursor(state); + } else { + return 'default'; + } +}; diff --git a/src/state/selectors/get_internal_is_brushing_available.ts b/src/state/selectors/get_internal_is_brushing_available.ts new file mode 100644 index 0000000000..34fcdc4e19 --- /dev/null +++ b/src/state/selectors/get_internal_is_brushing_available.ts @@ -0,0 +1,9 @@ +import { GlobalChartState } from '../chart_state'; + +export const getInternalIsBrushingAvailableSelector = (state: GlobalChartState): boolean => { + if (state.internalChartState) { + return state.internalChartState.isBrushAvailable(state); + } else { + return false; + } +}; diff --git a/src/state/selectors/get_legend_items.ts b/src/state/selectors/get_legend_items.ts new file mode 100644 index 0000000000..d3e1888e4c --- /dev/null +++ b/src/state/selectors/get_legend_items.ts @@ -0,0 +1,11 @@ +import { GlobalChartState } from '../chart_state'; +import { LegendItem } from '../../chart_types/xy_chart/legend/legend'; + +const EMPTY_LEGEND_LIST = new Map<string, LegendItem>(); +export const getLegendItemsSelector = (state: GlobalChartState): Map<string, LegendItem> => { + if (state.internalChartState) { + return state.internalChartState.getLegendItems(state); + } else { + return EMPTY_LEGEND_LIST; + } +}; diff --git a/src/state/selectors/get_legend_items_values.ts b/src/state/selectors/get_legend_items_values.ts new file mode 100644 index 0000000000..9a41a4f8be --- /dev/null +++ b/src/state/selectors/get_legend_items_values.ts @@ -0,0 +1,11 @@ +import { TooltipLegendValue } from '../../chart_types/xy_chart/tooltip/tooltip'; +import { GlobalChartState } from '../chart_state'; + +const EMPTY_ITEM_LIST = new Map<string, TooltipLegendValue>(); +export const getLegendItemsValuesSelector = (state: GlobalChartState): Map<string, TooltipLegendValue> => { + if (state.internalChartState) { + return state.internalChartState.getLegendItemsValues(state); + } else { + return EMPTY_ITEM_LIST; + } +}; diff --git a/src/state/selectors/get_legend_size.ts b/src/state/selectors/get_legend_size.ts new file mode 100644 index 0000000000..18dd4b534e --- /dev/null +++ b/src/state/selectors/get_legend_size.ts @@ -0,0 +1,94 @@ +import createCachedSelector from 're-reselect'; +import { getLegendItemsSelector } from './get_legend_items'; +import { CanvasTextBBoxCalculator } from '../../utils/bbox/canvas_text_bbox_calculator'; +import { BBox } from '../../utils/bbox/bbox_calculator'; +import { getSettingsSpecSelector } from './get_settings_specs'; +import { isVerticalAxis } from '../../chart_types/xy_chart/utils/axis_utils'; +import { getChartThemeSelector } from './get_chart_theme'; +import { GlobalChartState } from '../chart_state'; +import { getItemLabel } from '../../chart_types/xy_chart/legend/legend'; +import { getChartIdSelector } from './get_chart_id'; + +const getParentDimensionSelector = (state: GlobalChartState) => state.parentDimensions; + +const legendItemLabelsSelector = createCachedSelector( + [getSettingsSpecSelector, getLegendItemsSelector], + (settings, legendItems): string[] => { + const labels: string[] = []; + const { showLegendDisplayValue } = settings; + legendItems.forEach((item) => { + const labelY1 = getItemLabel(item, 'y1'); + if (item.displayValue.formatted.y1 !== null) { + labels.push(`${labelY1}${showLegendDisplayValue ? item.displayValue.formatted.y1 : ''}`); + } else { + labels.push(labelY1); + } + if (item.banded) { + const labelY0 = getItemLabel(item, 'y0'); + if (item.displayValue.formatted.y0 !== null) { + labels.push(`${labelY0}${showLegendDisplayValue ? item.displayValue.formatted.y0 : ''}`); + } else { + labels.push(labelY0); + } + } + }); + return labels; + }, +)(getChartIdSelector); + +const MARKER_WIDTH = 16; +// const MARKER_HEIGHT = 16; +const MARKER_LEFT_MARGIN = 4; +const VALUE_LEFT_MARGIN = 4; +const VERTICAL_PADDING = 4; + +export const getLegendSizeSelector = createCachedSelector( + [getSettingsSpecSelector, getChartThemeSelector, getParentDimensionSelector, legendItemLabelsSelector], + (settings, theme, parentDimensions, labels): BBox => { + const bboxCalculator = new CanvasTextBBoxCalculator(); + const bbox = labels.reduce( + (acc, label) => { + const bbox = bboxCalculator.compute( + label, + 1, + 12, + '"Inter UI", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', + 1.5, + 400, + ); + if (acc.height < bbox.height) { + acc.height = bbox.height; + } + if (acc.width < bbox.width) { + acc.width = bbox.width; + } + return acc; + }, + { width: 0, height: 0 }, + ); + + bboxCalculator.destroy(); + const { showLegend, showLegendDisplayValue, legendPosition } = settings; + const { + legend: { verticalWidth, spacingBuffer }, + } = theme; + if (!showLegend) { + return { width: 0, height: 0 }; + } + const legendItemWidth = + MARKER_WIDTH + MARKER_LEFT_MARGIN + bbox.width + (showLegendDisplayValue ? VALUE_LEFT_MARGIN : 0); + if (isVerticalAxis(legendPosition)) { + const legendItemHeight = bbox.height + VERTICAL_PADDING * 2; + return { + width: Math.floor(Math.min(legendItemWidth + spacingBuffer, verticalWidth)), + height: legendItemHeight, + }; + } else { + const isSingleLine = (parentDimensions.width - 20) / 200 > labels.length; + return { + height: isSingleLine ? bbox.height + 16 : bbox.height * 2 + 24, + width: Math.floor(Math.min(legendItemWidth + spacingBuffer, verticalWidth)), + }; + } + }, +)(getChartIdSelector); diff --git a/src/state/selectors/get_settings_specs.test.ts b/src/state/selectors/get_settings_specs.test.ts new file mode 100644 index 0000000000..270c0abc35 --- /dev/null +++ b/src/state/selectors/get_settings_specs.test.ts @@ -0,0 +1,37 @@ +import { getSettingsSpecSelector } from './get_settings_specs'; +import { getInitialState } from '../chart_state'; +import { DEFAULT_SETTINGS_SPEC } from '../../specs'; +describe('selectors - getSettingsSpecSelector', () => { + const state = getInitialState('chartId1'); + it('shall return the same reference', () => { + const settings = getSettingsSpecSelector(state); + expect(settings).toBe(DEFAULT_SETTINGS_SPEC); + }); + it('shall avoid recomputations', () => { + getSettingsSpecSelector(state); + expect(getSettingsSpecSelector.recomputations()).toBe(1); + getSettingsSpecSelector(state); + expect(getSettingsSpecSelector.recomputations()).toBe(1); + getSettingsSpecSelector({ ...state, specsInitialized: true }); + expect(getSettingsSpecSelector.recomputations()).toBe(1); + getSettingsSpecSelector({ ...state, parentDimensions: { width: 100, height: 100, top: 100, left: 100 } }); + expect(getSettingsSpecSelector.recomputations()).toBe(1); + }); + it('shall return new settings if settings changed', () => { + const updatedSettings = { + ...DEFAULT_SETTINGS_SPEC, + rotation: 90, + }; + const updatedState = { + ...state, + specs: { + [DEFAULT_SETTINGS_SPEC.id]: updatedSettings, + }, + }; + const settingsSpecToCheck = getSettingsSpecSelector(updatedState); + expect(settingsSpecToCheck).toBe(updatedSettings); + expect(getSettingsSpecSelector.recomputations()).toBe(2); + getSettingsSpecSelector(updatedState); + expect(getSettingsSpecSelector.recomputations()).toBe(2); + }); +}); diff --git a/src/state/selectors/get_settings_specs.ts b/src/state/selectors/get_settings_specs.ts new file mode 100644 index 0000000000..942c96551f --- /dev/null +++ b/src/state/selectors/get_settings_specs.ts @@ -0,0 +1,20 @@ +import createCachedSelector from 're-reselect'; +import { GlobalChartState } from '../chart_state'; +import { ChartTypes } from '../../chart_types'; +import { getSpecsFromStore } from '../utils'; +import { SettingsSpec } from '../../specs/settings'; +import { getChartIdSelector } from './get_chart_id'; +import { SpecTypes } from '../../chart_types/xy_chart/utils/specs'; + +const getSpecs = (state: GlobalChartState) => state.specs; + +export const getSettingsSpecSelector = createCachedSelector( + [getSpecs], + (specs): SettingsSpec => { + const settingsSpecs = getSpecsFromStore<SettingsSpec>(specs, ChartTypes.Global, SpecTypes.Settings); + if (settingsSpecs.length > 1) { + throw new Error('Multiple settings specs are configured on the same chart'); + } + return settingsSpecs[0]; + }, +)(getChartIdSelector); diff --git a/src/state/selectors/is_chart_empty.ts b/src/state/selectors/is_chart_empty.ts new file mode 100644 index 0000000000..2113a64d40 --- /dev/null +++ b/src/state/selectors/is_chart_empty.ts @@ -0,0 +1,9 @@ +import { GlobalChartState } from '../chart_state'; + +export const isInternalChartEmptySelector = (state: GlobalChartState): boolean | undefined => { + if (state.internalChartState) { + return state.internalChartState.isChartEmpty(state); + } else { + return undefined; + } +}; diff --git a/src/state/selectors/is_initialized.ts b/src/state/selectors/is_initialized.ts new file mode 100644 index 0000000000..97f943ad2f --- /dev/null +++ b/src/state/selectors/is_initialized.ts @@ -0,0 +1,3 @@ +import { GlobalChartState } from '../chart_state'; + +export const isInitialized = (state: GlobalChartState) => state.specsInitialized; diff --git a/src/state/spec_factory.ts b/src/state/spec_factory.ts new file mode 100644 index 0000000000..3cda252391 --- /dev/null +++ b/src/state/spec_factory.ts @@ -0,0 +1,58 @@ +import { useEffect, useRef } from 'react'; +import { Dispatch, bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import { upsertSpec, removeSpec } from './actions/specs'; +import { Spec } from '../specs'; + +export interface DispatchProps { + upsertSpec: (spec: Spec) => void; + removeSpec: (id: string) => void; +} + +function usePrevious(value: string) { + const ref = useRef<string>(); + useEffect(() => { + ref.current = value; + }); + return ref.current; +} + +export function specComponentFactory<U extends Spec, D extends keyof U>( + defaultProps: Pick<U, D | 'chartType' | 'specType'>, +) { + const spec = (props: U & DispatchProps) => { + const prevId = usePrevious(props.id); + const { removeSpec, upsertSpec, ...spec } = props; + useEffect(() => { + if (prevId && prevId !== props.id) { + removeSpec(prevId); + } + upsertSpec(spec); + }); + useEffect( + () => () => { + removeSpec(props.id); + }, + [], + ); + return null; + }; + spec.defaultProps = defaultProps; + return spec; +} + +const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => + bindActionCreators( + { + upsertSpec, + removeSpec, + }, + dispatch, + ); + +export function getConnect() { + return connect( + null, + mapDispatchToProps, + ); +} diff --git a/src/state/utils.test.ts b/src/state/utils.test.ts new file mode 100644 index 0000000000..678d8c43ed --- /dev/null +++ b/src/state/utils.test.ts @@ -0,0 +1,11 @@ +import { getSpecsFromStore } from './utils'; +import { ChartTypes } from '../chart_types'; +import { SpecTypes } from '../chart_types/xy_chart/utils/specs'; + +describe('State utils', () => { + it('getSpecsFromStore shall return always the same object reference excluding the array', () => { + const spec1 = { id: 'id1', chartType: ChartTypes.XYAxis, specType: SpecTypes.Series }; + const specs = getSpecsFromStore({ id1: spec1 }, ChartTypes.XYAxis, SpecTypes.Series); + expect(specs[0]).toBe(spec1); + }); +}); diff --git a/src/state/utils.ts b/src/state/utils.ts new file mode 100644 index 0000000000..ee20f9bb10 --- /dev/null +++ b/src/state/utils.ts @@ -0,0 +1,18 @@ +import { SpecList } from './chart_state'; +import { Spec } from '../specs'; +import { ChartTypes } from '../chart_types'; + +export function getSpecsFromStore<U extends Spec>(specs: SpecList, chartType: ChartTypes, specType?: string): U[] { + return Object.keys(specs) + .filter((specId) => { + const currentSpec = specs[specId]; + if (specType) { + return currentSpec.specType === specType && currentSpec.chartType === chartType; + } else { + return currentSpec.chartType === chartType; + } + }) + .map((specId) => { + return specs[specId] as U; + }); +} diff --git a/src/utils/bbox/bbox_calculator.ts b/src/utils/bbox/bbox_calculator.ts index dd172cdeec..3a33551b2d 100644 --- a/src/utils/bbox/bbox_calculator.ts +++ b/src/utils/bbox/bbox_calculator.ts @@ -1,11 +1,14 @@ -import { Option } from 'fp-ts/lib/Option'; - export interface BBox { width: number; height: number; } +export const DEFAULT_EMPTY_BBOX = { + width: 0, + height: 0, +}; + export interface BBoxCalculator { - compute(text: string, padding: number, fontSize?: number, fontFamily?: string): Option<BBox>; + compute(text: string, padding: number, fontSize?: number, fontFamily?: string): BBox; destroy(): void; } diff --git a/src/utils/bbox/canvas_text_bbox_calculator.test.ts b/src/utils/bbox/canvas_text_bbox_calculator.test.ts index eb726dca78..25e0306c71 100644 --- a/src/utils/bbox/canvas_text_bbox_calculator.test.ts +++ b/src/utils/bbox/canvas_text_bbox_calculator.test.ts @@ -1,62 +1,9 @@ -import { none } from 'fp-ts/lib/Option'; import { CanvasTextBBoxCalculator } from './canvas_text_bbox_calculator'; describe('CanvasTextBBoxCalculator', () => { test('can create a canvas for computing text measurement values', () => { const canvasBboxCalculator = new CanvasTextBBoxCalculator(); - const bbox = canvasBboxCalculator.compute('foo', 0).getOrElse({ - width: 0, - height: 0, - }); - expect(Math.abs(bbox.width - 23.2)).toBeLessThanOrEqual(2); - expect(bbox.height).toBe(16); - - canvasBboxCalculator.context = null; - expect(canvasBboxCalculator.compute('foo', 0)).toBe(none); - }); - test('can compute near the same width for the same text independently of the scale factor', () => { - let canvasBboxCalculator = new CanvasTextBBoxCalculator(undefined, 5); - - let bbox = canvasBboxCalculator.compute('foo', 0).getOrElse({ - width: 0, - height: 0, - }); - expect(Math.abs(bbox.width - 23.2)).toBeLessThanOrEqual(2); - expect(bbox.height).toBe(16); - - canvasBboxCalculator = new CanvasTextBBoxCalculator(undefined, 10); - - bbox = canvasBboxCalculator.compute('foo', 0).getOrElse({ - width: 0, - height: 0, - }); - expect(Math.abs(bbox.width - 23.2)).toBeLessThanOrEqual(2); - expect(bbox.height).toBe(16); - - canvasBboxCalculator = new CanvasTextBBoxCalculator(undefined, 50); - - bbox = canvasBboxCalculator.compute('foo', 0).getOrElse({ - width: 0, - height: 0, - }); - expect(Math.abs(bbox.width - 23.2)).toBeLessThanOrEqual(2); - expect(bbox.height).toBe(16); - - canvasBboxCalculator = new CanvasTextBBoxCalculator(undefined, 100); - - bbox = canvasBboxCalculator.compute('foo', 0).getOrElse({ - width: 0, - height: 0, - }); - expect(Math.abs(bbox.width - 23.2)).toBeLessThanOrEqual(2); - expect(bbox.height).toBe(16); - - canvasBboxCalculator = new CanvasTextBBoxCalculator(undefined, 1000); - - bbox = canvasBboxCalculator.compute('foo', 0).getOrElse({ - width: 0, - height: 0, - }); + const bbox = canvasBboxCalculator.compute('foo', 0); expect(Math.abs(bbox.width - 23.2)).toBeLessThanOrEqual(2); expect(bbox.height).toBe(16); }); diff --git a/src/utils/bbox/canvas_text_bbox_calculator.ts b/src/utils/bbox/canvas_text_bbox_calculator.ts index 78408cf7fd..0fa168e0df 100644 --- a/src/utils/bbox/canvas_text_bbox_calculator.ts +++ b/src/utils/bbox/canvas_text_bbox_calculator.ts @@ -1,42 +1,34 @@ -import { none, Option, some } from 'fp-ts/lib/Option'; -import { BBox, BBoxCalculator } from './bbox_calculator'; +import { BBox, BBoxCalculator, DEFAULT_EMPTY_BBOX } from './bbox_calculator'; export class CanvasTextBBoxCalculator implements BBoxCalculator { - context: CanvasRenderingContext2D | null; private attachedRoot: HTMLElement; private offscreenCanvas: HTMLCanvasElement; - private scaledFontSize: number; + private context: CanvasRenderingContext2D | null; - constructor(rootElement?: HTMLElement, scaledFontSize = 100) { + constructor(rootElement?: HTMLElement) { this.offscreenCanvas = document.createElement('canvas'); this.offscreenCanvas.style.position = 'absolute'; - this.offscreenCanvas.style.top = '-9999px'; - + this.offscreenCanvas.style.top = '-99999px'; + this.offscreenCanvas.style.left = '-99999px'; this.context = this.offscreenCanvas.getContext('2d'); this.attachedRoot = rootElement || document.documentElement; this.attachedRoot.appendChild(this.offscreenCanvas); - this.scaledFontSize = scaledFontSize; } - compute(text: string, padding: number, fontSize = 16, fontFamily = 'Arial'): Option<BBox> { + compute(text: string, padding: number, fontSize = 16, fontFamily = 'Arial', lineHeight = 1, fontWeight = 400): BBox { if (!this.context) { - return none; + return DEFAULT_EMPTY_BBOX; } - // Padding should be at least one to avoid browser measureText inconsistencies if (padding < 1) { padding = 1; } - - // We scale the text up to get a more accurate computation of the width of the text - // because `measureText` can vary a lot between browsers. - const scalingFactor = this.scaledFontSize / fontSize; - this.context.font = `${this.scaledFontSize}px ${fontFamily}`; + this.context.font = `${fontWeight} ${fontSize}px ${fontFamily}`; const measure = this.context.measureText(text); - return some({ - width: measure.width / scalingFactor + padding, - height: fontSize, - }); + return { + width: measure.width + padding, + height: fontSize * lineHeight, + }; } destroy(): void { this.attachedRoot.removeChild(this.offscreenCanvas); diff --git a/src/utils/bbox/dom_text_bbox_calculator.ts b/src/utils/bbox/dom_text_bbox_calculator.ts new file mode 100644 index 0000000000..57a5286022 --- /dev/null +++ b/src/utils/bbox/dom_text_bbox_calculator.ts @@ -0,0 +1,31 @@ +import { BBox, BBoxCalculator } from './bbox_calculator'; + +export class DOMTextBBoxCalculator implements BBoxCalculator { + private attachedRoot: HTMLElement; + private offscreenCanvas: HTMLSpanElement; + + constructor(rootElement?: HTMLElement) { + this.offscreenCanvas = document.createElement('span'); + this.offscreenCanvas.style.position = 'absolute'; + this.offscreenCanvas.style.top = '-9999px'; + this.offscreenCanvas.style.left = '-9999px'; + + this.attachedRoot = rootElement || document.documentElement; + this.attachedRoot.appendChild(this.offscreenCanvas); + } + compute(text: string, padding: number, fontSize = 16, fontFamily = 'Arial', lineHeight = 1, fontWeight = 400): BBox { + this.offscreenCanvas.style.fontSize = `${fontSize}px`; + this.offscreenCanvas.style.fontFamily = fontFamily; + this.offscreenCanvas.style.fontWeight = `${fontWeight}`; + this.offscreenCanvas.style.lineHeight = `${lineHeight}px`; + this.offscreenCanvas.innerHTML = text; + + return { + width: Math.ceil(this.offscreenCanvas.clientWidth + padding), + height: Math.ceil(this.offscreenCanvas.clientHeight), + }; + } + destroy(): void { + this.attachedRoot.removeChild(this.offscreenCanvas); + } +} diff --git a/src/utils/bbox/svg_text_bbox_calculator.ts b/src/utils/bbox/svg_text_bbox_calculator.ts index b2a874b3e2..fbc1507140 100644 --- a/src/utils/bbox/svg_text_bbox_calculator.ts +++ b/src/utils/bbox/svg_text_bbox_calculator.ts @@ -1,4 +1,3 @@ -import { Option, some } from 'fp-ts/lib/Option'; import { BBox, BBoxCalculator } from './bbox_calculator'; // not sure where to specify this, required for tests @@ -26,13 +25,13 @@ export class SvgTextBBoxCalculator implements BBoxCalculator { this.attachedRoot = rootElement || document.documentElement; this.attachedRoot.appendChild(this.svgElem); } - compute(text: string): Option<BBox> { + compute(text: string): BBox { this.textNode.textContent = text; const rect = this.textElem.getBoundingClientRect(); - return some({ + return { width: rect.width, height: rect.height, - }); + }; } destroy(): void { this.attachedRoot.removeChild(this.svgElem); diff --git a/src/utils/events.ts b/src/utils/events.ts new file mode 100644 index 0000000000..9b607705f0 --- /dev/null +++ b/src/utils/events.ts @@ -0,0 +1,6 @@ +import { CursorEvent } from '../specs'; +import { Scale } from './scales/scales'; + +export function isValidExternalPointerEvent(event: CursorEvent, mainScale: Scale): boolean { + return event.unit === undefined || event.unit === mainScale.unit; +} diff --git a/src/utils/geometry.ts b/src/utils/geometry.ts new file mode 100644 index 0000000000..149322f197 --- /dev/null +++ b/src/utils/geometry.ts @@ -0,0 +1,120 @@ +import { $Values } from 'utility-types'; +import { SpecId } from './ids'; +import { BarSeriesStyle, PointStyle, AreaStyle, LineStyle, ArcStyle } from './themes/theme'; + +export interface GeometryId { + specId: SpecId; + seriesKey: any[]; +} + +/** + * The accessor type + */ +export const AccessorType = Object.freeze({ + Y0: 'y0' as 'y0', + Y1: 'y1' as 'y1', +}); + +export type AccessorType = $Values<typeof AccessorType>; + +export interface GeometryValue { + y: any; + x: any; + accessor: AccessorType; +} + +export type IndexedGeometry = PointGeometry | BarGeometry; + +/** + * Array of **range** clippings [x1, x2] to be excluded during rendering + * + * Note: Must be scaled **range** values (i.e. pixel coordinates) **NOT** domain values + */ +export type ClippedRanges = [number, number][]; + +export interface PointGeometry { + x: number; + y: number; + radius: number; + color: string; + transform: { + x: number; + y: number; + }; + geometryId: GeometryId; + value: GeometryValue; + styleOverrides?: Partial<PointStyle>; +} +export interface BarGeometry { + x: number; + y: number; + width: number; + height: number; + color: string; + displayValue?: { + text: any; + width: number; + height: number; + hideClippedValue?: boolean; + isValueContainedInElement?: boolean; + }; + geometryId: GeometryId; + value: GeometryValue; + seriesStyle: BarSeriesStyle; +} + +export interface LineGeometry { + line: string; + points: PointGeometry[]; + color: string; + transform: { + x: number; + y: number; + }; + geometryId: GeometryId; + seriesLineStyle: LineStyle; + seriesPointStyle: PointStyle; + /** + * Ranges of `[x0, x1]` pairs to clip from series + */ + clippedRanges: ClippedRanges; +} + +export interface AreaGeometry { + area: string; + lines: string[]; + points: PointGeometry[]; + color: string; + transform: { + x: number; + y: number; + }; + geometryId: GeometryId; + seriesAreaStyle: AreaStyle; + seriesAreaLineStyle: LineStyle; + seriesPointStyle: PointStyle; + isStacked: boolean; + /** + * Ranges of `[x0, x1]` pairs to clip from series + */ + clippedRanges: ClippedRanges; +} + +export interface ArcGeometry { + arc: string; + color: string; + geometryId: GeometryId; + seriesArcStyle: ArcStyle; + transform: { + x: number; + y: number; + }; +} + +export function isPointGeometry(ig: IndexedGeometry): ig is PointGeometry { + return ig.hasOwnProperty('radius'); +} + +export function isBarGeometry(ig: IndexedGeometry): ig is BarGeometry { + return ig.hasOwnProperty('width') && ig.hasOwnProperty('height'); +} diff --git a/src/utils/ids.ts b/src/utils/ids.ts index d8e88bdc71..e86a47c69d 100644 --- a/src/utils/ids.ts +++ b/src/utils/ids.ts @@ -1,25 +1,17 @@ -/* eslint @typescript-eslint/no-empty-interface: off */ -import { iso, Newtype } from 'newtype-ts'; - -export interface GroupId extends Newtype<{ readonly GroupId: unique symbol }, string> {} -export interface AxisId extends Newtype<{ readonly AxisId: unique symbol }, string> {} -export interface SpecId extends Newtype<{ readonly SpecId: unique symbol }, string> {} -export interface AnnotationId extends Newtype<{ readonly AnnotationId: unique symbol }, string> {} - -const groupIdIso = iso<GroupId>(); -const axisIdIso = iso<AxisId>(); -const specIdIso = iso<SpecId>(); -const annotationIdIso = iso<AnnotationId>(); - -export function getGroupId(id: string): GroupId { - return groupIdIso.wrap(id); +export function getGroupId(id: string): string { + return id; } -export function getAxisId(id: string): AxisId { - return axisIdIso.wrap(id); +export function getAxisId(id: string): string { + return id; } -export function getSpecId(id: string): SpecId { - return specIdIso.wrap(id); +export function getSpecId(id: string): string { + return id; } -export function getAnnotationId(id: string): AnnotationId { - return annotationIdIso.wrap(id); +export function getAnnotationId(id: string): string { + return id; } + +export type GroupId = string; +export type AxisId = string; +export type SpecId = string; +export type AnnotationId = string; diff --git a/src/utils/point.ts b/src/utils/point.ts new file mode 100644 index 0000000000..79d639a89f --- /dev/null +++ b/src/utils/point.ts @@ -0,0 +1,4 @@ +export interface Point { + x: number; + y: number; +} diff --git a/src/utils/scales/scale_band.ts b/src/utils/scales/scale_band.ts index c869149bec..e8cf04f696 100644 --- a/src/utils/scales/scale_band.ts +++ b/src/utils/scales/scale_band.ts @@ -4,6 +4,7 @@ import { ScaleType, Scale } from './scales'; export class ScaleBand implements Scale { readonly bandwidth: number; + readonly bandwidthPadding: number; readonly step: number; readonly type: ScaleType; readonly domain: any[]; @@ -34,13 +35,13 @@ export class ScaleBand implements Scale { this.d3Scale.paddingInner(safeBarPadding); this.d3Scale.paddingOuter(safeBarPadding / 2); this.bandwidth = this.d3Scale.bandwidth() || 0; - this.step = this.d3Scale.step(); this.domain = this.d3Scale.domain(); this.range = range.slice(); if (overrideBandwidth) { this.bandwidth = overrideBandwidth * (1 - safeBarPadding); } + this.bandwidthPadding = this.bandwidth; // TO FIX: we are assiming that it's ordered this.isInverted = this.domain[0] > this.domain[1]; this.invertedScale = scaleQuantize() @@ -75,7 +76,3 @@ export class ScaleBand implements Scale { return this.domain.includes(value); } } - -export function isOrdinalScale(scale: Scale): scale is ScaleBand { - return scale.type === ScaleType.Ordinal; -} diff --git a/src/utils/scales/scale_continuous.ts b/src/utils/scales/scale_continuous.ts index 93e83742ec..0508a6d15e 100644 --- a/src/utils/scales/scale_continuous.ts +++ b/src/utils/scales/scale_continuous.ts @@ -31,12 +31,6 @@ const SCALES = { [ScaleType.Time]: scaleUtc, }; -export function limitToMin(value: number, positive: boolean) { - if (value === 0) { - return positive ? 1 : -1; - } - return value; -} /** * As log(0) = -Infinite, a log scale domain must be strictly-positive * or strictly-negative; the domain must not include or cross zero value. @@ -250,9 +244,12 @@ export class ScaleContinuous implements Scale { value: number, data: number[], ): { - value: any; + value: number; withinBandwidth: boolean; - } { + } | null { + if (data.length === 0) { + return null; + } const invertedValue = this.invert(value); const bisectValue = this.bandwidth === 0 ? invertedValue + this.minInterval / 2 : invertedValue; const leftIndex = bisectLeft(data, bisectValue); @@ -308,10 +305,6 @@ export class ScaleContinuous implements Scale { } } -export function isContinuousScale(scale: Scale): scale is ScaleContinuous { - return scale.type !== ScaleType.Ordinal; -} - export function isLogarithmicScale(scale: Scale) { return scale.type === ScaleType.Log; } diff --git a/src/utils/scales/scales.ts b/src/utils/scales/scales.ts index 587906b10e..f78c4cd8f7 100644 --- a/src/utils/scales/scales.ts +++ b/src/utils/scales/scales.ts @@ -13,11 +13,12 @@ export interface Scale { ) => { value: any; withinBandwidth: boolean; - }; + } | null; isSingleValue: () => boolean; /** Check if the passed value is within the scale domain */ isValueInDomain: (value: any) => boolean; bandwidth: number; + bandwidthPadding: number; minInterval: number; type: ScaleType; /** diff --git a/src/utils/themes/dark_theme.ts b/src/utils/themes/dark_theme.ts index c3e17b8c4e..920d39bf1e 100644 --- a/src/utils/themes/dark_theme.ts +++ b/src/utils/themes/dark_theme.ts @@ -61,6 +61,14 @@ export const DARK_THEME: Theme = { offsetY: 0, }, }, + arcSeriesStyle: { + arc: { + visible: true, + stroke: 'white', + strokeWidth: 1, + opacity: 1, + }, + }, sharedStyle: DEFAULT_GEOMETRY_STYLES, scales: { barsPadding: 0.25, diff --git a/src/utils/themes/light_theme.ts b/src/utils/themes/light_theme.ts index 5af9972261..bfc55d6993 100644 --- a/src/utils/themes/light_theme.ts +++ b/src/utils/themes/light_theme.ts @@ -60,6 +60,14 @@ export const LIGHT_THEME: Theme = { offsetY: 0, }, }, + arcSeriesStyle: { + arc: { + visible: true, + stroke: 'black', + strokeWidth: 1, + opacity: 1, + }, + }, sharedStyle: DEFAULT_GEOMETRY_STYLES, scales: { barsPadding: 0.25, diff --git a/src/utils/themes/theme.ts b/src/utils/themes/theme.ts index 29704d59e6..6efc793d5b 100644 --- a/src/utils/themes/theme.ts +++ b/src/utils/themes/theme.ts @@ -13,11 +13,15 @@ export interface TextStyle { fill: string; padding: number; } + +/** Shared style properties for varies geometries */ export interface GeometryStyle { - stroke: string; - strokeWidth: number; - fill?: string; - opacity?: number; + /** + * Opacity multiplier + * + * if set to `0.5` all given opacities will be halfed + */ + opacity: number; } /** Shared style properties for varies geometries */ @@ -146,6 +150,7 @@ export interface Theme { * You may use `CustomSeriesColorsMap` to assign colors to a given series or replace the `theme.colors.vizColors` colors to your desired colors. */ barSeriesStyle: BarSeriesStyle; + arcSeriesStyle: ArcSeriesStyle; sharedStyle: SharedGeometryStateStyle; axes: AxisConfig; scales: ScalesConfig; @@ -196,6 +201,19 @@ export interface AreaStyle { opacity: number; } +export interface ArcStyle { + /** is the arc is visible or hidden ? */ + visible: boolean; + /** a static fill color if defined, if not it will use the color of the series */ + fill?: string; + /** a static stroke color if defined, if not it will use the color of the series */ + stroke?: string; + /** the stroke width of the line */ + strokeWidth: number; + /** the opacity of each arc on the theme/series */ + opacity: number; +} + export interface RectStyle { /** a static fill color if defined, if not it will use the color of the series */ fill?: string; @@ -238,6 +256,10 @@ export interface AreaSeriesStyle { point: PointStyle; } +export interface ArcSeriesStyle { + arc: ArcStyle; +} + export interface CrosshairStyle { band: FillStyle & Visible; line: StrokeStyle & Visible & Partial<StrokeDashArray>; diff --git a/stories/annotations.tsx b/stories/annotations.tsx index 2dc5271850..5a38813f7e 100644 --- a/stories/annotations.tsx +++ b/stories/annotations.tsx @@ -21,8 +21,8 @@ import { } from '../src'; import { Icon } from '../src/components/icons/icon'; import { KIBANA_METRICS } from '../src/utils/data_samples/test_dataset_kibana'; -import { AccessorType } from '../src/chart_types/xy_chart/rendering/rendering'; import { getChartRotationKnob } from './common'; +import { AccessorType } from '../src/utils/geometry'; const dateFormatter = timeFormatter('HH:mm:ss'); @@ -65,7 +65,7 @@ storiesOf('Annotations', module) <Chart className={'story-chart'}> <Settings showLegend debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> <LineAnnotation - annotationId={getAnnotationId('anno_1')} + id={getAnnotationId('anno_1')} domainType={AnnotationDomainTypes.XDomain} dataValues={dataValues} style={style} @@ -91,7 +91,7 @@ storiesOf('Annotations', module) <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> <LineAnnotation - annotationId={getAnnotationId('anno_1')} + id={'anno_1'} domainType={AnnotationDomainTypes.XDomain} dataValues={dataValues} marker={<Icon type="alert" />} @@ -122,7 +122,7 @@ storiesOf('Annotations', module) <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> <LineAnnotation - annotationId={getAnnotationId('anno_')} + id={'anno_'} domainType={AnnotationDomainTypes.YDomain} dataValues={dataValues} marker={<Icon type="alert" />} @@ -153,7 +153,7 @@ storiesOf('Annotations', module) <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> <LineAnnotation - annotationId={getAnnotationId('anno_1')} + id={'anno_1'} domainType={AnnotationDomainTypes.XDomain} dataValues={dataValues} marker={<Icon type="alert" />} @@ -211,7 +211,7 @@ storiesOf('Annotations', module) <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> <LineAnnotation - annotationId={getAnnotationId('anno_1')} + id={'anno_1'} domainType={AnnotationDomainTypes.XDomain} dataValues={dataValues} style={style} @@ -241,13 +241,14 @@ storiesOf('Annotations', module) y0: 0, y1: 7, }, + details: 'details about this annotation', }, ]; return ( <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> - <RectAnnotation dataValues={dataValues} annotationId={getAnnotationId('rect')} /> + <RectAnnotation dataValues={dataValues} id={'rect'} /> <Axis id={getAxisId('bottom')} position={Position.Bottom} title={'x-domain axis'} /> <Axis id={getAxisId('left')} title={'y-domain axis'} position={Position.Left} /> <BarSeries @@ -275,7 +276,7 @@ storiesOf('Annotations', module) return ( <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> - <RectAnnotation dataValues={dataValues} annotationId={getAnnotationId('rect')} /> + <RectAnnotation dataValues={dataValues} id={'rect'} /> <Axis id={getAxisId('bottom')} position={Position.Bottom} title={'x-domain axis'} /> <Axis id={getAxisId('left')} title={'y-domain axis'} position={Position.Left} /> <BarSeries @@ -342,7 +343,7 @@ storiesOf('Annotations', module) return ( <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> - <RectAnnotation dataValues={dataValues} annotationId={getAnnotationId('rect')} /> + <RectAnnotation dataValues={dataValues} id={'rect'} /> <Axis id={getAxisId('bottom')} position={xAxisPosition} title={xAxisTitle} /> <Axis id={getAxisId('left')} title={yAxisTitle} position={yAxisPosition} /> <LineSeries @@ -433,7 +434,7 @@ storiesOf('Annotations', module) <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} /> <RectAnnotation dataValues={dataValues} - annotationId={getAnnotationId('rect')} + id={'rect'} style={style} renderTooltip={renderTooltip} zIndex={zIndex} @@ -482,7 +483,7 @@ storiesOf('Annotations', module) <Chart className={'story-chart'}> <Settings debug={boolean('debug', false)} rotation={getChartRotationKnob()} xDomain={xDomain} /> <LineAnnotation - annotationId={getAnnotationId('anno_1')} + id={'anno_1'} domainType={AnnotationDomainTypes.XDomain} dataValues={dataValues} style={style} @@ -540,7 +541,7 @@ storiesOf('Annotations', module) <Chart className={'story-chart'}> <RectAnnotation dataValues={dataValues} - annotationId={getAnnotationId('rect')} + id={'rect'} renderTooltip={isCustomTooltip ? tooltipFormatter : undefined} /> <Axis id={getAxisId('bottom')} position={Position.Bottom} title={'x-domain axis'} /> diff --git a/stories/area_chart.tsx b/stories/area_chart.tsx index d30a3e761b..6bf938e2b5 100644 --- a/stories/area_chart.tsx +++ b/stories/area_chart.tsx @@ -175,6 +175,7 @@ storiesOf('Area Chart', module) tickFormat={dateFormatter} /> <Axis + id={'left'} title={KIBANA_METRICS.metrics.kibana_os_load[0].metric.title} position={Position.Left} tickFormat={(d) => Number(d).toFixed(2)} @@ -213,6 +214,7 @@ storiesOf('Area Chart', module) tickFormat={dateFormatter} /> <Axis + id={'left'} title={KIBANA_METRICS.metrics.kibana_os_load[0].metric.title} position={Position.Left} tickFormat={(d) => Number(d).toFixed(2)} @@ -278,6 +280,7 @@ storiesOf('Area Chart', module) tickFormat={dateFormatter} /> <Axis + id={'left'} title={KIBANA_METRICS.metrics.kibana_os_load[0].metric.title} position={Position.Left} tickFormat={(d) => Number(d).toFixed(2)} @@ -327,6 +330,7 @@ storiesOf('Area Chart', module) tickFormat={dateFormatter} /> <Axis + id={'left'} title={KIBANA_METRICS.metrics.kibana_os_load[0].metric.title} position={Position.Left} tickFormat={(d) => Number(d).toFixed(2)} diff --git a/stories/bar_chart.tsx b/stories/bar_chart.tsx index 2ebb1bab7f..b9c67f1581 100644 --- a/stories/bar_chart.tsx +++ b/stories/bar_chart.tsx @@ -10,7 +10,6 @@ import { BarSeries, Chart, DARK_THEME, - getAnnotationId, getAxisId, getGroupId, getSpecId, @@ -1437,7 +1436,7 @@ storiesOf('Bar Chart', module) <Chart className={'story-chart'}> <Settings rotation={getChartRotationKnob()} theme={theme} debug={boolean('debug', true)} /> <LineAnnotation - annotationId={getAnnotationId('line-annotation')} + id={'line-annotation'} domainType={AnnotationDomainTypes.XDomain} dataValues={[{ dataValue: 2 }, { dataValue: 2.5 }, { dataValue: 3.5 }]} style={lineAnnotationStyle} @@ -1458,7 +1457,7 @@ storiesOf('Bar Chart', module) details: 'rect annotation', }, ]} - annotationId={getAnnotationId('rect')} + id={'rect'} /> <Axis id={getAxisId('discover-histogram-left-axis')} position={Position.Left} title={'left axis'} /> <Axis id={getAxisId('discover-histogram-bottom-axis')} position={Position.Bottom} title={'bottom axis'} /> diff --git a/stories/interactions.tsx b/stories/interactions.tsx index 688dc4272d..f94caac636 100644 --- a/stories/interactions.tsx +++ b/stories/interactions.tsx @@ -21,6 +21,7 @@ import { TooltipType, TooltipValue, TooltipValueFormatter, + HistogramBarSeries, } from '../src/'; import { array, boolean, number, select, button } from '@storybook/addon-knobs'; @@ -470,6 +471,62 @@ storiesOf('Interactions', module) yScaleType={ScaleType.Linear} xAccessor="x" yAccessors={['y']} + timeZone={'Europe/Rome'} + data={[ + { x: now, y: 2 }, + { x: now + oneDay, y: 7 }, + { x: now + oneDay * 2, y: 3 }, + { x: now + oneDay * 5, y: 6 }, + ]} + /> + <LineSeries + id={getSpecId('baras')} + xScaleType={ScaleType.Time} + yScaleType={ScaleType.Linear} + xAccessor="x" + yAccessors={['y']} + timeZone={'Europe/Rome'} + data={[ + { x: now, y: 2 }, + { x: now + oneDay, y: 7 }, + { x: now + oneDay * 2, y: 3 }, + { x: now + oneDay * 5, y: 6 }, + ]} + /> + </Chart> + ); + }) + .add('brush selection tool on histogram time charts', () => { + const now = DateTime.fromISO('2019-01-11T00:00:00.000') + .setZone('utc+1') + .toMillis(); + const oneDay = 1000 * 60 * 60 * 24; + const formatter = niceTimeFormatter([now, now + oneDay * 5]); + return ( + <Chart className={'story-chart'}> + <Settings + debug={boolean('debug', false)} + onBrushEnd={(start, end) => { + action('onBrushEnd')(formatter(start), formatter(end)); + }} + onElementClick={action('onElementClick')} + /> + <Axis + id={getAxisId('bottom')} + position={Position.Bottom} + title={'bottom'} + showOverlappingTicks={true} + tickFormat={formatter} + /> + <Axis id={getAxisId('left')} title={'left'} position={Position.Left} tickFormat={(d) => Number(d).toFixed(2)} /> + + <HistogramBarSeries + id={getSpecId('bars')} + xScaleType={ScaleType.Time} + yScaleType={ScaleType.Linear} + xAccessor="x" + yAccessors={['y']} + timeZone={'Europe/Rome'} data={[ { x: now, y: 2 }, { x: now + oneDay, y: 7 }, diff --git a/stories/mixed.tsx b/stories/mixed.tsx index 47619d757b..73a4557f19 100644 --- a/stories/mixed.tsx +++ b/stories/mixed.tsx @@ -17,7 +17,7 @@ import { Settings, } from '../src/'; import { timeFormatter } from '../src/utils/data/formatters'; -import { Fit } from '../src/chart_types/xy_chart/utils/specs'; +import { Fit, SeriesTypes } from '../src/chart_types/xy_chart/utils/specs'; storiesOf('Mixed Charts', module) .add('bar and lines', () => { @@ -290,10 +290,10 @@ storiesOf('Mixed Charts', module) const seriesType = select<string>( 'seriesType', { - Area: 'area', - Line: 'line', + Area: SeriesTypes.Area, + Line: SeriesTypes.Line, }, - 'area', + SeriesTypes.Area, ); const dataKey = select<string>( 'dataset', @@ -365,7 +365,7 @@ storiesOf('Mixed Charts', module) /> <Axis id={getAxisId('bottom')} position={Position.Bottom} title={'Bottom axis'} showOverlappingTicks={true} /> <Axis id={getAxisId('left')} title={'Left axis'} position={Position.Left} /> - {seriesType === 'area' ? ( + {seriesType === SeriesTypes.Area ? ( <AreaSeries id={getSpecId('test')} xScaleType={xScaleType} diff --git a/stories/scales.tsx b/stories/scales.tsx index 28d8adfdd2..e1f73a1f30 100644 --- a/stories/scales.tsx +++ b/stories/scales.tsx @@ -39,9 +39,6 @@ storiesOf('Scales', module) let data; switch (datasetSelected) { - case 'utc': - data = UTC_DATASET; - break; case 'local': data = CURRENT_TIMEZONE_DATASET; break; @@ -51,6 +48,10 @@ storiesOf('Scales', module) case 'utc-8': data = OTHER_MINUS8_TIMEZONE_DATASET; break; + case 'utc': + default: + data = UTC_DATASET; + break; } let tooltipFn: (d: number) => string; switch (tooltipSelected) { diff --git a/tsconfig.jest.json b/tsconfig.jest.json index f407711d1d..8d80e97a08 100644 --- a/tsconfig.jest.json +++ b/tsconfig.jest.json @@ -1,8 +1,4 @@ { "extends": "./tsconfig.json", - "include": [ - "src/**/*", - "scripts/setup_enzyme.ts", - "scripts/custom_matchers.ts" - ] + "include": ["src/**/*", "scripts/setup_enzyme.ts", "scripts/custom_matchers.ts"] } diff --git a/wiki/overview.md b/wiki/overview.md index e1b016f75f..797858c5fd 100644 --- a/wiki/overview.md +++ b/wiki/overview.md @@ -125,7 +125,7 @@ export interface SeriesSpec { /** An array of data */ data: Datum[]; /** The type of series you are looking to render */ - seriesType: 'bar' | 'line' | 'area'; + seriesType: SeriesTypes; /** Custom colors for series */ customSeriesColors?: CustomSeriesColorsMap; /** If the series should appear in the legend @@ -183,7 +183,7 @@ A `BarSeriesSpec` for example is the following intersection type: export type BarSeriesSpec = SeriesSpec & SeriesAccessors & SeriesScales & { - seriesType: 'bar'; + seriesType: SeriesTypes.Bar; }; ``` diff --git a/yarn.lock b/yarn.lock index 596bce006d..510171d21a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,52 +2,25 @@ # yarn lockfile v1 -"@babel/code-frame@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": +"@babel/code-frame@7.5.5", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.3.tgz#198d6d3af4567be3989550d97e068de94503074f" - integrity sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.0" - "@babel/helpers" "^7.4.3" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - convert-source-map "^1.1.0" - debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.11" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" - integrity sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg== +"@babel/core@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.0.tgz#9b00f73554edd67bebc86df8303ef678be3d7b48" + integrity sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helpers" "^7.5.5" - "@babel/parser" "^7.5.5" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" + "@babel/generator" "^7.6.0" + "@babel/helpers" "^7.6.0" + "@babel/parser" "^7.6.0" + "@babel/template" "^7.6.0" + "@babel/traverse" "^7.6.0" + "@babel/types" "^7.6.0" convert-source-map "^1.1.0" debug "^4.1.0" json5 "^2.1.0" @@ -56,18 +29,18 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.2.tgz#069a776e8d5e9eefff76236bc8845566bd31dd91" - integrity sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ== +"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.3.4", "@babel/core@^7.4.5": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.4.tgz#6ebd9fe00925f6c3e177bb726a188b5f578088ff" + integrity sha512-Rm0HGw101GY8FTzpWSyRbki/jzq+/PkNQJ+nSulrdY6gFGOsNseCqD6KHRYe2E+EdzuBdr2pxCp6s4Uk6eJ+XQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.2" + "@babel/generator" "^7.6.4" "@babel/helpers" "^7.6.2" - "@babel/parser" "^7.6.2" + "@babel/parser" "^7.6.4" "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.2" - "@babel/types" "^7.6.0" + "@babel/traverse" "^7.6.3" + "@babel/types" "^7.6.3" convert-source-map "^1.1.0" debug "^4.1.0" json5 "^2.1.0" @@ -76,47 +49,16 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.3.4", "@babel/core@^7.4.3": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.5.tgz#081f97e8ffca65a9b4b0fdc7e274e703f000c06a" - integrity sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA== +"@babel/generator@^7.4.0", "@babel/generator@^7.6.0", "@babel/generator@^7.6.3", "@babel/generator@^7.6.4": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671" + integrity sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w== dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.4" - "@babel/helpers" "^7.4.4" - "@babel/parser" "^7.4.5" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.4.5" - "@babel/types" "^7.4.4" - convert-source-map "^1.1.0" - debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.11" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.4.0", "@babel/generator@^7.4.4", "@babel/generator@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" - integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ== - dependencies: - "@babel/types" "^7.6.0" + "@babel/types" "^7.6.3" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.5.tgz#873a7f936a3c89491b43536d12245b626664e3cf" - integrity sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ== - dependencies: - "@babel/types" "^7.5.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - trim-right "^1.0.1" - "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -149,10 +91,10 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" -"@babel/helper-create-class-features-plugin@^7.4.0", "@babel/helper-create-class-features-plugin@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.5.tgz#401f302c8ddbc0edd36f7c6b2887d8fa1122e5a4" - integrity sha512-ZsxkyYiRA7Bg+ZTRpPvB6AbOFKTFFK4LrvTet8lInm0V468MWCaSYJE+I7v2z2r8KNLtYiV+K5kTCnR7dvyZjg== +"@babel/helper-create-class-features-plugin@^7.5.5", "@babel/helper-create-class-features-plugin@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.6.0.tgz#769711acca889be371e9bc2eb68641d55218021f" + integrity sha512-O1QWBko4fzGju6VoVvrZg0RROCVifcLxiApnGP3OWfWzvxRZFCoBD81K5ur5e3bVY2Vf/5rIJm8cqPKn8HUJng== dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/helper-member-expression-to-functions" "^7.5.5" @@ -161,7 +103,7 @@ "@babel/helper-replace-supers" "^7.5.5" "@babel/helper-split-export-declaration" "^7.4.4" -"@babel/helper-define-map@^7.4.0", "@babel/helper-define-map@^7.5.5": +"@babel/helper-define-map@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== @@ -170,15 +112,6 @@ "@babel/types" "^7.5.5" lodash "^4.17.13" -"@babel/helper-define-map@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz#6969d1f570b46bdc900d1eba8e5d59c48ba2c12a" - integrity sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.4.4" - lodash "^4.17.11" - "@babel/helper-explode-assignable-expression@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" @@ -210,13 +143,6 @@ dependencies: "@babel/types" "^7.4.4" -"@babel/helper-member-expression-to-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f" - integrity sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg== - dependencies: - "@babel/types" "^7.0.0" - "@babel/helper-member-expression-to-functions@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" @@ -232,16 +158,16 @@ "@babel/types" "^7.0.0" "@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz#96115ea42a2f139e619e98ed46df6019b94414b8" - integrity sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" + integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" "@babel/template" "^7.4.4" - "@babel/types" "^7.4.4" - lodash "^4.17.11" + "@babel/types" "^7.5.5" + lodash "^4.17.13" "@babel/helper-optimise-call-expression@^7.0.0": version "7.0.0" @@ -256,11 +182,11 @@ integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2" - integrity sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== dependencies: - lodash "^4.17.11" + lodash "^4.17.13" "@babel/helper-remap-async-to-generator@^7.1.0": version "7.1.0" @@ -273,17 +199,7 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz#aee41783ebe4f2d3ab3ae775e1cc6f1a90cefa27" - integrity sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.0.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/helper-replace-supers@^7.4.0", "@babel/helper-replace-supers@^7.5.5": +"@babel/helper-replace-supers@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== @@ -301,7 +217,7 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-split-export-declaration@^7.4.0", "@babel/helper-split-export-declaration@^7.4.4": +"@babel/helper-split-export-declaration@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== @@ -318,16 +234,7 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.2.0" -"@babel/helpers@^7.4.3", "@babel/helpers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.5.tgz#63908d2a73942229d1e6685bc2a0e730dde3b75e" - integrity sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g== - dependencies: - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@babel/helpers@^7.4.4", "@babel/helpers@^7.6.2": +"@babel/helpers@^7.6.0", "@babel/helpers@^7.6.2": version "7.6.2" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.2.tgz#681ffe489ea4dcc55f23ce469e58e59c1c045153" integrity sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA== @@ -345,15 +252,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.4.5", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" - integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== - -"@babel/parser@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" - integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== +"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.3", "@babel/parser@^7.6.4": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81" + integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A== "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" @@ -364,15 +266,7 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-class-properties@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.0.tgz#d70db61a2f1fd79de927eea91f6411c964e084b8" - integrity sha512-t2ECPNOXsIeK1JxJNKmgbzQtoG27KIlVE61vTqX0DKR9E9sZlVVxWUtEW9D5FlZ8b8j7SBNCHY47GgPKCKlpPg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.4.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-proposal-class-properties@^7.3.3": +"@babel/plugin-proposal-class-properties@7.5.5", "@babel/plugin-proposal-class-properties@^7.3.3": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A== @@ -380,12 +274,12 @@ "@babel/helper-create-class-features-plugin" "^7.5.5" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-proposal-decorators@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.0.tgz#8e1bfd83efa54a5f662033afcc2b8e701f4bb3a9" - integrity sha512-d08TLmXeK/XbgCo7ZeZ+JaeZDtDai/2ctapTRsWWkkmy7G/cqz8DQN/HlWG7RR4YmfXxmExsbU3SuCjlM7AtUg== +"@babel/plugin-proposal-decorators@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.6.0.tgz#6659d2572a17d70abd68123e89a12a43d90aa30c" + integrity sha512-ZSyYw9trQI50sES6YxREXKu+4b7MAg6Qx2cvyDDYjP2Hpzd3FleOUwC9cqn1+za8d0A2ZU8SHujxFao956efUg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.4.0" + "@babel/helper-create-class-features-plugin" "^7.6.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-decorators" "^7.2.0" @@ -405,15 +299,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.3.tgz#be27cd416eceeba84141305b93c282f5de23bbb4" - integrity sha512-xC//6DNSSHVjq8O2ge0dyYlhshsH4T7XdCVoxbi5HzLYWfsC5ooFlJjrXk8RcAT+hjHAK9UjBXdylzSoDK3t4g== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - -"@babel/plugin-proposal-object-rest-spread@^7.3.2", "@babel/plugin-proposal-object-rest-spread@^7.4.3", "@babel/plugin-proposal-object-rest-spread@^7.5.5": +"@babel/plugin-proposal-object-rest-spread@7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" integrity sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw== @@ -421,10 +307,10 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz#1ef173fcf24b3e2df92a678f027673b55e7e3005" - integrity sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g== +"@babel/plugin-proposal-object-rest-spread@^7.3.2", "@babel/plugin-proposal-object-rest-spread@^7.5.5", "@babel/plugin-proposal-object-rest-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" + integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" @@ -437,14 +323,14 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" -"@babel/plugin-proposal-unicode-property-regex@^7.4.0", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" - integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== +"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz#05413762894f41bfe42b9a5e80919bd575dcc802" + integrity sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + regexpu-core "^4.6.0" "@babel/plugin-syntax-async-generators@^7.2.0": version "7.2.0" @@ -516,7 +402,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-async-to-generator@^7.4.0", "@babel/plugin-transform-async-to-generator@^7.5.0": +"@babel/plugin-transform-async-to-generator@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== @@ -525,15 +411,6 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.1.0" -"@babel/plugin-transform-async-to-generator@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz#a3f1d01f2f21cadab20b33a82133116f14fb5894" - integrity sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-transform-block-scoped-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" @@ -541,37 +418,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-block-scoping@^7.4.0", "@babel/plugin-transform-block-scoping@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz#a35f395e5402822f10d2119f6f8e045e3639a2ce" - integrity sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg== +"@babel/plugin-transform-block-scoping@^7.6.0", "@babel/plugin-transform-block-scoping@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a" + integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.13" -"@babel/plugin-transform-block-scoping@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz#c13279fabf6b916661531841a23c4b7dae29646d" - integrity sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.11" - -"@babel/plugin-transform-classes@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.3.tgz#adc7a1137ab4287a555d429cc56ecde8f40c062c" - integrity sha512-PUaIKyFUDtG6jF5DUJOfkBdwAS/kFFV3XFk7Nn0a6vR7ZT8jYw5cGtIlat77wcnd0C6ViGqo/wyNf4ZHytF/nQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.4.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.4.0" - "@babel/helper-split-export-declaration" "^7.4.0" - globals "^11.1.0" - -"@babel/plugin-transform-classes@^7.4.3", "@babel/plugin-transform-classes@^7.5.5": +"@babel/plugin-transform-classes@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== @@ -585,20 +440,6 @@ "@babel/helper-split-export-declaration" "^7.4.4" globals "^11.1.0" -"@babel/plugin-transform-classes@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz#0ce4094cdafd709721076d3b9c38ad31ca715eb6" - integrity sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.4.4" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.4.4" - "@babel/helper-split-export-declaration" "^7.4.4" - globals "^11.1.0" - "@babel/plugin-transform-computed-properties@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" @@ -606,42 +447,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-destructuring@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.3.tgz#1a95f5ca2bf2f91ef0648d5de38a8d472da4350f" - integrity sha512-rVTLLZpydDFDyN4qnXdzwoVpk1oaXHIvPEOkOLyr88o7oHxVc/LyrnDx+amuBWGOwUb7D1s/uLsKBNTx08htZg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-destructuring@^7.4.3", "@babel/plugin-transform-destructuring@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz#f6c09fdfe3f94516ff074fe877db7bc9ef05855a" - integrity sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-destructuring@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz#9d964717829cc9e4b601fc82a26a71a4d8faf20f" - integrity sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ== +"@babel/plugin-transform-destructuring@7.6.0", "@babel/plugin-transform-destructuring@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" + integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-dotall-regex@^7.4.3", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" - integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz#44abb948b88f0199a627024e1508acaf8dc9b2f9" + integrity sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" - -"@babel/plugin-transform-duplicate-keys@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz#d952c4930f312a4dbfff18f0b2914e60c35530b3" - integrity sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + regexpu-core "^4.6.0" "@babel/plugin-transform-duplicate-keys@^7.5.0": version "7.5.0" @@ -658,30 +478,30 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-flow-strip-types@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.0.tgz#f3c59eecff68c99b9c96eaafe4fe9d1fa8947138" - integrity sha512-C4ZVNejHnfB22vI2TYN4RUp2oCmq6cSEAg4RygSvYZUECRqUu9O4PMEMNJ4wsemaRGg27BbgYctG4BZh+AgIHw== +"@babel/plugin-transform-flow-strip-types@7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz#d267a081f49a8705fc9146de0768c6b58dccd8f7" + integrity sha512-WyVedfeEIILYEaWGAUWzVNyqG4sfsNooMhXWsu/YzOvVGcsnPb5PguysjJqI3t3qiaYj0BR8T2f5njdjTGe44Q== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-flow" "^7.2.0" "@babel/plugin-transform-flow-strip-types@^7.0.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz#d267a081f49a8705fc9146de0768c6b58dccd8f7" - integrity sha512-WyVedfeEIILYEaWGAUWzVNyqG4sfsNooMhXWsu/YzOvVGcsnPb5PguysjJqI3t3qiaYj0BR8T2f5njdjTGe44Q== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.6.3.tgz#8110f153e7360cfd5996eee68706cfad92d85256" + integrity sha512-l0ETkyEofkqFJ9LS6HChNIKtVJw2ylKbhYMlJ5C6df+ldxxaLIyXY4yOdDQQspfFpV8/vDiaWoJlvflstlYNxg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-flow" "^7.2.0" -"@babel/plugin-transform-for-of@^7.4.3", "@babel/plugin-transform-for-of@^7.4.4": +"@babel/plugin-transform-for-of@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-function-name@^7.4.3", "@babel/plugin-transform-function-name@^7.4.4": +"@babel/plugin-transform-function-name@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== @@ -703,14 +523,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-amd@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6" - integrity sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-modules-amd@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" @@ -720,26 +532,17 @@ "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-commonjs@^7.4.3", "@babel/plugin-transform-modules-commonjs@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74" - integrity sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ== +"@babel/plugin-transform-modules-commonjs@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz#39dfe957de4420445f1fcf88b68a2e4aa4515486" + integrity sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g== dependencies: "@babel/helper-module-transforms" "^7.4.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-commonjs@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz#0bef4713d30f1d78c2e59b3d6db40e60192cac1e" - integrity sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw== - dependencies: - "@babel/helper-module-transforms" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - -"@babel/plugin-transform-modules-systemjs@^7.4.0", "@babel/plugin-transform-modules-systemjs@^7.5.0": +"@babel/plugin-transform-modules-systemjs@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" integrity sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg== @@ -748,14 +551,6 @@ "@babel/helper-plugin-utils" "^7.0.0" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-systemjs@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz#dc83c5665b07d6c2a7b224c00ac63659ea36a405" - integrity sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ== - dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-modules-umd@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" @@ -764,28 +559,20 @@ "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-named-capturing-groups-regex@^7.4.2", "@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" - integrity sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.6.0", "@babel/plugin-transform-named-capturing-groups-regex@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.3.tgz#aaa6e409dd4fb2e50b6e2a91f7e3a3149dbce0cf" + integrity sha512-jTkk7/uE6H2s5w6VlMHeWuH+Pcy2lmdwFoeWCVnvIrDUnB5gQqTVI8WfmEAhF2CDEarGrknZcmSFg1+bkfCoSw== dependencies: - regexp-tree "^0.1.6" + regexpu-core "^4.6.0" -"@babel/plugin-transform-new-target@^7.4.0", "@babel/plugin-transform-new-target@^7.4.4": +"@babel/plugin-transform-new-target@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-object-super@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598" - integrity sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.1.0" - "@babel/plugin-transform-object-super@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" @@ -794,7 +581,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.5.5" -"@babel/plugin-transform-parameters@^7.4.3", "@babel/plugin-transform-parameters@^7.4.4": +"@babel/plugin-transform-parameters@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== @@ -810,10 +597,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-react-constant-elements@7.2.0", "@babel/plugin-transform-react-constant-elements@^7.0.0", "@babel/plugin-transform-react-constant-elements@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.2.0.tgz#ed602dc2d8bff2f0cb1a5ce29263dbdec40779f7" - integrity sha512-YYQFg6giRFMsZPKUM9v+VcHOdfSQdz9jHCx3akAi3UYgyjndmdYGSXylQ/V+HswQt4fL8IklchD9HTsaOCrWQQ== +"@babel/plugin-transform-react-constant-elements@^7.0.0", "@babel/plugin-transform-react-constant-elements@^7.2.0": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.6.3.tgz#9fc9ea060b983c7c035acbe481cbe1fb1245bfff" + integrity sha512-1/YogSSU7Tby9rq2VCmhuRg+6pxsHy2rI7w/oo8RKoBt6uBUFG+mk6x13kK+FY1/ggN92HAfg7ADd1v1+NCOKg== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -834,9 +621,9 @@ "@babel/plugin-syntax-jsx" "^7.2.0" "@babel/plugin-transform-react-jsx-source@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.2.0.tgz#20c8c60f0140f5dd3cd63418d452801cf3f7180f" - integrity sha512-A32OkKTp4i5U6aE88GwwcuV4HAprUgHcTq0sSafLxjr6AW0QahrCRCjxogkbbcdtpbXkuTOlgpjophCxb6sh5g== + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz#583b10c49cf057e237085bcbd8cc960bd83bd96b" + integrity sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-jsx" "^7.2.0" @@ -850,7 +637,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-jsx" "^7.2.0" -"@babel/plugin-transform-regenerator@^7.4.3", "@babel/plugin-transform-regenerator@^7.4.5": +"@babel/plugin-transform-regenerator@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== @@ -864,10 +651,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-runtime@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.4.3.tgz#4d6691690ecdc9f5cb8c3ab170a1576c1f556371" - integrity sha512-7Q61bU+uEI7bCUFReT1NKn7/X6sDQsZ7wL1sJ9IYMAO7cI+eg6x9re1cEw2fCRMbbTVyoeUKWSV1M6azEfKCfg== +"@babel/plugin-transform-runtime@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.0.tgz#85a3cce402b28586138e368fce20ab3019b9713e" + integrity sha512-Da8tMf7uClzwUm/pnJ1S93m/aRXmoYNDD7TkHua8xBDdaAs54uZpTWvEt6NGwmoVMb9mZbntfTqmG2oSzN/7Vg== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -881,10 +668,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-spread@^7.2.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" - integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== +"@babel/plugin-transform-spread@^7.2.0", "@babel/plugin-transform-spread@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" + integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -896,7 +683,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" -"@babel/plugin-transform-template-literals@^7.2.0", "@babel/plugin-transform-template-literals@^7.4.4": +"@babel/plugin-transform-template-literals@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== @@ -911,123 +698,71 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-typescript@^7.3.2": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.5.5.tgz#6d862766f09b2da1cb1f7d505fe2aedab6b7d4b8" - integrity sha512-pehKf4m640myZu5B2ZviLaiBlxMCjSZ1qTEO459AXKX5GnPueyulJeCqZFs1nz/Ya2dDzXQ1NxZ/kKNWyD4h6w== +"@babel/plugin-transform-typescript@^7.6.0": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.6.3.tgz#dddb50cf3b8b2ef70b22e5326e9a91f05a1db13b" + integrity sha512-aiWINBrPMSC3xTXRNM/dfmyYuPNKY/aexYqBgh0HBI5Y+WO5oRAqW/oROYeYHrF4Zw12r9rK4fMk/ZlAmqx/FQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.5.5" + "@babel/helper-create-class-features-plugin" "^7.6.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-typescript" "^7.2.0" -"@babel/plugin-transform-unicode-regex@^7.4.3", "@babel/plugin-transform-unicode-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" - integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== +"@babel/plugin-transform-unicode-regex@^7.4.4", "@babel/plugin-transform-unicode-regex@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698" + integrity sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + regexpu-core "^4.6.0" "@babel/polyfill@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.4.4.tgz#78801cf3dbe657844eeabf31c1cae3828051e893" - integrity sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg== + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.6.0.tgz#6d89203f8b6cd323e8d946e47774ea35dc0619cc" + integrity sha512-q5BZJI0n/B10VaQQvln1IlDK3BTBJFbADx7tv+oXDPIDZuTo37H5Adb9jhlXm/fEN4Y7/64qD9mnrJJG7rmaTw== dependencies: core-js "^2.6.5" regenerator-runtime "^0.13.2" -"@babel/preset-env@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.3.tgz#e71e16e123dc0fbf65a52cbcbcefd072fbd02880" - integrity sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.4.3" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.4.0" - "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.4.0" - "@babel/plugin-transform-classes" "^7.4.3" - "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.4.3" - "@babel/plugin-transform-dotall-regex" "^7.4.3" - "@babel/plugin-transform-duplicate-keys" "^7.2.0" - "@babel/plugin-transform-exponentiation-operator" "^7.2.0" - "@babel/plugin-transform-for-of" "^7.4.3" - "@babel/plugin-transform-function-name" "^7.4.3" - "@babel/plugin-transform-literals" "^7.2.0" - "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.2.0" - "@babel/plugin-transform-modules-commonjs" "^7.4.3" - "@babel/plugin-transform-modules-systemjs" "^7.4.0" - "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.2" - "@babel/plugin-transform-new-target" "^7.4.0" - "@babel/plugin-transform-object-super" "^7.2.0" - "@babel/plugin-transform-parameters" "^7.4.3" - "@babel/plugin-transform-property-literals" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.4.3" - "@babel/plugin-transform-reserved-words" "^7.2.0" - "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" - "@babel/plugin-transform-sticky-regex" "^7.2.0" - "@babel/plugin-transform-template-literals" "^7.2.0" - "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.4.3" - "@babel/types" "^7.4.0" - browserslist "^4.5.2" - core-js-compat "^3.0.0" - invariant "^2.2.2" - js-levenshtein "^1.1.3" - semver "^5.5.0" - -"@babel/preset-env@^7.4.3": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.5.tgz#2fad7f62983d5af563b5f3139242755884998a58" - integrity sha512-f2yNVXM+FsR5V8UwcFeIHzHWgnhXg3NpRmy0ADvALpnhB0SLbCvrCRr4BLOUYbQNLS+Z0Yer46x9dJXpXewI7w== +"@babel/preset-env@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.0.tgz#aae4141c506100bb2bfaa4ac2a5c12b395619e50" + integrity sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-dynamic-import" "^7.5.0" "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.4.4" + "@babel/plugin-proposal-object-rest-spread" "^7.5.5" "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-syntax-json-strings" "^7.2.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.4.4" + "@babel/plugin-transform-async-to-generator" "^7.5.0" "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.4.4" - "@babel/plugin-transform-classes" "^7.4.4" + "@babel/plugin-transform-block-scoping" "^7.6.0" + "@babel/plugin-transform-classes" "^7.5.5" "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.4.4" + "@babel/plugin-transform-destructuring" "^7.6.0" "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/plugin-transform-duplicate-keys" "^7.2.0" + "@babel/plugin-transform-duplicate-keys" "^7.5.0" "@babel/plugin-transform-exponentiation-operator" "^7.2.0" "@babel/plugin-transform-for-of" "^7.4.4" "@babel/plugin-transform-function-name" "^7.4.4" "@babel/plugin-transform-literals" "^7.2.0" "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.2.0" - "@babel/plugin-transform-modules-commonjs" "^7.4.4" - "@babel/plugin-transform-modules-systemjs" "^7.4.4" + "@babel/plugin-transform-modules-amd" "^7.5.0" + "@babel/plugin-transform-modules-commonjs" "^7.6.0" + "@babel/plugin-transform-modules-systemjs" "^7.5.0" "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.0" "@babel/plugin-transform-new-target" "^7.4.4" - "@babel/plugin-transform-object-super" "^7.2.0" + "@babel/plugin-transform-object-super" "^7.5.5" "@babel/plugin-transform-parameters" "^7.4.4" "@babel/plugin-transform-property-literals" "^7.2.0" "@babel/plugin-transform-regenerator" "^7.4.5" @@ -1038,7 +773,7 @@ "@babel/plugin-transform-template-literals" "^7.4.4" "@babel/plugin-transform-typeof-symbol" "^7.2.0" "@babel/plugin-transform-unicode-regex" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/types" "^7.6.0" browserslist "^4.6.0" core-js-compat "^3.1.1" invariant "^2.2.2" @@ -1046,18 +781,18 @@ semver "^5.5.0" "@babel/preset-env@^7.4.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.5.5.tgz#bc470b53acaa48df4b8db24a570d6da1fef53c9a" - integrity sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.3.tgz#9e1bf05a2e2d687036d24c40e4639dc46cef2271" + integrity sha512-CWQkn7EVnwzlOdR5NOm2+pfgSNEZmvGjOhlCHBDq0J8/EStr+G+FvPEiz9B56dR6MoiUFjXhfE4hjLoAKKJtIQ== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-async-generator-functions" "^7.2.0" "@babel/plugin-proposal-dynamic-import" "^7.5.0" "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.5.5" + "@babel/plugin-proposal-object-rest-spread" "^7.6.2" "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.6.2" "@babel/plugin-syntax-async-generators" "^7.2.0" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-syntax-json-strings" "^7.2.0" @@ -1066,11 +801,11 @@ "@babel/plugin-transform-arrow-functions" "^7.2.0" "@babel/plugin-transform-async-to-generator" "^7.5.0" "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.5.5" + "@babel/plugin-transform-block-scoping" "^7.6.3" "@babel/plugin-transform-classes" "^7.5.5" "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.5.0" - "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/plugin-transform-destructuring" "^7.6.0" + "@babel/plugin-transform-dotall-regex" "^7.6.2" "@babel/plugin-transform-duplicate-keys" "^7.5.0" "@babel/plugin-transform-exponentiation-operator" "^7.2.0" "@babel/plugin-transform-for-of" "^7.4.4" @@ -1078,10 +813,10 @@ "@babel/plugin-transform-literals" "^7.2.0" "@babel/plugin-transform-member-expression-literals" "^7.2.0" "@babel/plugin-transform-modules-amd" "^7.5.0" - "@babel/plugin-transform-modules-commonjs" "^7.5.0" + "@babel/plugin-transform-modules-commonjs" "^7.6.0" "@babel/plugin-transform-modules-systemjs" "^7.5.0" "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.4.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.3" "@babel/plugin-transform-new-target" "^7.4.4" "@babel/plugin-transform-object-super" "^7.5.5" "@babel/plugin-transform-parameters" "^7.4.4" @@ -1089,12 +824,12 @@ "@babel/plugin-transform-regenerator" "^7.4.5" "@babel/plugin-transform-reserved-words" "^7.2.0" "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-spread" "^7.6.2" "@babel/plugin-transform-sticky-regex" "^7.2.0" "@babel/plugin-transform-template-literals" "^7.4.4" "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.4.4" - "@babel/types" "^7.5.5" + "@babel/plugin-transform-unicode-regex" "^7.6.2" + "@babel/types" "^7.6.3" browserslist "^4.6.0" core-js-compat "^3.1.1" invariant "^2.2.2" @@ -1109,7 +844,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-flow-strip-types" "^7.0.0" -"@babel/preset-react@7.0.0", "@babel/preset-react@^7.0.0": +"@babel/preset-react@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.0.0.tgz#e86b4b3d99433c7b3e9e91747e2653958bc6b3c0" integrity sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w== @@ -1120,18 +855,29 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/preset-typescript@7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz#88669911053fa16b2b276ea2ede2ca603b3f307a" - integrity sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg== +"@babel/preset-react@^7.0.0": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.6.3.tgz#d5242c828322520205ae4eda5d4f4f618964e2f6" + integrity sha512-07yQhmkZmRAfwREYIQgW0HEwMY9GBJVuPY4Q12UC72AbfaawuupVWa8zQs2tlL+yun45Nv/1KreII/0PLfEsgA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.3.2" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + +"@babel/preset-typescript@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.6.0.tgz#25768cb8830280baf47c45ab1a519a9977498c98" + integrity sha512-4xKw3tTcCm0qApyT6PqM9qniseCE79xGHiUnNdKGdxNsGUc2X7WwZybqIpnTmoukg3nhPceI5KPNzNqLNeIJww== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.6.0" "@babel/runtime-corejs2@^7.4.2": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.4.5.tgz#3d892f0560df21bafb384dd7727e33853e95d3c9" - integrity sha512-5yLuwzvIDecKwYMzJtiarky4Fb5643H3Ao5jwX0HrMR5oM5mn2iHH9wSZonxwNK0oAjAFUQAiOd4jT7/9Y2jMQ== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.6.3.tgz#de3f446b3fb688b98cbd220474d1a7cad909bcb8" + integrity sha512-nuA2o+rgX2+PrNTZ063ehncVcg7sn+tU71BB81SaWRVUbGwCOlb0+yQA1e0QqmzOfRSYOxfvf8cosYqFbJEiwQ== dependencies: core-js "^2.6.5" regenerator-runtime "^0.13.2" @@ -1143,24 +889,17 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@7.4.3": - version "7.4.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" - integrity sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA== - dependencies: - regenerator-runtime "^0.13.2" - -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.2": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12" - integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ== +"@babel/runtime@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.0.tgz#4fc1d642a9fd0299754e8b5de62c631cf5568205" + integrity sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ== dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.4.3", "@babel/runtime@^7.4.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" - integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.3.tgz#935122c74c73d2240cafd32ddb5fc2a6cd35cf1f" + integrity sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA== dependencies: regenerator-runtime "^0.13.2" @@ -1173,62 +912,34 @@ "@babel/parser" "^7.6.0" "@babel/types" "^7.6.0" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.4.5", "@babel/traverse@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" - integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.0", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9" + integrity sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.2" + "@babel/generator" "^7.6.3" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.2" - "@babel/types" "^7.6.0" + "@babel/parser" "^7.6.3" + "@babel/types" "^7.6.3" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" - integrity sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.5.5" - "@babel/types" "^7.5.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.6.0": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" - integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0", "@babel/types@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09" + integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA== dependencies: esutils "^2.0.2" lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.2.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0" - integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ== - dependencies: - esutils "^2.0.2" - lodash "^4.17.11" - to-fast-properties "^2.0.0" - -"@babel/types@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" - integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" +"@base2/pretty-print-object@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.0.tgz#860ce718b0b73f4009e153541faff2cb6b85d047" + integrity sha512-4Th98KlMHr5+JkxfcoDT//6vY8vM+iSPrLNpHhRyLx2CFYi8e2RfqPLdpbnpo0Q5lQC5hNB79yes07zb02fvCw== "@cnakazawa/watch@^1.0.3": version "1.0.3" @@ -1239,16 +950,16 @@ minimist "^1.2.0" "@commitlint/cli@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-8.1.0.tgz#a3d4236c0ac961d7026a53d728b179c696d6a045" - integrity sha512-83K5C2nIAgoZlzMegf0/MEBjX+ampUyc/u79RxgX9ZYjzos+RQtNyO7I43dztVxPXSwAnX9XRgoOfkGWA4nbig== - dependencies: - "@commitlint/format" "^8.1.0" - "@commitlint/lint" "^8.1.0" - "@commitlint/load" "^8.1.0" - "@commitlint/read" "^8.1.0" + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-8.2.0.tgz#fbf9969e04e2162d985eaa644fdad6ce807aadb6" + integrity sha512-8fJ5pmytc38yw2QWbTTJmXLfSiWPwMkHH4govo9zJ/+ERPBF2jvlxD/dQvk24ezcizjKc6LFka2edYC4OQ+Dgw== + dependencies: + "@commitlint/format" "^8.2.0" + "@commitlint/lint" "^8.2.0" + "@commitlint/load" "^8.2.0" + "@commitlint/read" "^8.2.0" babel-polyfill "6.26.0" - chalk "2.3.1" + chalk "2.4.2" get-stdin "7.0.0" lodash "4.17.14" meow "5.0.0" @@ -1256,89 +967,89 @@ resolve-global "1.0.0" "@commitlint/config-conventional@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-8.1.0.tgz#ba61fbf0ad4df52da2b5ee3034470371a2cbf039" - integrity sha512-/JY+FNBnrT91qzDVIoV1Buiigvj7Le7ezFw+oRqu0nYREX03k7xnaG/7t7rUSvm7hM6dnLSOlaUsevjgMI9AEw== + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-8.2.0.tgz#886a5538e3708e017ec2871e0cbce00f635d3102" + integrity sha512-HuwlHQ3DyVhpK9GHgTMhJXD8Zp8PGIQVpQGYh/iTrEU6TVxdRC61BxIDZvfWatCaiG617Z/U8maRAFrqFM4TqA== -"@commitlint/ensure@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-8.1.0.tgz#6c669f85c3005ed15c8141d83cf5312c43001613" - integrity sha512-dBU4CcjN0vJSDNOeSpaHNgQ1ra444u4USvI6PTaHVAS4aeDpZ5Cds1rxkZNsocu48WNycUu0jP84+zjcw2pPLQ== +"@commitlint/ensure@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-8.2.0.tgz#fad0c81c3d3bd09aa5fbcbcc483ae1f39bc8af8f" + integrity sha512-XZZih/kcRrqK7lEORbSYCfqQw6byfsFbLygRGVdJMlCPGu9E2MjpwCtoj5z7y/lKfUB3MJaBhzn2muJqS1gC6A== dependencies: lodash "4.17.14" -"@commitlint/execute-rule@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-8.1.0.tgz#e8386bd0836b3dcdd41ebb9d5904bbeb447e4715" - integrity sha512-+vpH3RFuO6ypuCqhP2rSqTjFTQ7ClzXtUvXphpROv9v9+7zH4L+Ex+wZLVkL8Xj2cxefSLn/5Kcqa9XyJTn3kg== +"@commitlint/execute-rule@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-8.2.0.tgz#aefb3744e22613660adefb7ebcccaa60bd24e78d" + integrity sha512-9MBRthHaulbWTa8ReG2Oii2qc117NuvzhZdnkuKuYLhker7sUXGFcVhLanuWUKGyfyI2o9zVr/NHsNbCCsTzAA== -"@commitlint/format@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-8.1.0.tgz#c3f3ca78bb74cbc1cce1368c0974b0cb8f31b98e" - integrity sha512-D0cmabUTQIKdABgt08d9JAvO9+lMRAmkcsZx8TMScY502R67HCw77JhzRDcw1RmqX5rN8JO6ZjDHO92Pbwlt+Q== +"@commitlint/format@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-8.2.0.tgz#0a2447fadac7c0421ce8a8d7e27dfa2172c737d4" + integrity sha512-sA77agkDEMsEMrlGhrLtAg8vRexkOofEEv/CZX+4xlANyAz2kNwJvMg33lcL65CBhqKEnRRJRxfZ1ZqcujdKcQ== dependencies: chalk "^2.0.1" -"@commitlint/is-ignored@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-8.1.0.tgz#c0583fa3c641b2d4898be1443e70e9c467429de2" - integrity sha512-HUSxx6kuLbqrQ8jb5QRzo+yR+CIXgA9HNcIcZ1qWrb+O9GOixt3mlW8li1IcfIgfODlaWoxIz0jYCxR08IoQLg== +"@commitlint/is-ignored@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-8.2.0.tgz#b6409ab28bf5a80f25e14da17da3916adb230a89" + integrity sha512-ADaGnKfbfV6KD1pETp0Qf7XAyc75xTy3WJlbvPbwZ4oPdBMsXF0oXEEGMis6qABfU2IXan5/KAJgAFX3vdd0jA== dependencies: "@types/semver" "^6.0.1" - semver "6.1.1" + semver "6.2.0" -"@commitlint/lint@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-8.1.0.tgz#ad10f4885c06f14c71de11dcd6bf2ca54a395141" - integrity sha512-WYjbUgtqvnlVH3S3XPZMAa+N7KO0yQ+GuUG20Qra+EtER6SRYawykmEs4wAyrmY8VcFXUnKgSlIQUsqmGKwNZQ== +"@commitlint/lint@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-8.2.0.tgz#aadc606379f3550eb877f16d4f5b103639cbf92a" + integrity sha512-ch9JN8aR37ufdjoWv50jLfvFz9rWMgLW5HEkMGLsM/51gjekmQYS5NJg8S2+6F5+jmralAO7VkUMI6FukXKX0A== dependencies: - "@commitlint/is-ignored" "^8.1.0" - "@commitlint/parse" "^8.1.0" - "@commitlint/rules" "^8.1.0" + "@commitlint/is-ignored" "^8.2.0" + "@commitlint/parse" "^8.2.0" + "@commitlint/rules" "^8.2.0" babel-runtime "^6.23.0" lodash "4.17.14" -"@commitlint/load@>6.1.1", "@commitlint/load@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-8.1.0.tgz#63b72ae5bb9152b8fa5b17c5428053032a9a49c8" - integrity sha512-ra02Dvmd7Gp1+uFLzTY3yGOpHjPzl5T9wYg/xrtPJNiOWXvQ0Mw7THw+ucd1M5iLUWjvdavv2N87YDRc428wHg== +"@commitlint/load@>6.1.1", "@commitlint/load@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-8.2.0.tgz#9ca53a0c795e4f63d796b4d42279e856549add1a" + integrity sha512-EV6PfAY/p83QynNd1llHxJiNxKmp43g8+7dZbyfHFbsGOdokrCnoelAVZ+WGgktXwLN/uXyfkcIAxwac015UYw== dependencies: - "@commitlint/execute-rule" "^8.1.0" - "@commitlint/resolve-extends" "^8.1.0" + "@commitlint/execute-rule" "^8.2.0" + "@commitlint/resolve-extends" "^8.2.0" babel-runtime "^6.23.0" chalk "2.4.2" cosmiconfig "^5.2.0" lodash "4.17.14" resolve-from "^5.0.0" -"@commitlint/message@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-8.1.0.tgz#8fb8046ddaa7e5c846a79da7cdbd15cf1a7770ae" - integrity sha512-AjHq022G8jQQ/3YrBOjwVBD4xF75hvC3vcvFoBIb7cC8vad1QWq+1w+aks0KlEK5IW+/+7ORZXIH+oyW7h3+8A== +"@commitlint/message@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-8.2.0.tgz#bdc0388183f6bc6006c7e7e197a721683011907a" + integrity sha512-LNsSwDLIFgE3nb/Sb1PIluYNy4Q8igdf4tpJCdv5JJDf7CZCZt3ZTglj0YutZZorpRRuHJsVIB2+dI4bVH3bFw== -"@commitlint/parse@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-8.1.0.tgz#833243c6d848e7a7e775a283b38697166ed2fd22" - integrity sha512-n4fEbZ5kdK5HChvne7Mj8rGGkKMfA4H11IuWiWmmMzgmZTNb/B04LPrzdUm4lm3f10XzM2JMM7PLXqofQJOGvA== +"@commitlint/parse@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-8.2.0.tgz#de80137e89ee5a2d3029656c9b33e90c88c6f56c" + integrity sha512-vzouqroTXG6QXApkrps0gbeSYW6w5drpUk7QAeZIcaCSPsQXDM8eqqt98ZzlzLJHo5oPNXPX1AAVSTrssvHemA== dependencies: conventional-changelog-angular "^1.3.3" conventional-commits-parser "^2.1.0" lodash "^4.17.11" -"@commitlint/read@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-8.1.0.tgz#effe07c965ba1735a5f7f8b7b19ac4d98c887507" - integrity sha512-PKsGMQFEr2sX/+orI71b82iyi8xFqb7F4cTvsLxzB5x6/QutxPVM3rg+tEVdi6rBKIDuqRIp2puDZQuREZs3vg== +"@commitlint/read@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-8.2.0.tgz#54c6549723d532c74434ee0d74e0459032dc9159" + integrity sha512-1tBai1VuSQmsOTsvJr3Fi/GZqX3zdxRqYe/yN4i3cLA5S2Y4QGJ5I3l6nGZlKgm/sSelTCVKHltrfWU8s5H7SA== dependencies: - "@commitlint/top-level" "^8.1.0" + "@commitlint/top-level" "^8.2.0" "@marionebl/sander" "^0.6.0" babel-runtime "^6.23.0" git-raw-commits "^1.3.0" -"@commitlint/resolve-extends@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-8.1.0.tgz#ed67f2ee484160ac8e0078bae52f172625157472" - integrity sha512-r/y+CeKW72Oa9BUctS1+I/MFCDiI3lfhwfQ65Tpfn6eZ4CuBYKzrCRi++GTHeAFKE3y8q1epJq5Rl/1GBejtBw== +"@commitlint/resolve-extends@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-8.2.0.tgz#b7f2f0c71c10f24b98a199ed11d2c14cfd7a318f" + integrity sha512-cwi0HUsDcD502HBP8huXfTkVuWmeo1Fiz3GKxNwMBBsJV4+bKa7QrtxbNpXhVuarX7QjWfNTvmW6KmFS7YK9uw== dependencies: "@types/node" "^12.0.2" import-fresh "^3.0.0" @@ -1346,32 +1057,32 @@ resolve-from "^5.0.0" resolve-global "^1.0.0" -"@commitlint/rules@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-8.1.0.tgz#009c64a8a23feb4647e5a25057997be62a272c8a" - integrity sha512-hlM8VfNjsOkbvMteFyqn0c3akiUjqG09Iid28MBLrXl/d+8BR3eTzwJ4wMta4oz/iqGyrIywvg1FpHrV977MPA== +"@commitlint/rules@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-8.2.0.tgz#4cd6a323ca1a3f3d33ae6dc723f8c88f3dcde347" + integrity sha512-FlqSBBP2Gxt5Ibw+bxdYpzqYR6HI8NIBpaTBhAjSEAduQtdWFMOhF0zsgkwH7lHN7opaLcnY2fXxAhbzTmJQQA== dependencies: - "@commitlint/ensure" "^8.1.0" - "@commitlint/message" "^8.1.0" - "@commitlint/to-lines" "^8.1.0" + "@commitlint/ensure" "^8.2.0" + "@commitlint/message" "^8.2.0" + "@commitlint/to-lines" "^8.2.0" babel-runtime "^6.23.0" -"@commitlint/to-lines@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/to-lines/-/to-lines-8.1.0.tgz#5bf2597f46acacec4b1b3dba832ac8934798b22a" - integrity sha512-Lh4OH1bInI8GME/7FggS0/XkIMEJdTObMbXRyPRGaPcWH5S7zpB6y+b4qjzBHXAbEv2O46QAAMjZ+ywPQCpmYQ== +"@commitlint/to-lines@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/to-lines/-/to-lines-8.2.0.tgz#dddb5916a457e1a79e437115a9b8eac7bf9ad52a" + integrity sha512-LXTYG3sMenlN5qwyTZ6czOULVcx46uMy+MEVqpvCgptqr/MZcV/C2J+S2o1DGwj1gOEFMpqrZaE3/1R2Q+N8ng== -"@commitlint/top-level@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@commitlint/top-level/-/top-level-8.1.0.tgz#f1950de73a1f76ef5c9e753a6b77402e0755d677" - integrity sha512-EvQuofuA/+0l1w9pkG/PRyIwACmZdIh9qxyax7w7mR8qqmSHscqf2jARIylh1TOx0uI9egO8MuPLiwC1RwyREA== +"@commitlint/top-level@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@commitlint/top-level/-/top-level-8.2.0.tgz#206e7cbc54dbe9494190677f887dd60943fed5b0" + integrity sha512-Yaw4KmYNy31/HhRUuZ+fupFcDalnfpdu4JGBgGAqS9aBHdMSSWdWqtAaDaxdtWjTZeN3O0sA2gOhXwvKwiDwvw== dependencies: find-up "^4.0.0" "@elastic/eui@^13.1.0": - version "13.1.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-13.1.0.tgz#a3100bb37d6317b493d0ba0b8723f622e7628406" - integrity sha512-Z0Xqduomk2rBvKDZuLww/U11J/nHwiqkpNMnrMPJ96mBi3UlwA9QucA1/Edu30aCGvGcwKq08RUALO4owz6OWQ== + version "13.8.2" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-13.8.2.tgz#4509fb319f0c8b16fbc91d208c7c70d6d565d11f" + integrity sha512-lwnBcFFFuo9dQA+ir72G4+tT2stoddQj6jt0MDDDGwwFST9rrasYyu174nmbGeC0UoaxX/lE0skn5gaXnhYmvg== dependencies: "@types/lodash" "^4.14.116" "@types/numeral" "^0.0.25" @@ -1405,25 +1116,25 @@ find-root "^1.1.0" source-map "^0.7.2" -"@emotion/cache@^10.0.14": - version "10.0.14" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.14.tgz#56093cff025c04b0330bdd92afe8335ed326dd18" - integrity sha512-HNGEwWnPlNyy/WPXBXzbjzkzeZFV657Z99/xq2xs5yinJHbMfi3ioCvBJ6Y8Zc8DQzO9F5jDmVXJB41Ytx3QMw== +"@emotion/cache@^10.0.17": + version "10.0.19" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.19.tgz#d258d94d9c707dcadaf1558def968b86bb87ad71" + integrity sha512-BoiLlk4vEsGBg2dAqGSJu0vJl/PgVtCYLBFJaEO8RmQzPugXewQCXZJNXTDFaRlfCs0W+quesayav4fvaif5WQ== dependencies: "@emotion/sheet" "0.9.3" "@emotion/stylis" "0.8.4" "@emotion/utils" "0.11.2" - "@emotion/weak-memoize" "0.2.3" + "@emotion/weak-memoize" "0.2.4" "@emotion/core@^10.0.9": - version "10.0.14" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.14.tgz#cac5c334b278d5b7688cfff39e460a5b50abb71c" - integrity sha512-G9FbyxLm3lSnPfLDcag8fcOQBKui/ueXmWOhV+LuEQg9HrqExuWnWaO6gm6S5rNe+AMcqLXVljf8pYgAdFLNSg== + version "10.0.21" + resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.21.tgz#2e8398d2b92fd90d4ed6ac4d0b66214971de3458" + integrity sha512-U9zbc7ovZ2ceIwbLXYZPJy6wPgnOdTNT4jENZ31ee6v2lojetV5bTbCVk6ciT8G3wQRyVaTTfUCH9WCrMzpRIw== dependencies: - "@babel/runtime" "^7.4.3" - "@emotion/cache" "^10.0.14" + "@babel/runtime" "^7.5.5" + "@emotion/cache" "^10.0.17" "@emotion/css" "^10.0.14" - "@emotion/serialize" "^0.11.8" + "@emotion/serialize" "^0.11.10" "@emotion/sheet" "0.9.3" "@emotion/utils" "0.11.2" @@ -1436,40 +1147,40 @@ "@emotion/utils" "0.11.2" babel-plugin-emotion "^10.0.14" -"@emotion/hash@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.2.tgz#53211e564604beb9befa7a4400ebf8147473eeef" - integrity sha512-RMtr1i6E8MXaBWwhXL3yeOU8JXRnz8GNxHvaUfVvwxokvayUY0zoBeWbKw1S9XkufmGEEdQd228pSZXFkAln8Q== +"@emotion/hash@0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.3.tgz#a166882c81c0c6040975dd30df24fae8549bd96f" + integrity sha512-14ZVlsB9akwvydAdaEnVnvqu6J2P6ySv39hYyl/aoB6w/V+bXX0tay8cF6paqbgZsN2n5Xh15uF4pE+GvE+itw== "@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6": version "0.6.6" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44" integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ== -"@emotion/is-prop-valid@0.8.2": - version "0.8.2" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.2.tgz#b9692080da79041683021fcc32f96b40c54c59dc" - integrity sha512-ZQIMAA2kLUWiUeMZNJDTeCwYRx1l8SQL0kHktze4COT22occKpDML1GDUXP5/sxhOMrZO8vZw773ni4H5Snrsg== +"@emotion/is-prop-valid@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.3.tgz#cbe62ddbea08aa022cdf72da3971570a33190d29" + integrity sha512-We7VBiltAJ70KQA0dWkdPMXnYoizlxOXpvtjmu5/MBnExd+u0PGgV27WCYanmLAbCwAU30Le/xA0CQs/F/Otig== dependencies: - "@emotion/memoize" "0.7.2" + "@emotion/memoize" "0.7.3" -"@emotion/memoize@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30" - integrity sha512-hnHhwQzvPCW1QjBWFyBtsETdllOM92BfrKWbUTmh9aeOlcVOiXvlPsK4104xH8NsaKfg86PTFsWkueQeUfMA/w== +"@emotion/memoize@0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.3.tgz#5b6b1c11d6a6dddf1f2fc996f74cf3b219644d78" + integrity sha512-2Md9mH6mvo+ygq1trTeVp2uzAKwE2P7In0cRpD/M9Q70aH8L+rxMLbb3JCN2JoSWsV2O+DdFjfbbXoMoLBczow== "@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6": version "0.6.6" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b" integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ== -"@emotion/serialize@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.8.tgz#e41dcf7029e45286a3e0cf922933e670fe05402c" - integrity sha512-Qb6Us2Yk1ZW8SOYH6s5z7qzXXb2iHwVeqc6FjXtac0vvxC416ki0eTtHNw4Q5smoyxdyZh3519NKGrQvvvrZ/Q== +"@emotion/serialize@^0.11.10", "@emotion/serialize@^0.11.11", "@emotion/serialize@^0.11.8": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.11.tgz#c92a5e5b358070a7242d10508143306524e842a4" + integrity sha512-YG8wdCqoWtuoMxhHZCTA+egL0RSGdHEc+YCsmiSBPBEDNuVeMWtjEWtGrhUterSChxzwnWBXvzSxIFQI/3sHLw== dependencies: - "@emotion/hash" "0.7.2" - "@emotion/memoize" "0.7.2" + "@emotion/hash" "0.7.3" + "@emotion/memoize" "0.7.3" "@emotion/unitless" "0.7.4" "@emotion/utils" "0.11.2" csstype "^2.5.7" @@ -1489,23 +1200,23 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a" integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A== -"@emotion/styled-base@^10.0.14": - version "10.0.14" - resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.14.tgz#1b78a93e067ea852b2069339fcfd72c32ec91e4d" - integrity sha512-1nC5iO/Rk0DY47M5wXCyWpbo/woiwXWfVbNKDM3QRi7CKq8CwC++PQ5HgiYflFrAt1vjzIVZqnzrIn3idUoQgg== +"@emotion/styled-base@^10.0.17": + version "10.0.19" + resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.19.tgz#53655274797194d86453354fdb2c947b46032db6" + integrity sha512-Sz6GBHTbOZoeZQKvkE9gQPzaJ6/qtoQ/OPvyG2Z/6NILlYk60Es1cEcTgTkm26H8y7A0GSgp4UmXl+srvsnFPg== dependencies: - "@babel/runtime" "^7.4.3" - "@emotion/is-prop-valid" "0.8.2" - "@emotion/serialize" "^0.11.8" + "@babel/runtime" "^7.5.5" + "@emotion/is-prop-valid" "0.8.3" + "@emotion/serialize" "^0.11.11" "@emotion/utils" "0.11.2" "@emotion/styled@^10.0.7": - version "10.0.14" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.14.tgz#538bcf0d67bf8f6de946bcfbee53dc7d0187b346" - integrity sha512-Ae8d5N/FmjvZKXjqWcjfhZhjCdkvxZSqD95Q72BYDNQnsOKLHIA4vWlMolLXDNkw1dIxV3l2pp82Z87HXj6eYQ== + version "10.0.17" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.17.tgz#0cd38b8b36259541f2c6717fc22607a120623654" + integrity sha512-zHMgWjHDMNjD+ux64POtDnjLAObniu3znxFBLSdV/RiEhSLjHIowfvSbbd/C33/3uwtI6Uzs2KXnRZtka/PpAQ== dependencies: - "@emotion/styled-base" "^10.0.14" - babel-plugin-emotion "^10.0.14" + "@emotion/styled-base" "^10.0.17" + babel-plugin-emotion "^10.0.17" "@emotion/stylis@0.8.4": version "0.8.4" @@ -1537,10 +1248,10 @@ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc" integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw== -"@emotion/weak-memoize@0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.3.tgz#dfa0c92efe44a1d1a7974fb49ffeb40ef2da5a27" - integrity sha512-zVgvPwGK7c1aVdUVc9Qv7SqepOGRDrqCw7KZPSZziWGxSlbII3gmvGLPzLX4d0n0BMbamBacUrN22zOMyFFEkQ== +"@emotion/weak-memoize@0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" + integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== "@hapi/address@2.x.x": version "2.1.2" @@ -1553,9 +1264,9 @@ integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== "@hapi/hoek@8.x.x": - version "8.2.4" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.2.4.tgz#684a14f4ca35d46f44abc87dfc696e5e4fe8a020" - integrity sha512-Ze5SDNt325yZvNO7s5C4fXDscjJ6dcqLFXJQ/M7dZRQCewuDj2iDUuBi6jLQt+APbW9RjjVEvLr35FXuOEqjow== + version "8.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.3.0.tgz#2b9db1cd00f3891005c77b3a8d608b88a6d0aa4d" + integrity sha512-C0QL9bmgUXTSuf8nDeGrpMjtJG7tPUr8wG6/wxPbP62tGwCwQtdMSJYfESowmY4P3Hn593f+8OzNY5bckcu/LQ== "@hapi/joi@^15.0.3": version "15.1.1" @@ -1568,9 +1279,9 @@ "@hapi/topo" "3.x.x" "@hapi/topo@3.x.x": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.4.tgz#42e2fe36f593d90ad258a08b582be128c141c45d" - integrity sha512-aVWQTOI9wBD6zawmOr6f+tdEIxQC8JXfQVLTjgGe8YEStAWGn/GNNVTobKJhbWKveQj2RyYF3oYbO9SC8/eOCA== + version "3.1.5" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.5.tgz#3baea17e456530edad69a75c3fc7cde97dd6d331" + integrity sha512-bi9m1jrui9LlvtVdLaHv0DqeOoe+I8dep+nEcTgW6XxJHL3xArQcilYz3tIp0cRC4gWlsVtABK7vNKg4jzEmAA== dependencies: "@hapi/hoek" "8.x.x" @@ -1632,7 +1343,7 @@ "@jest/types" "^24.9.0" jest-mock "^24.9.0" -"@jest/fake-timers@^24", "@jest/fake-timers@^24.8.0", "@jest/fake-timers@^24.9.0": +"@jest/fake-timers@^24", "@jest/fake-timers@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== @@ -1677,7 +1388,7 @@ graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/test-result@^24.8.0", "@jest/test-result@^24.9.0": +"@jest/test-result@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== @@ -1718,7 +1429,7 @@ source-map "^0.6.1" write-file-atomic "2.4.1" -"@jest/types@^24", "@jest/types@^24.8.0", "@jest/types@^24.9.0": +"@jest/types@^24", "@jest/types@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== @@ -1744,67 +1455,52 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@nodelib/fs.scandir@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" - integrity sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg== +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== dependencies: - "@nodelib/fs.stat" "2.0.1" + "@nodelib/fs.stat" "2.0.3" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.1", "@nodelib/fs.stat@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz#814f71b1167390cfcb6a6b3d9cdeb0951a192c14" - integrity sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw== +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@nodelib/fs.walk@^1.2.1": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz#6a6450c5e17012abd81450eb74949a4d970d2807" - integrity sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== dependencies: - "@nodelib/fs.scandir" "2.1.1" + "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" "@octokit/endpoint@^5.1.0": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.1.2.tgz#45fd879e33a25ee10fa4cffc4d098ee04135afe6" - integrity sha512-bBGGmcRFq1x0jrB29G/9KjYmO3cdHfk3476B2JOHRvLsNw1Pn3l+ZvbiqtcO9qAS4Ti+zFedLB84ziHZRZclQA== + version "5.4.0" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.4.0.tgz#5b44b3e8e92d88765daf127e1501174ecbca7bce" + integrity sha512-DWTNgEKg5KXzvNjKTzcFTnkZiL7te6pQxxumvxPjyjDpcY5V3xzywnNu1WVqySY3Ct1flF/kAoyDdZos6acq3Q== dependencies: - deepmerge "3.2.0" is-plain-object "^3.0.0" - universal-user-agent "^2.1.0" - url-template "^2.0.8" + universal-user-agent "^4.0.0" "@octokit/request-error@^1.0.1", "@octokit/request-error@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.0.2.tgz#e6dbc5be13be1041ef8eca9225520982add574cf" - integrity sha512-T9swMS/Vc4QlfWrvyeSyp/GjhXtYaBzCcibjGywV4k4D2qVrQKfEMPy8OxMDEj7zkIIdpHwqdpVbKCvnUPqkXw== - dependencies: - deprecation "^2.0.0" - once "^1.4.0" - -"@octokit/request@^4.0.1": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-4.1.0.tgz#e85dc377113baf2fe24433af8feb20e8a32e21b0" - integrity sha512-RvpQAba4i+BNH0z8i0gPRc1ShlHidj4puQjI/Tno6s+Q3/Mzb0XRSHJiOhpeFrZ22V7Mwjq1E7QS27P5CgpWYA== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.0.4.tgz#15e1dc22123ba4a9a4391914d80ec1e5303a23be" + integrity sha512-L4JaJDXn8SGT+5G0uX79rZLv0MNJmfGa4vb4vy1NnpjSnWDLJRy6m90udGwvMmavwsStgbv2QNkPzzTCMmL+ig== dependencies: - "@octokit/endpoint" "^5.1.0" - "@octokit/request-error" "^1.0.1" deprecation "^2.0.0" - is-plain-object "^3.0.0" - node-fetch "^2.3.0" once "^1.4.0" - universal-user-agent "^2.1.0" "@octokit/request@^5.0.0": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.0.2.tgz#59a920451f24811c016ddc507adcc41aafb2dca5" - integrity sha512-z1BQr43g4kOL4ZrIVBMHwi68Yg9VbkRUyuAgqCp1rU3vbYa69+2gIld/+gHclw15bJWQnhqqyEb7h5a5EqgZ0A== + version "5.1.0" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.1.0.tgz#5609dcc7b5323e529f29d535214383d9eaf0c05c" + integrity sha512-I15T9PwjFs4tbWyhtFU2Kq7WDPidYMvRB7spmxoQRZfxSmiqullG+Nz+KbSmpkfnlvHwTr1e31R5WReFRKMXjg== dependencies: "@octokit/endpoint" "^5.1.0" "@octokit/request-error" "^1.0.1" @@ -1812,31 +1508,12 @@ is-plain-object "^3.0.0" node-fetch "^2.3.0" once "^1.4.0" - universal-user-agent "^3.0.0" - -"@octokit/rest@^16.13.1": - version "16.26.0" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.26.0.tgz#5c12b28763219045e1c9a15182e8dfaed10004e8" - integrity sha512-NBpzre44ZAQWZhlH+zUYTgqI0pHN+c9rNj4d+pCydGEiKTGc1HKmoTghEUyr9GxazDyoAvmpx9nL0I7QS1Olvg== - dependencies: - "@octokit/request" "^4.0.1" - "@octokit/request-error" "^1.0.2" - atob-lite "^2.0.0" - before-after-hook "^1.4.0" - btoa-lite "^1.0.0" - deprecation "^2.0.0" - lodash.get "^4.4.2" - lodash.set "^4.3.2" - lodash.uniq "^4.5.0" - octokit-pagination-methods "^1.1.0" - once "^1.4.0" - universal-user-agent "^2.0.0" - url-template "^2.0.8" + universal-user-agent "^4.0.0" "@octokit/rest@^16.27.0": - version "16.28.7" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.28.7.tgz#a2c2db5b318da84144beba82d19c1a9dbdb1a1fa" - integrity sha512-cznFSLEhh22XD3XeqJw51OLSfyL2fcFKUO+v2Ep9MTAFfFLS1cK1Zwd1yEgQJmJoDnj4/vv3+fGGZweG+xsbIA== + version "16.33.0" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.33.0.tgz#13c1404b24c9871419eb31029de177e82f3eb851" + integrity sha512-t4jMR+odsfooQwmHiREoTQixVTX2DfdbSaO+lKrW9R5XBuk0DW+5T/JdfwtxAGUAHgvDDpWY/NVVDfEPTzxD6g== dependencies: "@octokit/request" "^5.0.0" "@octokit/request-error" "^1.0.2" @@ -1849,8 +1526,7 @@ lodash.uniq "^4.5.0" octokit-pagination-methods "^1.1.0" once "^1.4.0" - universal-user-agent "^3.0.0" - url-template "^2.0.8" + universal-user-agent "^4.0.0" "@reach/router@^1.2.1": version "1.2.1" @@ -1873,22 +1549,10 @@ fs-extra "^8.0.0" lodash "^4.17.4" -"@semantic-release/commit-analyzer@^6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-6.1.0.tgz#32bbe3c23da86e23edf072fbb276fa2f383fcb17" - integrity sha512-2lb+t6muGenI86mYGpZYOgITx9L3oZYF697tJoqXeQEk0uw0fm+OkkOuDTBA3Oax9ftoNIrCKv9bwgYvxrbM6w== - dependencies: - conventional-changelog-angular "^5.0.0" - conventional-commits-filter "^2.0.0" - conventional-commits-parser "^3.0.0" - debug "^4.0.0" - import-from "^2.1.0" - lodash "^4.17.4" - -"@semantic-release/commit-analyzer@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-6.2.0.tgz#5cd25ce67ba9ba5b46e47457505e63629e186695" - integrity sha512-oUtPydYcbtJsEY6WCPi4wynTgRecK5zCkKaGmHi+9Xl7d6jGf7LomnJCg++6dNF1tyavrbGMSdXTCPH6Dx9LbA== +"@semantic-release/commit-analyzer@^6.1.0", "@semantic-release/commit-analyzer@^6.2.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-6.3.0.tgz#e0fb2f6af7be2321ad9401d8ae25be0cc1005d83" + integrity sha512-sh51MVlV8VyrvGIemcvzueDADX/8qGbAgce1F0CtQv8hNKYyhdaJeHzfiM1rNXwCynDmcQj+Yq9rrWt71tBd/Q== dependencies: conventional-changelog-angular "^5.0.0" conventional-commits-filter "^2.0.0" @@ -1918,33 +1582,10 @@ micromatch "^4.0.0" p-reduce "^2.0.0" -"@semantic-release/github@^5.1.0": - version "5.2.10" - resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-5.2.10.tgz#bf325f11685d59b864c8946d7d30fcb749d89e37" - integrity sha512-z/UwIxKb+EMiJDIy/57MBzJ80ar5H9GJQRyML/ILQ8dlrPwXs7cTyTvC7AesrF7t1mJZtg3ht9Qf9RdtR/LGzw== - dependencies: - "@octokit/rest" "^16.13.1" - "@semantic-release/error" "^2.2.0" - aggregate-error "^2.0.0" - bottleneck "^2.0.1" - debug "^4.0.0" - dir-glob "^2.0.0" - fs-extra "^7.0.0" - globby "^9.0.0" - http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - issue-parser "^3.0.0" - lodash "^4.17.4" - mime "^2.0.3" - p-filter "^1.0.0" - p-retry "^3.0.0" - parse-github-url "^1.0.1" - url-join "^4.0.0" - -"@semantic-release/github@^5.4.2": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-5.4.2.tgz#1dbde876228c03ff9a000893a18aff5c6ab2cd61" - integrity sha512-8gkOa5tED/+sjAPwZRYsLaGr6VuAGLZinSvLsuF9/l4qLeYV8gvj7fhjFJepGu6y31t7PR2J9SWzmsqsBAyyKQ== +"@semantic-release/github@^5.1.0", "@semantic-release/github@^5.4.2": + version "5.5.3" + resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-5.5.3.tgz#280f5c3d1cbcd469005b0858867d8ceb41c7bc8f" + integrity sha512-7Fl6LRYA20Wn440gPWB+uZ3A1slokKS47Kd4uxQnXt4t4lXYTMrg1tpzkY1FUQgsWqq8PFgoJ3lCPoo8JOQwKg== dependencies: "@octokit/rest" "^16.27.0" "@semantic-release/error" "^2.2.0" @@ -1955,8 +1596,8 @@ fs-extra "^8.0.0" globby "^10.0.0" http-proxy-agent "^2.1.0" - https-proxy-agent "^2.2.1" - issue-parser "^4.0.0" + https-proxy-agent "^3.0.0" + issue-parser "^5.0.0" lodash "^4.17.4" mime "^2.4.3" p-filter "^2.0.0" @@ -1964,59 +1605,27 @@ parse-github-url "^1.0.1" url-join "^4.0.0" -"@semantic-release/npm@^5.0.5": - version "5.1.7" - resolved "https://registry.yarnpkg.com/@semantic-release/npm/-/npm-5.1.7.tgz#ed3bac977d46294bfd11df7621bb5a9b6d5523be" - integrity sha512-4THiFGp9APX1a+EJJsOYurJCR8TrRUgNCU9u46AkZekWfvtyzacfIBKCrmEljpYG8qDDnHLZwHSqyW4ID4iteA== - dependencies: - "@semantic-release/error" "^2.2.0" - aggregate-error "^3.0.0" - execa "^1.0.0" - fs-extra "^7.0.0" - lodash "^4.17.4" - nerf-dart "^1.0.0" - normalize-url "^4.0.0" - npm "^6.8.0" - rc "^1.2.8" - read-pkg "^5.0.0" - registry-auth-token "^3.3.1" - -"@semantic-release/npm@^5.1.13": - version "5.1.13" - resolved "https://registry.yarnpkg.com/@semantic-release/npm/-/npm-5.1.13.tgz#7b06d62b4d9c8336ae5a5c85eede26fb89f19e3b" - integrity sha512-pONvpoEtGH1nd6Wj3SryACNJ/YXXsvSSekE9Pdk6mnaRv7lGhXdaeJJr6Lr4L8WK98oZv4aJOr68vTac2Oc+dA== +"@semantic-release/npm@^5.0.5", "@semantic-release/npm@^5.1.13": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@semantic-release/npm/-/npm-5.2.0.tgz#e5643c43ca5f3eb7db3d403fe12e44c187c5f9c6" + integrity sha512-+WUoFNTVn4saPLbIBd+fCXL9nP6c49iOyvjLqWNq4lh2/sLZg993MMTBVvTxHRaojxb42R2RjePsO5AaFM3Lzw== dependencies: "@semantic-release/error" "^2.2.0" aggregate-error "^3.0.0" - execa "^1.0.0" + execa "^2.0.2" fs-extra "^8.0.0" - lodash "^4.17.4" + lodash "^4.17.15" nerf-dart "^1.0.0" normalize-url "^4.0.0" - npm "^6.8.0" + npm "^6.10.3" rc "^1.2.8" read-pkg "^5.0.0" registry-auth-token "^4.0.0" -"@semantic-release/release-notes-generator@^7.1.2": - version "7.1.4" - resolved "https://registry.yarnpkg.com/@semantic-release/release-notes-generator/-/release-notes-generator-7.1.4.tgz#8f4f752c5a8385abdaac1256127cef05988bc2ad" - integrity sha512-pWPouZujddgb6t61t9iA9G3yIfp3TeQ7bPbV1ixYSeP6L7gI1+Du82fY/OHfEwyifpymLUQW0XnIKgKct5IMMw== - dependencies: - conventional-changelog-angular "^5.0.0" - conventional-changelog-writer "^4.0.0" - conventional-commits-filter "^2.0.0" - conventional-commits-parser "^3.0.0" - debug "^4.0.0" - get-stream "^4.0.0" - import-from "^2.1.0" - into-stream "^4.0.0" - lodash "^4.17.4" - -"@semantic-release/release-notes-generator@^7.2.1": - version "7.2.1" - resolved "https://registry.yarnpkg.com/@semantic-release/release-notes-generator/-/release-notes-generator-7.2.1.tgz#2c0c340e7be2a3d27c28cb869b6737a70f2862fe" - integrity sha512-TdlYgYH6amhE80i9L9HPcTwYzk4Rma7qM1g7XJEEfip7dNXWgmrBeibN4DJmTg/qrUFDd4GD86lFDcYXNZDNow== +"@semantic-release/release-notes-generator@^7.1.2", "@semantic-release/release-notes-generator@^7.2.1": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@semantic-release/release-notes-generator/-/release-notes-generator-7.3.0.tgz#b94f3d84d7071eb8e921b53a9729ca48722e7c0f" + integrity sha512-6ozBLHM9XZR6Z8PFSKssLtwBYc5l1WOnxj034F8051QOo3TMKDDPKwdj2Niyc+e7ru7tGa3Ftq7nfN0YnD6//A== dependencies: conventional-changelog-angular "^5.0.0" conventional-changelog-writer "^4.0.0" @@ -2399,10 +2008,10 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz#310ec0775de808a6a2e4fd4268c245fd734c1165" integrity sha512-U9m870Kqm0ko8beHawRXLGLvSi/ZMrl89gJ5BNcT452fAjtF2p4uRzXkdzvGJJJYBgx7BmqlDjBN/eCp5AAX2w== -"@svgr/babel-plugin-svg-dynamic-title@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.2.0.tgz#43f0f689a5347a894160eb51b39a109889a4df20" - integrity sha512-gH2qItapwCUp6CCqbxvzBbc4dh4OyxdYKsW3EOkYexr0XUmQL0ScbdNh6DexkZ01T+sdClniIbnCObsXcnx3sQ== +"@svgr/babel-plugin-svg-dynamic-title@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.3.3.tgz#2cdedd747e5b1b29ed4c241e46256aac8110dd93" + integrity sha512-w3Be6xUNdwgParsvxkkeZb545VhXEwjGMwExMVBIdPQJeyMQHqm9Msnb2a1teHBqUYL66qtwfhNkbj1iarCG7w== "@svgr/babel-plugin-svg-em-dimensions@^4.2.0": version "4.2.0" @@ -2419,69 +2028,67 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.2.0.tgz#5f1e2f886b2c85c67e76da42f0f6be1b1767b697" integrity sha512-hYfYuZhQPCBVotABsXKSCfel2slf/yvJY8heTVX1PCTaq/IgASq1IyxPPKJ0chWREEKewIU/JMSsIGBtK1KKxw== -"@svgr/babel-preset@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-4.2.0.tgz#c9fc236445a02a8cd4e750085e51c181de00d6c5" - integrity sha512-iLetHpRCQXfK47voAs5/uxd736cCyocEdorisjAveZo8ShxJ/ivSZgstBmucI1c8HyMF5tOrilJLoFbhpkPiKw== +"@svgr/babel-preset@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-4.3.3.tgz#a75d8c2f202ac0e5774e6bfc165d028b39a1316c" + integrity sha512-6PG80tdz4eAlYUN3g5GZiUjg2FMcp+Wn6rtnz5WJG9ITGEF1pmFdzq02597Hn0OmnQuCVaBYQE1OVFAnwOl+0A== dependencies: "@svgr/babel-plugin-add-jsx-attribute" "^4.2.0" "@svgr/babel-plugin-remove-jsx-attribute" "^4.2.0" "@svgr/babel-plugin-remove-jsx-empty-expression" "^4.2.0" "@svgr/babel-plugin-replace-jsx-attribute-value" "^4.2.0" - "@svgr/babel-plugin-svg-dynamic-title" "^4.2.0" + "@svgr/babel-plugin-svg-dynamic-title" "^4.3.3" "@svgr/babel-plugin-svg-em-dimensions" "^4.2.0" "@svgr/babel-plugin-transform-react-native-svg" "^4.2.0" "@svgr/babel-plugin-transform-svg-component" "^4.2.0" -"@svgr/core@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-4.2.0.tgz#f32ef8b9d05312aaa775896ec30ae46a6521e248" - integrity sha512-nvzXaf2VavqjMCTTfsZfjL4o9035KedALkMzk82qOlHOwBb8JT+9+zYDgBl0oOunbVF94WTLnvGunEg0csNP3Q== +"@svgr/core@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-4.3.3.tgz#b37b89d5b757dc66e8c74156d00c368338d24293" + integrity sha512-qNuGF1QON1626UCaZamWt5yedpgOytvLj5BQZe2j1k1B8DUG4OyugZyfEwBeXozCUwhLEpsrgPrE+eCu4fY17w== dependencies: - "@svgr/plugin-jsx" "^4.2.0" + "@svgr/plugin-jsx" "^4.3.3" camelcase "^5.3.1" - cosmiconfig "^5.2.0" + cosmiconfig "^5.2.1" -"@svgr/hast-util-to-babel-ast@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.2.0.tgz#dd743435a5f3a8e84a1da067f27b5fae3d7b6b63" - integrity sha512-IvAeb7gqrGB5TH9EGyBsPrMRH/QCzIuAkLySKvH2TLfLb2uqk98qtJamordRQTpHH3e6TORfBXoTo7L7Opo/Ow== +"@svgr/hast-util-to-babel-ast@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.3.2.tgz#1d5a082f7b929ef8f1f578950238f630e14532b8" + integrity sha512-JioXclZGhFIDL3ddn4Kiq8qEqYM2PyDKV0aYno8+IXTLuYt6TOgHUbUAAFvqtb0Xn37NwP0BTHglejFoYr8RZg== dependencies: - "@babel/types" "^7.4.0" + "@babel/types" "^7.4.4" -"@svgr/plugin-jsx@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-4.2.0.tgz#15a91562c9b5f90640ea0bdcb2ad59d692ee7ae9" - integrity sha512-AM1YokmZITgveY9bulLVquqNmwiFo2Px2HL+IlnTCR01YvWDfRL5QKdnF7VjRaS5MNP938mmqvL0/8oz3zQMkg== +"@svgr/plugin-jsx@^4.3.3": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-4.3.3.tgz#e2ba913dbdfbe85252a34db101abc7ebd50992fa" + integrity sha512-cLOCSpNWQnDB1/v+SUENHH7a0XY09bfuMKdq9+gYvtuwzC2rU4I0wKGFEp1i24holdQdwodCtDQdFtJiTCWc+w== dependencies: - "@babel/core" "^7.4.3" - "@svgr/babel-preset" "^4.2.0" - "@svgr/hast-util-to-babel-ast" "^4.2.0" - rehype-parse "^6.0.0" - unified "^7.1.0" - vfile "^4.0.0" + "@babel/core" "^7.4.5" + "@svgr/babel-preset" "^4.3.3" + "@svgr/hast-util-to-babel-ast" "^4.3.2" + svg-parser "^2.0.0" -"@svgr/plugin-svgo@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-4.2.0.tgz#2a594a2d3312955e75fd87dc77ae51f377c809f3" - integrity sha512-zUEKgkT172YzHh3mb2B2q92xCnOAMVjRx+o0waZ1U50XqKLrVQ/8dDqTAtnmapdLsGurv8PSwenjLCUpj6hcvw== +"@svgr/plugin-svgo@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-4.3.1.tgz#daac0a3d872e3f55935c6588dd370336865e9e32" + integrity sha512-PrMtEDUWjX3Ea65JsVCwTIXuSqa3CG9px+DluF1/eo9mlDrgrtFE7NE/DjdhjJgSM9wenlVBzkzneSIUgfUI/w== dependencies: - cosmiconfig "^5.2.0" + cosmiconfig "^5.2.1" merge-deep "^3.0.2" - svgo "^1.2.1" + svgo "^1.2.2" "@svgr/webpack@^4.0.3": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-4.2.0.tgz#b7cdef42ae671a27ed4cfe118a0f2da7f4e9ebed" - integrity sha512-sm3UUJHmRlqEg8w8bjUT+FAMf5lkgCydxotEapinpd10kzrpQP++Qd+bmuepE3hsIUU68BO24vgQALQ92qBZEw== + version "4.3.3" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-4.3.3.tgz#13cc2423bf3dff2d494f16b17eb7eacb86895017" + integrity sha512-bjnWolZ6KVsHhgyCoYRFmbd26p8XVbulCzSG53BDQqAr+JOAderYK7CuYrB3bDjHJuF6LJ7Wrr42+goLRV9qIg== dependencies: - "@babel/core" "^7.4.3" + "@babel/core" "^7.4.5" "@babel/plugin-transform-react-constant-elements" "^7.0.0" - "@babel/preset-env" "^7.4.3" + "@babel/preset-env" "^7.4.5" "@babel/preset-react" "^7.0.0" - "@svgr/core" "^4.2.0" - "@svgr/plugin-jsx" "^4.2.0" - "@svgr/plugin-svgo" "^4.2.0" + "@svgr/core" "^4.3.3" + "@svgr/plugin-jsx" "^4.3.3" + "@svgr/plugin-svgo" "^4.3.1" loader-utils "^1.2.3" "@types/babel__core@^7.1.0": @@ -2518,16 +2125,16 @@ "@babel/types" "^7.3.0" "@types/cheerio@*": - version "0.22.11" - resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.11.tgz#61c0facf9636d14ba5f77fc65ed8913aa845d717" - integrity sha512-x0X3kPbholdJZng9wDMhb2swvUi3UYRNAuWAmIPIWlfgAJZp//cql/qblE7181Mg7SjWVwq6ldCPCLn5AY/e7w== + version "0.22.13" + resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.13.tgz#5eecda091a24514185dcba99eda77e62bf6523e6" + integrity sha512-OZd7dCUOUkiTorf97vJKwZnSja/DmHfuBAroe1kREZZTCf/tlFecwHhsOos3uVHxeKGZDwzolIrCUApClkdLuA== dependencies: "@types/node" "*" "@types/classnames@^2.2.7": - version "2.2.7" - resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.7.tgz#fb68cc9be8487e6ea5b13700e759bfbab7e0fefd" - integrity sha512-rzOhiQ55WzAiFgXRtitP/ZUT8iVNyllEpylJ5zHzR4vArUvMB39GTk+Zon/uAM0JxEFAWnwsxC2gH8s+tZ3Myg== + version "2.2.9" + resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.9.tgz#d868b6febb02666330410fe7f58f3c4b8258be7b" + integrity sha512-MNl+rT5UmZeilaPxAVs6YaPC2m6aA8rofviZbhbxpPpl61uKodfdQVsBtgJGTqGizEf02oW3tsVe7FYB8kK14A== "@types/d3-array@^1.2.6": version "1.2.7" @@ -2576,9 +2183,9 @@ "@types/enzyme" "*" "@types/enzyme@*", "@types/enzyme@^3.9.0": - version "3.9.2" - resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.9.2.tgz#bfbbc5f89cf3092d01712d843ffade2bf5578c24" - integrity sha512-f8lXku9JIa6vReljhHmHqMvaRcabdJzuOOVoLGjQvoL4ikQu0aQaHMI4uR/BCStYcpSbktTov5GpL2iruHaykA== + version "3.10.3" + resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.3.tgz#02b6c5ac7d0472005944a652e79045e2f6c66804" + integrity sha512-f/Kcb84sZOSZiBPCkr4He9/cpuSLcKRyQaEE20Q30Prx0Dn6wcyMAWI0yofL6yvd9Ht9G7EVkQeRqK0n5w8ILw== dependencies: "@types/cheerio" "*" "@types/react" "*" @@ -2594,9 +2201,9 @@ integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== "@types/expect-puppeteer@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/expect-puppeteer/-/expect-puppeteer-3.3.1.tgz#46e5944bf425b86ea13a563c7c8b86901414988d" - integrity sha512-3raSnf28NelDtv0ksvQPZs410taJZ4d70vA8sVzmbRPV04fpmQm9/BOxUCloETD/ZI1EXRpv0pzOQKhPTbm4jg== + version "3.3.2" + resolved "https://registry.yarnpkg.com/@types/expect-puppeteer/-/expect-puppeteer-3.3.2.tgz#246f91e5907ddcfabc2f146408a1f99c8d24c3b5" + integrity sha512-WRxRC9kn+ItWL+Ar/oRHwkdjM50ujJbyhrYknwZu2vetE28Eh9RqurAgn1jtyFpfi9bL3pXDUQSrXtDENmda2w== dependencies: "@types/jest" "*" "@types/puppeteer" "*" @@ -2610,6 +2217,14 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -2665,20 +2280,15 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== -"@types/lodash@^4.14.116": - version "4.14.132" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.132.tgz#8ce45ca8745ff2e004fac0de0ab46f61e390ffa0" - integrity sha512-RNUU1rrh85NgUJcjOOr96YXr+RHwInGbaQCZmlitqOaCKXffj8bh+Zxwuq5rjDy5OgzFldDVoqk4pyLEDiwxIw== - -"@types/lodash@^4.14.121": - version "4.14.130" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.130.tgz#04b3a690d5f4fc34579963c99adae067b8c8eb5a" - integrity sha512-H++wk0tbneBsRVfLkgAAd0IIpmpVr2Bj4T0HncoOsQf3/xrJexRYQK2Tqo0Ej3pFslM8GkMgdis9bu6xIb1ycw== +"@types/lodash@^4.14.116", "@types/lodash@^4.14.121": + version "4.14.144" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.144.tgz#12e57fc99064bce45e5ab3c8bc4783feb75eab8e" + integrity sha512-ogI4g9W5qIQQUhXAclq6zhqgqNUr7UlFaqDHbch7WLSLeeM/7d3CRaw7GLajxvyFvhJqw4Rpcz5bhoaYtIx6Tg== "@types/luxon@^1.11.1": - version "1.13.0" - resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.13.0.tgz#e92338702d0b1b96e8d5ea6fe39d9938891aacd0" - integrity sha512-XmDiRVoJWgVdqX9x1a/GU4p9bSgZY7q8SOyMLs3fx1AdQcxLYAPIt/jfZm2e+PBVRWuEx1FqYNJ37kBZ53TMqA== + version "1.15.2" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.15.2.tgz#528f11f7d6dc08cec0445d4bea8065a5bb6989b2" + integrity sha512-zHPoyVrLvNaiMRYdhmh88Rn489ZgAgbc6iLxR5Yi0VCNfeNYHcszbhJV2vDHLNrVGy35BPtWBRn4OP2F9BBvFw== "@types/minimatch@*", "@types/minimatch@^3.0.3": version "3.0.3" @@ -2693,9 +2303,9 @@ moment ">=2.14.0" "@types/node@*": - version "12.0.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.2.tgz#3452a24edf9fea138b48fad4a0a028a683da1e40" - integrity sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA== + version "12.12.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11" + integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w== "@types/node@^12.0.2": version "12.6.8" @@ -2713,14 +2323,14 @@ integrity sha512-ShHzHkYD+Ldw3eyttptCpUhF1/mkInWwasQkCNXZHOsJMJ/UMa8wXrxSrTJaVk0r4pLK/VnESVM0wFsfQzNEKQ== "@types/prop-types@*": - version "15.7.1" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.1.tgz#f1a11e7babb0c3cad68100be381d1e064c68f1f6" - integrity sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg== + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== "@types/puppeteer@*", "@types/puppeteer@^1.19.1": - version "1.19.1" - resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-1.19.1.tgz#942ca62288953a0f5fbbc25c103b5f2ba28b60ab" - integrity sha512-ReWZvoEfMiJIA3AG+eM+nCx5GKrU2ANVYY5TC0nbpeiTCtnJbcqnmBbR8TkXMBTvLBYcuTOAELbTcuX73siDNQ== + version "1.20.1" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-1.20.1.tgz#0aba5ae3d290daa91cd3ba9f66ba5e9fba3499cc" + integrity sha512-F91CqYDHETg3pQfIPNBNZKmi7R1xS1y4yycOYX7o6Xk16KF+IV+9LqTmVuG+FIxw/53/JEy94zKjjGjg92V6bg== dependencies: "@types/node" "*" @@ -2730,23 +2340,33 @@ integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== "@types/react-beautiful-dnd@^10.1.0": - version "10.1.2" - resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-10.1.2.tgz#74069f7b1d0cb67b7af99a2584b30e496e545d8b" - integrity sha512-76M5VRbhduUarM9wyMWQm3tLKCVMKTlhG0+W67dteg/HBE+kueIwuyLWzE0m5fmuilvrDXoM5NL890KLnHETZw== + version "10.1.3" + resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-10.1.3.tgz#a558eba3f807582a2e1d2db1bcca975525e7c331" + integrity sha512-VTbrLV4vIBgTRl6AIpY4vvZGHb6vEQypNAdmCG8+OZ0uvwEmPccRY5a4Qxvn4EgKi7wE4dBdCeWYrniuJ75R0A== dependencies: "@types/react" "*" "@types/react-dom@^16.8.2": - version "16.8.4" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.4.tgz#7fb7ba368857c7aa0f4e4511c4710ca2c5a12a88" - integrity sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA== + version "16.9.1" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.1.tgz#79206237cba9532a9f870b1cd5428bef6b66378c" + integrity sha512-1S/akvkKr63qIUWVu5IKYou2P9fHLb/P2VAwyxVV85JGaGZTcUniMiTuIqM3lXFB25ej6h+CYEQ27ERVwi6eGA== + dependencies: + "@types/react" "*" + +"@types/react-redux@^7.1.1": + version "7.1.4" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.4.tgz#e0d02a073e730b8b58a6341bddca2ea692ff0bce" + integrity sha512-SUV/7d+4L7C1Db/D4pqASgN1V1U2HnDEhEol9lYpPSguS76xFboZzf5ha2hTz6v31cUewyC7WksMh1q8JxhebQ== dependencies: + "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" "@types/react@*", "@types/react@^16.8.5": - version "16.8.18" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.18.tgz#fe66fb748b0b6ca9709d38b87b2d1356d960a511" - integrity sha512-lUXdKzRqWR4FebR5tGHkLCqnvQJS4fdXKCBrNGGbglqZg2gpU+J82pMONevQODUotATs9fc9k66bx3/St8vReg== + version "16.9.5" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.5.tgz#079dabd918b19b32118c25fd00a786bb6d0d5e51" + integrity sha512-jQ12VMiFOWYlp+j66dghOWcmDDwhca0bnlcTxS4Qz/fh5gi6wpaZDthPEu/Gc/YlAuO87vbiUXL8qKstFvuOaA== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -2762,9 +2382,9 @@ integrity sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA== "@types/semver@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.1.tgz#a984b405c702fa5a7ec6abc56b37f2ba35ef5af6" - integrity sha512-ffCdcrEE5h8DqVxinQjo+2d1q+FV5z7iNtPofw3JsrltSoSVlOGaW0rY8XxtO9XukdTn8TaCGWmk2VFGhI70mg== + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.2.tgz#5e8b09f0e4af53034b1d0fb9977a277847836205" + integrity sha512-G1Ggy7/9Nsa1Jt2yiBR2riEuyK2DFNnqow6R7cromXPMNynackRY1vqFTLz/gwnef1LHokbXThcPhqMRjUbkpQ== "@types/stack-utils@^1.0.1": version "1.0.1" @@ -2784,23 +2404,15 @@ "@types/react" "*" "@types/storybook__react" "*" -"@types/storybook__addon-knobs@^5.0.3": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@types/storybook__addon-knobs/-/storybook__addon-knobs-5.0.3.tgz#a6366877d7b21f9fa2cc9eb23650304388393350" - integrity sha512-NnSOu4ajk4kL1e1eRe9zzyspIghgFu8B9ELyrAl1jF/nJE26YK2oDTi7qr+k/+X33rNaYFo6e7+lsEqeI3MLXg== +"@types/storybook__addon-knobs@5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/storybook__addon-knobs/-/storybook__addon-knobs-5.0.4.tgz#8d29b295459279a7a8e91cf2fffc99a3727258ea" + integrity sha512-B43R3SWGjQe/dyGpzjjCLloMBcxhHUtLOYv1EwIEiCBaZrz8h4ItdHA3yMX3GO6L6MyH9BVhNUUc9QzdfnyyjQ== dependencies: "@types/react" "*" "@types/storybook__react" "*" -"@types/storybook__react@*": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/storybook__react/-/storybook__react-4.0.1.tgz#b6320c9d027b8ee7ef1445fef8b4cba196d48ace" - integrity sha512-knkZErqv8Iy2QbebqBa5tsy2itIMKdO6bcQ7C19nmgTc+j1pnQhXCGcVyARzAQ1/NAuSYudSWQAKG+plgK7hyQ== - dependencies: - "@types/react" "*" - "@types/webpack-env" "*" - -"@types/storybook__react@^4.0.2": +"@types/storybook__react@*", "@types/storybook__react@^4.0.2": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/storybook__react/-/storybook__react-4.0.2.tgz#f36fb399574c662e79c1a0cf6e429b6ff730da40" integrity sha512-U/+J5qccRdKFryvHkk1a0IeZaSIZLCmTwAQhTSDGeC3SPNIYPus+EtunBqP49r870l8czbfxtjeC3IL9P66ngQ== @@ -2808,44 +2420,22 @@ "@types/react" "*" "@types/webpack-env" "*" -"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" - integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== - "@types/url-parse@^1.4.3": version "1.4.3" resolved "https://registry.yarnpkg.com/@types/url-parse/-/url-parse-1.4.3.tgz#fba49d90f834951cb000a674efee3d6f20968329" integrity sha512-4kHAkbV/OfW2kb5BLVUuUMoumB3CP8rHqlw48aHvFy5tf9ER0AfOonBlX29l/DD68G70DmyhRlSYfQPSYpC5Vw== "@types/uuid@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5" - integrity sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw== - dependencies: - "@types/node" "*" - -"@types/vfile-message@*": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a" - integrity sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA== - dependencies: - "@types/node" "*" - "@types/unist" "*" - -"@types/vfile@^3.0.0": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-3.0.2.tgz#19c18cd232df11ce6fa6ad80259bc86c366b09b9" - integrity sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw== + version "3.4.5" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.5.tgz#d4dc10785b497a1474eae0ba7f0cb09c0ddfd6eb" + integrity sha512-MNL15wC3EKyw1VLF+RoVO4hJJdk9t/Hlv3rt1OL65Qvuadm4BYo6g9ZJQqoq7X8NBFSsQXgAujWciovh2lpVjA== dependencies: "@types/node" "*" - "@types/unist" "*" - "@types/vfile-message" "*" "@types/webpack-env@*": - version "1.13.9" - resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a" - integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg== + version "1.14.0" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.14.0.tgz#8edfc5f8e6eae20eeed3ca0d02974ed4ee5e4efc" + integrity sha512-Fv+0gYJzE/czLoRKq+gnXWr4yBpPM3tO3C8pDLFwqVKlMICQUq5OsxwwFZYDaVr7+L6mgNDp16iOcJHEz3J5RQ== "@types/yargs-parser@*": version "13.1.0" @@ -2860,39 +2450,56 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^2.3.2": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.3.2.tgz#7e112ca0bb29044d915baf10163a8199a20f7c69" - integrity sha512-tcnpksq1bXzcIRbYLeXkgp6l+ggEMXXUcl1wsSvL807fRtmvVQKygElwEUf4hBA76dNag3VAK1q2m3vd7qJaZA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.3.3.tgz#71e06c6887650301e02105c99b4c8f67454157e3" + integrity sha512-12cCbwu5PbQudkq2xCIS/QhB7hCMrsNPXK+vJtqy/zFqtzVkPRGy12O5Yy0gUK086f3VHV/P4a4R4CjMW853pA== dependencies: - "@typescript-eslint/experimental-utils" "2.3.2" + "@typescript-eslint/experimental-utils" "2.3.3" eslint-utils "^1.4.2" functional-red-black-tree "^1.0.1" regexpp "^2.0.1" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.3.2": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.3.2.tgz#e50f31264507e6fec7b33840bb6af260c24f4ea8" - integrity sha512-t+JGdTT6dRbmvKDlhlVkEueoZa0fhJNfG6z2cpnRPLwm3VwYr2BjR//acJGC1Yza0I9ZNcDfRY7ubQEvvfG6Jg== +"@typescript-eslint/experimental-utils@2.3.3": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.3.3.tgz#0685613063ff397cfa9209be2e6e81c0382a9b11" + integrity sha512-MQ4jKPMTU1ty4TigJCRKFPye2qyQdH8jzIIkceaHgecKFmkNS1hXPqKiZ+mOehkz6+HcN5Nuvwm+frmWZR9tdg== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.3.2" + "@typescript-eslint/typescript-estree" "2.3.3" eslint-scope "^5.0.0" +"@typescript-eslint/experimental-utils@^1.13.0": + version "1.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz#b08c60d780c0067de2fb44b04b432f540138301e" + integrity sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "1.13.0" + eslint-scope "^4.0.0" + "@typescript-eslint/parser@^2.3.2": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.3.2.tgz#e9b742e191cd1209930da469cde379591ad0af5b" - integrity sha512-nq1UQeNGdKdqdgF6Ww+Ov2OidWgiL96+JYdXXZ2rkP/OWyc6KMNSbs6MpRCpI8q+PmDa7hBnHNQIo7w/drYccA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.3.3.tgz#af519d6572bdee3e9610e21c8362766858976bc1" + integrity sha512-+cV53HuYFeeyrNW8x/rgPmbVrzzp/rpRmwbJnNtwn4K8mroL1BdjxwQh7X9cUHp9rm4BBiEWmD3cSBjKG7d5mw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.3.2" - "@typescript-eslint/typescript-estree" "2.3.2" + "@typescript-eslint/experimental-utils" "2.3.3" + "@typescript-eslint/typescript-estree" "2.3.3" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.3.2": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.3.2.tgz#107414aa04e689fe6f7251eb63fb500217f2b7f4" - integrity sha512-eZNEAai16nwyhIVIEaWQlaUgAU3S9CkQ58qvK0+3IuSdLJD3W1PNuehQFMIhW/mTP1oFR9GNoTcLg7gtXz6lzA== +"@typescript-eslint/typescript-estree@1.13.0": + version "1.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz#8140f17d0f60c03619798f1d628b8434913dc32e" + integrity sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw== + dependencies: + lodash.unescape "4.0.1" + semver "5.5.0" + +"@typescript-eslint/typescript-estree@2.3.3": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.3.3.tgz#be802220876bedfb80384cde1d46fe57ae7abf71" + integrity sha512-GkACs12Xp8d/STunNv/iSMYJFQrkrax9vuPZySlgSzoJJtw1cp6tbEw4qsLskQv6vloLrkFJHcTJ0a/yCB5cIA== dependencies: glob "^7.1.4" is-glob "^4.0.1" @@ -3093,12 +2700,7 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - -acorn-globals@^4.1.0: +acorn-globals@^4.1.0, acorn-globals@^4.3.0: version "4.3.4" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== @@ -3106,18 +2708,10 @@ acorn-globals@^4.1.0: acorn "^6.0.1" acorn-walk "^6.0.1" -acorn-globals@^4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.2.tgz#4e2c2313a597fd589720395f6354b41cd5ec8006" - integrity sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ== - dependencies: - acorn "^6.0.1" - acorn-walk "^6.0.1" - acorn-jsx@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== + version "5.0.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" + integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== acorn-walk@^6.0.1: version "6.2.0" @@ -3129,32 +2723,24 @@ acorn@^5.5.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1: +acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.7, acorn@^6.2.1: version "6.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== -acorn@^6.0.4, acorn@^6.0.5, acorn@^6.0.7: - version "6.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" - integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== - -acorn@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" - integrity sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q== - -address@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" - integrity sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg== +address@1.1.2, address@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== -address@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.0.tgz#ef8e047847fcd2c5b6f50c16965f924fd99fe709" - integrity sha512-4diPfzWbLEIElVG4AnqP+00SULlPzNuyJFNnmMrLgyaxG6tZXJ1sn7mjBu4fHrJE+Yp/jgylOweJn2xsLMFggQ== +agent-base@4, agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" -agent-base@4, agent-base@^4.1.0, agent-base@~4.2.1: +agent-base@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== @@ -3168,21 +2754,13 @@ agentkeepalive@^3.4.1: dependencies: humanize-ms "^1.2.1" -aggregate-error@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-2.2.0.tgz#f54b464db18cc77c907ae084451f39134707134a" - integrity sha512-E5n+IZkhh22/pFdUvHUU/o9z752lc+7tgHt+FXS/g6BjlbE9249dGmuS/SxIWMPhTljZJkFN+7OXE0+O5+WT8w== - dependencies: - clean-stack "^2.0.0" - indent-string "^3.0.0" - aggregate-error@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.0.tgz#5b5a3c95e9095f311c9ab16c19fb4f3527cd3f79" - integrity sha512-yKD9kEoJIR+2IFqhMwayIBgheLYbB3PS2OBhWae1L/ODTd/JF/30cW0bc9TqzRL3k4U41Dieu3BF4I29p8xesA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== dependencies: clean-stack "^2.0.0" - indent-string "^3.2.0" + indent-string "^4.0.0" "airbnb-js-shims@^1 || ^2": version "2.2.0" @@ -3208,12 +2786,12 @@ aggregate-error@^3.0.0: symbol.prototype.description "^1.0.0" airbnb-prop-types@^2.13.2: - version "2.13.2" - resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz#43147a5062dd2a4a5600e748a47b64004cc5f7fc" - integrity sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ== + version "2.15.0" + resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz#5287820043af1eb469f5b0af0d6f70da6c52aaef" + integrity sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA== dependencies: - array.prototype.find "^2.0.4" - function.prototype.name "^1.1.0" + array.prototype.find "^2.1.0" + function.prototype.name "^1.1.1" has "^1.0.3" is-regex "^1.0.4" object-is "^1.0.1" @@ -3221,29 +2799,19 @@ airbnb-prop-types@^2.13.2: object.entries "^1.1.0" prop-types "^15.7.2" prop-types-exact "^1.2.0" - react-is "^16.8.6" + react-is "^16.9.0" ajv-errors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== -ajv-keywords@^3.1.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" - integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== - -ajv@^6.1.0, ajv@^6.1.1, ajv@^6.9.1: - version "6.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" - integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" + integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@^6.5.5: +ajv@^6.1.0, ajv@^6.1.1, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== @@ -3402,11 +2970,6 @@ array-filter@^1.0.0: resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= -array-filter@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" - integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= - array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" @@ -3435,16 +2998,6 @@ array-includes@^3.0.3: define-properties "^1.1.2" es-abstract "^1.7.0" -array-map@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" - integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI= - -array-reduce@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" - integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= - array-union@^1.0.1, array-union@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -3472,13 +3025,13 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.find@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.4.tgz#556a5c5362c08648323ddaeb9de9d14bc1864c90" - integrity sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA= +array.prototype.find@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.0.tgz#630f2eaf70a39e608ac3573e45cf8ccd0ede9ad7" + integrity sha512-Wn41+K1yuO5p7wRZDl7890c3xvv5UBrfVXTVIe28rSQb6LS0fZMDrQB6PAcxQFRFy6vJTLDc3A2+3CjQdzVKRg== dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" + define-properties "^1.1.3" + es-abstract "^1.13.0" array.prototype.flat@^1.2.1: version "1.2.1" @@ -3577,17 +3130,12 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - -async@^2.1.4: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== +async@^2.1.4, async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== dependencies: - lodash "^4.17.11" + lodash "^4.17.14" asynckit@^0.4.0: version "0.4.0" @@ -3605,17 +3153,17 @@ atob@^2.1.1: integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== autoprefixer@^9.4.9, autoprefixer@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47" - integrity sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw== + version "9.6.4" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.4.tgz#e6453be47af316b2923eaeaed87860f52ad4b7eb" + integrity sha512-Koz2cJU9dKOxG8P1f8uVaBntOv9lP4yz9ffWvWaicv9gHBPhpQB22nGijwd8gqW9CNT+UdkbQOQNLVI8jN1ZfQ== dependencies: - browserslist "^4.6.3" - caniuse-lite "^1.0.30000980" + browserslist "^4.7.0" + caniuse-lite "^1.0.30000998" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.17" - postcss-value-parser "^4.0.0" + postcss "^7.0.18" + postcss-value-parser "^4.0.2" aws-sign2@~0.7.0: version "0.7.0" @@ -3699,29 +3247,22 @@ babel-plugin-add-react-displayname@^0.0.5: resolved "https://registry.yarnpkg.com/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz#339d4cddb7b65fd62d1df9db9fe04de134122bd5" integrity sha1-M51M3be2X9YtHfnbn+BN4TQSK9U= -babel-plugin-dynamic-import-node@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz#c0adfb07d95f4a4495e9aaac6ec386c4d7c2524e" - integrity sha512-fP899ELUnTaBcIzmrW7nniyqqdYWrWuJUyPWHxFa/c7r7hS6KC8FscNfLlBNIoPSc55kYMGEEKjPjJGCLbE1qA== - dependencies: - object.assign "^4.1.0" - -babel-plugin-dynamic-import-node@^2.3.0: +babel-plugin-dynamic-import-node@2.3.0, babel-plugin-dynamic-import-node@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== dependencies: object.assign "^4.1.0" -babel-plugin-emotion@^10.0.14, babel-plugin-emotion@^10.0.9: - version "10.0.14" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.14.tgz#c1d0e4621e303507ea7da57daa3cd771939d6df4" - integrity sha512-T7hdxJ4xXkKW3OXcizK0pnUJlBeNj/emjQZPDIZvGOuwl2adIgicQWRNkz6BuwKdDTrqaXQn1vayaL6aL8QW5A== +babel-plugin-emotion@^10.0.14, babel-plugin-emotion@^10.0.17, babel-plugin-emotion@^10.0.9: + version "10.0.21" + resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.21.tgz#9ebeb12edeea3e60a5476b0e07c9868605e65968" + integrity sha512-03o+T6sfVAJhNDcSdLapgv4IeewcFPzxlvBUVdSf7o5PI57ZSxoDvmy+ZulVWSu+rOWAWkEejNcsb29TuzJHbg== dependencies: "@babel/helper-module-imports" "^7.0.0" - "@emotion/hash" "0.7.2" - "@emotion/memoize" "0.7.2" - "@emotion/serialize" "^0.11.8" + "@emotion/hash" "0.7.3" + "@emotion/memoize" "0.7.3" + "@emotion/serialize" "^0.11.11" babel-plugin-macros "^2.0.0" babel-plugin-syntax-jsx "^6.18.0" convert-source-map "^1.5.0" @@ -3764,16 +3305,7 @@ babel-plugin-jest-hoist@^24.9.0: dependencies: "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.5.1.tgz#4a119ac2c2e19b458c259b9accd7ee34fd57ec6f" - integrity sha512-xN3KhAxPzsJ6OQTktCanNpIFnnMsCV+t8OloKxIL72D6+SUZYFn9qfklPgef5HyyDtzYZqqb+fs1S12+gQY82Q== - dependencies: - "@babel/runtime" "^7.4.2" - cosmiconfig "^5.2.0" - resolve "^1.10.0" - -babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.4.5: +babel-plugin-macros@2.6.1, babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.4.5: version "2.6.1" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.6.1.tgz#41f7ead616fc36f6a93180e89697f69f51671181" integrity sha512-6W2nwiXme6j1n2erPOnmRiWfObUhWH7Qw1LMi9XZy8cj+KtESu3T6asZvtk5bMQQjX8te35o7CFueiSdL/2NmQ== @@ -3794,15 +3326,15 @@ babel-plugin-minify-constant-folding@^0.5.0: dependencies: babel-helper-evaluate-path "^0.5.0" -babel-plugin-minify-dead-code-elimination@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.0.tgz#d23ef5445238ad06e8addf5c1cf6aec835bcda87" - integrity sha512-XQteBGXlgEoAKc/BhO6oafUdT4LBa7ARi55mxoyhLHNuA+RlzRmeMAfc31pb/UqU01wBzRc36YqHQzopnkd/6Q== +babel-plugin-minify-dead-code-elimination@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz#1a0c68e44be30de4976ca69ffc535e08be13683f" + integrity sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg== dependencies: babel-helper-evaluate-path "^0.5.0" babel-helper-mark-eval-scopes "^0.4.3" babel-helper-remove-or-void "^0.4.3" - lodash.some "^4.6.0" + lodash "^4.17.11" babel-plugin-minify-flip-comparisons@^0.4.3: version "0.4.3" @@ -3811,11 +3343,12 @@ babel-plugin-minify-flip-comparisons@^0.4.3: dependencies: babel-helper-is-void-0 "^0.4.3" -babel-plugin-minify-guarded-expressions@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.3.tgz#cc709b4453fd21b1f302877444c89f88427ce397" - integrity sha1-zHCbRFP9IbHzAod0RMifiEJ845c= +babel-plugin-minify-guarded-expressions@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz#818960f64cc08aee9d6c75bec6da974c4d621135" + integrity sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA== dependencies: + babel-helper-evaluate-path "^0.5.0" babel-helper-flip-expressions "^0.4.3" babel-plugin-minify-infinity@^0.4.3: @@ -3840,11 +3373,12 @@ babel-plugin-minify-replace@^0.5.0: resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz#d3e2c9946c9096c070efc96761ce288ec5c3f71c" integrity sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q== -babel-plugin-minify-simplify@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.0.tgz#1f090018afb90d8b54d3d027fd8a4927f243da6f" - integrity sha512-TM01J/YcKZ8XIQd1Z3nF2AdWHoDsarjtZ5fWPDksYZNsoOjQ2UO2EWm824Ym6sp127m44gPlLFiO5KFxU8pA5Q== +babel-plugin-minify-simplify@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz#f21613c8b95af3450a2ca71502fdbd91793c8d6a" + integrity sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A== dependencies: + babel-helper-evaluate-path "^0.5.0" babel-helper-flip-expressions "^0.4.3" babel-helper-is-nodes-equiv "^0.0.1" babel-helper-to-multiple-sequence-expressions "^0.5.0" @@ -3857,9 +3391,9 @@ babel-plugin-minify-type-constructors@^0.4.3: babel-helper-is-void-0 "^0.4.3" babel-plugin-named-asset-import@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.2.tgz#20978ed446b8e1bf4a2f42d0a94c0ece85f75f4f" - integrity sha512-CxwvxrZ9OirpXQ201Ec57OmGhmI8/ui/GwTDy0hSp6CmRvgRC0pSair6Z04Ck+JStA0sMPZzSJ3uE4n17EXpPQ== + version "0.3.4" + resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.4.tgz#4a8fc30e9a3e2b1f5ed36883386ab2d84e1089bd" + integrity sha512-S6d+tEzc5Af1tKIMbsf2QirCcPdQ+mKUCY2H1nJj1DyA1ShwpsoxEOAwbWsG5gcXNV/olpvQd9vrUWRx4bnhpw== babel-plugin-react-docgen@^3.0.0: version "3.1.0" @@ -3957,20 +3491,20 @@ babel-preset-jest@^24.9.0: babel-plugin-jest-hoist "^24.9.0" "babel-preset-minify@^0.5.0 || 0.6.0-alpha.5": - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.5.0.tgz#e25bb8d3590087af02b650967159a77c19bfb96b" - integrity sha512-xj1s9Mon+RFubH569vrGCayA9Fm2GMsCgDRm1Jb8SgctOB7KFcrVc2o8K3YHUyMz+SWP8aea75BoS8YfsXXuiA== + version "0.5.1" + resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz#25f5d0bce36ec818be80338d0e594106e21eaa9f" + integrity sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg== dependencies: babel-plugin-minify-builtins "^0.5.0" babel-plugin-minify-constant-folding "^0.5.0" - babel-plugin-minify-dead-code-elimination "^0.5.0" + babel-plugin-minify-dead-code-elimination "^0.5.1" babel-plugin-minify-flip-comparisons "^0.4.3" - babel-plugin-minify-guarded-expressions "^0.4.3" + babel-plugin-minify-guarded-expressions "^0.4.4" babel-plugin-minify-infinity "^0.4.3" babel-plugin-minify-mangle-names "^0.5.0" babel-plugin-minify-numeric-literals "^0.4.3" babel-plugin-minify-replace "^0.5.0" - babel-plugin-minify-simplify "^0.5.0" + babel-plugin-minify-simplify "^0.5.1" babel-plugin-minify-type-constructors "^0.4.3" babel-plugin-transform-inline-consecutive-adds "^0.4.3" babel-plugin-transform-member-expression-literals "^6.9.4" @@ -3983,30 +3517,28 @@ babel-preset-jest@^24.9.0: babel-plugin-transform-remove-undefined "^0.5.0" babel-plugin-transform-simplify-comparison-operators "^6.9.4" babel-plugin-transform-undefined-to-void "^6.9.4" - lodash.isplainobject "^4.0.6" + lodash "^4.17.11" babel-preset-react-app@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-9.0.0.tgz#703108142bc9dd7173bde6a1a0138a762abc76f9" - integrity sha512-YVsDA8HpAKklhFLJtl9+AgaxrDaor8gGvDFlsg1ByOS0IPGUovumdv4/gJiAnLcDmZmKlH6+9sVOz4NVW7emAg== - dependencies: - "@babel/core" "7.4.3" - "@babel/plugin-proposal-class-properties" "7.4.0" - "@babel/plugin-proposal-decorators" "7.4.0" - "@babel/plugin-proposal-object-rest-spread" "7.4.3" + version "9.0.2" + resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-9.0.2.tgz#247d37e883d6d6f4b4691e5f23711bb2dd80567d" + integrity sha512-aXD+CTH8Chn8sNJr4tO/trWKqe5sSE4hdO76j9fhVezJSzmpWYWUSc5JoPmdSxADwef5kQFNGKXd433vvkd2VQ== + dependencies: + "@babel/core" "7.6.0" + "@babel/plugin-proposal-class-properties" "7.5.5" + "@babel/plugin-proposal-decorators" "7.6.0" + "@babel/plugin-proposal-object-rest-spread" "7.5.5" "@babel/plugin-syntax-dynamic-import" "7.2.0" - "@babel/plugin-transform-classes" "7.4.3" - "@babel/plugin-transform-destructuring" "7.4.3" - "@babel/plugin-transform-flow-strip-types" "7.4.0" - "@babel/plugin-transform-react-constant-elements" "7.2.0" + "@babel/plugin-transform-destructuring" "7.6.0" + "@babel/plugin-transform-flow-strip-types" "7.4.4" "@babel/plugin-transform-react-display-name" "7.2.0" - "@babel/plugin-transform-runtime" "7.4.3" - "@babel/preset-env" "7.4.3" + "@babel/plugin-transform-runtime" "7.6.0" + "@babel/preset-env" "7.6.0" "@babel/preset-react" "7.0.0" - "@babel/preset-typescript" "7.3.3" - "@babel/runtime" "7.4.3" - babel-plugin-dynamic-import-node "2.2.0" - babel-plugin-macros "2.5.1" + "@babel/preset-typescript" "7.6.0" + "@babel/runtime" "7.6.0" + babel-plugin-dynamic-import-node "2.3.0" + babel-plugin-macros "2.6.1" babel-plugin-transform-react-remove-prop-types "0.4.24" babel-runtime@^6.18.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: @@ -4033,9 +3565,9 @@ balanced-match@^1.0.0: integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== base@^0.11.1: version "0.11.2" @@ -4062,11 +3594,6 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -before-after-hook@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-1.4.0.tgz#2b6bf23dca4f32e628fd2747c10a37c74a4b484d" - integrity sha512-l5r9ir56nda3qu14nAXIlyq1MmUSs0meCIaFAh8HwkFwP1F8eToOuS3ah2VAHHcY04jaYD7FpJC5JTXHYRbkzg== - before-after-hook@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" @@ -4077,15 +3604,15 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bin-links@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757" - integrity sha512-8eEHVgYP03nILphilltWjeIjMbKyJo3wvp9K816pHbhP301ismzw15mxAAEVQ/USUwcP++1uNrbERbp8lOA6Fg== +bin-links@^1.1.2, bin-links@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.3.tgz#702fd59552703727313bc624bdbc4c0d3431c2ca" + integrity sha512-TEwmH4PHU/D009stP+fkkazMJgkBNCv60z01lQ/Mn8E6+ThHoD03svMnBVuCowwXo2nP2qKyKZxKxp58OHRzxw== dependencies: - bluebird "^3.5.0" - cmd-shim "^2.0.2" - gentle-fs "^2.0.0" - graceful-fs "^4.1.11" + bluebird "^3.5.3" + cmd-shim "^3.0.0" + gentle-fs "^2.0.1" + graceful-fs "^4.1.15" write-file-atomic "^2.3.0" binary-extensions@^1.0.0: @@ -4100,10 +3627,15 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^3.3.5, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3: - version "3.5.4" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.4.tgz#d6cc661595de30d5b3af5fcedd3c0b3ef6ec5714" - integrity sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw== +bluebird@^3.3.5, bluebird@^3.5.1, bluebird@^3.5.3: + version "3.7.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.0.tgz#56a6a886e03f6ae577cffedeb524f8f2450293cf" + integrity sha512-aBQ1FxIa7kSWCcmKHlcHFlT2jt6J/l4FzC7KcPELkOJOsPOb/bccdhmIrKDfXhwFrmc7vDoDrrepFvGqjyXGJg== + +bluebird@^3.5.5: + version "3.7.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" + integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" @@ -4143,15 +3675,10 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -bottleneck@^2.0.1: - version "2.18.1" - resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.18.1.tgz#cf7c494d90283ecbe896baa46a1397ae8b3c19d7" - integrity sha512-EhSYARs0MHsNRBPrp1TaeHpgmWFUpA6yl3NNBPjGNilBaQZr4iSbrJ16JbQVXuZkIaB7YVYfaiMiRq7NgyZFQg== - bottleneck@^2.18.1: - version "2.19.4" - resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.4.tgz#63c505687a0ddaf89a6f515225c75e05833bb079" - integrity sha512-2poBdvpAGG+dkMVKZqtDhyuMN6JviD81h89W4bfmt3UO7O60F+qf/84V0alNqL8PM1RByl4SZ1fVMu/ZvxkmcA== + version "2.19.5" + resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" + integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== boxen@^1.2.1: version "1.3.0" @@ -4292,32 +3819,14 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.4.tgz#166c4ecef3b51737a42436ea8002aeea466ea2c7" - integrity sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag== - dependencies: - caniuse-lite "^1.0.30000955" - electron-to-chromium "^1.3.122" - node-releases "^1.1.13" - -browserslist@^4.5.2, browserslist@^4.6.2, browserslist@^4.6.3: - version "4.6.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453" - integrity sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA== - dependencies: - caniuse-lite "^1.0.30000984" - electron-to-chromium "^1.3.191" - node-releases "^1.1.25" - -browserslist@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.0.tgz#5274028c26f4d933d5b1323307c1d1da5084c9ff" - integrity sha512-Jk0YFwXBuMOOol8n6FhgkDzn3mY9PYLYGk29zybF05SbRTsMgPqmTNeQQhOghCxq5oFqAXE3u4sYddr4C0uRhg== +browserslist@4.7.0, browserslist@^4.6.0, browserslist@^4.6.6, browserslist@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" + integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== dependencies: - caniuse-lite "^1.0.30000967" - electron-to-chromium "^1.3.133" - node-releases "^1.1.19" + caniuse-lite "^1.0.30000989" + electron-to-chromium "^1.3.247" + node-releases "^1.1.29" bs-logger@0.x: version "0.2.6" @@ -4354,9 +3863,9 @@ buffer-xor@^1.0.3: integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.3.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -4392,22 +3901,23 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@^11.0.1, cacache@^11.3.2: - version "11.3.2" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa" - integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg== +cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== dependencies: - bluebird "^3.5.3" + bluebird "^3.5.5" chownr "^1.1.1" figgy-pudding "^3.5.1" - glob "^7.1.3" + glob "^7.1.4" graceful-fs "^4.1.15" + infer-owner "^1.0.3" lru-cache "^5.1.1" mississippi "^3.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" - rimraf "^2.6.2" + rimraf "^2.6.3" ssri "^6.0.1" unique-filename "^1.1.1" y18n "^4.0.0" @@ -4432,10 +3942,10 @@ cachedir@2.2.0: resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.2.0.tgz#19afa4305e05d79e417566882e0c8f960f62ff0e" integrity sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ== -call-limit@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.0.tgz#6fd61b03f3da42a2cd0ec2b60f02bd0e71991fea" - integrity sha1-b9YbA/PaQqLNDsK2DwK9DnGZH+o= +call-limit@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.1.tgz#ef15f2670db3f1992557e2d965abc459e6e358d4" + integrity sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ== call-me-maybe@^1.0.1: version "1.0.1" @@ -4466,7 +3976,7 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@3.0.x: +camel-case@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= @@ -4516,27 +4026,17 @@ can-use-dom@^0.1.0: resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a" integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo= -caniuse-lite@^1.0.30000955: - version "1.0.30000985" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000985.tgz#0eb40f6c8a8c219155cbe43c4975c0efb4a0f77f" - integrity sha512-1ngiwkgqAYPG0JSSUp3PUDGPKKY59EK7NrGGX+VOxaKCNzRbNc7uXMny+c3VJfZxtoK3wSImTvG9T9sXiTw2+w== - -caniuse-lite@^1.0.30000967: - version "1.0.30000971" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000971.tgz#d1000e4546486a6977756547352bc96a4cfd2b13" - integrity sha512-TQFYFhRS0O5rdsmSbF1Wn+16latXYsQJat66f7S7lizXW1PVpWJeZw9wqqVLIjuxDRz7s7xRUj13QCfd8hKn6g== - -caniuse-lite@^1.0.30000980, caniuse-lite@^1.0.30000984: - version "1.0.30000984" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000984.tgz#dc96c3c469e9bcfc6ad5bdd24c77ec918ea76fe0" - integrity sha512-n5tKOjMaZ1fksIpQbjERuqCyfgec/m9pferkFQbLmWtqLUdmt12hNhjSwsmPdqeiG2NkITOQhr1VYIwWSAceiA== +caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30000998: + version "1.0.30000999" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000999.tgz#427253a69ad7bea4aa8d8345687b8eec51ca0e43" + integrity sha512-1CUyKyecPeksKwXZvYw0tEoaMCo/RwBlXmEtN5vVnabvO0KPd9RQLcaAuR9/1F+KDMv6esmOFWlsXuzDk+8rxg== canvas@^2.4.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.5.0.tgz#cf0ef59d4790575689c0d50e59c7b8023a11f38a" - integrity sha512-wwRz2cLMgb9d+rnotOJCoc04Bzj3aJMpWc6JxAD6lP7bYz0ldcn0sKddoZ0vhD5T8HBxrK+XmRDJb68/2VqARw== + version "2.6.0" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.6.0.tgz#7a8f87b6148845d97e6ee30947fba1508bed4941" + integrity sha512-bEO9f1ThmbknLPxCa8Es7obPlN9W3stB1bo7njlhOFKIdUTldeTqXCh9YclCPAi2pSQs84XA0jq/QEZXSzgyMw== dependencies: - nan "^2.13.2" + nan "^2.14.0" node-pre-gyp "^0.11.0" simple-get "^3.0.3" @@ -4570,20 +4070,11 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -ccount@^1.0.0, ccount@^1.0.3: +ccount@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.4.tgz#9cf2de494ca84060a2a8d2854edd6dfb0445f386" integrity sha512-fpZ81yYfzentuieinmGnphk0pLkOTMm6MZdVqwd77ROvhko6iujLNGrHH5E7utq3ygWklwfmwuG+A7P+NpqT6w== -chalk@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796" - integrity sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g== - dependencies: - ansi-styles "^3.2.0" - escape-string-regexp "^1.0.5" - supports-color "^5.2.0" - chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -4646,10 +4137,10 @@ cheerio@^1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" -chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" - integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== +chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -4665,15 +4156,15 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.6: optionalDependencies: fsevents "^1.2.7" -chownr@^1.1.1: +chownr@^1.1.1, chownr@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== -chrome-trace-event@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" - integrity sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A== +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== dependencies: tslib "^1.9.0" @@ -4717,7 +4208,7 @@ classnames@^2.2.5, classnames@^2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -clean-css@4.2.x: +clean-css@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== @@ -4725,9 +4216,9 @@ clean-css@4.2.x: source-map "~0.6.0" clean-stack@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.1.0.tgz#9e7fec7f3f8340a2ab4f127c80273085e8fbbdd0" - integrity sha512-uQWrpRm+iZZUCAp7ZZJQbd4Za9I3AjR/3YTjmcnAtkauaIm/T5CT6U8zVI6e60T6OANqBFAzuR9/HB3NzuZCRA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cli-boxes@^1.0.0: version "1.0.0" @@ -4823,15 +4314,14 @@ clone-deep@^0.2.4: lazy-cache "^1.0.3" shallow-clone "^0.1.2" -clone-deep@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" - integrity sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ== +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== dependencies: - for-own "^1.0.0" is-plain-object "^2.0.4" - kind-of "^6.0.0" - shallow-clone "^1.0.0" + kind-of "^6.0.2" + shallow-clone "^3.0.0" clone@^1.0.2: version "1.0.4" @@ -4843,10 +4333,10 @@ clsx@^1.0.1: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg== -cmd-shim@^2.0.2, cmd-shim@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" - integrity sha1-b8vamUg6j9FdfTChlspp1oii79s= +cmd-shim@^3.0.0, cmd-shim@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-3.0.3.tgz#2c35238d3df37d98ecdd7d5f6b8dc6b21cadc7cb" + integrity sha512-DtGg+0xiFhQIntSBRzL2fRQBnmtAVwXIDo4Qq46HPpObYquxMaZS4sb82U9nH91qJrlosC1wa9gwr0QyL/HypA== dependencies: graceful-fs "^4.1.2" mkdirp "~0.5.0" @@ -4900,12 +4390,7 @@ colors@1.0.3: resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= -colors@^1.1.2: - version "1.3.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" - integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== - -colors@^1.3.3: +colors@^1.1.2, colors@^1.3.3: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -4930,20 +4415,25 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.7.tgz#419cd7fb3258b1ed838dc0953167a25e152f5b59" integrity sha512-Jrx3xsP4pPv4AwJUDWY9wOXGtwPXARej6Xd99h4TUGotmf8APuquKMpK+dnD3UgyxK7OEWaisjZz+3b5jtL6xQ== -commander@2.17.x: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - -commander@^2.11.0, commander@^2.17.1, commander@^2.19.0, commander@^2.20.0, commander@^2.9.0, commander@~2.20.0: +commander@2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== -commander@~2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== +commander@^2.11.0, commander@^2.17.1, commander@^2.19.0: + version "2.20.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.1.tgz#3863ce3ca92d0831dcf2a102f5fb4b5926afd0f9" + integrity sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== commitizen@^4.0.3: version "4.0.3" @@ -5050,11 +4540,9 @@ connect-history-api-fallback@^1.6.0: integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: version "1.1.0" @@ -5092,40 +4580,40 @@ conventional-changelog-angular@^1.3.3: q "^1.5.1" conventional-changelog-angular@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.3.tgz#299fdd43df5a1f095283ac16aeedfb0a682ecab0" - integrity sha512-YD1xzH7r9yXQte/HF9JBuEDfvjxxwDGGwZU1+ndanbY0oFgA+Po1T9JDSpPLdP0pZT6MhCAsdvFKC4TJ4MTJTA== + version "5.0.5" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.5.tgz#69b541bcf3e538a8578b1e5fbaabe9bd8f572b57" + integrity sha512-RrkdWnL/TVyWV1ayWmSsrWorsTDqjL/VwG5ZSEneBQrd65ONcfeA1cW7FLtNweQyMiKOyriCMTKRSlk18DjTrw== dependencies: compare-func "^1.3.1" q "^1.5.1" conventional-changelog-writer@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.3.tgz#916a2b302d0bb5ef18efd236a034c13fb273cde1" - integrity sha512-bIlpSiQtQZ1+nDVHEEh798Erj2jhN/wEjyw9sfxY9es6h7pREE5BNJjfv0hXGH/FTrAsEpHUq4xzK99eePpwuA== + version "4.0.9" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.9.tgz#44ac4c48121bc90e71cb2947e1ea1a6c222ccd7f" + integrity sha512-2Y3QfiAM37WvDMjkVNaRtZgxVzWKj73HE61YQ/95T53yle+CRwTVSl6Gbv/lWVKXeZcM5af9n9TDVf0k7Xh+cw== dependencies: compare-func "^1.3.1" - conventional-commits-filter "^2.0.1" + conventional-commits-filter "^2.0.2" dateformat "^3.0.0" - handlebars "^4.1.0" + handlebars "^4.4.0" json-stringify-safe "^5.0.1" lodash "^4.2.1" meow "^4.0.0" - semver "^5.5.0" + semver "^6.0.0" split "^1.0.0" - through2 "^2.0.0" + through2 "^3.0.0" conventional-commit-types@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/conventional-commit-types/-/conventional-commit-types-2.1.1.tgz#352eb53f56fbc7c1a6c1ba059c2b6670c90b2a8a" - integrity sha512-0Ts+fEdmjqYDOQ1yZ+LNgdSPO335XZw9qC10M7CxtLP3nIMGmeMhmkM8Taffa4+MXN13bRPlp0CtH+QfOzKTzw== + version "2.3.0" + resolved "https://registry.yarnpkg.com/conventional-commit-types/-/conventional-commit-types-2.3.0.tgz#bc3c8ebba0a9e4b3ecc548f1d0674e251ab8be22" + integrity sha512-6iB39PrcGYdz0n3z31kj6/Km6mK9hm9oMRhwcLnKxE7WNoeRKZbTAobliKrbYZ5jqyCvtcVEfjCiaEzhL3AVmQ== -conventional-commits-filter@^2.0.0, conventional-commits-filter@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.1.tgz#55a135de1802f6510b6758e0a6aa9e0b28618db3" - integrity sha512-92OU8pz/977udhBjgPEbg3sbYzIxMDFTlQT97w7KdhR9igNqdJvy8smmedAAgn4tPiqseFloKkrVfbXCVd+E7A== +conventional-commits-filter@^2.0.0, conventional-commits-filter@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1" + integrity sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ== dependencies: - is-subset "^0.1.1" + lodash.ismatch "^4.4.0" modify-values "^1.0.0" conventional-commits-parser@^2.1.0: @@ -5142,16 +4630,16 @@ conventional-commits-parser@^2.1.0: trim-off-newlines "^1.0.0" conventional-commits-parser@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.1.tgz#fe1c49753df3f98edb2285a5e485e11ffa7f2e4c" - integrity sha512-P6U5UOvDeidUJ8ebHVDIoXzI7gMlQ1OF/id6oUvp8cnZvOXMt1n8nYl74Ey9YMn0uVQtxmCtjPQawpsssBWtGg== + version "3.0.5" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.5.tgz#df471d6cb3f6fecfd1356ac72e0b577dbdae0a9c" + integrity sha512-qVz9+5JwdJzsbt7JbJ6P7NOXBGt8CyLFJYSjKAuPSgO+5UGfcsbk9EMR+lI8Unlvx6qwIc2YDJlrGIfay2ehNA== dependencies: JSONStream "^1.0.4" - is-text-path "^1.0.0" + is-text-path "^2.0.0" lodash "^4.2.1" meow "^4.0.0" split2 "^2.0.0" - through2 "^2.0.0" + through2 "^3.0.0" trim-off-newlines "^1.0.0" convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1: @@ -5195,33 +4683,18 @@ copy-to-clipboard@^3.0.8: dependencies: toggle-selection "^1.0.6" -core-js-compat@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.1.4.tgz#e4d0c40fbd01e65b1d457980fe4112d4358a7408" - integrity sha512-Z5zbO9f1d0YrJdoaQhphVAnKPimX92D6z8lCGphH89MNRxlL1prI9ExJPqVwP0/kgkQCv8c4GJGT8X16yUncOg== - dependencies: - browserslist "^4.6.2" - core-js-pure "3.1.4" - semver "^6.1.1" - core-js-compat@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.1.2.tgz#c29ab9722517094b98622175e2218c3b7398176d" - integrity sha512-X0Ch5f6itrHxhg5HSJucX6nNLNAGr+jq+biBh6nPGc3YAWz2a8p/ZIZY8cUkDzSRNG54omAuu3hoEF8qZbu/6Q== + version "3.2.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150" + integrity sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A== dependencies: - browserslist "^4.6.0" - core-js-pure "3.1.2" - semver "^6.0.0" - -core-js-pure@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.1.2.tgz#62fc435f35b7374b9b782013cdcb2f97e9f6dffa" - integrity sha512-5ckIdBF26B3ldK9PM177y2ZcATP2oweam9RskHSoqfZCrJ2As6wVg8zJ1zTriFsZf6clj/N1ThDFRGaomMsh9w== + browserslist "^4.6.6" + semver "^6.3.0" -core-js-pure@3.1.4, core-js-pure@^3.0.1: - version "3.1.4" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.1.4.tgz#5fa17dc77002a169a3566cc48dc774d2e13e3769" - integrity sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA== +core-js-pure@^3.0.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.2.1.tgz#879a23699cff46175bfd2d09158b5c50645a3c45" + integrity sha512-+qpvnYrsi/JDeQTArB7NnNc2VoMYLE1YSkziCDHgjexC2KH7OFiGhLUd3urxfyWmNjSwSW7NYXPWHMhuIJx9Ow== core-js@^1.0.0: version "1.2.7" @@ -5229,14 +4702,14 @@ core-js@^1.0.0: integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: - version "2.6.8" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.8.tgz#dc3a1e633a04267944e0cb850d3880f340248139" - integrity sha512-RWlREFU74TEkdXzyl1bka66O3kYp8jeTXrvJZDzVVMH8AiHUSOFpL1yfhQJ+wHocAm1m+4971W1PPzfLuCv1vg== + version "2.6.9" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" + integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== core-js@^3.0.1, core-js@^3.0.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07" - integrity sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ== + version "3.2.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" + integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -5244,24 +4717,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0: integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= corejs-upgrade-webpack-plugin@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/corejs-upgrade-webpack-plugin/-/corejs-upgrade-webpack-plugin-2.1.0.tgz#6afa44672486353ae639c297548c0686b64fb325" - integrity sha512-gc+S4t8VT9YFSgOPrhZlD6kDoGZtUq71QwXxS2neGNPhli0veKhbzzilODIpy73TjXGUrCHCpevK8vBnzUPuhw== + version "2.2.0" + resolved "https://registry.yarnpkg.com/corejs-upgrade-webpack-plugin/-/corejs-upgrade-webpack-plugin-2.2.0.tgz#503293bf1fdcb104918eb40d0294e4776ad6923a" + integrity sha512-J0QMp9GNoiw91Kj/dkIQFZeiCXgXoja/Wlht1SPybxerBWh4NCmb0pOgCv61lrlQZETwvVVfAFAA3IqoEO9aqQ== dependencies: resolve-from "^5.0.0" - webpack "^4.33.0" - -cosmiconfig@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" - integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== - dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^4.0.0" - require-from-string "^2.0.1" + webpack "^4.38.0" -cosmiconfig@^5.0.1, cosmiconfig@^5.0.7, cosmiconfig@^5.2.0: +cosmiconfig@^5.0.0, cosmiconfig@^5.0.1, cosmiconfig@^5.0.7, cosmiconfig@^5.2.0, cosmiconfig@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== @@ -5322,14 +4785,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -create-react-context@<=0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.2.tgz#9836542f9aaa22868cd7d4a6f82667df38019dca" - integrity sha512-KkpaLARMhsTsgp0d2NA/R94F/eDLbhXERdIq3LvX2biCAXcDvHYoOqHfWCHf1+OLj+HKBotLG3KqaOOf+C1C+A== - dependencies: - fbjs "^0.8.0" - gud "^1.0.0" - create-react-context@^0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3" @@ -5338,6 +4793,14 @@ create-react-context@^0.2.1: fbjs "^0.8.0" gud "^1.0.0" +create-react-context@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.3.0.tgz#546dede9dc422def0d3fc2fe03afe0bc0f4f7d8c" + integrity sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw== + dependencies: + gud "^1.0.0" + warning "^4.0.3" + cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -5398,11 +4861,11 @@ crypto-random-string@^1.0.0: integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= css-box-model@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.1.2.tgz#c0e2c9d23b1b2fd98759706b88cfd4e2c38db727" - integrity sha512-pFBTZXDPcr61VZzhZgZaulX1Ot0Q5CfXMjFjbWK5NuzZFsi9H4kBOyEZ9FiBvbe1TimJxIJO4WFsLP4/EBBtkg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.0.tgz#3a26377b4162b3200d2ede4b064ec5b6a75186d0" + integrity sha512-lri0br+jSNV0kkkiGEp9y9y3Njq2PmpqbeGWRFQJuZteZzY9iC9GZhQ8Y4WpPwM/2YocjHePxy14igJY7YKzkA== dependencies: - tiny-invariant "^1.0.4" + tiny-invariant "^1.0.6" css-loader@^2.1.0, css-loader@^2.1.1: version "2.1.1" @@ -5446,14 +4909,6 @@ css-select@^2.0.0: domutils "^1.7.0" nth-check "^1.0.2" -css-tree@1.0.0-alpha.28: - version "1.0.0-alpha.28" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" - integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - css-tree@1.0.0-alpha.29: version "1.0.0-alpha.29" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" @@ -5462,10 +4917,13 @@ css-tree@1.0.0-alpha.29: mdn-data "~1.1.0" source-map "^0.5.3" -css-url-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" - integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= +css-tree@1.0.0-alpha.33: + version "1.0.0-alpha.33" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" + integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== + dependencies: + mdn-data "2.0.4" + source-map "^0.5.3" css-what@2.1, css-what@^2.1.2: version "2.1.3" @@ -5484,39 +4942,22 @@ csso@^3.5.1: dependencies: css-tree "1.0.0-alpha.29" -cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": +cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0", cssom@^0.3.4: version "0.3.8" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== -cssom@^0.3.4: - version "0.3.6" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.6.tgz#f85206cee04efa841f3c5982a74ba96ab20d65ad" - integrity sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A== - -cssstyle@^1.0.0: +cssstyle@^1.0.0, cssstyle@^1.1.1: version "1.4.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== dependencies: cssom "0.3.x" -cssstyle@^1.1.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.2.2.tgz#427ea4d585b18624f6fdbf9de7a2a1a3ba713077" - integrity sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow== - dependencies: - cssom "0.3.x" - -csstype@^2.2.0: - version "2.6.4" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f" - integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg== - -csstype@^2.5.2, csstype@^2.5.7: - version "2.6.6" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.6.tgz#c34f8226a94bbb10c32cc0d714afdf942291fc41" - integrity sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg== +csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" + integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== currently-unhandled@^0.4.1: version "0.4.1" @@ -5533,10 +4974,10 @@ cwd@^0.10.0: find-pkg "^0.1.2" fs-exists-sync "^0.1.0" -cyclist@~0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" - integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= cz-conventional-changelog@3.0.1: version "3.0.1" @@ -5578,14 +5019,14 @@ d3-collection@1, d3-collection@^1.0.7: integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A== d3-color@1: - version "1.2.3" - resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.2.3.tgz#6c67bb2af6df3cc8d79efcc4d3a3e83e28c8048f" - integrity sha512-x37qq3ChOTLd26hnps36lexMRhNXEtVxZ4B25rL0DVdDsGQIJGB18S7y9XDwlDD6MD/ZBzITCf4JjGMM10TZkw== + version "1.4.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.4.0.tgz#89c45a995ed773b13314f06460df26d60ba0ecaf" + integrity sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg== d3-format@1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.3.2.tgz#6a96b5e31bcb98122a30863f7d92365c00603562" - integrity sha512-Z18Dprj96ExragQ0DeGi+SYPQ7pPfRMtUXtsg/ChVIKNBCzjO8XYJvRTC1usblx52lqge56V5ect+frYTQc8WQ== + version "1.4.1" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.1.tgz#c45f74b17c5a290c072a4ba7039dd19662cd5ce6" + integrity sha512-TUswGe6hfguUX1CtKxyG2nymO+1lyThbkS1ifLX0Sr+dOQtAD5gkrffpHnx+yHNKUZ0Bmg5T4AjUQwugPDrm0g== d3-interpolate@1: version "1.3.2" @@ -5595,9 +5036,9 @@ d3-interpolate@1: d3-color "1" d3-path@1: - version "1.0.7" - resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.7.tgz#8de7cd693a75ac0b5480d3abaccd94793e58aae8" - integrity sha512-q0cW1RpvA5c5ma2rch62mX8AYaiLX0+bdaSM2wxSU9tXjU4DNvkx9qiUvjkuWCj3p22UO/hlPivujqMiR9PDzA== + version "1.0.8" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.8.tgz#4a0606a794d104513ec4a8af43525f374b278719" + integrity sha512-J6EfUNwcMQ+aM5YPOB8ZbgAZu6wc82f/0WFxrxwV6Ll8wBwLaHLKCqQ5Imub02JriCVVdPjgI+6P3a4EWJCxAg== d3-random@^1.1.2: version "1.1.2" @@ -5632,16 +5073,17 @@ d3-time-format@2: d3-time "1" d3-time@1: - version "1.0.11" - resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.11.tgz#1d831a3e25cd189eb256c17770a666368762bbce" - integrity sha512-Z3wpvhPLW4vEScGeIMUckDW7+3hWKOQfAWg/U7PlWBnQmeKQ00gCUsTtWSYulrKNA7ta8hJ+xXc6MHrMuITwEw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1" + integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA== -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== dependencies: - es5-ext "^0.10.9" + es5-ext "^0.10.50" + type "^1.0.1" dargs@^4.0.1: version "4.1.0" @@ -5666,17 +5108,12 @@ data-urls@^1.0.0, data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= - dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -5690,7 +5127,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@^3.1.0, debug@^3.2.5, debug@^3.2.6: +debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -5727,12 +5164,12 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== dependencies: - mimic-response "^1.0.0" + mimic-response "^2.0.0" dedent@0.7.0: version "0.7.0" @@ -5740,9 +5177,16 @@ dedent@0.7.0: integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= deep-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" deep-extend@^0.6.0: version "0.6.0" @@ -5759,11 +5203,6 @@ deep-object-diff@^1.1.0: resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.0.tgz#d6fabf476c2ed1751fc94d5ca693d2ed8c18bc5a" integrity sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw== -deepmerge@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.2.0.tgz#58ef463a57c08d376547f8869fdc5bcee957f44e" - integrity sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow== - default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" @@ -5847,14 +5286,14 @@ dependency-graph@^0.8.0: integrity sha512-DCvzSq2UiMsuLnj/9AL484ummEgLtZIcRS7YvtO38QnpX3vqh9nJ8P+zhu8Ja+SmLrBHO2iDbva20jq38qvBkQ== deprecation@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.0.0.tgz#dd0427cd920c78bc575ec39dab2f22e7c304fb9d" - integrity sha512-lbQN037mB3VfA2JFuguM5GCJ+zPinMeCrFe+AfSZ6eqrnJA/Fs+EYMnd6Nb2mn9lf2jO9xwEd9o9lic+D4vkcw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -5940,7 +5379,7 @@ dir-glob@2.0.0: arrify "^1.0.1" path-type "^3.0.0" -dir-glob@^2.0.0, dir-glob@^2.2.2: +dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== @@ -6024,7 +5463,15 @@ dom-converter@^0.2: dependencies: "@babel/runtime" "^7.1.2" -dom-serializer@0, dom-serializer@~0.1.1: +dom-serializer@0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" + integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== @@ -6047,6 +5494,11 @@ domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -6121,9 +5573,9 @@ dotenv@^6.2.0: integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== dotenv@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.0.0.tgz#ed310c165b4e8a97bb745b0a9d99c31bda566440" - integrity sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg== + version "8.1.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.1.0.tgz#d811e178652bfb8a1e593c6dd704ec7e90d85ea2" + integrity sha512-GUE3gqcDCaMltj2++g6bRQ5rBJWtkWTmqmD0fo1RnnMuUqHNCt2oTPeDnS9n6fKYvlhn7AeBkb38lymBtWBQdA== duplexer2@~0.1.0: version "0.1.4" @@ -6171,29 +5623,19 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ejs@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" - integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== - -electron-to-chromium@^1.3.122: - version "1.3.200" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.200.tgz#78fb858b466269e8eb46d31a52562f00c865127f" - integrity sha512-PUurrpyDA74MuAjJRD+79ss5BqJlU3mdArRbuu4wO/dt6jc3Ic/6BDmFJxkdwbfq39cHf/XKm2vW98XSvut9Dg== - -electron-to-chromium@^1.3.133: - version "1.3.136" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.136.tgz#758a156109077536780cfa8207b1aeaa99843e33" - integrity sha512-xHkYkbEi4kI+2w5v6yBGCQTRXL7N0PWscygTFZu/1bArnPSo2WR9xjdw4m06RR4J5PncrWJcuOVv+MAG2mK5JQ== + version "2.7.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.1.tgz#5b5ab57f718b79d4aca9254457afecd36fa80228" + integrity sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ== -electron-to-chromium@^1.3.191: - version "1.3.193" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.193.tgz#de9b89959288070bffb14557daf8cf9f75b2caf8" - integrity sha512-WX01CG1UoPtTUFaKKwMn+u8nJ63loP6hNxePWtk1pN8ibWMyX1q6TiWPsz1ABBKXezvmaIdtP+0BwzjC1wyCaw== +electron-to-chromium@^1.3.247: + version "1.3.280" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.280.tgz#5f8950c8329e3e11b59c705fd59b4b8d9b3de5b9" + integrity sha512-qYWNMjKLEfQAWZF2Sarvo+ahigu0EArnpCFSoUuZJS3W5wIeVfeEvsgmT2mgIrieQkeQ0+xFmykK3nx2ezekPQ== elliptic@^6.0.0: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== + version "6.5.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" + integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -6214,12 +5656,12 @@ emojis-list@^2.0.0: integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= emotion-theming@^10.0.10, emotion-theming@^10.0.9: - version "10.0.14" - resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.14.tgz#e548d388493d07bedbb0d9d3bbe221766174b1f4" - integrity sha512-zMGhPSYz48AAR6DYjQVaZHeO42cYKPq4VyB1XjxzgR62/NmO99679fx8qDDB1QZVYGkRWZtsOe+zJE/e30XdbA== + version "10.0.19" + resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.19.tgz#66d13db74fccaefad71ba57c915b306cf2250295" + integrity sha512-dQRBPLAAQ6eA8JKhkLCIWC8fdjPbiNC1zNTdFF292h9amhZXofcNGUP7axHoHX4XesqQESYwZrXp53OPInMrKw== dependencies: - "@babel/runtime" "^7.4.3" - "@emotion/weak-memoize" "0.2.3" + "@babel/runtime" "^7.5.5" + "@emotion/weak-memoize" "0.2.4" hoist-non-react-statics "^3.3.0" emotion@^9.1.2: @@ -6242,21 +5684,14 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" -end-of-stream@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - -end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: +enhanced-resolve@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== @@ -6265,32 +5700,52 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: memory-fs "^0.4.0" tapable "^1.0.0" +enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + entities@^1.1.1, entities@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + env-ci@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-4.1.1.tgz#b8438fc7258a0dc7a4f4c4816de730767946a718" - integrity sha512-eTgpkALDeYRGNhYM2fO9LKsWDifoUgKL7hxpPZqFMP2IU7f+r89DtKqCmk3yQB/jxS8CmZTfKnWO5TiIDFs9Hw== + version "4.5.0" + resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-4.5.0.tgz#96fdb4fde14cfc16b70126da1be7853440e0d6ec" + integrity sha512-0b5ihp/O/tsxWvzEY/Ags+3SL+F9eFci9ZF2Mqx/NHYCaV3cfpoPZW8qx1fcQAHOjWD9wSWsByewzimvGar/4Q== dependencies: execa "^1.0.0" java-properties "^1.0.0" +env-paths@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" + integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= + enzyme-adapter-react-16@^1.10.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.13.1.tgz#2e8ee300e38674b9914ae52b04af9493050355e2" - integrity sha512-DCKbkiVlfLTbn4SXO8mXDQx1SmmwON5oKXn2QfQSMCt8eTYGwUXy/OBGSuss6KKwY5w5QfK1sQFxhgFOkMCjrw== + version "1.15.0" + resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.0.tgz#f7f72ab13b6596f944918c60f42e4ce38d890860" + integrity sha512-p5k5TAG9hiyFNgJ7ABkfg5Poc3Gp5D2uArDEv7BW/FE0AflqIRfHFi4G3Ei+MpPuwy5Ao+ZisYWKuxC5LRCr1Q== dependencies: enzyme-adapter-utils "^1.12.0" + enzyme-shallow-equal "^1.0.0" has "^1.0.3" object.assign "^4.1.0" object.values "^1.1.0" prop-types "^15.7.2" react-is "^16.8.6" react-test-renderer "^16.0.0-0" - semver "^5.6.0" + semver "^5.7.0" enzyme-adapter-utils@^1.12.0: version "1.12.0" @@ -6304,10 +5759,18 @@ enzyme-adapter-utils@^1.12.0: prop-types "^15.7.2" semver "^5.6.0" +enzyme-shallow-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.0.tgz#d8e4603495e6ea279038eef05a4bf4887b55dc69" + integrity sha512-VUf+q5o1EIv2ZaloNQQtWCJM9gpeux6vudGVH6vLmfPXFLRuxl5+Aq3U260wof9nn0b0i+P5OEUXm1vnxkRpXQ== + dependencies: + has "^1.0.3" + object-is "^1.0.1" + enzyme@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.9.0.tgz#2b491f06ca966eb56b6510068c7894a7e0be3909" - integrity sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg== + version "3.10.0" + resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.10.0.tgz#7218e347c4a7746e133f8e964aada4a3523452f6" + integrity sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg== dependencies: array.prototype.flat "^1.2.1" cheerio "^1.0.0-rc.2" @@ -6350,22 +5813,10 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.7.0, es-abstract@^1.9.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - -es-abstract@^1.5.1: - version "1.14.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" - integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== +es-abstract@^1.10.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.14.2, es-abstract@^1.15.0, es-abstract@^1.4.3, es-abstract@^1.5.1, es-abstract@^1.7.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.15.0.tgz#8884928ec7e40a79e3c9bc812d37d10c8b24cc57" + integrity sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ== dependencies: es-to-primitive "^1.2.0" function-bind "^1.1.1" @@ -6375,8 +5826,8 @@ es-abstract@^1.5.1: is-regex "^1.0.4" object-inspect "^1.6.0" object-keys "^1.1.1" - string.prototype.trimleft "^2.0.0" - string.prototype.trimright "^2.0.0" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" es-to-primitive@^1.2.0: version "1.2.0" @@ -6387,10 +5838,10 @@ es-to-primitive@^1.2.0: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.50" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.50.tgz#6d0e23a0abdb27018e5ac4fd09b412bc5517a778" - integrity sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw== +es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@^0.10.51: + version "0.10.51" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.51.tgz#ed2d7d9d48a12df86e0299287e93a09ff478842f" + integrity sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ== dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -6411,9 +5862,9 @@ es6-iterator@~2.0.3: es6-symbol "^3.1.1" es6-promise@^4.0.3: - version "4.2.6" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" - integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== es6-promisify@^5.0.0: version "5.0.0" @@ -6428,12 +5879,12 @@ es6-shim@^0.35.5: integrity sha512-E9kK/bjtCQRpN1K28Xh4BlmP8egvZBGJJ+9GtnzOwt7mdqtrjHFuVGr7QJfdjBIKqrlU5duPf3pCBoDrkjVYFg== es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= + version "3.1.2" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.2.tgz#859fdd34f32e905ff06d752e7171ddd4444a7ed1" + integrity sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ== dependencies: - d "1" - es5-ext "~0.10.14" + d "^1.0.1" + es5-ext "^0.10.51" escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" @@ -6445,19 +5896,7 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^1.11.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510" - integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -escodegen@^1.9.1: +escodegen@^1.11.0, escodegen@^1.9.1: version "1.12.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== @@ -6485,17 +5924,17 @@ eslint-import-resolver-node@^0.3.2: resolve "^1.5.0" eslint-module-utils@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz#8b93499e9b00eab80ccb6614e69f03678e84e09a" - integrity sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw== + version "2.4.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz#7b4675875bf96b0dbf1b21977456e5bb1f5e018c" + integrity sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw== dependencies: debug "^2.6.8" pkg-dir "^2.0.0" eslint-plugin-import@^2.17.3: - version "2.17.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz#00548b4434c18faebaba04b24ae6198f280de189" - integrity sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q== + version "2.18.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6" + integrity sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ== dependencies: array-includes "^3.0.3" contains-path "^0.1.0" @@ -6504,35 +5943,39 @@ eslint-plugin-import@^2.17.3: eslint-import-resolver-node "^0.3.2" eslint-module-utils "^2.4.0" has "^1.0.3" - lodash "^4.17.11" minimatch "^3.0.4" + object.values "^1.1.0" read-pkg-up "^2.0.0" resolve "^1.11.0" eslint-plugin-jest@^22.6.4: - version "22.6.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.6.4.tgz#2895b047dd82f90f43a58a25cf136220a21c9104" - integrity sha512-36OqnZR/uMCDxXGmTsqU4RwllR0IiB/XF8GW3ODmhsjiITKuI0GpgultWFt193ipN3HARkaIcKowpE6HBvRHNg== + version "22.17.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.17.0.tgz#dc170ec8369cd1bff9c5dd8589344e3f73c88cf6" + integrity sha512-WT4DP4RoGBhIQjv+5D0FM20fAdAUstfYAf/mkufLNTojsfgzc5/IYW22cIg/Q4QBavAZsROQlqppiWDpFZDS8Q== + dependencies: + "@typescript-eslint/experimental-utils" "^1.13.0" eslint-plugin-prettier@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz#8695188f95daa93b0dc54b249347ca3b79c4686d" - integrity sha512-XWX2yVuwVNLOUhQijAkXz+rMPPoCr7WFiAl8ig6I7Xn+pPVhDhzg4DxHpmbeb0iqjO9UronEA3Tb09ChnFVHHA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba" + integrity sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA== dependencies: prettier-linter-helpers "^1.0.0" eslint-plugin-react@^7.13.0: - version "7.13.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.13.0.tgz#bc13fd7101de67996ea51b33873cd9dc2b7e5758" - integrity sha512-uA5LrHylu8lW/eAH3bEQe9YdzpPaFd9yAJTwTi/i/BKTD7j6aQMKVAdGM/ML72zD6womuSK7EiGtMKuK06lWjQ== + version "7.16.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.16.0.tgz#9928e4f3e2122ed3ba6a5b56d0303ba3e41d8c09" + integrity sha512-GacBAATewhhptbK3/vTP09CbFrgUJmBSaaRcWdbQLFvUZy9yVcQxigBNHGPU/KE2AyHpzj3AWXpxoMTsIDiHug== dependencies: array-includes "^3.0.3" doctrine "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.1.0" + jsx-ast-utils "^2.2.1" + object.entries "^1.1.0" object.fromentries "^2.0.0" + object.values "^1.1.0" prop-types "^15.7.2" - resolve "^1.10.1" + resolve "^1.12.0" eslint-scope@^4.0.0, eslint-scope@^4.0.3: version "4.0.3" @@ -6548,26 +5991,16 @@ eslint-scope@^5.0.0: integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== dependencies: esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-utils@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" - integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q== + estraverse "^4.1.1" -eslint-utils@^1.4.2: +eslint-utils@^1.3.1, eslint-utils@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== dependencies: eslint-visitor-keys "^1.0.0" -eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== - -eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== @@ -6647,22 +6080,12 @@ esrecurse@^4.1.0: dependencies: estraverse "^4.1.0" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - -estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -esutils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= - -esutils@^2.0.2: +esutils@^2.0.0, esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== @@ -6672,11 +6095,16 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -eventemitter3@^3.0.0, eventemitter3@^3.1.0: +eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== +eventemitter3@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" + integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== + events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" @@ -6728,7 +6156,7 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^2.1.0: +execa@^2.0.2, execa@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-2.1.0.tgz#e5d3ecd837d2a60ec50f3da78fd39767747bbe99" integrity sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw== @@ -6792,10 +6220,10 @@ expect@^24.1.0, expect@^24.9.0: jest-message-util "^24.9.0" jest-regex-util "^24.9.0" -express@^4.17.0: - version "4.17.0" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.0.tgz#288af62228a73f4c8ea2990ba3b791bb87cd4438" - integrity sha512-1Z7/t3Z5ZnBG252gKUPyItc4xdeaA0X934ca2ewckAsVsw9EG71i++ZHZPYnus8g/s5Bty8IMpSVEuRkmwwPRQ== +express@^4.17.0, express@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== dependencies: accepts "~1.3.7" array-flatten "1.1.1" @@ -6849,9 +6277,9 @@ extend@^3.0.0, extend@~3.0.2: integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== external-editor@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" - integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -6914,15 +6342,14 @@ fast-glob@^2.0.2, fast-glob@^2.2.6: micromatch "^3.1.10" fast-glob@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602" - integrity sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.0.tgz#77375a7e3e6f6fc9b18f061cddd28b8d1eec75ae" + integrity sha512-TrUz3THiq2Vy3bjfQUB2wNyPdGBeGmdjbzzBLhfHN4YFurYptCKwGq/TfiRavbGywFRzY6U2CdmQ1zmsY5yYaw== dependencies: - "@nodelib/fs.stat" "^2.0.1" - "@nodelib/fs.walk" "^1.2.1" - glob-parent "^5.0.0" - is-glob "^4.0.1" - merge2 "^1.2.3" + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" micromatch "^4.0.2" fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: @@ -6957,9 +6384,9 @@ faye-websocket@^0.10.0: websocket-driver ">=0.5.1" faye-websocket@~0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38" - integrity sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg= + version "0.11.3" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" + integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== dependencies: websocket-driver ">=0.5.1" @@ -7068,7 +6495,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^2.0.0: +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -7166,17 +6593,7 @@ find-versions@^3.0.0: array-uniq "^2.1.0" semver-regex "^2.0.0" -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= - dependencies: - detect-file "^1.0.0" - is-glob "^3.1.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -findup-sync@^3.0.0: +findup-sync@3.0.0, findup-sync@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== @@ -7196,9 +6613,9 @@ flat-cache@^2.0.1: write "1.0.3" flatted@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" - integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== flush-write-stream@^1.0.0: version "1.1.1" @@ -7209,16 +6626,16 @@ flush-write-stream@^1.0.0: readable-stream "^2.3.6" focus-lock@^0.6.3: - version "0.6.4" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.4.tgz#066af3ed5875d85745ab45ef4fbbb43e8a73514a" - integrity sha512-+waElh6m7dbNmEabXQIblZjJMIRQOoHMNqB8RZkyemK+vN1XQ9uHLi740DVwTcK5fzAq3g+tBglLjIqUDHX/Og== + version "0.6.5" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.5.tgz#f6eb37832a9b1b205406175f5277396a28c0fce1" + integrity sha512-i/mVBOoa9o+tl+u9owOJUF8k8L85odZNIsctB+JAK2HFT8jckiBwmk+3uydlm6FN8czgnkIwQtBv6yyAbrzXjw== follow-redirects@^1.0.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" - integrity sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f" + integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A== dependencies: - debug "^3.2.6" + debug "^3.0.0" for-in@^0.1.3: version "0.1.8" @@ -7237,22 +6654,15 @@ for-own@^0.1.3: dependencies: for-in "^1.0.1" -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= - dependencies: - for-in "^1.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-ts-checker-webpack-plugin@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.1.1.tgz#caf2a210778fb1e171b6993ca0a40f9b6589e3b7" - integrity sha512-gqWAEMLlae/oeVnN6RWCAhesOJMswAN1MaKNqhhjXHV5O0/rTUjWI4UbgQHdlrVbCnb+xLotXmJbBlC66QmpFw== +fork-ts-checker-webpack-plugin@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.5.0.tgz#ce1d77190b44d81a761b10b6284a373795e41f0c" + integrity sha512-zEhg7Hz+KhZlBhILYpXy+Beu96gwvkROWJiTXOCyOOMMrdBIRPvsBpBqgTI4jfJGrJXcqGwJR8zsBGDmzY0jsA== dependencies: babel-code-frame "^6.22.0" chalk "^2.4.1" @@ -7282,10 +6692,10 @@ forwarded@~0.1.2: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= -fp-ts@^1.0.0, fp-ts@^1.14.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.18.2.tgz#b9a7025174e1a59bc43b485b3a0ca6f78e371d01" - integrity sha512-kznerusCuG5dUt0bH6eiQHVp2fstPiSlyzGb//rYgMMxCuromWEoVS0riH++86vyJm9Nv1B+pbe6udDx1tqjfA== +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== fragment-cache@^0.2.1: version "0.2.1" @@ -7307,7 +6717,7 @@ from2@^1.3.0: inherits "~2.0.1" readable-stream "~1.1.10" -from2@^2.1.0, from2@^2.1.1, from2@^2.3.0: +from2@^2.1.0, from2@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= @@ -7403,20 +6813,26 @@ function-bind@^1.0.2, function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function.prototype.name@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" - integrity sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg== +function.prototype.name@^1.1.0, function.prototype.name@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.1.tgz#6d252350803085abc2ad423d4fe3be2f9cbda392" + integrity sha512-e1NzkiJuw6xqVH7YSdiW/qDHebcmMhPNe6w+4ZYYEg0VA+LaLzx37RimbPLuonHhYGFGPx1ME2nSi74JiaCr/Q== dependencies: - define-properties "^1.1.2" + define-properties "^1.1.3" function-bind "^1.1.1" - is-callable "^1.1.3" + functions-have-names "^1.1.1" + is-callable "^1.1.4" functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +functions-have-names@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.1.1.tgz#79d35927f07b8e7103d819fed475b64ccf7225ea" + integrity sha512-U0kNHUoxwPNPWOJaMG7Z00d4a/qZVrFtzWJRaK8V9goaVOCXBSQSJpt3MYGNtkScKEBKovxLjnNdC9MlXwo5Pw== + fuse.js@^3.4.4: version "3.4.5" resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.5.tgz#8954fb43f9729bd5dbcb8c08f251db552595a7a6" @@ -7448,15 +6864,17 @@ genfun@^5.0.0: resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA== -gentle-fs@^2.0.0, gentle-fs@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/gentle-fs/-/gentle-fs-2.0.1.tgz#585cfd612bfc5cd52471fdb42537f016a5ce3687" - integrity sha512-cEng5+3fuARewXktTEGbwsktcldA+YsnUEaXZwcK/3pjSE1X9ObnTs+/8rYf8s+RnIcQm2D5x3rwpN7Zom8Bew== +gentle-fs@^2.0.1, gentle-fs@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/gentle-fs/-/gentle-fs-2.2.1.tgz#1f38df4b4ead685566257201fd526de401ebb215" + integrity sha512-e7dRgUM5fsS+7wm2oggZpgcRx6sEvJHXujPH5RzgQ1ziQY4+HuVBYsnUzJwJ+C7mjOJN27DjiFy1TaL+TNltow== dependencies: aproba "^1.1.2" + chownr "^1.1.2" fs-vacuum "^1.2.10" graceful-fs "^4.1.11" iferr "^0.1.5" + infer-owner "^1.0.4" mkdirp "^0.5.1" path-is-inside "^1.0.2" read-cmd-shim "^1.0.1" @@ -7472,11 +6890,6 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" - integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg== - get-stdin@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" @@ -7559,10 +6972,10 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" - integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== +glob-parent@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== dependencies: is-glob "^4.0.1" @@ -7571,7 +6984,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.1.4, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: +glob@7.1.4, glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== @@ -7583,6 +6996,18 @@ glob@7.1.4, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glo once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.0.3, glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^0.1.0, global-dirs@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" @@ -7645,12 +7070,12 @@ global-prefix@^3.0.0: which "^1.3.1" global@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== dependencies: min-document "^2.19.0" - process "~0.5.1" + process "^0.11.10" globals@^11.1.0, globals@^11.7.0: version "11.12.0" @@ -7757,20 +7182,15 @@ got@^6.7.1: url-parse-lax "^1.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== -graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== - -graceful-fs@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" - integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -7781,34 +7201,23 @@ gud@^1.0.0: resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== -gzip-size@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" - integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA== +gzip-size@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== dependencies: duplexer "^0.1.1" - pify "^3.0.0" + pify "^4.0.1" handle-thing@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== -handlebars@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" - integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - -handlebars@^4.1.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.3.1.tgz#6febc1890851f62a8932d495cc88d29390fa850d" - integrity sha512-c0HoNHzDiHpBt4Kqe99N8tdLPKAnGCQ73gYMPWtAYM4PwGnf7xl8PBUHJqh9ijlzt2uQKaSRxbXRt+rZ7M2/kA== +handlebars@^4.1.2, handlebars@^4.4.0: + version "4.4.3" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.4.3.tgz#180bae52c1d0e9ec0c15d7e82a4362d662762f6e" + integrity sha512-B0W4A2U1ww3q7VVthTKfh+epHx+q4mCt6iK+zEAzbMBpWQAwxCeKxEGpj/1oQTpzPXDNSOG7hmG14TsISH50yw== dependencies: neo-async "^2.6.0" optimist "^0.6.1" @@ -7910,41 +7319,30 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hast-util-from-parse5@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.0.tgz#a505a05766e0f96e389bfb0b1dd809eeefcef47b" - integrity sha512-A7ev5OseS/J15214cvDdcI62uwovJO2PB60Xhnq7kaxvvQRFDEccuqbkrFXU03GPBGopdPqlpQBRqIcDS/Fjbg== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - hast-util-parse-selector@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.1.tgz#4ddbae1ae12c124e3eb91b581d2556441766f0ab" - integrity sha512-Xyh0v+nHmQvrOqop2Jqd8gOdyQtE8sIP9IQf7mlVDqp924W4w/8Liuguk2L2qei9hARnQSG2m+wAOCxM7npJVw== + version "2.2.2" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.2.tgz#66aabccb252c47d94975f50a281446955160380b" + integrity sha512-jIMtnzrLTjzqgVEQqPEmwEZV+ea4zHRFTP8Z2Utw0I5HuBOXHzUPPQWr6ouJdJqDKLbFU/OEiYwZ79LalZkmmw== hastscript@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.0.0.tgz#fee10382c1bc4ba3f1be311521d368c047d2c43a" - integrity sha512-xJtuJ8D42Xtq5yJrnDg/KAIxl2cXBXKoiIJwmWX9XMf8113qHTGl/Bf7jEsxmENJ4w6q4Tfl8s/Y6mEZo8x8qw== + version "5.1.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.0.tgz#a19b3cca6a26a2bcd0f1b1eac574af9427c1c7df" + integrity sha512-7mOQX5VfVs/gmrOGlN8/EDfp1GqV6P3gTNVt+KnX4gbYhpASTM8bklFdFQCbFRAadURXAmw0R1QQdBdqp7jswQ== dependencies: comma-separated-tokens "^1.0.0" hast-util-parse-selector "^2.2.0" property-information "^5.0.1" space-separated-tokens "^1.0.0" -he@1.2.x, he@^1.1.1: +he@^1.1.1, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== highlight.js@^9.12.0: - version "9.15.8" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.8.tgz#f344fda123f36f1a65490e932cf90569e4999971" - integrity sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA== + version "9.15.10" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2" + integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw== highlight.js@~9.12.0: version "9.12.0" @@ -7965,7 +7363,7 @@ hoist-non-react-statics@^2.3.1: resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: +hoist-non-react-statics@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== @@ -7984,15 +7382,17 @@ hook-std@^2.0.0: resolved "https://registry.yarnpkg.com/hook-std/-/hook-std-2.0.0.tgz#ff9aafdebb6a989a354f729bb6445cf4a3a7077c" integrity sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g== -hosted-git-info@^2.1.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" - integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== +hosted-git-info@^2.1.4, hosted-git-info@^2.7.1, hosted-git-info@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== -hosted-git-info@^2.6.0, hosted-git-info@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== +hosted-git-info@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.2.tgz#8b7e3bd114b59b51786f8bade0f39ddc80275a97" + integrity sha512-ezZMWtHXm7Eb7Rq4Mwnx2vs79WUx2QmRg3+ZqeGroKzfDO+EprOcgRPYghsOP9JuYBfK18VojmRTGCg8Ma+ktw== + dependencies: + lru-cache "^5.1.1" hpack.js@^2.1.6: version "2.1.6" @@ -8005,9 +7405,9 @@ hpack.js@^2.1.6: wbuf "^1.1.0" html-element-map@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.0.1.tgz#3c4fcb4874ebddfe4283b51c8994e7713782b592" - integrity sha512-BZSfdEm6n706/lBfXKWa4frZRZcT5k1cOusw95ijZsHlI+GdgY0v95h6IzO3iIDf2ROwq570YTwqNPqHcNMozw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.1.0.tgz#e5aab9a834caf883b421f8bd9eaedcaac887d63c" + integrity sha512-iqiG3dTZmy+uUaTmHarTL+3/A2VW9ox/9uasKEZC+R/wAtUrTcRlXPSaPqsnWPfIu8wqn09jQNwMRqzL54jSYA== dependencies: array-filter "^1.0.0" @@ -8023,29 +7423,29 @@ html-entities@^1.2.0, html-entities@^1.2.1: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= -html-minifier@^3.5.20: - version "3.5.21" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== +html-minifier@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-4.0.0.tgz#cca9aad8bce1175e02e17a8c33e46d8988889f56" + integrity sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig== dependencies: - camel-case "3.0.x" - clean-css "4.2.x" - commander "2.17.x" - he "1.2.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.4.x" + camel-case "^3.0.0" + clean-css "^4.2.1" + commander "^2.19.0" + he "^1.2.0" + param-case "^2.1.1" + relateurl "^0.2.7" + uglify-js "^3.5.1" html-webpack-plugin@^4.0.0-beta.2: - version "4.0.0-beta.5" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.5.tgz#2c53083c1151bfec20479b1f8aaf0039e77b5513" - integrity sha512-y5l4lGxOW3pz3xBTFdfB9rnnrWRPVxlAhX6nrBYIcW+2k2zC3mSp/3DxlWVCMBfnO6UAnoF8OcFn0IMy6kaKAQ== + version "4.0.0-beta.8" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.8.tgz#d9a8d4322d8cf310f1568f6f4f585a80df0ad378" + integrity sha512-n5S2hJi3/vioRvEDswZP2WFgZU8TUqFoYIrkg5dt+xDC4TigQEhIcl4Y81Qs2La/EqKWuJZP8+ikbHGVmzQ4Mg== dependencies: - html-minifier "^3.5.20" - loader-utils "^1.1.0" + html-minifier "^4.0.0" + loader-utils "^1.2.3" lodash "^4.17.11" pretty-error "^2.1.1" - tapable "^1.1.0" + tapable "^1.1.3" util.promisify "1.0.0" html@^1.0.0: @@ -8077,7 +7477,7 @@ http-deceiver@^1.2.7: resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= -http-errors@1.7.2, http-errors@~1.7.2: +http-errors@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== @@ -8098,10 +7498,21 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-parser-js@>=0.4.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.0.tgz#d65edbede84349d0dc30320815a15d39cc3cbbd8" - integrity sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w== +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +"http-parser-js@>=0.4.0 <0.4.11": + version "0.4.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= http-proxy-agent@^2.1.0: version "2.1.0" @@ -8111,7 +7522,7 @@ http-proxy-agent@^2.1.0: agent-base "4" debug "3.1.0" -http-proxy-middleware@^0.19.1: +http-proxy-middleware@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== @@ -8122,11 +7533,11 @@ http-proxy-middleware@^0.19.1: micromatch "^3.1.10" http-proxy@^1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a" - integrity sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g== + version "1.18.0" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a" + integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ== dependencies: - eventemitter3 "^3.0.0" + eventemitter3 "^4.0.0" follow-redirects "^1.0.0" requires-port "^1.0.0" @@ -8145,11 +7556,19 @@ https-browserify@^1.0.0: integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= https-proxy-agent@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" - integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== + version "2.2.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz#271ea8e90f836ac9f119daccd39c19ff7dfb0793" + integrity sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + +https-proxy-agent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.0.tgz#0106efa5d63d6d6f3ab87c999fa4877a3fd1ff97" + integrity sha512-y4jAxNEihqvBI5F3SaO2rtsjIOnnNA8sEbuiP+UhJZJHeM2NRm6c09ax2tgqme+SgUUvjao2fJXF4h3D6Cb2HQ== dependencies: - agent-base "^4.1.0" + agent-base "^4.3.0" debug "^3.1.0" humanize-ms@^1.2.1: @@ -8188,9 +7607,9 @@ icss-replace-symbols@^1.1.0: integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= icss-utils@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.0.tgz#339dbbffb9f8729a243b701e1c29d4cc58c52f0e" - integrity sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== dependencies: postcss "^7.0.14" @@ -8210,9 +7629,9 @@ iferr@^1.0.2: integrity sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg== ignore-walk@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.2.tgz#99d83a246c196ea5c93ef9315ad7b0819c35069b" - integrity sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw== + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== dependencies: minimatch "^3.0.4" @@ -8226,12 +7645,7 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" - integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== - -ignore@^5.1.4: +ignore@^5.1.1, ignore@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== @@ -8257,9 +7671,9 @@ import-fresh@^2.0.0: resolve-from "^3.0.0" import-fresh@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" - integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -8283,7 +7697,7 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= -import-local@^2.0.0: +import-local@2.0.0, import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== @@ -8308,20 +7722,25 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" -indent-string@^3.0.0, indent-string@^3.2.0: +indent-string@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflight@^1.0.4, inflight@~1.0.6: version "1.0.6" @@ -8331,7 +7750,7 @@ inflight@^1.0.4, inflight@~1.0.6: once "^1.3.0" wrappy "1" -inherits@2, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -8341,7 +7760,7 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= -inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1: +inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= @@ -8365,25 +7784,6 @@ init-package-json@^1.10.3: validate-npm-package-license "^3.0.1" validate-npm-package-name "^3.0.0" -inquirer@6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" - integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.11" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.0.0" - through "^2.3.6" - inquirer@6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" @@ -8404,9 +7804,9 @@ inquirer@6.5.0: through "^2.3.6" inquirer@^6.2.0, inquirer@^6.2.2: - version "6.3.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" - integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== dependencies: ansi-escapes "^3.2.0" chalk "^2.4.2" @@ -8414,7 +7814,7 @@ inquirer@^6.2.0, inquirer@^6.2.2: cli-width "^2.0.0" external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.17.11" + lodash "^4.17.12" mute-stream "0.0.7" run-async "^2.2.0" rxjs "^6.4.0" @@ -8430,26 +7830,18 @@ internal-ip@^4.3.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" -interpret@^1.0.0, interpret@^1.1.0, interpret@^1.2.0: +interpret@1.2.0, interpret@^1.0.0, interpret@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== -into-stream@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-4.0.0.tgz#ef10ee2ffb6f78af34c93194bbdc36c35f7d8a9d" - integrity sha512-i29KNyE5r0Y/UQzcQ0IbZO1MYJ53Jn0EcFRZPj5FzWKYH17kDFEOwuA+3jroymOI06SW1dEDnly9A1CAreC5dg== - dependencies: - from2 "^2.1.1" - p-is-promise "^2.0.0" - into-stream@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-5.1.0.tgz#b05f37d8fed05c06a0b43b556d74e53e5af23878" - integrity sha512-cbDhb8qlxKMxPBk/QxTtYg1DQ4CwXmadu7quG3B7nrJsgSncEreF2kwWKZFdnjc/lSNNIkFPsjI7SM0Cx/QXPw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-5.1.1.tgz#f9a20a348a11f3c13face22763f2d02e127f4db8" + integrity sha512-krrAJ7McQxGGmvaYbB7Q1mcA+cRwg9Ij2RfWIeVesNBgVDZmzY/Fa4IpZUT3bmdRzMzdf/mzltCG2Dq99IZGBA== dependencies: from2 "^2.3.0" - p-is-promise "^2.0.0" + p-is-promise "^3.0.0" invariant@2.2.4, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: version "2.2.4" @@ -8478,11 +7870,21 @@ ip@^1.1.0, ip@^1.1.5: resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -ipaddr.js@1.9.0, ipaddr.js@^1.9.0: +ipaddr.js@1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== +ipaddr.js@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -8515,6 +7917,11 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -8537,12 +7944,7 @@ is-buffer@^1.0.2, is-buffer@^1.1.4, is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== - -is-callable@^1.1.3, is-callable@^1.1.4: +is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== @@ -8562,9 +7964,9 @@ is-ci@^2.0.0: ci-info "^2.0.0" is-cidr@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-3.0.0.tgz#1acf35c9e881063cd5f696d48959b30fed3eed56" - integrity sha512-8Xnnbjsb0x462VoYiGlhEi+drY8SFwrHiSYuzc/CEwco55vkehTaxAyIjEdpi3EMvLPPJAJi9FlzP+h+03gp0Q== + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-3.1.0.tgz#72e233d8e1c4cd1d3f11713fcce3eba7b0e3476f" + integrity sha512-3kxTForpuj8O4iHn0ocsn1jxRm5VYm60GDghK6HXmpn4IyZOoRy9/GmdjFA2yEMqw91TB1/K3bFTuI7FlFNR1g== dependencies: cidr-regex "^2.0.10" @@ -8616,9 +8018,12 @@ is-directory@^0.3.1: integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-dom@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/is-dom/-/is-dom-1.0.9.tgz#483832d52972073de12b9fe3f60320870da8370d" - integrity sha1-SDgy1SlyBz3hK5/j9gMghw2oNw0= + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-dom/-/is-dom-1.1.0.tgz#af1fced292742443bb59ca3f76ab5e80907b4e8a" + integrity sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ== + dependencies: + is-object "^1.0.1" + is-window "^1.0.2" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" @@ -8715,15 +8120,20 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0, is-obj@^1.0.1: +is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= + is-path-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.1.0.tgz#2e0c7e463ff5b7a0eb60852d851a6809347a124c" - integrity sha512-Sc5j3/YnM8tDeyCsVeKlm/0p95075DyLmDEIkSgQ7mXkrOX+uTCtmQFm0CYzVyJwcCCmO3k8qfJt17SxQwB5Zw== + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== is-path-in-cwd@^2.0.0: version "2.1.0" @@ -8782,20 +8192,15 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - is-retry-allowed@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== -is-root@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.0.0.tgz#838d1e82318144e5a6f77819d90207645acc7019" - integrity sha512-F/pJIk8QD6OX5DNhRB7hWamLsUilmkDGho48KbgZ6xg/lmAZXHxzXQ91jzB3yRSw5kdQGGGc4yz8HYhTYIMWPg== +is-root@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" + integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" @@ -8831,6 +8236,13 @@ is-text-path@^1.0.0: dependencies: text-extensions "^1.0.0" +is-text-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-2.0.0.tgz#b2484e2b720a633feb2e85b67dc193ff72c75636" + integrity sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw== + dependencies: + text-extensions "^2.0.0" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -8851,6 +8263,11 @@ is-whitespace-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.3.tgz#b3ad9546d916d7d3ffa78204bca0c26b56257fac" integrity sha512-SNPgMLz9JzPccD3nPctcj8sZlX9DAMJSKH8bP7Z6bohCwuNgX8xbWr1eTAYXX9Vpi/aSn8Y1akL9WgM3t43YNQ== +is-window@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-window/-/is-window-1.0.2.tgz#2c896ca53db97de45d3c33133a65d8c9f563480d" + integrity sha1-LIlspT25feRdPDMTOmXYyfVjSA0= + is-windows@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" @@ -8916,21 +8333,10 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -issue-parser@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/issue-parser/-/issue-parser-3.0.1.tgz#ee8dd677fdb5be64541f81fa5e7267baa271a7ee" - integrity sha512-5wdT3EE8Kq38x/hJD8QZCJ9scGoOZ5QnzwXyClkviSWTS+xOCE6hJ0qco3H5n5jCsFqpbofZCcMWqlXJzF72VQ== - dependencies: - lodash.capitalize "^4.2.1" - lodash.escaperegexp "^4.1.2" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.uniqby "^4.7.0" - -issue-parser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/issue-parser/-/issue-parser-4.0.0.tgz#397817323abbb70c7c29cea2ff62448cf83b686c" - integrity sha512-1RmmAXHl5+cqTZ9dRr861xWy0Gkc9TWTEklgjKv+nhlB1dY1NmGBV8b20jTWRL5cPGpOIXkz84kEcDBM8Nc0cw== +issue-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/issue-parser/-/issue-parser-5.0.0.tgz#0e22a40bc275b6c7da6ddf4a9b979e8ca9faf0d4" + integrity sha512-q/16W7EPHRL0FKVz9NU++TUsoygXGj6JOi88oulyAcQG+IEZ0T6teVdE+VLbe19OfL/tbV8Wi3Dfo0HedeHW0Q== dependencies: lodash.capitalize "^4.2.1" lodash.escaperegexp "^4.1.2" @@ -9237,20 +8643,13 @@ jest-message-util@^24.9.0: slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24, jest-mock@^24.9.0: +jest-mock@^24, jest-mock@^24.5.0, jest-mock@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== dependencies: "@jest/types" "^24.9.0" -jest-mock@^24.5.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56" - integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A== - dependencies: - "@jest/types" "^24.8.0" - jest-pnp-resolver@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" @@ -9376,25 +8775,7 @@ jest-snapshot@^24.9.0: pretty-format "^24.9.0" semver "^6.2.0" -jest-util@^24.5.0: - version "24.8.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1" - integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA== - dependencies: - "@jest/console" "^24.7.1" - "@jest/fake-timers" "^24.8.0" - "@jest/source-map" "^24.3.0" - "@jest/test-result" "^24.8.0" - "@jest/types" "^24.8.0" - callsites "^3.0.0" - chalk "^2.0.1" - graceful-fs "^4.1.15" - is-ci "^2.0.0" - mkdirp "^0.5.1" - slash "^2.0.0" - source-map "^0.6.0" - -jest-util@^24.9.0: +jest-util@^24.5.0, jest-util@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== @@ -9473,7 +8854,7 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= -js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.9.0: +js-yaml@^3.13.0, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -9586,14 +8967,14 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json3@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= + version "3.3.3" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" + integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== json5@2.x, json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== dependencies: minimist "^1.2.0" @@ -9618,11 +8999,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -9638,12 +9014,13 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jsx-ast-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.1.0.tgz#0ee4e2c971fb9601c67b5641b71be80faecf0b36" - integrity sha512-yDGDG2DS4JcqhA6blsuYbtsT09xL8AoLuUR2Gb5exrw7UEM19sBcOTq+YBBhrNbl0PUC4R4LnFu+dHg2HKeVvA== +jsx-ast-utils@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz#4d4973ebf8b9d2837ee91a8208cc66f3a2776cfb" + integrity sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ== dependencies: array-includes "^3.0.3" + object.assign "^4.1.0" keymirror@^0.1.1: version "0.1.1" @@ -9726,11 +9103,11 @@ lazy-property@~1.0.0: integrity sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc= lazy-universal-dotenv@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.0.tgz#e71f07f89d8de6bbf491478e4503df3c96729b8d" - integrity sha512-Mbf5AeGOs74lE5BdQXHFJ7Rt383jxnWKNfW2EWL0Pibnhea5JRStRIiUpdTenyMxCGuCjlMpYQhhay1XZBSSQA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" + integrity sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ== dependencies: - "@babel/runtime" "^7.0.0" + "@babel/runtime" "^7.5.0" app-root-dir "^1.0.2" core-js "^3.0.4" dotenv "^8.0.0" @@ -9768,10 +9145,10 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libcipm@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-3.0.3.tgz#2e764effe0b90d458790dab3165794c804075ed3" - integrity sha512-71V5CpTI+zFydTc5IjJ/tx8JHbXEJvmYF2zaSVW1V3X1rRnRjXqh44iuiyry1xgi3ProUQ1vX1uwFiWs00+2og== +libcipm@^4.0.4: + version "4.0.7" + resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-4.0.7.tgz#76cd675c98bdaae64db88b782b01b804b6d02c8a" + integrity sha512-fTq33otU3PNXxxCTCYCYe7V96o59v/o7bvtspmbORXpgFk+wcWrGf5x6tBgui5gCed/45/wtPomBsZBYm5KbIw== dependencies: bin-links "^1.1.2" bluebird "^3.5.1" @@ -9781,7 +9158,7 @@ libcipm@^3.0.3: ini "^1.3.5" lock-verify "^2.0.2" mkdirp "^0.5.1" - npm-lifecycle "^2.0.3" + npm-lifecycle "^3.0.0" npm-logical-tree "^1.2.1" npm-package-arg "^6.1.0" pacote "^9.1.0" @@ -9789,41 +9166,41 @@ libcipm@^3.0.3: rimraf "^2.6.2" worker-farm "^1.6.0" -libnpm@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/libnpm/-/libnpm-2.0.1.tgz#a48fcdee3c25e13c77eb7c60a0efe561d7fb0d8f" - integrity sha512-qTKoxyJvpBxHZQB6k0AhSLajyXq9ZE/lUsZzuHAplr2Bpv9G+k4YuYlExYdUCeVRRGqcJt8hvkPh4tBwKoV98w== +libnpm@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/libnpm/-/libnpm-3.0.1.tgz#0be11b4c9dd4d1ffd7d95c786e92e55d65be77a2" + integrity sha512-d7jU5ZcMiTfBqTUJVZ3xid44fE5ERBm9vBnmhp2ECD2Ls+FNXWxHSkO7gtvrnbLO78gwPdNPz1HpsF3W4rjkBQ== dependencies: bin-links "^1.1.2" bluebird "^3.5.3" find-npm-prefix "^1.0.2" - libnpmaccess "^3.0.1" + libnpmaccess "^3.0.2" libnpmconfig "^1.2.1" - libnpmhook "^5.0.2" - libnpmorg "^1.0.0" - libnpmpublish "^1.1.0" - libnpmsearch "^2.0.0" - libnpmteam "^1.0.1" + libnpmhook "^5.0.3" + libnpmorg "^1.0.1" + libnpmpublish "^1.1.2" + libnpmsearch "^2.0.2" + libnpmteam "^1.0.2" lock-verify "^2.0.2" - npm-lifecycle "^2.1.0" + npm-lifecycle "^3.0.0" npm-logical-tree "^1.2.1" npm-package-arg "^6.1.0" - npm-profile "^4.0.1" - npm-registry-fetch "^3.8.0" + npm-profile "^4.0.2" + npm-registry-fetch "^4.0.0" npmlog "^4.1.2" - pacote "^9.2.3" + pacote "^9.5.3" read-package-json "^2.0.13" stringify-package "^1.0.0" -libnpmaccess@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.1.tgz#5b3a9de621f293d425191aa2e779102f84167fa8" - integrity sha512-RlZ7PNarCBt+XbnP7R6PoVgOq9t+kou5rvhaInoNibhPO7eMlRfS0B8yjatgn2yaHIwWNyoJDolC/6Lc5L/IQA== +libnpmaccess@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.2.tgz#8b2d72345ba3bef90d3b4f694edd5c0417f58923" + integrity sha512-01512AK7MqByrI2mfC7h5j8N9V4I7MHJuk9buo8Gv+5QgThpOgpjB7sQBDDkeZqRteFb1QM/6YNdHfG7cDvfAQ== dependencies: aproba "^2.0.0" get-stream "^4.0.0" npm-package-arg "^6.1.0" - npm-registry-fetch "^3.8.0" + npm-registry-fetch "^4.0.0" libnpmconfig@^1.2.1: version "1.2.1" @@ -9834,30 +9211,30 @@ libnpmconfig@^1.2.1: find-up "^3.0.0" ini "^1.3.5" -libnpmhook@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-5.0.2.tgz#d12817b0fb893f36f1d5be20017f2aea25825d94" - integrity sha512-vLenmdFWhRfnnZiNFPNMog6CK7Ujofy2TWiM2CrpZUjBRIhHkJeDaAbJdYCT6W4lcHtyrJR8yXW8KFyq6UAp1g== +libnpmhook@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-5.0.3.tgz#4020c0f5edbf08ebe395325caa5ea01885b928f7" + integrity sha512-UdNLMuefVZra/wbnBXECZPefHMGsVDTq5zaM/LgKNE9Keyl5YXQTnGAzEo+nFOpdRqTWI9LYi4ApqF9uVCCtuA== dependencies: aproba "^2.0.0" figgy-pudding "^3.4.1" get-stream "^4.0.0" - npm-registry-fetch "^3.8.0" + npm-registry-fetch "^4.0.0" -libnpmorg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-1.0.0.tgz#979b868c48ba28c5820e3bb9d9e73c883c16a232" - integrity sha512-o+4eVJBoDGMgRwh2lJY0a8pRV2c/tQM/SxlqXezjcAg26Qe9jigYVs+Xk0vvlYDWCDhP0g74J8UwWeAgsB7gGw== +libnpmorg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-1.0.1.tgz#5d2503f6ceb57f33dbdcc718e6698fea6d5ad087" + integrity sha512-0sRUXLh+PLBgZmARvthhYXQAWn0fOsa6T5l3JSe2n9vKG/lCVK4nuG7pDsa7uMq+uTt2epdPK+a2g6btcY11Ww== dependencies: aproba "^2.0.0" figgy-pudding "^3.4.1" get-stream "^4.0.0" - npm-registry-fetch "^3.8.0" + npm-registry-fetch "^4.0.0" -libnpmpublish@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-1.1.1.tgz#ff0c6bb0b4ad2bda2ad1f5fba6760a4af37125f0" - integrity sha512-nefbvJd/wY38zdt+b9SHL6171vqBrMtZ56Gsgfd0duEKb/pB8rDT4/ObUQLrHz1tOfht1flt2zM+UGaemzAG5g== +libnpmpublish@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-1.1.3.tgz#e3782796722d79eef1a0a22944c117e0c4ca4280" + integrity sha512-/3LsYqVc52cHXBmu26+J8Ed7sLs/hgGVFMH1mwYpL7Qaynb9RenpKqIKu0sJ130FB9PMkpMlWjlbtU8A4m7CQw== dependencies: aproba "^2.0.0" figgy-pudding "^3.5.1" @@ -9865,28 +9242,28 @@ libnpmpublish@^1.1.0: lodash.clonedeep "^4.5.0" normalize-package-data "^2.4.0" npm-package-arg "^6.1.0" - npm-registry-fetch "^3.8.0" + npm-registry-fetch "^4.0.0" semver "^5.5.1" ssri "^6.0.1" -libnpmsearch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-2.0.0.tgz#de05af47ada81554a5f64276a69599070d4a5685" - integrity sha512-vd+JWbTGzOSfiOc+72MU6y7WqmBXn49egCCrIXp27iE/88bX8EpG64ST1blWQI1bSMUr9l1AKPMVsqa2tS5KWA== +libnpmsearch@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-2.0.2.tgz#9a4f059102d38e3dd44085bdbfe5095f2a5044cf" + integrity sha512-VTBbV55Q6fRzTdzziYCr64+f8AopQ1YZ+BdPOv16UegIEaE8C0Kch01wo4s3kRTFV64P121WZJwgmBwrq68zYg== dependencies: figgy-pudding "^3.5.1" get-stream "^4.0.0" - npm-registry-fetch "^3.8.0" + npm-registry-fetch "^4.0.0" -libnpmteam@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-1.0.1.tgz#ff704b1b6c06ea674b3b1101ac3e305f5114f213" - integrity sha512-gDdrflKFCX7TNwOMX1snWojCoDE5LoRWcfOC0C/fqF7mBq8Uz9zWAX4B2RllYETNO7pBupBaSyBDkTAC15cAMg== +libnpmteam@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-1.0.2.tgz#8b48bcbb6ce70dd8150c950fcbdbf3feb6eec820" + integrity sha512-p420vM28Us04NAcg1rzgGW63LMM6rwe+6rtZpfDxCcXxM0zUTLl7nPFEnRF3JfFBF5skF/yuZDUthTsHgde8QA== dependencies: aproba "^2.0.0" figgy-pudding "^3.4.1" get-stream "^4.0.0" - npm-registry-fetch "^3.8.0" + npm-registry-fetch "^4.0.0" libnpx@^10.2.0: version "10.2.0" @@ -9943,7 +9320,7 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -loader-runner@^2.3.0: +loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== @@ -9995,7 +9372,7 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash-es@^4.17.11: +lodash-es@^4.17.15: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== @@ -10063,6 +9440,11 @@ lodash.isequal@^4.1.1, lodash.isequal@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= +lodash.ismatch@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" + integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= + lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" @@ -10088,21 +9470,11 @@ lodash.set@^4.3.2: resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= -lodash.some@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.tail@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" - integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ= - lodash.template@^4.0.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" @@ -10158,7 +9530,7 @@ lodash@4.17.14: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== -lodash@4.17.15, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1, lodash@~4.17.10: +lodash@4.17.15, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1, lodash@~4.17.10: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -10170,10 +9542,10 @@ log-symbols@^2.1.0, log-symbols@^2.2.0: dependencies: chalk "^2.0.1" -loglevel@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" - integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= +loglevel@^1.6.4: + version "1.6.6" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312" + integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ== loglevelnext@^1.0.1: version "1.0.5" @@ -10233,7 +9605,7 @@ lowlight@~1.9.1: fault "^1.0.2" highlight.js "~9.12.0" -lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3, lru-cache@^4.1.5: +lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -10249,14 +9621,14 @@ lru-cache@^5.1.1: yallist "^3.0.2" luxon@^1.11.3: - version "1.15.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.15.0.tgz#d06643c437982332a3feff4ee7c718bdbbae09fd" - integrity sha512-HIpK4zIonObWHj9UC80ElykmM/0jTuuXcbPYBYbDGZ3Cq2bL9rACcmppoc6zm5JnmHpnK5bRMIp8/+ei4O0y2Q== + version "1.19.3" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.19.3.tgz#86c04a1395529b4386ae235a8fe16d0a82a0695b" + integrity sha512-YwTDjGRQC0QC9Iya2g2eKZfgEFqRId4ZoLHORQcfTMB/5xrTx427V7ZPjQJ1vzvhA2vJfG2bh1Kv8V8IFMWCUA== macos-release@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.2.0.tgz#ab58d55dd4714f0a05ad4b0e90f4370fef5cdea8" - integrity sha512-iV2IDxZaX8dIcM7fG6cI46uNmHUxHE4yN+Z8tKHAW1TBPMZDIKHf/3L+YnOuj/FK9il14UaVdHmiQ1tsi90ltA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" + integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== make-dir@^1.0.0: version "1.3.0" @@ -10285,17 +9657,17 @@ make-error@1.x: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== -make-fetch-happen@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083" - integrity sha512-7R5ivfy9ilRJ1EMKIOziwrns9fGeAD4bAha8EB7BIiBBLHm2KeTUGCrICFt2rbHfzheTLynv50GnNTK1zDTrcQ== +make-fetch-happen@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.0.tgz#a8e3fe41d3415dd656fe7b8e8172e1fb4458b38d" + integrity sha512-nFr/vpL1Jc60etMVKeaLOqfGjMMb3tAHFVJWxHOFCFS04Zmd7kGlMxo0l1tzfhoQje0/UPnd0X8OeGUiXXnfPA== dependencies: agentkeepalive "^3.4.1" - cacache "^11.0.1" + cacache "^12.0.0" http-cache-semantics "^3.8.1" http-proxy-agent "^2.1.0" https-proxy-agent "^2.2.1" - lru-cache "^4.1.2" + lru-cache "^5.1.1" mississippi "^3.0.0" node-fetch-npm "^2.0.2" promise-retry "^1.1.1" @@ -10359,17 +9731,17 @@ markdown-table@^1.1.0: integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== markdown-to-jsx@^6.9.1, markdown-to-jsx@^6.9.3: - version "6.10.2" - resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.10.2.tgz#644f602b81d088f10aef1c3674874876146cf38b" - integrity sha512-eDCsRobOkbQ4PqCphrxNi/U8geA8DGf52dMP4BrrYsVFyQ2ILFnXIB5sRcIxnRK2nPl8k5hUYdRNRXLlQNYLYg== + version "6.10.3" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.10.3.tgz#7f0946684acd321125ff2de7fd258a9b9c7c40b7" + integrity sha512-PSoUyLnW/xoW6RsxZrquSSz5eGEOTwa15H5eqp3enmrp8esmgDJmhzd6zmQ9tgAA9TxJzx1Hmf3incYU/IamoQ== dependencies: prop-types "^15.6.2" unquote "^1.1.0" marked-terminal@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-3.2.0.tgz#3fc91d54569332bcf096292af178d82219000474" - integrity sha512-Yr1yVS0BbDG55vx7be1D0mdv+jGs9AW563o/Tt/7FTsId2J0yqhrTeXAqq/Q0DyyXltIn6CSxzesQuFqXgafjQ== + version "3.3.0" + resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-3.3.0.tgz#25ce0c0299285998c7636beaefc87055341ba1bd" + integrity sha512-+IUQJ5VlZoAFsM5MHNT7g3RHSkA3eETqhRCdXv4niUMAKHQ7lb1yvAcuGPmm4soxhmtX13u4Li6ZToXtvSEH+A== dependencies: ansi-escapes "^3.1.0" cardinal "^2.1.1" @@ -10418,6 +9790,11 @@ mdast-util-compact@^1.0.0: dependencies: unist-util-visit "^1.1.0" +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + mdn-data@~1.1.0: version "1.1.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" @@ -10433,13 +9810,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - mem@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" @@ -10449,15 +9819,10 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" -memoize-one@^5.0.0: - version "5.0.5" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.5.tgz#8cd3809555723a07684afafcd6f756072ac75d7e" - integrity sha512-ey6EpYv0tEaIbM/nTDOpHciXUvd+ackQrJgEzBwemhZZIWZjcyodqEcrmqDy2BKRTM3a65kKBV4WtLXJDt26SQ== - -memoize-one@^5.0.1: - version "5.0.4" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.4.tgz#005928aced5c43d890a4dfab18ca908b0ec92cbc" - integrity sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA== +memoize-one@^5.0.0, memoize-one@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" + integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== memoizerific@^1.11.3: version "1.11.3" @@ -10466,10 +9831,18 @@ memoizerific@^1.11.3: dependencies: map-or-similar "^1.5.0" -memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= +memory-fs@^0.4.0, memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== dependencies: errno "^0.1.3" readable-stream "^2.0.1" @@ -10539,10 +9912,10 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" - integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== +merge2@^1.2.3, merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== merge@^1.2.1: version "1.2.1" @@ -10559,7 +9932,7 @@ microevent.ts@~0.1.1: resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0" integrity sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g== -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -10594,29 +9967,36 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.40.0, "mime-db@>= 1.40.0 < 2": +mime-db@1.40.0: version "1.40.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +mime-db@1.42.0, "mime-db@>= 1.40.0 < 2": + version "1.42.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" + integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== + +mime-types@^2.1.12, mime-types@~2.1.19: version "2.1.24" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== dependencies: mime-db "1.40.0" +mime-types@~2.1.17, mime-types@~2.1.24: + version "2.1.25" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" + integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== + dependencies: + mime-db "1.42.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.0.3, mime@^2.4.2: - version "2.4.3" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.3.tgz#229687331e86f68924e6cb59e1cdd937f18275fe" - integrity sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw== - -mime@^2.4.3: +mime@^2.0.3, mime@^2.4.3, mime@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== @@ -10631,10 +10011,10 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mimic-response@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" + integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== min-document@^2.19.0: version "2.19.0" @@ -10693,28 +10073,20 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.4, minipass@^2.6.0, minipass@^2.8.6: - version "2.8.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.8.6.tgz#620d889ace26356391d010ecb9458749df9b6db5" - integrity sha512-lFG7d6g3+/UaFDCOtqPiKAC9zngWWsQZl1g5q6gaONqrjq61SX2xFqXMleQiFVyDpYwa018E9hmlAFY22PCb+A== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== +minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.1, minizlib@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.2.tgz#6f0ccc82fa53e1bf2ff145f220d2da9fa6e3a166" - integrity sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ== +minizlib@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== dependencies: - minipass "^2.2.1" + minipass "^2.9.0" mississippi@^3.0.0: version "3.0.0" @@ -10748,26 +10120,13 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" -mobx-react@^5.4.3: - version "5.4.4" - resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-5.4.4.tgz#b3de9c6eabcd0ed8a40036888cb0221ab9568b80" - integrity sha512-2mTzpyEjVB/RGk2i6KbcmP4HWcAUFox5ZRCrGvSyz49w20I4C4qql63grPpYrS9E9GKwgydBHQlA4y665LuRCQ== - dependencies: - hoist-non-react-statics "^3.0.0" - react-lifecycles-compat "^3.0.2" - -mobx@^4.9.2: - version "4.9.4" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-4.9.4.tgz#bb37a0e4e05f0b02be89ced9d23445cad73377ad" - integrity sha512-RaEpydw7D1ebp1pdFHrEMZcLk4nALAZyHAroCPQpqLzuIXIxJpLmMIe5PUZwYHqvlcWL6DVqDYCANZpPOi9iXA== - modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -10817,12 +10176,12 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1, ms@^2.0.0: +ms@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.1.1: +ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -10861,7 +10220,7 @@ mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1, nan@^2.13.2, nan@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -10889,9 +10248,9 @@ natural-compare@^1.4.0: integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= nearley@^2.7.10: - version "2.16.0" - resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.16.0.tgz#77c297d041941d268290ec84b739d0ee297e83a7" - integrity sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg== + version "2.19.0" + resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.19.0.tgz#37717781d0fd0f2bfc95e233ebd75678ca4bda46" + integrity sha512-2v52FTw7RPqieZr3Gth1luAXZR7Je6q3KaDHY5bjl/paDUdMu35fZ8ICNgiYJRr3tf3NMvIQQR1r27AvEr9CRA== dependencies: commander "^2.19.0" moo "^0.4.3" @@ -10913,7 +10272,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.0: +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== @@ -10989,10 +10348,10 @@ node-fetch@^2.3.0, node-fetch@^2.6.0: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -node-forge@0.7.5: - version "0.7.5" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" - integrity sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ== +node-forge@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" + integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== node-gyp@^3.8.0: version "3.8.0" @@ -11012,21 +10371,21 @@ node-gyp@^3.8.0: tar "^2.0.0" which "1" -node-gyp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45" - integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA== +node-gyp@^5.0.2, node-gyp@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.5.tgz#f6cf1da246eb8c42b097d7cd4d6c3ce23a4163af" + integrity sha512-WABl9s4/mqQdZneZHVWVG4TVr6QQJZUC6PAx47ITSk9lreZ1n+7Z9mMAIbA3vnO4J9W20P7LhCxtzfWsAD/KDw== dependencies: + env-paths "^1.0.0" glob "^7.0.3" graceful-fs "^4.1.2" mkdirp "^0.5.0" nopt "2 || 3" npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" request "^2.87.0" rimraf "2" semver "~5.3.0" - tar "^4.4.8" + tar "^4.4.12" which "1" node-int64@^0.4.0: @@ -11034,10 +10393,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-libs-browser@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.0.tgz#c72f60d9d46de08a940dedbb25f3ffa2f9bbaa77" - integrity sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA== +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -11049,7 +10408,7 @@ node-libs-browser@^2.0.0: events "^3.0.0" https-browserify "^1.0.0" os-browserify "^0.3.0" - path-browserify "0.0.0" + path-browserify "0.0.1" process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" @@ -11061,7 +10420,7 @@ node-libs-browser@^2.0.0: tty-browserify "0.0.0" url "^0.11.0" util "^0.11.0" - vm-browserify "0.0.4" + vm-browserify "^1.0.1" node-modules-regexp@^1.0.0: version "1.0.0" @@ -11111,26 +10470,12 @@ node-pre-gyp@^0.12.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.13: - version "1.1.26" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.26.tgz#f30563edc5c7dc20cf524cc8652ffa7be0762937" - integrity sha512-fZPsuhhUHMTlfkhDLGtfY80DSJTjOcx+qD1j5pqPkuhUHVS7xHZIg9EE4DHK8O3f0zTxXHX5VIkDG8pu98/wfQ== - dependencies: - semver "^5.3.0" - -node-releases@^1.1.19: - version "1.1.20" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.20.tgz#f77f9f9a4fcb22e74ba88fe15732a3a8b037146d" - integrity sha512-YnC3NemTLgzOkQTmR4+0yl/7pIsXZcfWXoquNp0Dql03GQ+CYURhnjUDFsSJxpX/Q9nw8lAjLFdnACQoKs6h5w== - dependencies: - semver "^5.3.0" - -node-releases@^1.1.25: - version "1.1.25" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.25.tgz#0c2d7dbc7fed30fbe02a9ee3007b8c90bf0133d3" - integrity sha512-fI5BXuk83lKEoZDdH3gRhtsNgh05/wZacuXkgbiYkceE7+QIMXOg98n9ZV7mz27B+kFHnqHcUpscZZlGRSmTpQ== +node-releases@^1.1.29: + version "1.1.35" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.35.tgz#32a74a3cd497aa77f23d509f483475fd160e4c48" + integrity sha512-JGcM/wndCN/2elJlU0IGdVEJQQnJwsLbgPCFd2pY7V0mxf17bZ0Gb/lgOtL29ZQhvEX5shnVhxQyZz3ex94N8w== dependencies: - semver "^5.3.0" + semver "^6.3.0" node-sass@^4.11.0: version "4.12.0" @@ -11215,9 +10560,9 @@ normalize-url@1.9.1: sort-keys "^1.0.0" normalize-url@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" - integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== npm-audit-report@^1.3.2: version "1.3.2" @@ -11237,21 +10582,21 @@ npm-cache-filename@~1.0.2: resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11" integrity sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE= -npm-install-checks@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.0.tgz#d4aecdfd51a53e3723b7b2f93b2ee28e307bc0d7" - integrity sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc= +npm-install-checks@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.2.tgz#ab2e32ad27baa46720706908e5b14c1852de44d9" + integrity sha512-E4kzkyZDIWoin6uT5howP8VDvkM+E8IQDcHAycaAxMbwkqhIg5eEYALnXOl3Hq9MrkdQB/2/g1xwBINXdKSRkg== dependencies: semver "^2.3.0 || 3.x || 4 || 5" -npm-lifecycle@^2.0.3, npm-lifecycle@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.1.1.tgz#0027c09646f0fd346c5c93377bdaba59c6748fdf" - integrity sha512-+Vg6I60Z75V/09pdcH5iUo/99Q/vop35PaI99elvxk56azSVVsdsSsS/sXqKDNwbRRNN1qSxkcO45ZOu0yOWew== +npm-lifecycle@^3.0.0, npm-lifecycle@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.4.tgz#de6975c7d8df65f5150db110b57cce498b0b604c" + integrity sha512-tgs1PaucZwkxECGKhC/stbEgFyc3TGh2TJcg2CDr6jbvQRdteHNhmMeljRzpe4wgFAXQADoy1cSqqi7mtiAa5A== dependencies: byline "^5.0.0" graceful-fs "^4.1.15" - node-gyp "^4.0.0" + node-gyp "^5.0.2" resolve-from "^4.0.0" slide "^1.1.6" uid-number "0.0.6" @@ -11263,61 +10608,54 @@ npm-logical-tree@^1.2.1: resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88" integrity sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg== -"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" - integrity sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA== +"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0, npm-package-arg@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7" + integrity sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg== dependencies: - hosted-git-info "^2.6.0" + hosted-git-info "^2.7.1" osenv "^0.1.5" - semver "^5.5.0" + semver "^5.6.0" validate-npm-package-name "^3.0.0" -npm-packlist@^1.1.12, npm-packlist@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" - integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== +npm-packlist@^1.1.12, npm-packlist@^1.1.6, npm-packlist@^1.4.4: + version "1.4.6" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" + integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-pick-manifest@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz#32111d2a9562638bb2c8f2bf27f7f3092c8fae40" - integrity sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA== +npm-pick-manifest@^3.0.0, npm-pick-manifest@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz#f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7" + integrity sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw== dependencies: figgy-pudding "^3.5.1" npm-package-arg "^6.0.0" semver "^5.4.1" -npm-profile@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-4.0.1.tgz#d350f7a5e6b60691c7168fbb8392c3603583f5aa" - integrity sha512-NQ1I/1Q7YRtHZXkcuU1/IyHeLy6pd+ScKg4+DQHdfsm769TGq6HPrkbuNJVJS4zwE+0mvvmeULzQdWn2L2EsVA== +npm-profile@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-4.0.2.tgz#8272a71c19634d0dce9c35a5daf8ee589cbb0f52" + integrity sha512-VRsC04pvRH+9cF+PoVh2nTmJjiG21yu59IHpsBpkxk+jaGAV8lxx96G4SDc0jOHAkfWLXbc6kIph3dGAuRnotQ== dependencies: aproba "^1.1.2 || 2" figgy-pudding "^3.4.1" - npm-registry-fetch "^3.8.0" + npm-registry-fetch "^4.0.0" -npm-registry-fetch@^3.8.0, npm-registry-fetch@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.9.0.tgz#44d841780e2833f06accb34488f8c7450d1a6856" - integrity sha512-srwmt8YhNajAoSAaDWndmZgx89lJwIZ1GWxOuckH4Coek4uHv5S+o/l9FLQe/awA+JwTnj4FJHldxhlXdZEBmw== +npm-registry-fetch@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz#2b1434f93ccbe6b6385f8e45f45db93e16921d7a" + integrity sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A== dependencies: JSONStream "^1.3.4" bluebird "^3.5.1" figgy-pudding "^3.4.1" - lru-cache "^4.1.3" - make-fetch-happen "^4.0.1" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" npm-package-arg "^6.1.0" + safe-buffer "^5.2.0" npm-run-path@^2.0.0: version "2.0.2" @@ -11338,10 +10676,10 @@ npm-user-validate@~1.0.0: resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951" integrity sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE= -npm@^6.8.0: - version "6.9.0" - resolved "https://registry.yarnpkg.com/npm/-/npm-6.9.0.tgz#5296720486814a64a7fb082de00c4b5cfd11211f" - integrity sha512-91V+zB5hDxO+Jyp2sUKS7juHlIM95dGQxTeQtmZI1nAI/7kjWXFipPrtwwKjhyKmV4GsS2LzJhrxRjGWsU9z/w== +npm@^6.10.3: + version "6.12.0" + resolved "https://registry.yarnpkg.com/npm/-/npm-6.12.0.tgz#255e6fbb514be15c6595f9cbc5bc248e251e1476" + integrity sha512-juj5VkB3/k+PWbJUnXD7A/8oc8zLusDnK/sV9PybSalsbOVOTIp5vSE0rz5rQ7BsmUgQS47f/L2GYQnWXaKgnQ== dependencies: JSONStream "^1.3.5" abbrev "~1.1.1" @@ -11349,16 +10687,16 @@ npm@^6.8.0: ansistyles "~0.1.3" aproba "^2.0.0" archy "~1.0.0" - bin-links "^1.1.2" - bluebird "^3.5.3" + bin-links "^1.1.3" + bluebird "^3.5.5" byte-size "^5.0.1" - cacache "^11.3.2" - call-limit "~1.1.0" - chownr "^1.1.1" + cacache "^12.0.3" + call-limit "^1.1.1" + chownr "^1.1.2" ci-info "^2.0.0" cli-columns "^3.1.2" cli-table3 "^0.5.1" - cmd-shim "~2.0.2" + cmd-shim "^3.0.3" columnify "~1.5.4" config-chain "^1.1.12" detect-indent "~5.0.0" @@ -11369,22 +10707,27 @@ npm@^6.8.0: find-npm-prefix "^1.0.2" fs-vacuum "~1.2.10" fs-write-stream-atomic "~1.0.10" - gentle-fs "^2.0.1" - glob "^7.1.3" - graceful-fs "^4.1.15" + gentle-fs "^2.2.1" + glob "^7.1.4" + graceful-fs "^4.2.2" has-unicode "~2.0.1" - hosted-git-info "^2.7.1" + hosted-git-info "^2.8.5" iferr "^1.0.2" + infer-owner "^1.0.4" inflight "~1.0.6" - inherits "~2.0.3" + inherits "^2.0.4" ini "^1.3.5" init-package-json "^1.10.3" is-cidr "^3.0.0" json-parse-better-errors "^1.0.2" lazy-property "~1.0.0" - libcipm "^3.0.3" - libnpm "^2.0.1" - libnpmhook "^5.0.2" + libcipm "^4.0.4" + libnpm "^3.0.1" + libnpmaccess "^3.0.2" + libnpmhook "^5.0.3" + libnpmorg "^1.0.1" + libnpmsearch "^2.0.2" + libnpmteam "^1.0.2" libnpx "^10.2.0" lock-verify "^2.1.0" lockfile "^1.0.4" @@ -11393,51 +10736,53 @@ npm@^6.8.0: lodash.union "~4.6.0" lodash.uniq "~4.5.0" lodash.without "~4.4.0" - lru-cache "^4.1.5" + lru-cache "^5.1.1" meant "~1.0.1" mississippi "^3.0.0" mkdirp "~0.5.1" move-concurrently "^1.0.1" - node-gyp "^3.8.0" + node-gyp "^5.0.5" nopt "~4.0.1" normalize-package-data "^2.5.0" npm-audit-report "^1.3.2" npm-cache-filename "~1.0.2" - npm-install-checks "~3.0.0" - npm-lifecycle "^2.1.0" - npm-package-arg "^6.1.0" - npm-packlist "^1.4.1" - npm-pick-manifest "^2.2.3" - npm-registry-fetch "^3.9.0" + npm-install-checks "^3.0.2" + npm-lifecycle "^3.1.4" + npm-package-arg "^6.1.1" + npm-packlist "^1.4.4" + npm-pick-manifest "^3.0.2" + npm-profile "^4.0.2" + npm-registry-fetch "^4.0.0" npm-user-validate "~1.0.0" npmlog "~4.1.2" once "~1.4.0" opener "^1.5.1" osenv "^0.1.5" - pacote "^9.5.0" + pacote "^9.5.8" path-is-inside "~1.0.2" promise-inflight "~1.0.1" qrcode-terminal "^0.12.0" - query-string "^6.2.0" + query-string "^6.8.2" qw "~1.0.1" read "~1.0.7" - read-cmd-shim "~1.0.1" + read-cmd-shim "^1.0.4" read-installed "~4.0.3" - read-package-json "^2.0.13" - read-package-tree "^5.2.2" - readable-stream "^3.1.1" + read-package-json "^2.1.0" + read-package-tree "^5.3.1" + readable-stream "^3.4.0" + readdir-scoped-modules "^1.1.0" request "^2.88.0" retry "^0.12.0" rimraf "^2.6.3" safe-buffer "^5.1.2" - semver "^5.6.0" - sha "~2.0.1" + semver "^5.7.1" + sha "^3.0.0" slide "~1.1.6" sorted-object "~2.0.1" sorted-union-stream "~2.1.3" ssri "^6.0.1" - stringify-package "^1.0.0" - tar "^4.4.8" + stringify-package "^1.0.1" + tar "^4.4.12" text-table "~0.2.0" tiny-relative-date "^1.3.0" uid-number "0.0.6" @@ -11449,8 +10794,8 @@ npm@^6.8.0: validate-npm-package-license "^3.0.4" validate-npm-package-name "~3.0.0" which "^1.3.1" - worker-farm "^1.6.0" - write-file-atomic "^2.4.2" + worker-farm "^1.7.0" + write-file-atomic "^2.4.3" "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2, npmlog@~4.1.2: version "4.1.2" @@ -11551,14 +10896,14 @@ object.entries@^1.0.4, object.entries@^1.1.0: has "^1.0.3" object.fromentries@^2.0.0, "object.fromentries@^2.0.0 || ^1.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab" - integrity sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA== + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.1.tgz#050f077855c7af8ae6649f45c80b16ee2d31e704" + integrity sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA== dependencies: - define-properties "^1.1.2" - es-abstract "^1.11.0" + define-properties "^1.1.3" + es-abstract "^1.15.0" function-bind "^1.1.1" - has "^1.0.1" + has "^1.0.3" object.getownpropertydescriptors@^2.0.3: version "2.0.3" @@ -11628,7 +10973,7 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -open@^6.1.0: +open@^6.1.0, open@^6.3.0: version "6.4.0" resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== @@ -11640,13 +10985,6 @@ opener@^1.5.1: resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== -opn@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035" - integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw== - dependencies: - is-wsl "^1.1.0" - opn@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" @@ -11698,15 +11036,6 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - os-locale@^3.0.0, os-locale@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -11716,7 +11045,7 @@ os-locale@^3.0.0, os-locale@^3.1.0: lcid "^2.0.0" mem "^4.0.0" -os-name@^3.0.0: +os-name@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== @@ -11749,13 +11078,6 @@ p-each-series@^1.0.0: dependencies: p-reduce "^1.0.0" -p-filter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-1.0.0.tgz#629d317150209c8fd508ba137713ef4bb920e9db" - integrity sha1-Yp0xcVAgnI/VCLoTdxPvS7kg6ds= - dependencies: - p-map "^1.0.0" - p-filter@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c" @@ -11778,6 +11100,11 @@ p-is-promise@^2.0.0: resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== +p-is-promise@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-3.0.0.tgz#58e78c7dfe2e163cf2a04ff869e7c1dba64a5971" + integrity sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ== + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -11785,20 +11112,13 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== dependencies: p-try "^2.0.0" -p-limit@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" - integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== - dependencies: - p-try "^2.0.0" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -11820,11 +11140,6 @@ p-locate@^4.0.0, p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-map@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== - p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -11840,7 +11155,7 @@ p-reduce@^2.0.0: resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.1.0.tgz#09408da49507c6c274faa31f28df334bc712b64a" integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== -p-retry@^3.0.0: +p-retry@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== @@ -11875,18 +11190,20 @@ package-json@^4.0.0: registry-url "^3.0.3" semver "^5.1.0" -pacote@^9.1.0, pacote@^9.2.3, pacote@^9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.0.tgz#85f3013a3f6dd51c108b0ccabd3de8102ddfaeda" - integrity sha512-aUplXozRbzhaJO48FaaeClmN+2Mwt741MC6M3bevIGZwdCaP7frXzbUOfOWa91FPHoLITzG0hYaKY363lxO3bg== +pacote@^9.1.0, pacote@^9.5.3, pacote@^9.5.8: + version "9.5.8" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.8.tgz#23480efdc4fa74515855c9ecf39cf64078f99786" + integrity sha512-0Tl8Oi/K0Lo4MZmH0/6IsT3gpGf9eEAznLXEQPKgPq7FscnbUOyopnVpwXlnQdIbCUaojWy1Wd7VMyqfVsRrIw== dependencies: bluebird "^3.5.3" - cacache "^11.3.2" + cacache "^12.0.2" + chownr "^1.1.2" figgy-pudding "^3.5.1" get-stream "^4.1.0" glob "^7.1.3" + infer-owner "^1.0.4" lru-cache "^5.1.1" - make-fetch-happen "^4.0.1" + make-fetch-happen "^5.0.0" minimatch "^3.0.4" minipass "^2.3.5" mississippi "^3.0.0" @@ -11894,8 +11211,8 @@ pacote@^9.1.0, pacote@^9.2.3, pacote@^9.5.0: normalize-package-data "^2.4.0" npm-package-arg "^6.1.0" npm-packlist "^1.1.12" - npm-pick-manifest "^2.2.3" - npm-registry-fetch "^3.8.0" + npm-pick-manifest "^3.0.0" + npm-registry-fetch "^4.0.0" osenv "^0.1.5" promise-inflight "^1.0.1" promise-retry "^1.1.1" @@ -11904,7 +11221,7 @@ pacote@^9.1.0, pacote@^9.2.3, pacote@^9.5.0: safe-buffer "^5.1.2" semver "^5.6.0" ssri "^6.0.1" - tar "^4.4.8" + tar "^4.4.10" unique-filename "^1.1.1" which "^1.3.1" @@ -11914,15 +11231,15 @@ pako@~1.0.5: integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== parallel-transform@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" - integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== dependencies: - cyclist "~0.2.2" + cyclist "^1.0.1" inherits "^2.0.3" readable-stream "^2.1.5" -param-case@2.1.x: +param-case@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= @@ -11937,9 +11254,9 @@ parent-module@^1.0.0: callsites "^3.0.0" parse-asn1@^5.0.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" - integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -12000,7 +11317,7 @@ parse5@4.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== -parse5@5.1.0, parse5@^5.0.0: +parse5@5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== @@ -12022,10 +11339,10 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== path-dirname@^1.0.0: version "1.0.2" @@ -12129,9 +11446,9 @@ performance-now@^2.1.0: integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= picomatch@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" - integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + version "2.1.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" + integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== pify@^2.0.0, pify@^2.3.0: version "2.3.0" @@ -12211,9 +11528,9 @@ pkg-up@2.0.0: find-up "^2.1.0" please-upgrade-node@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" - integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ== + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== dependencies: semver-compare "^1.0.0" @@ -12246,14 +11563,14 @@ popper.js@^1.14.4, popper.js@^1.14.7: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2" integrity sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA== -portfinder@^1.0.20: - version "1.0.20" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" - integrity sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw== +portfinder@^1.0.25: + version "1.0.25" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" + integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== dependencies: - async "^1.5.2" - debug "^2.2.0" - mkdirp "0.5.x" + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.1" posix-character-classes@^0.1.0: version "0.1.1" @@ -12286,11 +11603,11 @@ postcss-flexbugs-fixes@^4.1.0: postcss "^7.0.0" postcss-load-config@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" - integrity sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" + integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== dependencies: - cosmiconfig "^4.0.0" + cosmiconfig "^5.0.0" import-cwd "^2.0.0" postcss-loader@^3.0.0: @@ -12359,24 +11676,15 @@ postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d" - integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ== - -postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.16" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.16.tgz#48f64f1b4b558cb8b52c88987724359acb010da2" - integrity sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" +postcss-value-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== -postcss@^7.0.17, postcss@^7.0.7: - version "7.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" - integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== +postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.18, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: + version "7.0.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233" + integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -12447,13 +11755,20 @@ pretty-quick@^2.0.0: mri "^1.1.4" multimatch "^4.0.0" -prismjs@^1.8.4, prismjs@~1.16.0: +prismjs@^1.8.4: version "1.16.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.16.0.tgz#406eb2c8aacb0f5f0f1167930cb83835d10a4308" integrity sha512-OA4MKxjFZHSvZcisLGe14THYsug/nF6O1f0pAJc0KN0wTyAcLqmsbE+lTGKSpyh+9pEW57+k6pg2AfYR+coyHA== optionalDependencies: clipboard "^2.0.0" +prismjs@~1.17.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.17.1.tgz#e669fcbd4cdd873c35102881c33b14d0d68519be" + integrity sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q== + optionalDependencies: + clipboard "^2.0.0" + private@^0.1.6, private@^0.1.8, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -12469,11 +11784,6 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -process@~0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= - progress@^2.0.0, progress@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -12502,12 +11812,12 @@ promise.allsettled@^1.0.0: function-bind "^1.1.1" promise.prototype.finally@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.0.tgz#66f161b1643636e50e7cf201dc1b84a857f3864e" - integrity sha512-7p/K2f6dI+dM8yjRQEGrTQs5hTQixUAdOGpMEA3+pVxpX5oHKRSKAXyLw9Q9HUWDTdwtoo39dSHGQtN90HcEwQ== + version "3.1.1" + resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.1.tgz#cb279d3a5020ca6403b3d92357f8e22d50ed92aa" + integrity sha512-gnt8tThx0heJoI3Ms8a/JdkYBVhYP/wv+T7yQimR+kdOEJL21xTFbiJhMRqnSPcr54UVvMbsscDk2w+ivyaLPw== dependencies: - define-properties "^1.1.2" - es-abstract "^1.9.0" + define-properties "^1.1.3" + es-abstract "^1.13.0" function-bind "^1.1.1" promise@^7.1.1: @@ -12550,10 +11860,10 @@ prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, object-assign "^4.1.1" react-is "^16.8.1" -property-information@^5.0.0, property-information@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.1.0.tgz#e4755eee5319f03f7f6f5a9bc1a6a7fea6609e2c" - integrity sha512-tODH6R3+SwTkAQckSp2S9xyYX8dEKYkeXw+4TmJzTxnNzd6mQPu1OD4f9zPrvw/Rm4wpPgI+Zp63mNSGNzUgHg== +property-information@^5.0.1: + version "5.3.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.3.0.tgz#bc87ac82dc4e72a31bb62040544b1bf9653da039" + integrity sha512-IslotQn1hBCZDY7SaJ3zmCjVea219VTwmOk6Pu3z9haU9m4+T8GwaDubur+6NMHEU+Fjs/6/p66z6QULPkcL1w== dependencies: xtend "^4.0.1" @@ -12673,11 +11983,16 @@ qrcode-terminal@^0.12.0: resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== -qs@6.7.0, qs@^6.6.0: +qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@^6.6.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.0.tgz#d1297e2a049c53119cb49cca366adbbacc80b409" + integrity sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA== + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -12691,10 +12006,10 @@ query-string@^4.1.0: object-assign "^4.1.0" strict-uri-encode "^1.0.0" -query-string@^6.2.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.5.0.tgz#2e1a70125af01f6f04573692d02c09302a1d8bfc" - integrity sha512-TYC4hDjZSvVxLMEucDMySkuAS9UIzSbAiYGyA9GWCjLKB8fQpviFbjd20fD7uejCDxZS+ftSdBKE6DS+xucJFg== +query-string@^6.8.2: + version "6.8.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.8.3.tgz#fd9fb7ffb068b79062b43383685611ee47777d4b" + integrity sha512-llcxWccnyaWlODe7A9hRjkvdCKamEKTh+wH8ITdTc3OhchaqUZteiSCX/2ablWHVrkVIe04dntnaZJ7BdyW0lQ== dependencies: decode-uri-component "^0.2.0" split-on-first "^1.0.0" @@ -12725,10 +12040,10 @@ qw@~1.0.1: resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4" integrity sha1-77/cdA+a0FQwRCassYNBLMi5ltQ= -raf-schd@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.0.tgz#9855756c5045ff4ed4516e14a47719387c3c907b" - integrity sha512-m7zq0JkIrECzw9mO5Zcq6jN4KayE34yoIS9hJoiZNXyOAT06PPA8PrR+WtJIeFW09YjUfNkMMN9lrmAt6BURCA== +raf-schd@^4.0.0, raf-schd@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" + integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== raf@^3.4.0: version "3.4.1" @@ -12803,6 +12118,11 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" +re-reselect@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/re-reselect/-/re-reselect-3.4.0.tgz#0f2303f3c84394f57f0cd31fea08a1ca4840a7cd" + integrity sha512-JsecfN+JlckncVXTWFWjn0Vk6uInl8GSf4eEd9tTk5qXHlgqkPdILpnYpgZcISXNYAzvfvsCZviaDk8AxyS5sg== + react-ace@^5.5.0: version "5.10.0" resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.10.0.tgz#e328b37ac52759f700be5afdb86ada2f5ec84c5e" @@ -12837,12 +12157,11 @@ react-beautiful-dnd@^10.1.0: tiny-invariant "^1.0.4" react-clientside-effect@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.0.tgz#db823695f75e9616a5e4dd6d908e5ea627fb2516" - integrity sha512-cVIsGG7SNHsQsCP4+fw7KFUB0HiYiU8hbvL640XaLCbZ31aK8/lj0qOKJ2K+xRjuQz/IM4Q4qclI0aEqTtcXtA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837" + integrity sha512-nRmoyxeok5PBO6ytPvSjKp9xwXg9xagoTK1mMjwnQxqM9Hd7MNPl+LS1bOSOe+CV2+4fnEquc7H/S8QD3q697A== dependencies: "@babel/runtime" "^7.0.0" - shallowequal "^1.1.0" react-color@^2.17.0: version "2.17.3" @@ -12857,44 +12176,44 @@ react-color@^2.17.0: tinycolor2 "^1.4.1" react-dev-utils@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.0.1.tgz#5c03d85a0b2537d0c46af7165c24a7dfb274bef2" - integrity sha512-pnaeMo/Pxel8aZpxk1WwxT3uXxM3tEwYvsjCYn5R7gNxjhN1auowdcLDzFB8kr7rafAj2rxmvfic/fbac5CzwQ== + version "9.1.0" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.1.0.tgz#3ad2bb8848a32319d760d0a84c56c14bdaae5e81" + integrity sha512-X2KYF/lIGyGwP/F/oXgGDF24nxDA2KC4b7AFto+eqzc/t838gpSGiaU8trTqHXOohuLxxc5qi1eDzsl9ucPDpg== dependencies: - "@babel/code-frame" "7.0.0" - address "1.0.3" - browserslist "4.5.4" + "@babel/code-frame" "7.5.5" + address "1.1.2" + browserslist "4.7.0" chalk "2.4.2" cross-spawn "6.0.5" detect-port-alt "1.1.6" escape-string-regexp "1.0.5" filesize "3.6.1" find-up "3.0.0" - fork-ts-checker-webpack-plugin "1.1.1" + fork-ts-checker-webpack-plugin "1.5.0" global-modules "2.0.0" globby "8.0.2" - gzip-size "5.0.0" + gzip-size "5.1.1" immer "1.10.0" - inquirer "6.2.2" - is-root "2.0.0" + inquirer "6.5.0" + is-root "2.1.0" loader-utils "1.2.3" - opn "5.4.0" + open "^6.3.0" pkg-up "2.0.0" - react-error-overlay "^5.1.6" + react-error-overlay "^6.0.3" recursive-readdir "2.2.2" - shell-quote "1.6.1" - sockjs-client "1.3.0" + shell-quote "1.7.2" + sockjs-client "1.4.0" strip-ansi "5.2.0" text-table "0.2.0" react-docgen-typescript-loader@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/react-docgen-typescript-loader/-/react-docgen-typescript-loader-3.1.0.tgz#09cacf872617c97f946ee920d2239f51d543be41" - integrity sha512-gY+b7RkRPty5ZN4NMQ+jwx9MzTVuIj6LJCwdWRAi1+nrHJfH2gMMytQfxFdzQ7BlgD4COWnSE8Ixtl2L62kCRw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/react-docgen-typescript-loader/-/react-docgen-typescript-loader-3.3.0.tgz#c1f5c1db9a2b6a6bca220bc50fee0a071bc75499" + integrity sha512-gC0TeWTz7s7OMyeABppQGbbrtSNi0yl/gBgZJElBtaBFNSJlHH1sfgQybHZmlZqFcn4UBa+8DOGT6wEJKWTV6g== dependencies: "@webpack-contrib/schema-utils" "^1.0.0-beta.0" loader-utils "^1.2.3" - react-docgen-typescript "^1.12.3" + react-docgen-typescript "^1.15.0" react-docgen-typescript-webpack-plugin@^1.1.0: version "1.1.0" @@ -12904,10 +12223,10 @@ react-docgen-typescript-webpack-plugin@^1.1.0: ajv "^6.1.1" react-docgen-typescript "^1.2.3" -react-docgen-typescript@^1.12.3, react-docgen-typescript@^1.2.3: - version "1.12.4" - resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.12.4.tgz#9ec8080e9ef41067ff17153bf42b3b2d49ae5503" - integrity sha512-OSmUfmdtcz4kLRWPiR8uUdE8ta+s5DV0uXOz1YsWaAUf3Ty64use7DYWK97zH8ZOlD4slq5zUfGc+UbfGLqfEQ== +react-docgen-typescript@^1.15.0, react-docgen-typescript@^1.2.3: + version "1.15.0" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-1.15.0.tgz#963f14210841f9b51ed18c65152a6cc37f1c3184" + integrity sha512-8xObdkRQbrc0505tEdVRO+pdId8pKFyD6jhLYM9FDdceKma+iB+a17Dk7e3lPRBRh8ArQLCedOCOfN/bO338kw== react-docgen@^4.1.0: version "4.1.1" @@ -12923,35 +12242,35 @@ react-docgen@^4.1.0: recast "^0.17.3" react-dom@^16.8.3: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" - integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA== + version "16.10.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.10.2.tgz#4840bce5409176bc3a1f2bd8cb10b92db452fda6" + integrity sha512-kWGDcH3ItJK4+6Pl9DZB16BXYAZyrYQItU4OMy0jAkv5aNqc+mAKb4TpFtAteI6TJZu+9ZlNhaeNQSVQDHJzkw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.6" + scheduler "^0.16.2" react-draggable@^3.1.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.3.0.tgz#2ed7ea3f92e7d742d747f9e6324860606cd4d997" - integrity sha512-U7/jD0tAW4T0S7DCPK0kkKLyL0z61sC/eqU+NUfDjnq+JtBKaYKDHpsK2wazctiA4alEzCXUnzkREoxppOySVw== + version "3.3.2" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.3.2.tgz#966ef1d90f2387af3c2d8bd3516f601ea42ca359" + integrity sha512-oaz8a6enjbPtx5qb0oDWxtDNuybOylvto1QLydsXgKmwT7e3GXC2eMVDwEMIUYJIFqVG72XpOv673UuuAq6LhA== dependencies: classnames "^2.2.5" prop-types "^15.6.0" react-element-to-jsx-string@^14.0.2: - version "14.0.3" - resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.0.3.tgz#64f50fdbf6ba154d6439da3d7307f79069b94d58" - integrity sha512-ziZAm7OwEfFtyhCmQiFNI87KFu+G9EP8qVW4XtDHdKNqqprYifLzqXkzHqC1vnVsPhyp2znoPm0bJHAf1mUBZA== + version "14.1.0" + resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.1.0.tgz#31fcc3a82459d5e57ef852aa6879bcd0a578a8cb" + integrity sha512-uvfAsY6bn2c8HMBkxwj+2MMXcvNIkKDl0aZg2Jhzp+c096hZaXUNivVCP2H4RBtmGSSJcfMqQA5oPk8YdqFOVw== dependencies: + "@base2/pretty-print-object" "^1.0.0" is-plain-object "3.0.0" - stringify-object "3.3.0" -react-error-overlay@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.6.tgz#0cd73407c5d141f9638ae1e0c63e7b2bf7e9929d" - integrity sha512-X1Y+0jR47ImDVr54Ab6V9eGk0Hnu7fVWGeHQSOXHf/C2pF9c6uy3gef8QUeuUiWlNb0i08InPSE5a/KJzNzw1Q== +react-error-overlay@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.3.tgz#c378c4b0a21e88b2e159a3e62b2f531fd63bf60d" + integrity sha512-bOUvMWFQVk5oz8Ded9Xb7WVdEi3QGLC8tH7HmYP0Fdp4Bn3qw0tRFmr5TW6mvahzvmrK4a6bqWGfCevBflP+Xw== react-fast-compare@2.0.4: version "2.0.4" @@ -12969,9 +12288,9 @@ react-focus-lock@^1.17.7, react-focus-lock@^1.18.3: react-clientside-effect "^1.2.0" react-helmet-async@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.0.2.tgz#bb55dd8268f7b15aac69c6b22e2f950abda8cc44" - integrity sha512-qzzchrM/ibHuPS/60ief8jaibPunuRdeta4iBDQV+ri2SFKwOV+X2NlEpvevZOauhmHrH/I6dI4E90EPVfJBBg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.0.3.tgz#68a176dd266c2caf63762879c573a866b89a2098" + integrity sha512-hthnzAPasSX0ZU0adR1YW51xtMhwQuMwxtyjb/OeS2Gu2bzqFnCtt2h93nENE0+97NPeUS0+YHOriEMX8j/W0w== dependencies: "@babel/runtime" "7.3.4" invariant "2.2.4" @@ -12987,9 +12306,9 @@ react-hotkeys@2.0.0-pre4: prop-types "^15.6.1" react-input-autosize@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8" - integrity sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA== + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" + integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== dependencies: prop-types "^15.5.8" @@ -13002,15 +12321,10 @@ react-inspector@^3.0.2: is-dom "^1.0.9" prop-types "^15.6.1" -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.3, react-is@^16.8.6: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" - integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== - -react-is@^16.8.4: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" - integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== +react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.3, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: + version "16.10.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.10.2.tgz#984120fd4d16800e9a738208ab1fba422d23b5ab" + integrity sha512-INBT1QEgtcCCgvccr5/86CfD71fw9EPmDxgiJX4I2Ddr6ZsV6iFXsuby+qWJPtmNuMY0zByTsG4468P7nHuNWA== react-is@~16.3.0: version "16.3.2" @@ -13031,20 +12345,20 @@ react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.2, react-lifecycles integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== react-popper-tooltip@^2.8.3: - version "2.8.3" - resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.8.3.tgz#1c63e7473a96362bd93be6c94fa404470a265197" - integrity sha512-g5tfxmuj8ClNVwH4zswYJcD3GKoc5RMeRawd/WZnbyZGEDecsRKaVL+Kj7L3BG7w5qb6/MHcLTG8yE4CidwezQ== + version "2.9.1" + resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.9.1.tgz#cc602c89a937aea378d9e2675b1ce62805beb4f6" + integrity sha512-LSbvXLEQlNKWig2GMKQW/1bBwCkWIr9cpJ+WJpSGGGhX45CthRtwyilPPLJQkc3qI6UMTAXPp0Fe/pj9E77trg== dependencies: - "@babel/runtime" "^7.4.5" - react-popper "^1.3.3" + "@babel/runtime" "^7.6.3" + react-popper "^1.3.4" -react-popper@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.3.tgz#2c6cef7515a991256b4f0536cd4bdcb58a7b6af6" - integrity sha512-ynMZBPkXONPc5K4P5yFWgZx5JGAUIP3pGGLNs58cfAPgK67olx7fmLp+AdpZ0+GoQ+ieFDa/z4cdV6u7sioH6w== +react-popper@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.4.tgz#f0cd3b0d30378e1f663b0d79bcc8614221652ced" + integrity sha512-9AcQB29V+WrBKk6X7p0eojd1f25/oJajVdMZkywIoAV6Ag7hzE1Mhyeup2Q1QnvFRtGQFQvtqfhlEoDAPfKAVA== dependencies: "@babel/runtime" "^7.1.2" - create-react-context "<=0.2.2" + create-react-context "^0.3.0" popper.js "^1.14.4" prop-types "^15.6.1" typed-styles "^0.0.7" @@ -13061,27 +12375,39 @@ react-reconciler@^0.20.1: scheduler "^0.13.6" react-redux@^5.0.7: - version "5.1.1" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.1.tgz#88e368682c7fa80e34e055cd7ac56f5936b0f52f" - integrity sha512-LE7Ned+cv5qe7tMV5BPYkGQ5Lpg8gzgItK07c67yHvJ8t0iaD9kPFPAli/mYkiyJYrs2pJgExR2ZgsGqlrOApg== + version "5.1.2" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57" + integrity sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q== dependencies: "@babel/runtime" "^7.1.2" - hoist-non-react-statics "^3.1.0" + hoist-non-react-statics "^3.3.0" invariant "^2.2.4" loose-envify "^1.1.0" prop-types "^15.6.1" react-is "^16.6.0" react-lifecycles-compat "^3.0.0" +react-redux@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.1.tgz#ce6eee1b734a7a76e0788b3309bf78ff6b34fa0a" + integrity sha512-QsW0vcmVVdNQzEkrgzh2W3Ksvr8cqpAv5FhEk7tNEft+5pp7rXxAudTz3VOPawRkLIepItpkEIyLcN/VVXzjTg== + dependencies: + "@babel/runtime" "^7.5.5" + hoist-non-react-statics "^3.3.0" + invariant "^2.2.4" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^16.9.0" + react-resize-detector@^4.0.5: - version "4.2.0" - resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-4.2.0.tgz#b87aee6b37c9e8a52daca8736b3230cf6a2a8647" - integrity sha512-AtOaNIxs0ydua7tEoglXR3902/EdlIj9PXDu1Zj0ug2VAUnkSQjguLGzaG/N6CXLOhJSccTsUCZxjLayQ1mE9Q== + version "4.2.1" + resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-4.2.1.tgz#8982b74c3e1cf949afaa3c41050458c87b033982" + integrity sha512-ZfPMBPxXi0o3xox42MIEtz84tPSVMW9GgwLHYvjVXlFM+OkNzbeEtpVSV+mSTJmk4Znwomolzt35zHN9LNBQMQ== dependencies: - lodash "^4.17.11" - lodash-es "^4.17.11" + lodash "^4.17.15" + lodash-es "^4.17.15" prop-types "^15.7.2" - raf-schd "^4.0.0" + raf-schd "^4.0.2" resize-observer-polyfill "^1.5.1" react-select@^2.2.0: @@ -13098,9 +12424,9 @@ react-select@^2.2.0: react-transition-group "^2.2.1" react-spring@^8.0.8: - version "8.0.20" - resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-8.0.20.tgz#e25967f6059364b09cf0339168d73014e87c9d17" - integrity sha512-40ZUQ5uI5YHsoQWLPchWNcEUh6zQ6qvcVDeTI2vW10ldoCN3PvDsII9wBH2xEbMl+BQvYmHzGdfLTQxPxJWGnQ== + version "8.0.27" + resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-8.0.27.tgz#97d4dee677f41e0b2adcb696f3839680a3aa356a" + integrity sha512-nDpWBe3ZVezukNRandTeLSPcwwTMjNVu1IDq9qA/AMiUqHuRN4BeSWvKr3eIxxg1vtiYiOLy4FqdfCP5IoP77g== dependencies: "@babel/runtime" "^7.3.1" prop-types "^15.5.8" @@ -13117,14 +12443,14 @@ react-syntax-highlighter@^8.0.1: refractor "^2.4.1" react-test-renderer@^16.0.0-0: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1" - integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw== + version "16.10.2" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.10.2.tgz#4d8492f8678c9b43b721a7d79ed0840fdae7c518" + integrity sha512-k9Qzyev6cTIcIfrhgrFlYQAFxh5EEDO6ALNqYqmKsWVA7Q/rUMTay5nD3nthi6COmYsd4ghVYyi8U86aoeMqYQ== dependencies: object-assign "^4.1.1" prop-types "^15.6.2" react-is "^16.8.6" - scheduler "^0.13.6" + scheduler "^0.16.2" react-textarea-autosize@^7.1.0: version "7.1.0" @@ -13158,14 +12484,13 @@ react-virtualized@^9.18.5: react-lifecycles-compat "^3.0.4" react@^16.8.3: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" - integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw== + version "16.10.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.10.2.tgz#a5ede5cdd5c536f745173c8da47bda64797a4cf0" + integrity sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.13.6" reactcss@^1.2.0: version "1.2.3" @@ -13181,10 +12506,10 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" -read-cmd-shim@^1.0.1, read-cmd-shim@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b" - integrity sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs= +read-cmd-shim@^1.0.1, read-cmd-shim@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.4.tgz#b4a53d43376211b45243f0072b6e603a8e37640d" + integrity sha512-Pqpl3qJ/QdOIjRYA0q5DND/gLvGOfpIz/fYVDGYpOXfW/lFrIttmLsBnd6IkyK10+JHU9zhsaudfvrQTBB9YFQ== dependencies: graceful-fs "^4.1.2" @@ -13202,10 +12527,10 @@ read-installed@~4.0.3: optionalDependencies: graceful-fs "^4.1.2" -"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a" - integrity sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg== +"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13, read-package-json@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.0.tgz#e3d42e6c35ea5ae820d9a03ab0c7291217fc51d5" + integrity sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A== dependencies: glob "^7.1.1" json-parse-better-errors "^1.0.1" @@ -13214,16 +12539,14 @@ read-installed@~4.0.3: optionalDependencies: graceful-fs "^4.1.2" -read-package-tree@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.2.tgz#4b6a0ef2d943c1ea36a578214c9a7f6b7424f7a8" - integrity sha512-rW3XWUUkhdKmN2JKB4FL563YAgtINifso5KShykufR03nJ5loGFlkUMe1g/yxmqX073SoYYTsgXu7XdDinKZuA== +read-package-tree@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636" + integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw== dependencies: - debuglog "^1.0.1" - dezalgo "^1.0.0" - once "^1.3.0" read-package-json "^2.0.0" readdir-scoped-modules "^1.0.0" + util-promisify "^2.1.0" read-pkg-up@^1.0.1: version "1.0.1" @@ -13302,17 +12625,7 @@ read-pkg@^4.0.1: parse-json "^4.0.0" pify "^3.0.0" -read-pkg@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.1.1.tgz#5cf234dde7a405c90c88a519ab73c467e9cb83f5" - integrity sha512-dFcTLQi6BZ+aFUaICg7er+/usEoqFdQxiEBsEMNGoipenihtxxtdrQuBXvyANCEI8VuUIVYFgeHGx9sLLvim4w== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^4.0.0" - type-fest "^0.4.1" - -read-pkg@^5.1.1: +read-pkg@^5.0.0, read-pkg@^5.1.1: version "5.2.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== @@ -13342,10 +12655,10 @@ read@1, read@~1.0.1, read@~1.0.7: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9" - integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw== +"readable-stream@2 || 3", readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -13361,10 +12674,10 @@ readable-stream@~1.1.10: isarray "0.0.1" string_decoder "~0.10.x" -readdir-scoped-modules@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" - integrity sha1-n6+jfShr5dksuuve4DDcm19AZ0c= +readdir-scoped-modules@^1.0.0, readdir-scoped-modules@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" + integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== dependencies: debuglog "^1.0.1" dezalgo "^1.0.0" @@ -13456,10 +12769,15 @@ redeyed@~2.1.0: dependencies: esprima "~4.0.0" -redux@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5" - integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg== +redux-devtools-extension@^2.13.8: + version "2.13.8" + resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1" + integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg== + +redux@^4.0.0, redux@^4.0.1, redux@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.4.tgz#4ee1aeb164b63d6a1bcc57ae4aa0b6e6fa7a3796" + integrity sha512-vKv4WdiJxOWKxK0yRoaK3Y4pxxB0ilzVx6dszU2W8wLxlb2yikRph4iV/ymtdJ6ZxpBLFbyrxklnT5yBbQSl3Q== dependencies: loose-envify "^1.4.0" symbol-observable "^1.2.0" @@ -13470,15 +12788,15 @@ reflect.ownkeys@^0.2.0: integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA= refractor@^2.4.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.9.0.tgz#0a381aadb51513e4e6ec1ed410b5104dd65e2489" - integrity sha512-lCnCYvXpqd8hC7ksuvo516rz5q4NwzBbq0X5qjH5pxRfcQKiQxKZ8JctrSQmrR/7pcV2TRrs9TT+Whmq/wtluQ== + version "2.10.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.10.0.tgz#4cc7efc0028a87924a9b31d82d129dec831a287b" + integrity sha512-maW2ClIkm9IYruuFYGTqKzj+m31heq92wlheW4h7bOstP+gf8bocmMec+j7ljLcaB1CAID85LMB3moye31jH1g== dependencies: hastscript "^5.0.0" parse-entities "^1.1.2" - prismjs "~1.16.0" + prismjs "~1.17.0" -regenerate-unicode-properties@^8.0.2: +regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== @@ -13506,14 +12824,14 @@ regenerator-runtime@^0.12.0, regenerator-runtime@^0.12.1: integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== regenerator-runtime@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" - integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" + integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== regenerator-transform@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.0.tgz#2ca9aaf7a2c239dd32e4761218425b8c7a86ecaf" - integrity sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w== + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== dependencies: private "^0.1.6" @@ -13525,11 +12843,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.6: - version "0.1.10" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.10.tgz#d837816a039c7af8a8d64d7a7c3cf6a1d93450bc" - integrity sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ== - regexp.prototype.flags@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" @@ -13542,19 +12855,19 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpu-core@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" - integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^8.0.2" + regenerate-unicode-properties "^8.1.0" regjsgen "^0.5.0" regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.1.0" -registry-auth-token@^3.0.1, registry-auth-token@^3.3.1: +registry-auth-token@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A== @@ -13589,16 +12902,7 @@ regjsparser@^0.6.0: dependencies: jsesc "~0.5.0" -rehype-parse@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.0.tgz#f681555f2598165bee2c778b39f9073d17b16bca" - integrity sha512-V2OjMD0xcSt39G4uRdMTqDXXm6HwkUbLMDayYKA/d037j8/OtVSQ+tqKwYWOuyBeoCs/3clXRe30VUjeMDTBSA== - dependencies: - hast-util-from-parse5 "^5.0.0" - parse5 "^5.0.0" - xtend "^4.0.1" - -relateurl@0.2.x: +relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= @@ -13729,11 +13033,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-from-string@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" @@ -13749,6 +13048,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + resize-observer-polyfill@^1.5.0, resize-observer-polyfill@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" @@ -13809,14 +13113,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@1.x, resolve@^1.1.6, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.5.0, resolve@^1.8.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232" - integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw== - dependencies: - path-parse "^1.0.6" - -resolve@^1.10.0, resolve@^1.3.2: +resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== @@ -13856,20 +13153,20 @@ right-pad@^1.0.1: resolved "https://registry.yarnpkg.com/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" integrity sha1-jKCMLLtbVedNr6lr9/0aJ9VoyNA= -rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -13921,9 +13218,9 @@ rx@^4.1.0: integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= rxjs@^6.4.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" - integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== + version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== dependencies: tslib "^1.9.0" @@ -13932,12 +13229,12 @@ safe-buffer@5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== -safe-buffer@5.1.2, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.2: +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== @@ -13990,16 +13287,15 @@ sass-graph@^3.0.4: yargs "^12.0.2" sass-loader@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.1.0.tgz#16fd5138cb8b424bf8a759528a1972d72aad069d" - integrity sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w== + version "7.3.1" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.3.1.tgz#a5bf68a04bcea1c13ff842d747150f7ab7d0d23f" + integrity sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA== dependencies: - clone-deep "^2.0.1" + clone-deep "^4.0.1" loader-utils "^1.0.1" - lodash.tail "^4.1.1" neo-async "^2.5.0" - pify "^3.0.0" - semver "^5.5.0" + pify "^4.0.1" + semver "^6.3.0" sax@^1.2.4, sax@~1.2.4: version "1.2.4" @@ -14007,11 +13303,11 @@ sax@^1.2.4, sax@~1.2.4: integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== saxes@^3.1.9: - version "3.1.9" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.9.tgz#c1c197cd54956d88c09f960254b999e192d7058b" - integrity sha512-FZeKhJglhJHk7eWG5YM0z46VHmI3KJpMBAQm3xa9meDvd+wevB5GuBB0wc0exPInZiBBHqi00DbS8AcvCGCFMw== + version "3.1.11" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" + integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== dependencies: - xmlchars "^1.3.1" + xmlchars "^2.1.1" scheduler@^0.13.3, scheduler@^0.13.6: version "0.13.6" @@ -14021,6 +13317,14 @@ scheduler@^0.13.3, scheduler@^0.13.6: loose-envify "^1.1.0" object-assign "^4.1.1" +scheduler@^0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.16.2.tgz#f74cd9d33eff6fc554edfb79864868e4819132c1" + integrity sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -14061,26 +13365,26 @@ select@^1.1.2: resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= -selfsigned@^1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.4.tgz#cdd7eccfca4ed7635d47a08bf2d5d3074092e2cd" - integrity sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw== +selfsigned@^1.10.7: + version "1.10.7" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" + integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== dependencies: - node-forge "0.7.5" + node-forge "0.9.0" semantic-release-slack-bot@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/semantic-release-slack-bot/-/semantic-release-slack-bot-1.2.0.tgz#895d95c802d855853f257b403eb15587f0b5b98d" - integrity sha512-Bqny8WmV3CuJSfwpn0POxVmt3dZZ+WzoecwF+SFzkuzE0Aad/wyZdzmXGnBCKs0UE7n0b/tGeojQchLnhwvwmQ== + version "1.3.0" + resolved "https://registry.yarnpkg.com/semantic-release-slack-bot/-/semantic-release-slack-bot-1.3.0.tgz#fcdaae5cbfe2019fabf4f558d2d340a888dcfc08" + integrity sha512-Q56c30yBukmI/Ewm20JxdZ1qr4x9yXtvUMRKlbZPLDpM5rP0Ika1C0rGbkEM3AJDNWKtT5osj93L4vI3J86LIg== dependencies: "@semantic-release/error" "^2.2.0" node-fetch "^2.3.0" slackify-markdown "^1.1.1" semantic-release@^15.13.19: - version "15.13.19" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-15.13.19.tgz#d1d05b3516fb8701d81f4e6b9be42bafffef13cb" - integrity sha512-6eqqAmzGaJWgP5R5IkWIQK9is+cWUp/A+pwzxf/YaG1hJv1eD25klUP7Y0fedsPOxxI8eLuDUVlEs7U8SOlK0Q== + version "15.13.24" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-15.13.24.tgz#f0b9544427d059ba5e3c89ac1545234130796be7" + integrity sha512-OPshm6HSp+KmZP9dUv1o3MRILDgOeHYWPI+XSpQRERMri7QkaEiIPkZzoNm2d6KDeFDnp03GphQQS4+Zfo+x/Q== dependencies: "@semantic-release/commit-analyzer" "^6.1.0" "@semantic-release/error" "^2.2.0" @@ -14097,8 +13401,8 @@ semantic-release@^15.13.19: get-stream "^5.0.0" git-log-parser "^1.2.0" hook-std "^2.0.0" - hosted-git-info "^2.7.1" - lodash "^4.17.4" + hosted-git-info "^3.0.0" + lodash "^4.17.15" marked "^0.7.0" marked-terminal "^3.2.0" p-locate "^4.0.0" @@ -14107,7 +13411,7 @@ semantic-release@^15.13.19: resolve-from "^5.0.0" semver "^6.0.0" signale "^1.2.1" - yargs "^13.1.0" + yargs "^14.0.0" semver-compare@^1.0.0: version "1.0.0" @@ -14126,22 +13430,22 @@ semver-regex@^2.0.0: resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -"semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.5, semver@^5.5.1: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +semver@5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b" - integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ== +semver@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" + integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== -semver@^6.0.0, semver@^6.1.1, semver@^6.2.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -14171,9 +13475,9 @@ send@0.17.1: statuses "~1.5.0" serialize-javascript@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" - integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== + version "1.9.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" + integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== serve-favicon@^2.5.0: version "2.5.0" @@ -14247,13 +13551,12 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -sha@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae" - integrity sha1-YDCCL70smCOUn49y7WQR7lzyWq4= +sha@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/sha/-/sha-3.0.0.tgz#b2f2f90af690c16a3a839a6a6c680ea51fedd1ae" + integrity sha512-DOYnM37cNsLNSGIG/zZWch5CKIRNoLdYUQTQlcgkRkoYIUwDYjqDyye16YcDZg/OPdcbUgTKMjc4SY6TB7ZAPw== dependencies: graceful-fs "^4.1.2" - readable-stream "^2.0.2" shallow-clone@^0.1.2: version "0.1.2" @@ -14265,21 +13568,19 @@ shallow-clone@^0.1.2: lazy-cache "^0.2.3" mixin-object "^2.0.1" -shallow-clone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" - integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA== - dependencies: - is-extendable "^0.1.1" - kind-of "^5.0.0" - mixin-object "^2.0.1" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" shallow-equal@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.0.tgz#fd828d2029ff4e19569db7e19e535e94e2d1f5cc" integrity sha512-Z21pVxR4cXsfwpMKMhCEIO1PCi5sp7KEp+CmOpBQ+E8GpHwKOw2sEzk7sgblM3d/j4z4gakoWEoPcjK0VJQogA== -shallowequal@1.1.0, shallowequal@^1.1.0: +shallowequal@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== @@ -14308,15 +13609,10 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" - integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= - dependencies: - array-filter "~0.0.0" - array-map "~0.0.0" - array-reduce "~0.0.0" - jsonify "~0.0.0" +shell-quote@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== shelljs@0.7.6: version "0.7.6" @@ -14361,26 +13657,26 @@ simple-concat@^1.0.0: integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= simple-get@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.3.tgz#924528ac3f9d7718ce5e9ec1b1a69c0be4d62efa" - integrity sha512-Wvre/Jq5vgoz31Z9stYWPLn0PqRqmBDpFSdypAnHu5AvRVCYPRYGnvryNLiXu8GOBNDH82J2FRHUGMjjHUpXFw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" + integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== dependencies: - decompress-response "^3.3.0" + decompress-response "^4.2.0" once "^1.3.1" simple-concat "^1.0.0" simplebar-react@^1.0.0-alpha.6: - version "1.1.0" - resolved "https://registry.yarnpkg.com/simplebar-react/-/simplebar-react-1.1.0.tgz#9241817265aee28b40abced66d6a2663e046d721" - integrity sha512-0nbUpoB5Gq3z2dbhRjPxwTLlscgFjCw8vKQRmbXIr47JMc5BeHj/WbZdVAESuKAvua7ESh6mkxbzywMNgRdbCw== + version "1.2.3" + resolved "https://registry.yarnpkg.com/simplebar-react/-/simplebar-react-1.2.3.tgz#bd81fa9827628470e9470d06caef6ece15e1c882" + integrity sha512-1EOWJzFC7eqHUp1igD1/tb8GBv5aPQA5ZMvpeDnVkpNJ3jAuvmrL2kir3HuijlxhG7njvw9ssxjjBa89E5DrJg== dependencies: prop-types "^15.6.1" - simplebar "^4.1.0" + simplebar "^4.2.3" -simplebar@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/simplebar/-/simplebar-4.1.0.tgz#c4b78b278dd0ce41ed70a71473bfad8132a6260f" - integrity sha512-kX+CsWbWLeufIsqJl8xg5J4WbYMyq5NONR/aTaehN8XLQxOthSgRT/uAXsqX9Yrw3iiGxD9PPwM1PmEJfWAdcg== +simplebar@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/simplebar/-/simplebar-4.2.3.tgz#dac40aced299c17928329eab3d5e6e795fafc10c" + integrity sha512-9no0pK7/1y+8/oTF3sy/+kx0PjQ3uk4cYwld5F1CJGk2gx+prRyUq8GRfvcVLq5niYWSozZdX73a2wIr1o9l/g== dependencies: can-use-dom "^0.1.0" core-js "^3.0.1" @@ -14469,10 +13765,10 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -sockjs-client@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177" - integrity sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg== +sockjs-client@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" + integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== dependencies: debug "^3.2.5" eventsource "^1.0.7" @@ -14549,10 +13845,10 @@ source-map-support@^0.5.6: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@~0.5.10, source-map-support@~0.5.12: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== +source-map-support@~0.5.12: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -14642,10 +13938,10 @@ spdy-transport@^3.0.0: readable-stream "^3.0.6" wbuf "^1.7.3" -spdy@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.0.tgz#81f222b5a743a329aa12cea6a390e60e9b613c52" - integrity sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q== +spdy@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" + integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== dependencies: debug "^4.1.0" handle-thing "^2.0.0" @@ -14754,9 +14050,9 @@ stealthy-require@^1.1.1: integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= store2@^2.7.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/store2/-/store2-2.8.0.tgz#032d5dcbd185a5d74049d67a1765ff1e75faa04b" - integrity sha512-FBJpcOEZQLZBIGL4Yp7W5RgZ0ejaURmcfUjIpyOb64BpI8z/iJXw7zd/NTBeq304dVMxuWVDZEUUCGn7llaVrA== + version "2.10.0" + resolved "https://registry.yarnpkg.com/store2/-/store2-2.10.0.tgz#46b82bb91878daf1b0d56dec2f1d41e54d5103cf" + integrity sha512-tWEpK0snS2RPUq1i3R6OahfJNjWCQYNxq0+by1amCSuw0mXtymJpzmZIeYpA1UAa+7B0grCpNYIbDcd7AgTbFg== stream-browserify@^2.0.1: version "2.0.2" @@ -14851,12 +14147,12 @@ string-width@^3.0.0, string-width@^3.1.0: strip-ansi "^5.1.0" string.prototype.matchall@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-3.0.1.tgz#5a9e0b64bcbeb336aa4814820237c2006985646d" - integrity sha512-NSiU0ILQr9PQ1SZmM1X327U5LsM+KfDTassJfqN1al1+0iNpKzmQ4BfXOJwRnTEqv8nKJ67mFpqRoPaGWwvy5A== + version "3.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-3.0.2.tgz#c1fdb23f90058e929a69cfa2e8b12300daefe030" + integrity sha512-hsRe42jQ8+OJej2GVjhnSVodQ3NQgHV0FDD6dW7ZTM22J4uIbuYiAADCCc1tfyN7ocEl/KUUbudM36E2tZcF8w== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.14.2" function-bind "^1.1.1" has-symbols "^1.0.0" regexp.prototype.flags "^1.2.0" @@ -14880,15 +14176,15 @@ string.prototype.padstart@^3.0.0: function-bind "^1.0.2" string.prototype.trim@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= + version "1.2.0" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz#75a729b10cfc1be439543dae442129459ce61e3d" + integrity sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg== dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.0" - function-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.13.0" + function-bind "^1.1.1" -string.prototype.trimleft@^2.0.0: +string.prototype.trimleft@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== @@ -14896,7 +14192,7 @@ string.prototype.trimleft@^2.0.0: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimright@^2.0.0: +string.prototype.trimright@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== @@ -14905,11 +14201,11 @@ string.prototype.trimright@^2.0.0: function-bind "^1.1.1" string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - safe-buffer "~5.1.0" + safe-buffer "~5.2.0" string_decoder@~0.10.x: version "0.10.31" @@ -14933,19 +14229,10 @@ stringify-entities@^1.0.1: is-alphanumerical "^1.0.0" is-hexadecimal "^1.0.0" -stringify-object@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -stringify-package@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.0.tgz#e02828089333d7d45cd8c287c30aa9a13375081b" - integrity sha512-JIQqiWmLiEozOC0b0BtxZ/AOUtdUZHCBPgqIZ2kSJJqGwgb9neo44XdTHUC4HZSGqi03hOeB7W/E8rAlKnGe9g== +stringify-package@^1.0.0, stringify-package@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85" + integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== strip-ansi@5.2.0, strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" @@ -15035,25 +14322,25 @@ stylis@^3.5.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== +supports-color@6.1.0, supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^5.0.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.5.0: +supports-color@^5.0.0, supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - supports-hyperlinks@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" @@ -15062,17 +14349,21 @@ supports-hyperlinks@^1.0.1: has-flag "^2.0.0" supports-color "^5.0.0" -svgo@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.2.tgz#0253d34eccf2aed4ad4f283e11ee75198f9d7316" - integrity sha512-rAfulcwp2D9jjdGu+0CuqlrAUin6bBWrpoqXWwKDZZZJfXcUXQSxLJOFJCQCSA0x0pP2U0TxSlJu2ROq5Bq6qA== +svg-parser@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.2.tgz#d134cc396fa2681dc64f518330784e98bd801ec8" + integrity sha512-1gtApepKFweigFZj3sGO8KT8LvVZK8io146EzXrpVuWCDAbISz/yMucco3hWTkpZNoPabM+dnMOpy6Swue68Zg== + +svgo@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" + integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== dependencies: chalk "^2.4.1" coa "^2.0.2" css-select "^2.0.0" css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.28" - css-url-regex "^1.1.0" + css-tree "1.0.0-alpha.33" csso "^3.5.1" js-yaml "^3.13.1" mkdirp "~0.5.1" @@ -15105,16 +14396,16 @@ tabbable@^1.1.0: integrity sha512-nOWwx35/JuDI4ONuF0ZTo6lYvI0fY0tZCH1ErzY2EXfu4az50ZyiUX8X073FLiZtmWUVlkRnuXsehjJgCw9tYg== table@^5.2.3: - version "5.4.0" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.0.tgz#d772a3216e68829920a41a32c18eda286c95d780" - integrity sha512-nHFDrxmbrkU7JAFKqKbDJXfzrX2UBsWmrieXFTGxiI5e4ncg3VqsZeI4EzNmX0ncp4XNGVeoxIWJXfCIXwrsvw== + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== dependencies: - ajv "^6.9.1" - lodash "^4.17.11" + ajv "^6.10.2" + lodash "^4.17.14" slice-ansi "^2.1.0" string-width "^3.0.0" -tapable@^1.0.0, tapable@^1.1.0: +tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== @@ -15128,7 +14419,7 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4: +tar@^4, tar@^4.4.10, tar@^4.4.12: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -15141,30 +14432,17 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.3" -tar@^4.4.8: - version "4.4.8" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" - integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.4" - minizlib "^1.1.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - telejson@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/telejson/-/telejson-2.2.1.tgz#d9ee7e7eba0c81d9378257342fde7142a03787e2" - integrity sha512-JtFAnITek+Z9t+uQjVl4Fxur9Z3Bi3flytBLc3KZVXmMUHLXdtAxiP0g8IBkHvKn1kQIYZC57IG0jjGH1s64HQ== + version "2.2.2" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-2.2.2.tgz#d61d721d21849a6e4070d547aab302a9bd22c720" + integrity sha512-YyNwnKY0ilabOwYgC/J754En1xOe5PBIUIw+C9e0+5HjVVcnQE5/gdu2yET2pmSbp5bxIDqYNjvndj2PUkIiYA== dependencies: global "^4.3.2" is-function "^1.0.1" is-regex "^1.0.4" is-symbol "^1.0.2" isobject "^3.0.1" - lodash.get "^4.4.2" + lodash "^4.17.11" memoizerific "^1.11.3" term-size@^1.2.0: @@ -15174,50 +14452,25 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -terser-webpack-plugin@^1.1.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.4.tgz#56f87540c28dd5265753431009388f473b5abba3" - integrity sha512-64IiILNQlACWZLzFlpzNaG0bpQ4ytaB7fwOsbpsdIV70AfLUmIGGeuKL0YV2WmtcrURjE2aOvHD4/lrFV3Rg+Q== - dependencies: - cacache "^11.3.2" - find-cache-dir "^2.0.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^1.7.0" - source-map "^0.6.1" - terser "^3.17.0" - webpack-sources "^1.3.0" - worker-farm "^1.7.0" - -terser-webpack-plugin@^1.2.4: - version "1.3.0" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz#69aa22426299f4b5b3775cbed8cb2c5d419aa1d4" - integrity sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg== +terser-webpack-plugin@^1.2.4, terser-webpack-plugin@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" + integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== dependencies: - cacache "^11.3.2" - find-cache-dir "^2.0.0" + cacache "^12.0.2" + find-cache-dir "^2.1.0" is-wsl "^1.1.0" - loader-utils "^1.2.3" schema-utils "^1.0.0" serialize-javascript "^1.7.0" source-map "^0.6.1" - terser "^4.0.0" - webpack-sources "^1.3.0" + terser "^4.1.2" + webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^3.17.0: - version "3.17.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" - integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== - dependencies: - commander "^2.19.0" - source-map "~0.6.1" - source-map-support "~0.5.10" - -terser@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.1.2.tgz#b2656c8a506f7ce805a3f300a2ff48db022fa391" - integrity sha512-jvNoEQSPXJdssFwqPSgWjsOrb+ELoE+ILpHPKXC83tIxOlh2U75F1KuB2luLD/3a6/7K3Vw5pDn+hvu0C4AzSw== +terser@^4.1.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.0.tgz#22c46b4817cf4c9565434bfe6ad47336af259ac3" + integrity sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -15238,6 +14491,11 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== +text-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.0.0.tgz#43eabd1b495482fae4a2bf65e5f56c29f69220f6" + integrity sha512-F91ZqLgvi1E0PdvmxMgp+gcf6q8fMH7mhdwWfzXnl1k+GbpQDmi8l7DzLC5JTASKbwpY3TfxajAUzAXcv2NmsQ== + text-table@0.2.0, text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -15256,15 +14514,22 @@ through2@^2.0.0, through2@^2.0.2, through2@~2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" +through2@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" + integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + dependencies: + readable-stream "2 || 3" + through@2, "through@>=2.2.7 <3", through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= thunky@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.3.tgz#f5df732453407b09191dae73e2a8cc73f381a826" - integrity sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow== + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== timed-out@^4.0.0: version "4.0.1" @@ -15272,9 +14537,9 @@ timed-out@^4.0.0: integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== dependencies: setimmediate "^1.0.4" @@ -15283,10 +14548,10 @@ tiny-emitter@^2.0.0: resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== -tiny-invariant@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.4.tgz#346b5415fd93cb696b0c4e8a96697ff590f92463" - integrity sha512-lMhRd/djQJ3MoaHEBrw8e2/uM4rs9YMNk0iOr8rHQ0QdbM7D4l0gFl3szKdeixrlyfm9Zqi4dxHCM2qVG8ND5g== +tiny-invariant@^1.0.4, tiny-invariant@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" + integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== tiny-relative-date@^1.3.0: version "1.3.0" @@ -15417,11 +14682,6 @@ trim-off-newlines@^1.0.0: resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - trim-trailing-lines@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.2.tgz#d2f1e153161152e9f02fabc670fb40bec2ea2e3a" @@ -15466,9 +14726,9 @@ ts-jest@^24.1.0: yargs-parser "10.x" ts-loader@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.1.2.tgz#ff6bc767334970226438949fbde2e211147a1325" - integrity sha512-dudxFKm0Ellrg/gLNlu+97/UgwvoMK0SdUVImPUSzq3IcRUVtShylZvcMX+CgvCQL1BEKb913NL0gAP1GA/OFw== + version "6.2.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.1.tgz#67939d5772e8a8c6bdaf6277ca023a4812da02ef" + integrity sha512-Dd9FekWuABGgjE1g0TlQJ+4dFUfYGbYcs52/HQObE0ZmUNjQlmLAS7xXsSzy23AMaMwipsx5sNHvoEpT2CZq1g== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" @@ -15477,14 +14737,14 @@ ts-loader@^6.1.2: semver "^6.0.0" ts-pnp@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.2.tgz#be8e4bfce5d00f0f58e0666a82260c34a57af552" - integrity sha512-f5Knjh7XCyRIzoC/z1Su1yLLRrPrFCgtUAh/9fCSP6NKbATwpOL1+idQVXQokK9GRFURn/jYPGPfegIctwunoA== + version "1.1.4" + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.4.tgz#ae27126960ebaefb874c6d7fa4729729ab200d90" + integrity sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw== tslib@^1.8.1, tslib@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== tsutils@^3.17.1: version "3.17.1" @@ -15522,11 +14782,6 @@ type-fest@^0.3.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== -type-fest@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" - integrity sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw== - type-fest@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" @@ -15545,6 +14800,11 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + typed-styles@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" @@ -15556,29 +14816,21 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^3.6.3: - version "3.6.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.3.tgz#fea942fabb20f7e1ca7164ff626f1a9f3f70b4da" - integrity sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw== + version "3.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" + integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== ua-parser-js@^0.7.18: - version "0.7.19" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b" - integrity sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ== - -uglify-js@3.4.x: - version "3.4.10" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" - integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== - dependencies: - commander "~2.19.0" - source-map "~0.6.1" + version "0.7.20" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098" + integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw== -uglify-js@^3.1.4: - version "3.6.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" - integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== +uglify-js@^3.1.4, uglify-js@^3.5.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.1.tgz#ae7688c50e1bdcf2f70a0e162410003cf9798311" + integrity sha512-+dSJLJpXBb6oMHP+Yvw8hUgElz4gLTh82XuX68QiJVTXaE5ibl6buzhNkQdYhBlIhozWOC9ge16wyRmjG4TwVQ== dependencies: - commander "~2.20.0" + commander "2.20.0" source-map "~0.6.1" uid-number@0.0.6: @@ -15634,20 +14886,6 @@ unified@^6.1.6: vfile "^2.0.0" x-is-string "^0.1.0" -unified@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13" - integrity sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw== - dependencies: - "@types/unist" "^2.0.0" - "@types/vfile" "^3.0.0" - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^1.1.0" - trough "^1.0.0" - vfile "^3.0.0" - x-is-string "^0.1.0" - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -15671,9 +14909,9 @@ unique-filename@^1.1.1: unique-slug "^2.0.0" unique-slug@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" - integrity sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== dependencies: imurmurhash "^0.1.4" @@ -15701,13 +14939,6 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== -unist-util-stringify-position@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.0.tgz#4c452c0dbcbc509f7bcd366e9a8afd646f9d51ae" - integrity sha512-Uz5negUTrf9zm2ZT2Z9kdOL7Mr7FJLyq3ByqagUi7QZRVK1HnspVazvSqwHt73jj7APHtpuJ4K110Jm8O6/elw== - dependencies: - "@types/unist" "^2.0.2" - unist-util-visit-parents@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" @@ -15722,19 +14953,12 @@ unist-util-visit@^1.1.0, unist-util-visit@^1.3.0: dependencies: unist-util-visit-parents "^2.0.0" -universal-user-agent@^2.0.0, universal-user-agent@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.1.0.tgz#5abfbcc036a1ba490cb941f8fd68c46d3669e8e4" - integrity sha512-8itiX7G05Tu3mGDTdNY2fB4KJ8MgZLS54RdG6PkkfwMAavrXu1mV/lls/GABx9O3Rw4PnTtasxrvbMQoBYY92Q== - dependencies: - os-name "^3.0.0" - -universal-user-agent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-3.0.0.tgz#4cc88d68097bffd7ac42e3b7c903e7481424b4b9" - integrity sha512-T3siHThqoj5X0benA5H0qcDnrKGXzU8TKoX15x/tQHw1hQBvIEBHjxQ2klizYsqBOO/Q+WuxoQUihadeeqDnoA== +universal-user-agent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.0.tgz#27da2ec87e32769619f68a14996465ea1cb9df16" + integrity sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA== dependencies: - os-name "^3.0.0" + os-name "^3.1.0" universalify@^0.1.0: version "0.1.2" @@ -15765,9 +14989,9 @@ unzip-response@^2.0.1: integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= upath@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" - integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== update-notifier@^2.3.0, update-notifier@^2.5.0: version "2.5.0" @@ -15803,9 +15027,9 @@ urix@^0.1.0: integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-join@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a" - integrity sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo= + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== url-loader@^1.1.2: version "1.1.2" @@ -15831,11 +15055,6 @@ url-parse@^1.4.3: querystringify "^2.1.1" requires-port "^1.0.0" -url-template@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" - integrity sha1-/FZaPMy/93MMd19WQflVV5FDnyE= - url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -15859,6 +15078,13 @@ util-extend@^1.0.1: resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" integrity sha1-p8IW0mdUUWljeztu3GypEZ4v+T8= +util-promisify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53" + integrity sha1-PCI2R2xNMsX/PEcAKt18E7moKlM= + dependencies: + object.getownpropertydescriptors "^2.0.3" + util.promisify@1.0.0, util.promisify@^1.0.0, util.promisify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" @@ -15897,11 +15123,11 @@ utils-merge@1.0.1: integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@^3.0.1, uuid@^3.1.0, uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== -v8-compile-cache@^2.0.2: +v8-compile-cache@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== @@ -15947,14 +15173,6 @@ vfile-message@^1.0.0: dependencies: unist-util-stringify-position "^1.1.1" -vfile-message@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.0.tgz#750bbb86fe545988a67e899b329bbcabb73edef6" - integrity sha512-YS6qg6UpBfIeiO+6XlhPOuJaoLvt1Y9g2cmlwqhBOOU0XRV8j5RLeoz72t6PWLvNXq3EBG1fQ05wNPrUoz0deQ== - dependencies: - "@types/unist" "^2.0.2" - unist-util-stringify-position "^1.1.1" - vfile@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" @@ -15965,33 +15183,10 @@ vfile@^2.0.0: unist-util-stringify-position "^1.0.0" vfile-message "^1.0.0" -vfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" - integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ== - dependencies: - is-buffer "^2.0.0" - replace-ext "1.0.0" - unist-util-stringify-position "^1.0.0" - vfile-message "^1.0.0" - -vfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.0.tgz#ebf3b48af9fcde524d5e08d5f75812058a5f78ad" - integrity sha512-WMNeHy5djSl895BqE86D7WqA0Ie5fAIeGCa7V1EqiXyJg5LaGch2SUaZueok5abYQGH6mXEAsZ45jkoILIOlyA== - dependencies: - "@types/unist" "^2.0.2" - is-buffer "^2.0.0" - replace-ext "1.0.0" - unist-util-stringify-position "^2.0.0" - vfile-message "^2.0.0" - -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= - dependencies: - indexof "0.0.1" +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== w3c-hr-time@^1.0.1: version "1.0.1" @@ -16021,13 +15216,13 @@ wait-on@^3.3.0: rx "^4.1.0" wait-port@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/wait-port/-/wait-port-0.2.2.tgz#d51a491e484a17bf75a947e711a2f012b4e6f2e3" - integrity sha1-1RpJHkhKF791qUfnEaLwErTm8uM= + version "0.2.6" + resolved "https://registry.yarnpkg.com/wait-port/-/wait-port-0.2.6.tgz#261e615adb2e10c8b91c836722c85919ccf081cc" + integrity sha512-nXE5Yp0Zs1obhFVc0Da7WVJc3y0LxoCq3j4mtV0NdI5P/ZvRdKp5yhuojvMOcOxSwpQL1hGbOgMNQ+4wpRpwCA== dependencies: - chalk "^1.1.3" - commander "^2.9.0" - debug "^2.6.6" + chalk "^2.4.2" + commander "^3.0.2" + debug "^4.1.1" walker@^1.0.7, walker@~1.0.5: version "1.0.7" @@ -16043,14 +15238,14 @@ warning@^3.0.0: dependencies: loose-envify "^1.0.0" -warning@^4.0.2: +warning@^4.0.2, warning@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== dependencies: loose-envify "^1.0.0" -watchpack@^1.5.0: +watchpack@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== @@ -16073,77 +15268,76 @@ wcwidth@^1.0.0: dependencies: defaults "^1.0.3" -web-namespaces@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.3.tgz#9bbf5c99ff0908d2da031f1d732492a96571a83f" - integrity sha512-r8sAtNmgR0WKOKOxzuSgk09JsHlpKlB+uHi937qypOu3PZ17UxPrierFKDye/uNHjNTTEshu5PId8rojIPj/tA== - webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== webpack-cli@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.2.tgz#aed2437b0db0a7faa2ad28484e166a5360014a91" - integrity sha512-FLkobnaJJ+03j5eplxlI0TUxhGCOdfewspIGuvDVtpOlrAuKMFC57K42Ukxqs1tn8947/PM6tP95gQc0DCzRYA== + version "3.3.10" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13" + integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg== dependencies: - chalk "^2.4.1" - cross-spawn "^6.0.5" - enhanced-resolve "^4.1.0" - findup-sync "^2.0.0" - global-modules "^1.0.0" - import-local "^2.0.0" - interpret "^1.1.0" - loader-utils "^1.1.0" - supports-color "^5.5.0" - v8-compile-cache "^2.0.2" - yargs "^12.0.5" + chalk "2.4.2" + cross-spawn "6.0.5" + enhanced-resolve "4.1.0" + findup-sync "3.0.0" + global-modules "2.0.0" + import-local "2.0.0" + interpret "1.2.0" + loader-utils "1.2.3" + supports-color "6.1.0" + v8-compile-cache "2.0.3" + yargs "13.2.4" -webpack-dev-middleware@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz#ef751d25f4e9a5c8a35da600c5fda3582b5c6cff" - integrity sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA== +webpack-dev-middleware@^3.7.0, webpack-dev-middleware@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" + integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== dependencies: memory-fs "^0.4.1" - mime "^2.4.2" + mime "^2.4.4" + mkdirp "^0.5.1" range-parser "^1.2.1" webpack-log "^2.0.0" webpack-dev-server@^3.3.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.4.1.tgz#a5fd8dec95dec410098e7d9a037ff9405395d51a" - integrity sha512-CRqZQX2ryMtrg0r3TXQPpNh76eM1HD3Wmu6zDBxIKi/d2y+4aa28Ia8weNT0bfgWpY6Vs3Oq/K8+DjfbR+tWYw== + version "3.9.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz#27c3b5d0f6b6677c4304465ac817623c8b27b89c" + integrity sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" - chokidar "^2.1.6" + chokidar "^2.1.8" compression "^1.7.4" connect-history-api-fallback "^1.6.0" debug "^4.1.1" del "^4.1.1" - express "^4.17.0" + express "^4.17.1" html-entities "^1.2.1" - http-proxy-middleware "^0.19.1" + http-proxy-middleware "0.19.1" import-local "^2.0.0" internal-ip "^4.3.0" ip "^1.1.5" + is-absolute-url "^3.0.3" killable "^1.0.1" - loglevel "^1.6.1" + loglevel "^1.6.4" opn "^5.5.0" - portfinder "^1.0.20" + p-retry "^3.0.1" + portfinder "^1.0.25" schema-utils "^1.0.0" - selfsigned "^1.10.4" - semver "^6.0.0" + selfsigned "^1.10.7" + semver "^6.3.0" serve-index "^1.9.1" sockjs "0.3.19" - sockjs-client "1.3.0" - spdy "^4.0.0" + sockjs-client "1.4.0" + spdy "^4.0.1" strip-ansi "^3.0.1" supports-color "^6.1.0" url "^0.11.0" - webpack-dev-middleware "^3.7.0" + webpack-dev-middleware "^3.7.2" webpack-log "^2.0.0" + ws "^6.2.1" yargs "12.0.5" webpack-hot-middleware@^2.25.0: @@ -16174,79 +15368,79 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-sources@^1.1.0, webpack-sources@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== +webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" webpack@^4.29.5: - version "4.32.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.32.1.tgz#afe0cc7dd2b196e5a58f8d1d385311cfbb5d68c0" - integrity sha512-R0S2tfWP2tZ8ZC2dwgnUVfa9LPvhGWJXjqfgIQ6jply+9ncBbt8IZ9p83uVeqsZ/s8zKA3XyepciWNHnSxxnHg== + version "4.41.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.2.tgz#c34ec76daa3a8468c9b61a50336d8e3303dce74e" + integrity sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" "@webassemblyjs/wasm-edit" "1.8.5" "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.0.5" - acorn-dynamic-import "^4.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^1.0.0" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" enhanced-resolve "^4.1.0" - eslint-scope "^4.0.0" + eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" schema-utils "^1.0.0" - tapable "^1.1.0" - terser-webpack-plugin "^1.1.0" - watchpack "^1.5.0" - webpack-sources "^1.3.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.1" + watchpack "^1.6.0" + webpack-sources "^1.4.1" -webpack@^4.33.0: - version "4.37.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.37.0.tgz#3508ef10f7996612c2be6026076d89760f776f54" - integrity sha512-iJPPvL7XpbcbwOthbzpa2BSPlmGp8lGDokAj/LdWtK80rsPoPOdANSbDBf2GAVLKZD3GhCuQ/gGkgN9HWs0Keg== +webpack@^4.33.0, webpack@^4.38.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.0.tgz#db6a254bde671769f7c14e90a1a55e73602fc70b" + integrity sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" "@webassemblyjs/wasm-edit" "1.8.5" "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.2.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^1.0.0" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" enhanced-resolve "^4.1.0" - eslint-scope "^4.0.0" + eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" schema-utils "^1.0.0" - tapable "^1.1.0" - terser-webpack-plugin "^1.1.0" - watchpack "^1.5.0" - webpack-sources "^1.3.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.1" + watchpack "^1.6.0" + webpack-sources "^1.4.1" websocket-driver@>=0.5.1: - version "0.7.0" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" - integrity sha1-DK+dLXVdk67gSdS90NP+LMoqJOs= + version "0.7.3" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" + integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== dependencies: - http-parser-js ">=0.4.0" + http-parser-js ">=0.4.0 <0.4.11" + safe-buffer ">=5.1.0" websocket-extensions ">=0.1.1" websocket-extensions@>=0.1.1: @@ -16394,10 +15588,10 @@ write-file-atomic@2.4.1: imurmurhash "^0.1.4" signal-exit "^3.0.2" -write-file-atomic@^2.0.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.2.tgz#a7181706dfba17855d221140a9c06e15fcdd87b9" - integrity sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g== +write-file-atomic@^2.0.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" @@ -16417,7 +15611,7 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" -ws@^6.1.0, ws@^6.1.2: +ws@^6.1.0, ws@^6.1.2, ws@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== @@ -16439,15 +15633,15 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xmlchars@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-1.3.1.tgz#1dda035f833dbb4f86a0c28eaa6ca769214793cf" - integrity sha512-tGkGJkN8XqCod7OT+EvGYK5Z4SfDQGD30zAa58OcnAa0RRWgzUEK72tkXhsX1FZd+rgnhRxFtmO+ihkp8LHSkw== +xmlchars@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^3.2.1: version "3.2.1" @@ -16465,9 +15659,9 @@ yallist@^2.1.2: integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yargs-parser@10.x, yargs-parser@^10.0.0: version "10.1.0" @@ -16484,18 +15678,18 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.0.tgz#7016b6dd03e28e1418a510e258be4bff5a31138f" - integrity sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA== +yargs-parser@^13.1.0, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" + integrity sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -16514,7 +15708,7 @@ yargs-parser@^9.0.2: dependencies: camelcase "^4.1.0" -yargs@12.0.5, yargs@^12.0.1, yargs@^12.0.2, yargs@^12.0.5: +yargs@12.0.5, yargs@^12.0.1, yargs@^12.0.2: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== @@ -16532,16 +15726,33 @@ yargs@12.0.5, yargs@^12.0.1, yargs@^12.0.2, yargs@^12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.0" + yargs@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766" + integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw== dependencies: cliui "^4.0.0" decamelize "^1.1.1" find-up "^2.1.0" get-caller-file "^1.0.1" - os-locale "^2.0.0" + os-locale "^3.1.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" @@ -16550,29 +15761,29 @@ yargs@^11.0.0: y18n "^3.2.1" yargs-parser "^9.0.2" -yargs@^13.1.0: - version "13.2.4" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" - integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== +yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== dependencies: cliui "^5.0.0" find-up "^3.0.0" get-caller-file "^2.0.1" - os-locale "^3.1.0" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.1.0" + yargs-parser "^13.1.1" -yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== +yargs@^14.0.0: + version "14.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.0.tgz#f116a9242c4ed8668790b40759b4906c276e76c3" + integrity sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg== dependencies: cliui "^5.0.0" + decamelize "^1.2.0" find-up "^3.0.0" get-caller-file "^2.0.1" require-directory "^2.1.1" @@ -16581,7 +15792,7 @@ yargs@^13.3.0: string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.1.1" + yargs-parser "^15.0.0" yargs@^7.0.0: version "7.1.0"