From 6deb5178cdbfea651db23421e3cb2ed9e46542b2 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Fri, 10 Apr 2020 15:07:24 +0200 Subject: [PATCH 1/8] feat(brush): add multi axis brushing This commit allow the consumer to configure the direction used for the brush tool. The direction is by default along the X axis, but can be changed to be along the Y axis or have a rectangular selection along both axis. For the Y axis values, we are returning an array of values, one for each Y axis defined (this is determined by the groupId associated with different axis/series groups) BREAKING CHANGE: The type used by the `BrushEndListener` is now changed to reflect this change. The new type is on form of `{ x?: [number, number]; y?: Array<{ groupId: GroupId; values: [number, number]; }> }` where x contains an array of [min,max] values, and the y property is an optional array of objects, containing the GroupId and the values of the brush for that specific axis. fix #587 --- .playground/playground.tsx | 61 +++------ .../state/chart_state.interactions.test.ts | 30 ++--- .../state/selectors/get_brush_area.ts | 97 +++++++++++--- .../state/selectors/on_brush_end_caller.ts | 118 +++++++++++++----- src/specs/settings.tsx | 29 ++++- stories/interactions/11_brush_time.tsx | 7 +- stories/interactions/12_brush_time_hist.tsx | 7 +- 7 files changed, 234 insertions(+), 115 deletions(-) diff --git a/.playground/playground.tsx b/.playground/playground.tsx index deed09e964..af13d89476 100644 --- a/.playground/playground.tsx +++ b/.playground/playground.tsx @@ -17,61 +17,36 @@ * under the License. */ import React from 'react'; -import { - Chart, - ScaleType, - Position, - Axis, - Settings, - PartitionElementEvent, - XYChartElementEvent, - BarSeries, -} from '../src'; +import { Chart, ScaleType, Position, Axis, Settings, BarSeries, DataGenerator } from '../src'; -export class Playground extends React.Component<{}, { isSunburstShown: boolean }> { - onClick = (elements: Array) => { - // eslint-disable-next-line no-console - console.log(elements[0]); - }; +export class Playground extends React.Component { render() { + const dg = new DataGenerator(); + const data = dg.generateBasicSeries(10); + const data2 = dg.generateBasicSeries(10); + return ( <>
- + { + // eslint-disable-next-line no-console + console.log(values); }} /> + + + { - return `${d} $`; - }, - }} + data={data2} />
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 index bb4762964f..0555437932 100644 --- a/src/chart_types/xy_chart/state/chart_state.interactions.test.ts +++ b/src/chart_types/xy_chart/state/chart_state.interactions.test.ts @@ -21,7 +21,7 @@ import { BarSeriesSpec, BasicSeriesSpec, AxisSpec, SeriesTypes } from '../utils/ import { Position } from '../../../utils/commons'; import { ScaleType } from '../../../scales'; import { chartStoreReducer, GlobalChartState } from '../../../state/chart_state'; -import { SettingsSpec, DEFAULT_SETTINGS_SPEC, SpecTypes, TooltipType } from '../../../specs'; +import { SettingsSpec, DEFAULT_SETTINGS_SPEC, SpecTypes, TooltipType, XYBrushArea } from '../../../specs'; import { computeSeriesGeometriesSelector } from './selectors/compute_series_geometries'; import { getProjectedPointerPositionSelector } from './selectors/get_projected_pointer_position'; import { @@ -782,7 +782,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { }); describe('brush', () => { test('can respond to a brush end event', () => { - const brushEndListener = jest.fn((): void => { + const brushEndListener = jest.fn((): void => { return; }); const onBrushCaller = createOnBrushEndCaller(); @@ -827,8 +827,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[0][0]).toBe(0); - expect(brushEndListener.mock.calls[0][1]).toBe(2.5); + expect(brushEndListener.mock.calls[0][0]).toEqual({ x: [0, 2.5] }); } const start2 = { x: 75, y: 0 }; const end2 = { x: 100, y: 0 }; @@ -840,8 +839,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[1][0]).toBe(2.5); - expect(brushEndListener.mock.calls[1][1]).toBe(3); + expect(brushEndListener.mock.calls[1][0]).toEqual({ x: [2.5, 3] }); } const start3 = { x: 75, y: 0 }; @@ -853,8 +851,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[2][0]).toBe(2.5); - expect(brushEndListener.mock.calls[2][1]).toBe(3); + expect(brushEndListener.mock.calls[2][0]).toEqual({ x: [2.5, 3] }); } const start4 = { x: 25, y: 0 }; @@ -866,12 +863,11 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[3][0]).toBe(0); - expect(brushEndListener.mock.calls[3][1]).toBe(0.5); + expect(brushEndListener.mock.calls[3][0]).toEqual({ x: [0, 0.5] }); } }); test('can respond to a brush end event on rotated chart', () => { - const brushEndListener = jest.fn((): void => { + const brushEndListener = jest.fn((): void => { return; }); const onBrushCaller = createOnBrushEndCaller(); @@ -906,8 +902,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[0][0]).toBe(0); - expect(brushEndListener.mock.calls[0][1]).toBe(1); + expect(brushEndListener.mock.calls[0][0]).toEqual({ x: [0, 1] }); } const start2 = { x: 0, y: 75 }; const end2 = { x: 0, y: 100 }; @@ -919,8 +914,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[1][0]).toBe(1); - expect(brushEndListener.mock.calls[1][1]).toBe(1); + expect(brushEndListener.mock.calls[1][0]).toEqual({ x: [1, 1] }); } const start3 = { x: 0, y: 75 }; @@ -932,8 +926,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[2][0]).toBe(1); - expect(brushEndListener.mock.calls[2][1]).toBe(1); // max of chart + expect(brushEndListener.mock.calls[2][0]).toEqual({ x: [1, 1] }); // max of chart } const start4 = { x: 0, y: 25 }; @@ -945,8 +938,7 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener).not.toBeCalled(); } else { expect(brushEndListener).toBeCalled(); - expect(brushEndListener.mock.calls[3][0]).toBe(0); - expect(brushEndListener.mock.calls[3][1]).toBe(0); + expect(brushEndListener.mock.calls[3][0]).toEqual({ x: [0, 0] }); } }); }); 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 index d709b62c7c..9e9a8e18c7 100644 --- a/src/chart_types/xy_chart/state/selectors/get_brush_area.ts +++ b/src/chart_types/xy_chart/state/selectors/get_brush_area.ts @@ -22,6 +22,10 @@ import { Dimensions } from '../../../../utils/dimensions'; import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; import { computeChartDimensionsSelector } from './compute_chart_dimensions'; import { getChartIdSelector } from '../../../../state/selectors/get_chart_id'; +import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs'; +import { BrushAxis } from '../../../../specs'; +import { Rotation } from '../../../../utils/commons'; +import { Point } from '../../../../utils/point'; const getMouseDownPosition = (state: GlobalChartState) => state.interactions.pointer.down; const getCurrentPointerPosition = (state: GlobalChartState) => { @@ -30,8 +34,14 @@ const getCurrentPointerPosition = (state: GlobalChartState) => { /** @internal */ export const getBrushAreaSelector = createCachedSelector( - [getMouseDownPosition, getCurrentPointerPosition, getChartRotationSelector, computeChartDimensionsSelector], - (mouseDownPosition, cursorPosition, chartRotation, { chartDimensions }): Dimensions | null => { + [ + getMouseDownPosition, + getCurrentPointerPosition, + getChartRotationSelector, + computeChartDimensionsSelector, + getSettingsSpecSelector, + ], + (mouseDownPosition, cursorPosition, chartRotation, { chartDimensions }, { brushAxis }): Dimensions | null => { if (!mouseDownPosition) { return null; } @@ -39,22 +49,73 @@ export const getBrushAreaSelector = createCachedSelector( x: mouseDownPosition.position.x, y: mouseDownPosition.position.y, }; - if (chartRotation === 0 || chartRotation === 180) { - const area = { - left: brushStart.x - chartDimensions.left, - width: cursorPosition.x - brushStart.x, - top: 0, - height: chartDimensions.height, - }; - return area; - } else { - const area = { - left: 0, - width: chartDimensions.width, - top: brushStart.y - chartDimensions.top, - height: cursorPosition.y - brushStart.y, - }; - return area; + switch (brushAxis) { + case BrushAxis.Y: + return getBrushForYAxis(chartDimensions, chartRotation, cursorPosition, brushStart); + case BrushAxis.Both: + return getBrushForBothAxis(chartDimensions, cursorPosition, brushStart); + case BrushAxis.X: + default: + return getBrushForXAxis(chartDimensions, chartRotation, cursorPosition, brushStart); } }, )(getChartIdSelector); + +function getBrushForXAxis( + chartDimensions: Dimensions, + chartRotation: Rotation, + cursorPosition: Point, + brushStart: Point, +) { + if (chartRotation === 0 || chartRotation === 180) { + const area = { + left: brushStart.x - chartDimensions.left, + width: cursorPosition.x - brushStart.x, + top: 0, + height: chartDimensions.height, + }; + return area; + } else { + const area = { + left: 0, + width: chartDimensions.width, + top: brushStart.y - chartDimensions.top, + height: cursorPosition.y - brushStart.y, + }; + return area; + } +} + +function getBrushForYAxis( + chartDimensions: Dimensions, + chartRotation: Rotation, + cursorPosition: Point, + brushStart: Point, +) { + if (chartRotation === -90 || chartRotation === 90) { + const area = { + left: brushStart.x - chartDimensions.left, + width: cursorPosition.x - brushStart.x, + top: 0, + height: chartDimensions.height, + }; + return area; + } else { + const area = { + left: 0, + width: chartDimensions.width, + top: brushStart.y - chartDimensions.top, + height: cursorPosition.y - brushStart.y, + }; + return area; + } +} + +function getBrushForBothAxis(chartDimensions: Dimensions, cursorPosition: Point, brushStart: Point) { + return { + left: brushStart.x - chartDimensions.left, + width: cursorPosition.x - brushStart.x, + top: brushStart.y - chartDimensions.top, + height: cursorPosition.y - brushStart.y, + }; +} 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 index feedc95031..0d1934a546 100644 --- 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 @@ -20,17 +20,21 @@ 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 { BrushAxis, XYBrushArea, XYBrushYValues, BrushEndListener } 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'; +import { Scale } from '../../../../scales'; +import { Dimensions } from '../../../../utils/dimensions'; +import { GroupId } from '../../../../utils/ids'; +import { Rotation } from '../../../../utils/commons'; const getLastDragSelector = (state: GlobalChartState) => state.interactions.pointer.lastDrag; interface Props { - settings: SettingsSpec | undefined; + onBrushEnd: BrushEndListener | undefined; lastDrag: DragState | null; } @@ -38,7 +42,7 @@ function hasDragged(prevProps: Props | null, nextProps: Props | null) { if (nextProps === null) { return false; } - if (!nextProps.settings || !nextProps.settings.onBrushEnd) { + if (!nextProps.onBrushEnd) { return false; } const prevLastDrag = prevProps !== null ? prevProps.lastDrag : null; @@ -77,40 +81,26 @@ export function createOnBrushEndCaller(): (state: GlobalChartState) => void { computeChartDimensionsSelector, isHistogramModeEnabledSelector, ], - (lastDrag, settings, computedScales, { chartDimensions }, histogramMode): void => { + (lastDrag, { onBrushEnd, rotation, brushAxis }, computedScales, { chartDimensions }, histogramMode): void => { const nextProps = { lastDrag, - settings, + onBrushEnd, }; if (lastDrag !== null && hasDragged(prevProps, nextProps)) { - if (settings && settings.onBrushEnd) { - let startPos = lastDrag.start.position.x - chartDimensions.left; - let endPos = lastDrag.end.position.x - chartDimensions.left; - let chartMax = chartDimensions.width; - if (settings.rotation === -90 || settings.rotation === 90) { - startPos = lastDrag.start.position.y - chartDimensions.top; - endPos = lastDrag.end.position.y - chartDimensions.top; - chartMax = chartDimensions.height; + if (onBrushEnd) { + const brushArea: XYBrushArea = {}; + const { yScales, xScale } = computedScales; + + if (brushAxis === BrushAxis.X || brushAxis === BrushAxis.Both) { + brushArea.x = getValuesForXBrush(chartDimensions, lastDrag, rotation, histogramMode, xScale); } - let minPos = Math.max(Math.min(startPos, endPos), 0); - let maxPos = Math.min(Math.max(startPos, endPos), chartMax); - if (settings.rotation === -90 || settings.rotation === 180) { - minPos = chartMax - minPos; - maxPos = chartMax - maxPos; + if (brushAxis === BrushAxis.Y || brushAxis === BrushAxis.Both) { + brushArea.y = getValuesForYBrush(chartDimensions, lastDrag, rotation, yScales); } - if (maxPos === minPos) { - // if 0 size brush, avoid computing the value - return; + if (brushArea.x !== undefined || brushArea.y !== undefined) { + onBrushEnd(brushArea); } - const { xScale } = computedScales; - const offset = histogramMode ? 0 : -(xScale.bandwidth + xScale.bandwidthPadding) / 2; - const minPosScaled = xScale.invert(minPos + offset); - const maxPosScaled = xScale.invert(maxPos + offset); - const minValue = Math.max(Math.min(minPosScaled, maxPosScaled), xScale.domain[0]); - const maxValue = Math.min(Math.max(minPosScaled, maxPosScaled), xScale.domain[1]); - - settings.onBrushEnd(minValue, maxValue); } } prevProps = nextProps; @@ -124,3 +114,73 @@ export function createOnBrushEndCaller(): (state: GlobalChartState) => void { } }; } + +function getValuesForXBrush( + chartDimensions: Dimensions, + lastDrag: DragState, + rotation: Rotation, + histogramMode: boolean, + xScale: Scale, +): [number, number] | undefined { + let startPos = lastDrag.start.position.x - chartDimensions.left; + let endPos = lastDrag.end.position.x - chartDimensions.left; + let chartMax = chartDimensions.width; + if (rotation === -90 || rotation === 90) { + startPos = lastDrag.start.position.y - chartDimensions.top; + endPos = lastDrag.end.position.y - chartDimensions.top; + chartMax = chartDimensions.height; + } + let minPos = Math.max(Math.min(startPos, endPos), 0); + let maxPos = Math.min(Math.max(startPos, endPos), chartMax); + if (rotation === -90 || rotation === 180) { + minPos = chartMax - minPos; + maxPos = chartMax - maxPos; + } + if (maxPos === minPos) { + // if 0 size brush, avoid computing the value + return; + } + + const offset = histogramMode ? 0 : -(xScale.bandwidth + xScale.bandwidthPadding) / 2; + const minPosScaled = xScale.invert(minPos + offset); + const maxPosScaled = xScale.invert(maxPos + offset); + const minValue = Math.max(Math.min(minPosScaled, maxPosScaled), xScale.domain[0]); + const maxValue = Math.min(Math.max(minPosScaled, maxPosScaled), xScale.domain[1]); + return [minValue, maxValue]; +} + +function getValuesForYBrush( + chartDimensions: Dimensions, + lastDrag: DragState, + rotation: Rotation, + yScales: Map, +): XYBrushYValues[] | undefined { + const yValues: XYBrushYValues[] = []; + yScales.forEach((yScale, key) => { + let startPos = lastDrag.start.position.y - chartDimensions.top; + let endPos = lastDrag.end.position.y - chartDimensions.top; + let chartMax = chartDimensions.height; + if (rotation === -90 || rotation === 90) { + startPos = lastDrag.start.position.x - chartDimensions.left; + endPos = lastDrag.end.position.y - chartDimensions.left; + chartMax = chartDimensions.width; + } + let minPos = Math.max(Math.min(startPos, endPos), 0); + let maxPos = Math.min(Math.max(startPos, endPos), chartMax); + if (rotation === -90 || rotation === 180) { + minPos = chartMax - minPos; + maxPos = chartMax - maxPos; + } + if (maxPos === minPos) { + // if 0 size brush, avoid computing the value + return; + } + + const minPosScaled = yScale.invert(minPos); + const maxPosScaled = yScale.invert(maxPos); + const minValue = Math.max(Math.min(minPosScaled, maxPosScaled), yScale.domain[0]); + const maxValue = Math.min(Math.max(minPosScaled, maxPosScaled), yScale.domain[1]); + yValues.push({ values: [minValue, maxValue], groupId: key }); + }); + return yValues.length === 0 ? undefined : yValues; +} diff --git a/src/specs/settings.tsx b/src/specs/settings.tsx index 24c65aaaee..4451377882 100644 --- a/src/specs/settings.tsx +++ b/src/specs/settings.tsx @@ -32,18 +32,28 @@ import { Accessor } from '../utils/accessor'; import { Position, Rendering, Rotation, Color } from '../utils/commons'; import { ScaleContinuousType, ScaleOrdinalType } from '../scales'; import { PrimitiveValue } from '../chart_types/partition_chart/layout/utils/group_by_rollup'; +import { GroupId } from '../utils/ids'; export interface LayerValue { groupByRollup: PrimitiveValue; value: number; } +export interface XYBrushYValues { + groupId: GroupId; + values: [number, number]; +} +export interface XYBrushArea { + x?: [number, number]; + y?: Array; +} + export type XYChartElementEvent = [GeometryValue, XYChartSeriesIdentifier]; export type PartitionElementEvent = [Array, SeriesIdentifier]; export type ElementClickListener = (elements: Array) => void; export type ElementOverListener = (elements: Array) => void; -export type BrushEndListener = (min: number, max: number) => void; +export type BrushEndListener = (brushArea: XYBrushArea) => void; export type LegendItemListener = (series: XYChartSeriesIdentifier | null) => void; export type PointerUpdateListener = (event: PointerEvent) => void; /** @@ -100,6 +110,14 @@ export const TooltipType = Object.freeze({ export type TooltipType = $Values; +export const BrushAxis = Object.freeze({ + X: 'x' as 'x', + Y: 'y' as 'y', + Both: 'both' as 'both', +}); + +export type BrushAxis = $Values; + export interface TooltipValue { /** * The label of the tooltip value @@ -215,6 +233,11 @@ export interface SettingsSpec extends Spec { xDomain?: Domain | DomainRange; resizeDebounce?: number; legendColorPicker?: LegendColorPicker; + /** + * Block the brush tool on a specific axis: x, y or both. + * @default BrushAxis.X + */ + brushAxis?: BrushAxis; } export type DefaultSettingsProps = @@ -231,7 +254,8 @@ export type DefaultSettingsProps = | 'showLegendExtra' | 'theme' | 'legendPosition' - | 'hideDuplicateAxes'; + | 'hideDuplicateAxes' + | 'brushAxis'; export const DEFAULT_TOOLTIP_TYPE = TooltipType.VerticalCursor; export const DEFAULT_TOOLTIP_SNAP = true; @@ -263,6 +287,7 @@ export const DEFAULT_SETTINGS_SPEC: SettingsSpec = { showLegendExtra: false, hideDuplicateAxes: false, theme: LIGHT_THEME, + brushAxis: BrushAxis.X, }; export type SettingsSpecProps = Partial>; diff --git a/stories/interactions/11_brush_time.tsx b/stories/interactions/11_brush_time.tsx index e2b72cc470..e281702360 100644 --- a/stories/interactions/11_brush_time.tsx +++ b/stories/interactions/11_brush_time.tsx @@ -38,8 +38,11 @@ export const example = () => { { - action('onBrushEnd')(formatter(start), formatter(end)); + onBrushEnd={({ x }) => { + if (!x) { + return; + } + action('onBrushEnd')(formatter(x[0]), formatter(x[1])); }} onElementClick={action('onElementClick')} rotation={getChartRotationKnob()} diff --git a/stories/interactions/12_brush_time_hist.tsx b/stories/interactions/12_brush_time_hist.tsx index 6ff4133acb..c7f46ddf3e 100644 --- a/stories/interactions/12_brush_time_hist.tsx +++ b/stories/interactions/12_brush_time_hist.tsx @@ -34,8 +34,11 @@ export const example = () => { { - action('onBrushEnd')(formatter(start), formatter(end)); + onBrushEnd={({ x }) => { + if (!x) { + return; + } + action('onBrushEnd')(formatter(x[0]), formatter(x[1])); }} onElementClick={action('onElementClick')} rotation={getChartRotationKnob()} From 725bf8a12496961436ea1ce25674520aabc201f3 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Tue, 14 Apr 2020 18:47:11 +0200 Subject: [PATCH 2/8] refactor: clean up code --- .../state/selectors/get_brush_area.ts | 72 +++++++++---------- .../state/selectors/on_brush_end_caller.ts | 41 ++++++----- src/chart_types/xy_chart/utils/specs.ts | 4 ++ src/specs/settings.tsx | 6 +- .../9a_brush_selection_linear.tsx | 60 ++++++++++++++++ stories/interactions/interactions.stories.tsx | 1 + 6 files changed, 124 insertions(+), 60 deletions(-) create mode 100644 stories/interactions/9a_brush_selection_linear.tsx 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 index 9e9a8e18c7..8fe9d753a0 100644 --- a/src/chart_types/xy_chart/state/selectors/get_brush_area.ts +++ b/src/chart_types/xy_chart/state/selectors/get_brush_area.ts @@ -67,23 +67,13 @@ function getBrushForXAxis( cursorPosition: Point, brushStart: Point, ) { - if (chartRotation === 0 || chartRotation === 180) { - const area = { - left: brushStart.x - chartDimensions.left, - width: cursorPosition.x - brushStart.x, - top: 0, - height: chartDimensions.height, - }; - return area; - } else { - const area = { - left: 0, - width: chartDimensions.width, - top: brushStart.y - chartDimensions.top, - height: cursorPosition.y - brushStart.y, - }; - return area; - } + const rotated = isRotated(chartRotation); + return { + left: rotated ? 0 : getLeftPoint(chartDimensions, brushStart), + top: rotated ? getTopPoint(chartDimensions, brushStart) : 0, + height: rotated ? getHeight(cursorPosition, brushStart) : chartDimensions.height, + width: rotated ? chartDimensions.width : getWidth(cursorPosition, brushStart), + }; } function getBrushForYAxis( @@ -92,30 +82,36 @@ function getBrushForYAxis( cursorPosition: Point, brushStart: Point, ) { - if (chartRotation === -90 || chartRotation === 90) { - const area = { - left: brushStart.x - chartDimensions.left, - width: cursorPosition.x - brushStart.x, - top: 0, - height: chartDimensions.height, - }; - return area; - } else { - const area = { - left: 0, - width: chartDimensions.width, - top: brushStart.y - chartDimensions.top, - height: cursorPosition.y - brushStart.y, - }; - return area; - } + const rotated = isRotated(chartRotation); + return { + left: rotated ? getLeftPoint(chartDimensions, brushStart) : 0, + top: rotated ? 0 : getTopPoint(chartDimensions, brushStart), + height: rotated ? chartDimensions.height : getHeight(cursorPosition, brushStart), + width: rotated ? getWidth(cursorPosition, brushStart) : chartDimensions.width, + }; } function getBrushForBothAxis(chartDimensions: Dimensions, cursorPosition: Point, brushStart: Point) { return { - left: brushStart.x - chartDimensions.left, - width: cursorPosition.x - brushStart.x, - top: brushStart.y - chartDimensions.top, - height: cursorPosition.y - brushStart.y, + left: getLeftPoint(chartDimensions, brushStart), + top: getTopPoint(chartDimensions, brushStart), + height: getHeight(cursorPosition, brushStart), + width: getWidth(cursorPosition, brushStart), }; } + +export function isRotated(chartRotation: Rotation) { + return chartRotation === -90 || chartRotation === 90; +} +export function getLeftPoint({ left }: Dimensions, { x }: Point) { + return x - left; +} +export function getTopPoint({ top }: Dimensions, { y }: Point) { + return y - top; +} +export function getHeight(cursorPosition: Point, brushStart: Point) { + return cursorPosition.y - brushStart.y; +} +export function getWidth(cursorPosition: Point, brushStart: Point) { + return cursorPosition.x - brushStart.x; +} 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 index 0d1934a546..d2c98c1c2e 100644 --- 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 @@ -20,7 +20,7 @@ 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 { BrushAxis, XYBrushArea, XYBrushYValues, BrushEndListener } from '../../../../specs'; +import { BrushAxis, XYBrushArea, GroupBrushExtent, BrushEndListener } from '../../../../specs'; import { ChartTypes } from '../../../index'; import { getComputedScalesSelector } from './get_computed_scales'; import { computeChartDimensionsSelector } from './compute_chart_dimensions'; @@ -30,6 +30,7 @@ import { Scale } from '../../../../scales'; import { Dimensions } from '../../../../utils/dimensions'; import { GroupId } from '../../../../utils/ids'; import { Rotation } from '../../../../utils/commons'; +import { getLeftPoint, getTopPoint, isRotated } from './get_brush_area'; const getLastDragSelector = (state: GlobalChartState) => state.interactions.pointer.lastDrag; @@ -93,10 +94,10 @@ export function createOnBrushEndCaller(): (state: GlobalChartState) => void { const { yScales, xScale } = computedScales; if (brushAxis === BrushAxis.X || brushAxis === BrushAxis.Both) { - brushArea.x = getValuesForXBrush(chartDimensions, lastDrag, rotation, histogramMode, xScale); + brushArea.x = getXBrushExtent(chartDimensions, lastDrag, rotation, histogramMode, xScale); } if (brushAxis === BrushAxis.Y || brushAxis === BrushAxis.Both) { - brushArea.y = getValuesForYBrush(chartDimensions, lastDrag, rotation, yScales); + brushArea.y = getYBrushExtents(chartDimensions, lastDrag, rotation, yScales); } if (brushArea.x !== undefined || brushArea.y !== undefined) { onBrushEnd(brushArea); @@ -115,21 +116,23 @@ export function createOnBrushEndCaller(): (state: GlobalChartState) => void { }; } -function getValuesForXBrush( +function getXBrushExtent( chartDimensions: Dimensions, lastDrag: DragState, rotation: Rotation, histogramMode: boolean, xScale: Scale, ): [number, number] | undefined { - let startPos = lastDrag.start.position.x - chartDimensions.left; - let endPos = lastDrag.end.position.x - chartDimensions.left; + let startPos = getLeftPoint(chartDimensions, lastDrag.start.position); + let endPos = getLeftPoint(chartDimensions, lastDrag.end.position); let chartMax = chartDimensions.width; - if (rotation === -90 || rotation === 90) { - startPos = lastDrag.start.position.y - chartDimensions.top; - endPos = lastDrag.end.position.y - chartDimensions.top; + + if (isRotated(rotation)) { + startPos = getTopPoint(chartDimensions, lastDrag.start.position); + endPos = getTopPoint(chartDimensions, lastDrag.end.position); chartMax = chartDimensions.height; } + let minPos = Math.max(Math.min(startPos, endPos), 0); let maxPos = Math.min(Math.max(startPos, endPos), chartMax); if (rotation === -90 || rotation === 180) { @@ -149,20 +152,20 @@ function getValuesForXBrush( return [minValue, maxValue]; } -function getValuesForYBrush( +function getYBrushExtents( chartDimensions: Dimensions, lastDrag: DragState, rotation: Rotation, yScales: Map, -): XYBrushYValues[] | undefined { - const yValues: XYBrushYValues[] = []; - yScales.forEach((yScale, key) => { - let startPos = lastDrag.start.position.y - chartDimensions.top; - let endPos = lastDrag.end.position.y - chartDimensions.top; +): GroupBrushExtent[] | undefined { + const yValues: GroupBrushExtent[] = []; + yScales.forEach((yScale, groupId) => { + let startPos = getTopPoint(chartDimensions, lastDrag.start.position); + let endPos = getTopPoint(chartDimensions, lastDrag.end.position); let chartMax = chartDimensions.height; - if (rotation === -90 || rotation === 90) { - startPos = lastDrag.start.position.x - chartDimensions.left; - endPos = lastDrag.end.position.y - chartDimensions.left; + if (isRotated(rotation)) { + startPos = getLeftPoint(chartDimensions, lastDrag.start.position); + endPos = getLeftPoint(chartDimensions, lastDrag.end.position); chartMax = chartDimensions.width; } let minPos = Math.max(Math.min(startPos, endPos), 0); @@ -180,7 +183,7 @@ function getValuesForYBrush( const maxPosScaled = yScale.invert(maxPos); const minValue = Math.max(Math.min(minPosScaled, maxPosScaled), yScale.domain[0]); const maxValue = Math.min(Math.max(minPosScaled, maxPosScaled), yScale.domain[1]); - yValues.push({ values: [minValue, maxValue], groupId: key }); + yValues.push({ extent: [minValue, maxValue], groupId }); }); return yValues.length === 0 ? undefined : yValues; } diff --git a/src/chart_types/xy_chart/utils/specs.ts b/src/chart_types/xy_chart/utils/specs.ts index 81138d6500..30c50a8a01 100644 --- a/src/chart_types/xy_chart/utils/specs.ts +++ b/src/chart_types/xy_chart/utils/specs.ts @@ -71,6 +71,10 @@ export type PointStyleAccessor = ( datum: RawDataSeriesDatum, seriesIdentifier: XYChartSeriesIdentifier, ) => PointStyleOverride; + +/** + * The global id used by default to group together series + */ export const DEFAULT_GLOBAL_ID = '__global__'; export type FilterPredicate = (series: XYChartSeriesIdentifier) => boolean; diff --git a/src/specs/settings.tsx b/src/specs/settings.tsx index 4451377882..d165b295ef 100644 --- a/src/specs/settings.tsx +++ b/src/specs/settings.tsx @@ -39,13 +39,13 @@ export interface LayerValue { value: number; } -export interface XYBrushYValues { +export interface GroupBrushExtent { groupId: GroupId; - values: [number, number]; + extent: [number, number]; } export interface XYBrushArea { x?: [number, number]; - y?: Array; + y?: Array; } export type XYChartElementEvent = [GeometryValue, XYChartSeriesIdentifier]; diff --git a/stories/interactions/9a_brush_selection_linear.tsx b/stories/interactions/9a_brush_selection_linear.tsx new file mode 100644 index 0000000000..35b3c9eae5 --- /dev/null +++ b/stories/interactions/9a_brush_selection_linear.tsx @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ + +import { action } from '@storybook/addon-actions'; +import React from 'react'; +import { AreaSeries, Axis, Chart, Position, ScaleType, Settings, BrushAxis } from '../../src'; + +import { getChartRotationKnob } from '../utils/knobs'; +import { select } from '@storybook/addon-knobs'; + +const brushAxisSelect = select( + 'brush axis', + { + x: BrushAxis.X, + y: BrushAxis.Y, + both: BrushAxis.Both, + }, + BrushAxis.Both, +); + +export const example = () => { + return ( + + + + Number(d).toFixed(2)} /> + + Number(d).toFixed(2)} /> + + + + ); +}; diff --git a/stories/interactions/interactions.stories.tsx b/stories/interactions/interactions.stories.tsx index a4e35d82be..ff286fde58 100644 --- a/stories/interactions/interactions.stories.tsx +++ b/stories/interactions/interactions.stories.tsx @@ -35,6 +35,7 @@ export { example as clickHoversOnLegendItemsAreaChart } from './6_clicks_legend_ export { example as clickHoversOnLegendItemsLineChart } from './7_clicks_legend_items_line'; export { example as clickHoversOnLegendItemsMixedChart } from './8_clicks_legend_items_mixed'; export { example as brushSelectionToolOnLinear } from './9_brush_selection_linear'; +export { example as brushTool } from './9a_brush_selection_linear'; export { example as brushSelectionToolOnBarChartLinear } from './10_brush_selection_bar'; export { example as brushSelectionToolOnTimeCharts } from './11_brush_time'; From d9d22a491a68fed54ab21b999ddf8fe236120a2c Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 15 Apr 2020 14:53:34 +0200 Subject: [PATCH 3/8] test: add VRTs and brush area tests --- integration/page_objects/common.ts | 66 +++++++++++++++ ...ush-tool-visually-looks-correct-1-snap.png | Bin 0 -> 27442 bytes ...how-rectangular-brush-selection-1-snap.png | Bin 0 -> 27763 bytes ...gular-brush-selection-90-degree-1-snap.png | Bin 0 -> 27287 bytes ...ation-90-show-x-brush-selection-1-snap.png | Bin 0 -> 27823 bytes ...how-x-brush-selection-90-degree-1-snap.png | Bin 0 -> 26723 bytes ...ation-90-show-y-brush-selection-1-snap.png | Bin 0 -> 27139 bytes ...how-y-brush-selection-90-degree-1-snap.png | Bin 0 -> 27664 bytes integration/tests/interactions.test.ts | 45 +++++++++- .../state/selectors/get_brush_area.test.ts | 77 ++++++++++++++++++ .../state/selectors/get_brush_area.ts | 61 ++++++-------- .../9a_brush_selection_linear.tsx | 19 ++--- 12 files changed, 223 insertions(+), 45 deletions(-) create mode 100644 integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-tool-visually-looks-correct-1-snap.png create mode 100644 integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-rectangular-brush-selection-1-snap.png create mode 100644 integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-rectangular-brush-selection-90-degree-1-snap.png create mode 100644 integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-x-brush-selection-1-snap.png create mode 100644 integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-x-brush-selection-90-degree-1-snap.png create mode 100644 integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-y-brush-selection-1-snap.png create mode 100644 integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-y-brush-selection-90-degree-1-snap.png create mode 100644 src/chart_types/xy_chart/state/selectors/get_brush_area.test.ts diff --git a/integration/page_objects/common.ts b/integration/page_objects/common.ts index 15c6c1bb43..8d087b2999 100644 --- a/integration/page_objects/common.ts +++ b/integration/page_objects/common.ts @@ -132,6 +132,51 @@ class CommonPage { await page.mouse.click(element.left + mousePosition.x, element.top + mousePosition.y); } + /** + * Drag mouse relative to element + * + * @param mousePosition + * @param selector + */ + async dragMouseRelativeToDOMElement( + start: { x: number; y: number }, + end: { x: number; y: number }, + selector: string, + ) { + const element = await this.getBoundingClientRect(selector); + await page.mouse.move(element.left + start.x, element.top + start.y); + await page.mouse.down(); + await page.mouse.move(element.left + end.x, element.top + end.y); + } + + /** + * Drop mouse + * + * @param mousePosition + * @param selector + */ + async dropMouse() { + await page.mouse.up(); + } + + /** + * Drag and drop mouse relative to element + * + * @param mousePosition + * @param selector + */ + async dragAndDropMouseRelativeToDOMElement( + start: { x: number; y: number }, + end: { x: number; y: number }, + selector: string, + ) { + const element = await this.getBoundingClientRect(selector); + await page.mouse.move(element.left + start.x, element.top + start.y); + await page.mouse.down(); + await page.mouse.move(element.left + end.x, element.top + end.y); + await page.mouse.up(); + } + /** * Expect an element given a url and selector from storybook * @@ -201,6 +246,27 @@ class CommonPage { }); } + /** + * Expect a chart given a url from storybook with mouse move + * + * @param url Storybook url from knobs section + * @param start - the start postion of mouse relative to chart + * @param end - the end postion of mouse relative to chart + * @param options + */ + async expectChartWithDragAtUrlToMatchScreenshot( + url: string, + start: { x: number; y: number }, + end: { x: number; y: number }, + options?: Omit, + ) { + const action = async () => await this.dragMouseRelativeToDOMElement(start, end, this.chartSelector); + await this.expectChartAtUrlToMatchScreenshot(url, { + ...options, + action, + }); + } + /** * Loads storybook page from raw url, and waits for element * diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-tool-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-interactions-brush-tool-visually-looks-correct-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..2416a2eb5ada0880e1a2c0244fd9ef4f3992bdf6 GIT binary patch literal 27442 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 literal 0 HcmV?d00001 diff --git a/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-rectangular-brush-selection-1-snap.png b/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-rectangular-brush-selection-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..88f5f6e70c0bce9744ed865f08f5ff3f87449a18 GIT binary patch literal 27763 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 z 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 b=>?B@Hb<-6Td9MarYOIvYpdN=F}?8LSmP71 literal 0 HcmV?d00001 diff --git a/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-x-brush-selection-1-snap.png b/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-x-brush-selection-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7ed0a6cce5ab078d18cf39618e50c752bbfc7d69 GIT binary patch literal 27823 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 TdwvclkWsptdo}LwvON1=(GwM1 literal 0 HcmV?d00001 diff --git a/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-x-brush-selection-90-degree-1-snap.png b/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-x-brush-selection-90-degree-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..a35307631e279b0340403c7ffb0d15041fc566b4 GIT binary patch literal 26723 zcmb@u1z449*DZ_%Dxrjglp@js(v2eB9ZE=}G)R{PQi61Yk`jV|f{T<~Gy*E!CDPq+ z=EIKneZO~~^Pm5}elEGT8(C{T&wbB(%rVCt^9fK^l)}Au^&$oa2Cj^>xGDz5={XFH zQx@kj;U~Ypn$E+2PC2SdiDBe-P{6-j!;lfbtL~b(FzoSUa5HK4ILk!NpqWG_x&TEw zaT#4`yl{tAd1a#{)AuXaw@4mC!D%}`L(U{qIxDu;{{G~-0?tL}tl5t^T-I20!;06q zzAxCkQ@h5;Z_N+) z8xFTeQ|490#ZCMe(u0r>i4DFPC7a=(_tM`#ab&w{Tli@C_^>)_$a(XJ)_NWF(VH}> z(6vj)E0+!is}ISIjg7zm{JBQrvr3YuU3mJb=<&Mf>}IdQtmqN?xJhuiqHce=TIt@s zGowdarP(<-Ee&<}_+dD6@@4-10UvaV{Y+bL-HNUwp9@T#k4cii@% zP5JBcrLrLEgE6eWMduN>SxS+eu@|~R6!`efZ^X*{n^-pBRj2LdGGdHAD^j#rK7Nex zYk67JbfLm+9m7r_$yJC70}~U|EJqz5pa0UuIT{)|7mk$9C$V=LozbAy*C z1_tVKlmxF5Op=f_uW+_)ihv@=<;`SSrE1)lf8Bz4cgK+AaDE4S$=E$u?1 za}P?a44cDmW*r=)9L=RTZ2VH$+uzqgIoupQKH7HNkQNuGRf~VFB5o2Qz<+MirD~n> zXTDy-yaW6kTOfiJK9RYbqKw`FAluQU|;%3atxg|{gJ#Ghx##jN?Vc^Y=dE_==jPR%M+ ze0MHSLN=aLZ|0Gy>b|_kMwb--lV6wJ+}tpR?9r5M3B1dZw-*-|7lu%Tb?g{BmyX9p z?S5!zwYz@sVTc%Tgz#TYqdq*J`=cf0csE6<%!j8}qz4wnZJ`kD-(WN~J>3P%cSTG0 z_M=2HpJmPuUYV5}-EyBwOC#jz7;oL0{`tVRVRAK*W9C;^nh*pN5i#-Uk0#9oRXYuA zGpR#rCaNB+3w?zz&S2pw>*}@%Zx1;R+%^-AUg|G?6%v96v9a^Bv?|KG-O;);Ss32e zxKLZW-1*k)*RLZQV>h+qWfnQ&#N078^L3kBqL@#u>>nOXiXPp71Jh=&LFluR>~rMC zV?FS4aM8@wb?4J$o+k70V)bDuS^m-j#|L4Oqba4Mml8q5NltC_BC8if4(F6Ql_la@ z)3!_m zP0hw(m(kZfb5p(~`eSohDKjO5HVIrdU8xcW{V9h!cuYdY@|G!&EPv*`%gFF8DJdxq z;hZddvO3Yg#ly2UNqx-Mn~}bI=q(^1&{yHc*<}%V>p_XKme#9wvjnc6R_Jc4$1!Tz z!#Cw@D>sRmHS@k26;72A>3eNzZx%(8TF5zaM6crz_=kZ*sH-6tJOgAyw;#Vo?7@$pwrKf4pc+>!`Ct8le1%kMX< zd44W)KjC|Szl^c*4L`#%=ko0Q{LI{3=3Y}%6Q15=OM!^wjM5SJpx5NQGi5j!o+8u` zS;#J9c+PO9yvxtG>HcEE(R|5!<;>dJ+Lx^XONCW?qs-5p-EIV6>T9c_P!c&pGq3OQHvtpYE>D&VC8M&}>3b zJ=&>Ny{CbRh2{3^-K(8O-m2Skp(C)*3NkVm?%lg*HCz_e($bRXLlpf8t~WEmrgqVp zQ$(bL&3hGF-*dG=hPr`=o4e3`^D!(!U!@1HwY7ET&UvAT0rUGVF1)Z65PtSME90CY z3GJ{p&(C4+%K9f6U8VOeJUjg464?X`}HRHAh{Rd9g1_@lxDSvnENg zUHLGC?wgnxDO1y%Hl+#g-o2BVRP?r*-E@CsVez)0z&2AZiMD6JJRUt+V^sK%6f;-z zgTSJrhPwL8cC)(2pB)xI_c}~9g;A&r=+J%c{FIzbHR5yZRdsy0Tx>na11V-_*5_ze zX41@Y5v8uLuV`<-`Y45s^Jv89d;jB3-;NGNeYfc=RclcN>1<{D4CTY#EfQ&PB{elQ zajff~IyB04;x@G(OR~nyM`~u?x%RYmI-aW|7~L&z8PiPE%^4}1;kv(As&J({hRr}x zON%61JrHuq>1W6Z5KmJp8QvG+X}L=|nU~NdLs2b-tXVOPP1=JSJxXD8@%)Wp7_O;4upOl>3*u>=J$cTP4 zi_YnT{bk|Ub#3>Of$4?sOX2VCy~0z`)wK!~WuWKg;pzVIqha*;a5UnNB={U)r|y#I zR5N|b)V#s50OScNDz}$~g}2w%*HOQ7a^+WB?K1})7gy2L^q0>+1RO0gxsY-&MSrTV z+DB9*CG>#}$`>%#d%Jwpuuz+Unc4VoZ<9aYy*BPKZ|-opOV7}dyrbiKUaoLV2$gV) zlFyzRWM@Ca6;!7e>mlYgN%hV-gZ+Wt^RMbM4=P0;ETTR+&MH2ydAN6#41zUNA%XPj zRat5|(Vej~&Pziw9C7t?Pu3dPyt|0r?Z|(g9k>xHB&MWvY1}S$*=yND*Jao#PruS# zlS0mAd8ECSt-5V>5{)`O+6U&)x=U1(k&&V6wfSSnWz9Sx);IcS)cr#_e!DmmOYDA+Q^&0sho8jYNI_gPEdWsn2 z%QZ=}lbTprvB2wkc6Rul-MQ9lYGPt%_ePy5YM!Hmk?10RfVcy^u3^$1@Bn!oBuZ&o z0u<|HqM4i@2jTxCyNEl`C9zXwiZW`AzBL!L&RTuo06ZqB!HC~fmnLj1fIfNb+q-*w zNs2r+L(&ow=P*3B7T#4>QU*2D4t%zJWM!4OioT9;oF3bJbE%$}Pv9Sr^JH&-8wl7d zDtCV*qiboow0z+m^^9;8>Zsfvkux`^R}$VNav5=>_pVNXSmUuBk>|P!#P` z`yDp?k=-&WYuj9~$Z?LDm@s-ck<=BJ89q>IOUhj_X`x z%-wq<7gO=Z?RFB4jS5M#)tS-?QBT%})BESoO4CIE_T*`*dA;Y95u&1xlkW(eCF0mW z=I@1*0tG^*K^s$;^c!hfvj)eD#gm^!cjFVhPDS@`45SFn92>Ib_tzWUCJ1;rN1`uF z7g0PDn<7saAWoBcEEuog$Hc(U^mq`}64KNDQqDp`J_9<`|RUMrRUxV1HngC*g ze>|S{Be!{*o&8AGQe8TQtXVzK9Im2m+{Ss6(j>e5Wou7AGt=TNKNUHZvOi!=Ro!;z$T@p8;xQu6}c&PkwH6(GPl*eS1j z<*P||J{NOes+<;Wy|yQ zTlg*9RK4NcB?>`Z#H1M+-J`6UJl_p(Idy}myEyAjGSq(S0>osd=F4}zy>`4tD1;h+ zueotWX*ihbT$xFJBM--G2|hVl%$=C1+x(TCP-Af=)~?g?zR>9QDXr-CwCqob%q=+# zZMd#yf`f3`Z7p;%~I~{VLnwr`@ zOG{=zEi7u!H<_7q2i~HTl$2H@6>%0^Ez!3gywA<8Gwbnv?qCx`jM`P&)LKdTUGPEm z-UmDB^aDnP>>?s~Um*jq#$Z1M%5;^S{5H;+I`;P`G&~5HM4Z<(j`^soiZ&055(lGM z%!T4i%x!s(yL%dxMm-W5!!NS3-I@(7lGWw8(VG$I@2~r5#@(4qLHhW8P0d~4>py<{ zh*;X6q8DvOvU%11@G=K5S4x+mQ+L=&>p{Umy9rS}uNe#e!QvP({CGN)?E~_CZp=V* zVLWccrs}XUNS!~(g6V^asoRz5kmnRyOmJ7L@j?AvPp%6S1g!i@3oY_KbjLAXi)#Vg ze>E_0Kfn6O{ZA6VJJ4Ij^GLVk!`5GTy1Sd{(PDz>_4p{m6TS})HBx3?*LWxM54E4E z_DS;0je_hDNE7h^%= zNJ_A+B71rcn;3}C`Lm}X3qZZ&u6ynB+maHVNiXxY+StX0h@tx$JfRw<>pMTAZdH)1 ztXnPL9l)y!5*28K6bIXu`9?M)Q%G)_15l?&_gsuTT|dxoxfoVNZ^;_! z?dgf|CJ?5&goQ_e@pX0`vb7yb7Z~?P+ffn7T%-`qrKK@9<)Te0j%#ac9liS(x3WFH za%6o+$?fJg{#ej0e?~95FCn5?_|!+ZyUw7hBFIN%MGy{i^gIDTpF@jHsd;26N7VcR z->^LAIb$d!pl-1%i=%!xT;{}LP?cysSkiSu*f=3*;T}V%MMD7G_T~%Bp`^g5*qI2b zI9O{%nA4YWzl{w6H3>C#*^<+f#tXj%o2n_6CQ7NdK4uyn)dyxxYmok|(2b#|q2aiZ zX?(HqfmAg8wFyu1LD6qU$*Yv&F+W^61BK`Lp>Rv<}FDxXSU+CPVoM-{WbZbQcWY>B= z$ZrL3Dj|*&Mg=?s0kZn}$STR1f%btkd3vtMzBuAdCPfyzHT_Uv5}rt=++0LKhd*E;;{hiQBw#BjcD&V zPj$dAZf@?EV%Mo$$4;@9FK{q1Gb@qxjE;7$cZzlbJqIF%bLrBVvF-i2U%wu%&$I)X zDY5Do)6=8mNpN?Xp6J$ARWz32H?S;=uX}e5uzj5kF!kc=k42vXTU(hdwlt^8j*f}!Q5Ucu&u%sAJV9!mxc`E*y4WW^P{S;5um33UjsifXa{qO` zYW20P{M8uiTrWNfk=a;n7D?}_xnz#8ynduaNsmro%|16)dMGU9^(EnW`L(dR05+iK zR7(*PQ{p-Pe06d0nLurpXq6ErhNdN3rTn7FC!87+!RSe=!IIa}(Zs)h|5g-iTy!pW zT{Qwd;eB2nz%(Zp*GnL@m(Qo8&z(N?*wT`7#D$J6xL;o=EPJilE#~BVTgxk+7jxfj z#*SCia~5|kk61HOqkG|liAv%A5IF&a_zQI=?r9ySn11`RxJ-QRIQb&4edlOay_Ot} zTt!qtRu=ssEh|7vem<*eHW5gvz&T}QWi2c$9*$Od0U5i^!69aA%O)4i((HQd>+3sv zP&D`h^P1ymPLZ4Ed<*e_ZB>%bUj6IuWfh+&J!3o!4z;L6` z!CW*UnRT{-#9#`vq(;yv>Tr3#egDpt!TtE6Br4X66t8d{PGHgv5zVO1gkQ#NA6k&} zYUI#!``jdQN@}^Td+{hslf+#Pey!BjFf!OsO*Loev@3+Lw<1p}KW?_(X#kC8i`!{` zP%=G}BBGDQ+t-w~oeSYVa>M#pE3fG4=*t8Qht01+bK>mZoGi@IW6pwFX}hYk0}yZl z^8_>sjJ)rvAdnSCq4F1KNEEG?_&hb=D}#+9DHMOs+>&d-`r!`%M7{r;VbRPM2=cY% zSG_pM$qKquhej3U1zs_Y;&N>{K~#CpKj7**1zxdbFY7G}T8C#e0eoKXt_i=xc+qu! zy5n?(UxdReLhR@hTvuZWleXJ0dw`I#PmDC29dR*A9|q;%k5E)P8_|>- z0N$n@r>%&4Sf;N*I!J@=3vJfgEluJp9@^>)r^cFo+2g%>ULmq_-Iqr&!!Ls46`@oz zo)$t1*xL;%L8BQM7+Bf$oSL2O>F%yYg#E@TEQ{=;yUY#6-kruu1)2@>5(~DSvkgJ``?&BP$}+^TQD{jYDC=JXC$xDc^qn z90hWw*t^S@gjO(O^qk3}qM{-i8;ovy?+=a^S#+gtSpReNX|{IVzlkWvj#zn|<)Ox| zkRLjABLve;lwF=B?roc$>Tiax2<^}G_n&G)c-y0$4ObzM7XJ<5L>K#JQ+$#w^HDRA z^o7O65si(KICWnaoz?X86tuK@gTJ%V^c2+F0sS1yl#8|-etxwj(U*b>x7#}}^vtvC z2gYG1M}gDgq^#Zuy-Gn*KfA7?rzbpD_3YUx(B2+)jcAhLt4(_=0+1x1|3odQQOp0JVb_KKorWbKUw%hp3GmOulKa(vBMvydGu_gN_wmdGhlLl7|$pvZqk^cn$6g$ifTg&QlD&4wg*dX&7stXp4acl{lAORqZ!*H zIK8Gl2QXv%Y z($da6{S&a9mq!%-04(!^-R^GH{HndjOXbTVP-gQEKZ$sh-*F{uh}n@yd4^#OvH{oRQ1D}HqJbNliA=eUxpnu^~&e}12 zUD1BYVO}F{!CN#RK!hL0DMw2%RJ9b%C>$Zu%V-_gB=OJNC1hH1RunsFv0~*<{&*P;&LGjWB?ei{`4!^CpQ(a>D`c3{e zoc(sB^V;#YtVzNt44Y}(!ZmWF3&R$dsxH|)V*^;D@9xZ;0bB>_9&~1D&uEi6aVFQ~LMu`iwXuC`$v8zN<;ICEw~*Ma@V}g5cLZBp26eRx#36 zNlhhBW#D1y*Tv0qNQj#dt3e+Pg~6JTSc7l*3+3)lM`Oz=mEJc=IwQA6_ zOhkH?MD{b&YV%vF^IHT;H|GRzf1W%6GD7pwRtiO{vK7d<9W{XbAiDxf2F9?vyZh5(AKnv2Gisd0k?5q64$-CEYxDjAoR4JJbCibZQTqy!qA_D#!81e zvs6G+gXLYr+t?R_o}I%HuLY#q9sY*lMr^rP+mq_)k>5&$AEz}iA$)g|D5 z7(`dDsOal=fR0N48s3Raakl=P4*UZoatr}MLC`Yl*>Rwc1a;vPC#UwI-Qvq<|MCKy zxs2be>|6Xa%2Z>h=zWN2PEKZ%+3ew0_JUoJsfTv4VXK7*bQ!rj3Jb>nmfw?k@!|#W z+ML|nPJyM@yd$98Q9T9N8eCKyon3W3kNKkKewKfeFVk%bL?NlT^3rH>BSdkd&;>74 zWrpGH_wjUf&IV|`|Ilp<$;6&R#5iiN$j$j)V^Z^E#~q|w2tK6RVfPE(dSV+ zKF^NZh1x8+)`9*eX-#HXBWkjhS&@)MN4l<6zPq;X=NT!8&FI9(zj z(<(HSmEZhuc8r39oGs=qL}fl$Vhurn2$+rbNl8f+Yc0%3-+5|Up)GvO0o6@yfB|dv z?@S9nt~|IxDEf=6_5{=QIN2^<_rzr7r`wWyE2ND9*h<(REi*~+<8G>Ee~&cJ)-^-V znZ+k>Kz9sUSvtV+kp|0jRdRCjMuh9HZ`YIEX2_PlOyW`CNx92|XJCJ8(HMj#NT2Q= z9y&!PGL8FeEG$B^F~j*mW#T3?I=6^f868%oG=5lp$$MsId$XBnfl{dD!I3c>wF~qc zGAaJC3IE2fbX4j1g@=ZR+o5F;42fj4#Aa9^n$4i&Uosie8raz0&Jyidaj&!*_;leZ ziGgQWjDa^9w1aVZhwiAU^+f(8#e3EN*^&gx_B{+SaaJS9Ik3>L?%nfRcAD~-ps@|(--wVSr#v4!&7)FW7Ud^J@-jJQdwKVgk7x@L(Sx0~?dzi@5FZlb9t}=`ruaUTZI8De-S=KpZGjG@8>a=`A`tx3IdWPN{Vd48iS}QpMmI5s>f6S>r0Q+-7!6Dc8-Xhm0nivjgM+{Q{OQ*@dqY$- z1ILeFSKq-w5`-|bxL?y-!*mK>PUAYFA zt^X>5qb{I5K4xB3Vv2^N7b)Zf?)-D@xIU9$OAv}iT4Zwz3sc!y$rBxd%TN*ZbamCt zv?l~erdjnD`GQr!ibwB&mWD%PjRlxuxsLh*<_S{_#dI6)RWhu)Rrxer4Gwz~PAo|G z@$;t@*ZwE7O5w7BA|p>1MeuZQ&mDLW898~{KM*VtO#HB*cA$%hc=CXxw>ZaBWLJ}U z83*^H%L)Va%hLceC{`8mnfFM+=$2#rZ}sBynrk4nVFWci{~zrEXcO}pa|ikBEc4f*ccGS;hrn}m`4bi~SQC$fipB`TIufu#G!zY{F#Hnr^UI>%o5gPpV# zcqxwZEX1vk6Cl~<64c!d7=PRR;4TA?;^;4Xcd=7jxDu;;i7eZZ(`DlLanOnTPked= zjD5teuBcEBscJ=X5)jex9n++Eu0pV#DS=KtxK|iH`uL~=Lwq3qnc~d8Ey9YUb z7#SfcbsY(A%K7OuS~W%?XRHPuL7Td_3!d|n4c$+xjkqO?K)D1!sH%ZA=3CZTtnT$a#C`tK# zD6!HQJra=-K4HpH~H!vP60s)Jn?xE3im5f;X1NV z&|D@@t6zHCXQQm4EUqWRsJR&d@9{YE;+&xK!r0emXNX8h9KnE;=!`UH`wNY+fYYcm zNdR7eD-C1e-z&L{!a{qxRzP9mcYSs+UOaQt=F9*9^Kjtfarp zn0Czo&5e&AJJ{c)e%%ZFHamw$#UXICf-(bRy1Egi{_wUrID(``L zVtjrB#;-0$SL8>YdtAPk;~9Nhc|UZQ@UV4 zW%g%#5%4267l^B(rBGb#m!|dlC;s=0RfPP`l(s7ZrMh1lBNT+}VP=a}dq^>BdNmZn zU?y}p-0XFnYQitE9qs6?+WIUrshX{>If(nJZkB>DsG(>e)4$0=C|aN0;u?o6Exyur zgn{b9jDxL2z8qvu{J)@sJ!3y9AB18vJ!$a5^rCiW5>9DNN<{;Dp`7q5LdUY~l`IoeGYi6W8@(1ea);no9*M#oX_4jt53-AbwG$#Dn<4B&fE zShB_hfdvnU4cH?{K_=SR+A1<>4iDZ|(bjhDU@O<-WbkjwhNay1!*Uz1yR;+WLeI9f z-A#?B5^0-;`t&@vWmavL(bW5H;psAe-R}#|9+GaBOl{)Mi8j%Z0g9JI*P3o@Y;0V{ zd&S7aG*LF6Z@l^Y2O^No%$UU|B&_Zqe){~`{$R%*iY&z6*c!uzHTIv%P!+TWO4a=lD1gj>05nNhvR^eDtB+f&u^_FBcS&_> zfb{U}hSDo(C~0sH&k=+Li3vs3{~3^&X<-{o$@+CNuUlUzAR%c)02jnTFEL^7+2wO- z8f`r3igPBW{UMYJxHnC;zop)V-%&jIowH~(9qU?fFvn%Go2y~oYpuFBi3Y#JCe!rH zf@_S_V6Qs{d}xk)C1@&-U|6Zu;*>*{`9(&!%Dkyi$?kVUBxE;7A2)az3Dis4o>N4? zp$R9j!Ki+6Rn0~atcJ@K>m6>^N1oFy8|u*FbZ~( zp%;hCV`h^*Lcnp+oguedOHzgLHCfoh!qygTRQS<(@jkT7%yXXL$BA``drr`F5^@%t zg>#3%`iq?BG{0qK3v*I*K^8IhTiAiBJhPgbiV86bM(*2!r8ckh!YqEb&+-1K8hHD_ zdmJ7u6VsD7;kq4e#pkAP7b?{|YSEnGtk3s^^xN~`r(#z51thBTj?FqbuuO<77 zOtGDuocgTp`#q>%5G%CDq%jPUpxYAF!AzF90(s{KZxb)=(E;-N2W`U2e*B}^|JHb)s3huX#T>l7S zHvQnyWzqRqFwRC<7E}_K4&vScvl<2zGEl4L z+uL^)N_`(UMPM&PFSeU%#H%n8cp~}HK~vEoJR_4?@aWy){`Tai`!1Lb!)&rqm&trL zpz`xxPZ$L&9ugEtq<=Lynl?C1sIZFnYVtWYe*$>$U~%EHrdwmy!P%YsBUg*?{8_k; z$jHcV;4cI9>yfqfO)zT=4z~K?l5>nm85)lBqfOS9luYu;$wC!%r`%F~8;nksTBoLX z#$`o5_dGe#CeG!;X%*a8%xK`!K+s%p7VOn?8IBb4tFZL}O;x1#Et~^rT%({&b~{)_ zqoA<}&8!-;V!&3XVm=YTYas||V5x{%l>!e7@p41CP&;m?tf3(R1|wj0LYv>!D!^ek z^rT0DMf>B^=g&{WQL6^0@J^}EKCey1sw6mEL`^@})T6oJ_q9L#WE{@-kK0W(6yc*9 zOBz3=Prmc!Qr&fQ7;V+e`_85)~Y_uH@%O2>yEesJw@p4%eb7EsZ6g4 z$np`_8S^oe^rO<78m33qPU6Mrey&zQa*4G$Q8(Bd^}SbKP}_lvbOVR}@$Tg~FAx%O z#HIL&sTxRdBV;q|2I+4kj83nb5EyKX!ugpf8&xvo9WBT%`={0&u`3^Yt zb-FT&K}g>;*Eo?0_mcw^@J>-!6OpN z9QZPHY7y7SVy5^M%R$%qeW`^y~1EsMlX zmX=^@+O+DI!O!bn2EW2@vER8S}~YrhKq3=2z3!TB%R zER6sp50Igas`h^%_EtO!jPx^v3iYcJift7HWH z6=>jcBNqit)dTNiezfrM!8+nGsyN!4pBwyJ8O5oCv5RI z#Nro2q4??2ainn5T~H|pt4)&|yPESsZuK5BWQAQw)UP{d(^6BPBNqs%`*JASZR{Bq z0~1q=s|RHCPOl|L+6Wovg}%Gc7=hlqF*GC)B<#2OU4esx^9|bcFihmrLP+^XRpI0D zhco9p?b<89#?&1}dEZ|_e$B<&c7wQq)|kNch^FQUsh}Gl$FA0Y8)PCRd3r*}H2H~v zzWxZK`6}nY$S#rndONQpe5Z7V>VE_TWJ=4XQv18gaCG>r5f&;N9&e!+Am6646y(QP z)XyMNXz{I}jZe%qkY; z^<&rFR!x@3l;}wPgE{O{y-ZzMWCMnuwb~#(y6nNAAE^ko!X;*?awcbFatfYCA`WQI z$!AYRC?(quee&HXUfdAFZW0G~F<7li2a}e3vHHrKm{WG@>Ax%#wSr~wzm17rCPliI zbjwF3OBWi@J?1T;5|ROQ6Rrz*P!t3O4s*FNJLsi?1#k}BJHcx|)nfw|&VPK=LkIia zGpdvkEVieXC_#bm!wB{!5dc z{n5fk$9?%iN^FV{0D3Uzs2`l&+~sNFy{7&+HD$=ORBfI$LmH`VXgF}e^!7AB$I4S=^qj5I zbv?7sHNTp5w8VC3@PiM8hDrkBw4jr~x3*FJ1$IWh+Gj7zC%$`;v8E{xUkNg^AIKv7 zSIHWvUnla(*^D_6DNi!hm=(?-wiSHT`42DxCR>{IhBfm_0D4tIir;xc-i?76nw`p4 z#fTuh7VhvQAPe5QP2%F5(bbyO+nA|_A-+=ZyE5sjbGywkUn+N&|+ru60i zIo-roxj_IHML6uTa&jmbL<5KTKM5rY{r@b4NVFE6-!xr#iirx}~A;%kqRXuEaku-`vaBKMuX(-LHV57=#{?})r4 zSw}Ru_+=6Ert=F42^*^ui3c=8XdQ8BNW(DDZSU&iJY(=UMjurH)PvZ2>7U(*k3Q%q zvc>yzUcSJ2nauPW0UarMonxw#slFlp=FJT4?<$D%p5!5`xs;mkhE*jnsyTWNQk)4W zn6^)Rh7a>)%YRXXzV@Mw3~;N{%0vn4r*a|I=@ySKs6H__(3S@os0z z))B(&w`%`xSo6o=zLtROwbzW5YPfcbcxVek;%WteVccXI4Q%r5SAR9CW1|n1oIp}2 z=16yOb_VKNU%AoU;^~o9@sCvkA0x z5w1rFu3JOcLA&FeX%y+no#EfU;=93bCKM+G8HNE}n}+jRVl`2_p?FB=4tP)>T@# z#_&Q^A|;GL_2%i^las>+FQGZb|BJRv$wjvx}Y#i6sK50Xv`z1a-{At8%bUYM(NoWrW0acw$VSC4ka31#K2wo)4O7{<1 zsmp&2Rh&KjY~#zFYju%a7 zF{B9-89wcw=3s2YTJz<`-&H!IkS-0&d3g!{M}Or(sZ9nLn51bDBON)9Rg)_CW>TDcjAUlk#{uG}%ZHOy zM&d7WhCyHZrfI61Ze?PWl}U3MIeEX>r6OD+-i-@!580iCWpMCr z<2cE_QjPEXn&%N9WpJIhUU);H*w*PmNnb zUec2!w#PO0Y2f`6kM~bf;?PkywZ2SH$u{zH5E-&ZrPrHLC(S0Ouuj_Z*=OHMN094N z>KhRSokHa$2el=KGp4?aT~7jQOcIqj?ivU+KBN^7p%8gx`6MT}l705%Sqp74*S-8! z1rv8D6@OQlN23%>Brgt|K5r(K@=L3il3aN`5_|u#OYl+knV_rp5NsrZOSgYChT!vC+)_H1sN$T`G3sYjeUDU1~3rDXqxk81Z)XlLufML zU;$YTMtFkB!QfhtOz6No9ZEL@1TK=Roy*{X0>=)x1i?Fznvr3e!(g@#=kB_(G-AGi{sP`5-0%*Q6#+fhMLZ!q`jIYj4FsbyYvsWObYTuApkPo6 z%7s&i%Nsc1B;Kb6qw7(!r$7o^*=wc@v;--*5`Btt`2zNef9-aBuvgW6PeK4kfwcZn274{ zV#k4Ur1ABBcT81%ai>VDaj38)Q`E%K{xa6JtFJ@)MK7Pf{92ODXIzUR>xZoG;5}cD zg|#a485Ek|nW^O=$Fm-@x>-Aw$E75iDjE-ExGw8z3uR6wXcJB&yK zJ?FNBSAj>O|LRQcfEa|Wya!5mDcmgE$Q<3;et+S#Vs1_j4RKJ{;Gi5`gyHf?CE{Pl zfc_H^p3$|-V<5(yeGBrxt566~Z2(f3YlI{N?k7aafD+V*|l8l8ux1v-NgrPZ!$}j};d5rUGJP1|*7VH4MKt`|LY$ z&rjSYi6(R}I>&3_bdxQzPCD^%>qv@=r#G=`NvAYN@|fOtK#C1xEfvaUGpQFIRpo6` zU3W3n0=hmXR|66>8MwJ<%X9X~!8tLZfMW3W!cWJ7RDsx*QePap2?|l}HVDDGXb6_? zGYl_XKcs?Zk;d$uIt{1(R~<3yC^JzsZi~B7Dwaa#_qj8Q;y8nD-<+Tb#l0OVJMJQY?KM=H#+>u`iUvYX62ZYE z$^U_eX_$(s^S%T(*2@Tcv9y}QCgqnk>frdb&YIC(xbT7?R9Ml#HOeQUEDIO z+4>4Sj60Z$Z5uA*N|RbS~7!OH{l?IR!>{t73L29C3qmgG&tgJ zL^LDLMWpqG;k-B?0fUav<<-d5?CS33h?;J_l3#C@mGfQhhmQ4iPSk=gtFIk(gCi+RN)O)*j#s(Z^tj z^Hd!>=o=VkU)YPUDb~Fo*cXVMvV#kLsx*DIDlv^4`(W&~~#)cyqvZ4TiR*$`l*j(YS$-BPSHHU-s(X0u9(rQp1(mhJVoZaR zmTfL_`~=CvIaPiy{GaermlX{Xshr5c%01|C!Q)jJKDEL#cj(JqmSLQv$YEMGA0Ce+ zcYk#5O+Nn|M^Z+SjzHbvlb8E$qTf6BYeeuQpSRh2V6P9&S9(A8!t@?a2WX1915Hsm z$H#1LejFao2SP}#tO&YQQND%ilVlIk{TKB7?4-4i3ze5Q)fP8ZpmDy;{oc-}1oa$Z zbh=FUx)+_Abjn%4t8PyMQ3)y6YoeXPI~OS5oqFEPhg*fgO~uAdMg3X-g?q|7ZgpsK zRS@0L&WuE*;;of^>-;4uis+xKsO_=K|R@k*-Sy>49 zHYbnl&FS)1Qbn!8)+_j7GXMIFxcjeOVM@)SwhKl3IiVI0J#0 z+uZQ>oc{!(f?F>xiHy;U?p{C!N00|rJp?fXoFw4EgJ(x+yi+;MNPWYq>UkJIngpOc zioMlEwlr&Upbo2<9rGCOBIRyUZ)kgJ;~Pjxb||qwDhxK~Q(6Bzj%jb)GsguF3Oj}; z$=ox10MC7Z#~gtY9tH{vOypUB(P>;6n=dSGDkogkCOc;`I;RXt6Y1YNy?j2Ve4wTr ztE;)}Sh>r*=qR^-{L>A$LVzCB$@83G!lp~#-r53nEjusoEb{yVczjaI`kiXPY|n9Q zgE4qs1FO~iKVztA^$UL@sety5&0=PhxARRFzT(3=Y5x#AQOfaC-h&>IXTrAa?&p2q zKckKk{{C9uzB)%d_kEzhJntVLEJcHlQ^(+GO^ONS=42yi1wfx#VX*l2%pIw;uG{-q zr%$DJ{hGdYUtE6iYFeUYu)|L-t}7**jegiQUOw+bt*I$#!)3pXT~c0LRTCT_F6ziF zK~|Ng2Qj4XWhL3>96+0&xoQu3H#3Kw^u$4WPvixX8f|zNuM>t{c+a${s`1;@&B@qs zP+36Z*KC#OcXWP!8l+*1jdSnUcjF%X&gigIp5D=`K`29O#$=mQT+lK(EAOj<1LM&s~k zhe9!0L%ldJ)xB*if915jf3fz5-XnG==PZ< zH}e_#|5e+$M?<~$dwir#MeLGmMd`k)p{bBCyF#@SMIIC>GD68MBuu-u2)WcL#5CD% zk&-QyODWgnRxU-zwKU4OhH;zo{@Tx}y`HnrI?q~X9c%YTdrfBM_xt`n-_Pa!etqR- zLqhZ;IJTCbB&G~ZgiB9c6iQ>;8~A>$^|oOLmb}8{%F& zuZz8krJsTEV*cXC5dRUI6^6NkT)M-Xb!ZM3Up3IWRA+AkC01hARugSTNcL-9_gaTE z>Isn*5^f=tt}Uv4v(pf)!?_9 zaUrd?XGdn;Dcb(ztwHA7op)EYR6WVRi{(ReT^(<5bNkqGqOhu$%x*RY#LYlQ664~TUcur-3f2HlHOP==V+f? zs#B=({l$gBAuKud8jF=fvstkM`j_JePcD6uWU_zr?f%g~iK;x}sieD-#z&vRe$cFUs^o}b#+QHn^6eJ&YszH=k?w&pJl z{e#LCwlS#c?;d(YNCA+n6ZRPZZt;*`mOnpP*#^CQ{Ps zUhYSPsQo1J>XS&H|LH-IMxpuruQ{~IFCt(2nW65kH1|MV=DF@_??W%t)4qjj+SfnJ z*WR9IS9SmF3BKp$JV1KAoAdBK}dvA(t=0rsJx2ia_Li*oUwK<>&jS0%!u9KKiPGJa`u z3vMMPb)6rFWNxdUpzLMck}nFgW(MfSMI@P`aTQj^=oo9bW=_v>DIeYu{$o#^YqJMi zqc~J(r0s!e^2oviSx;(tqTL$4_o~s~aG6~(^yT=Cuqiv~=%4sNTg(&lCju6F%@i9v z6sr14mcI3)=;5$S0Sk&|#KrueyTw87#+*hk>jK^xE;0sxt+oh%aayF_zFu+MxkrAf z{bR`^V?m}_0eT6j;bU`+4~{iV-C}ot@yv=^=`43~+w%Eqycb{6?i;W289;L03D-~S zb76%-Muq@PVQz>0V6=)0&M3RPp1LN`{C@Q;YaWI`dYj z__C$eT)XB6sI`}uNv{m1OYzdAc9?_#~Zb?<(l{S^A5_Yg0%)_zM1@h}t! zU)YA^`-{R{t^)KBjXkwzcA~%MQ|l$lh`7Bz{)P7UNFQLHh3NXb>(I)&5#7e^Vo64u z#za#PDs`o;Q~r#voWH#KMT25;XOu7ZxfZUb_ky__NnPi#&$v7Gd9>yJI-89ZW4|gI z=_9xzm(R(`AyYQ=MT&x?GpvdNovmq6qI@2kUka!wN?4-0K@mi`4;MD1fcH(;5ghCF z>(}=jWaBCYnCq!TtR2EeH#)o5Uug7*)4759s$b(Kn;dd|<#L5C))-@}ODz0=Mhm&) zc2lWUA6$r50X{e*tb4d@%pN-}MS^8rOw_R9;q&BuhW10U!b4(I1dI(xE`O6$zPhZ1 zJpMGap8Pwx=lRBmpJ(5R7HOo*2fmtDS>?>P;O{;>dY=`3;<`}YHd5=YVqQ%_{u~ua z3UrC;vwu^dqwxg_+e!+G@IuI=cCWnZ=I&lyT@5!){s))+hYsxls4qxr{f&VZv_U&- zda+8)dRXshT&=~5Y-J5(=&YPFj!+RL!+wCKyLORMZC;xlA zv~7BPd{bacuP|7ch%s;+LHP77y;Q;|q;um9i}sH}#;3j0Q|{egA5|KxAAxArG~B;U z?Baz3p%;g{Ynp9x1-w^gwXZT1{WE`MzT+jnWO|Kjmsr57Gu^b@OO1$rg+QFl$UIoe z$S9)jp#JKY;45`~EbGo#cm6|e>^3p&?QUXX_Xi8-iRrc!==)06wdC1T*V|+SnWn$+ zyBr)GMsmzpG&1Qm)_SMW#nY3ho?Ea4Er_SkF#F|sRc?0VHf15sZtUPB|4Vd8*;NTHVys58f@JemJkItNVhHp~k{g%VmGM>6eY{ z)}!= zi_=X>J=cq=-{q@H{0ScsX=>`_yke?m2t;jK!fPrN?NA^h6{L04|QHFXj6i z?B0Ee!|%hAdsbLEuLv7lq7ExcFHu>zwj7qr2Wnk{es7;N?C_#S6fiQPv?fA=gOzDC z+WMR0$7s9l?2pyYRLE^^=g3 z6J4UfjDe*aEmwI8qvA%~H~IN@IKQHNX(U~$)v6=+ zMod8~xPl?rirGa{N{W4XB<4Zz$`ChCD>5Ep2)i+GkbY7zQ+f|I!WyF;Y__1Z#5%XI zD>Dr;0rvA9&S0bROK&(qT2DYS1uwKMemkk{z_!nu>^WuU;IJ&Zf`$_3>D1RW$f=8i zx11SRPK3h{k`YX-D?YSzT+@b?hG#brsFL?+n?GzYPX}4OF|NU8RSA#=TcM~2cZbO0 z9`?mZH~wqdTzq-M=PWnH%reh890@04`oSMT*oSx{OumP`y?vm$@zmU2=>Ke?3WO1l zjI`BY!?m2Ov)t=^T3Y4xyP&qvsZXI`u{>^#BqUFw_A@&0x^Qp&u$3qDeQT7IY@M9? za;+0xdyMSfq?&0=^c4W`2)_$qOgn_fE<)`-GX#Flz9A?#$4LsEk$(g(PX}t0h0PK4HP% zH-$?c1G*cbpXe^T2UQOTzuOwFEGToVBJ$DWEd}U2_^1r!KdxPq%=-OObY*5)C*)!o z;Ai>rN0@o_33}ied#JPU1t@G~;#{&j;XnMYo+zX^JTlLi8 z*n1qP6W+P??uHKn=5E-y5s<(mgNHKE;>~Y*UGIYSnpCeMAEpC!{Tg>!3Iq;_pTvkS z@EFQ;_|D{1snHb!Rs4yn`V%USPk9U@?-(_5^O1Z97=<#*s9qhZwXBVij)i z;F=TAZDf0gO{8g$QBNL!JkJcM@qc{wOPh^%O?n6G95MW(*U)sPiv_uU@Ive2x0-sX z!&Y8hEDzHM$6s&B^8kx{s$YRW4=QIgQZSh8SYYCDR63FK2;6!4(A!?vRu2QvaaMJek;p#9%>nr5)>5F7%bmNWQhw$5=T&E z!R4a6dI4dAqBorMNx^ULgW=?dAQy`kECC99kj;<5{5@oRHDy`cdk2R>>M3G)~8z=S#+zB)eBe> z#>Y_pF9ZWErsU=4ukB81@Y*za4^}Lq`{vHN7NSbN2Rhe;=S$osSzR|f@EhO&m?(KX z{f)B0)&O|OwgaB7jYI5^XNvhfMF>!x^vW$#OWH+sfW0e_w z4S|8tiJC~yCQw_EG~heRJ*lkYJv6i@W};gN_nd7?m@lFsIKMgwUckRX6k=v33lADV zzyc5u%gW0O4GcPn%WLeiv9Z}uCRAy8HvQ|!h#+>he8_a>l>8(kDy6ksRz_yE`D{VIypBF@E+^(MD=RC|ic14=39fXIVQ)jFNsifG zf7fK$&8n(!gm0ro5r{1|cp7ucyS4nYeEAvblYKodM{jUx+x*29in|7*+UI_Ffarl| zax{rKwhE1SI6NcKKvy9&Y1=p zEB>F!#zvoF{pH(1KW&A_0J$KBS5~B0tSN`Tx&*`r((aklh_PZ3`3wH1N#RT6*M{E? zHNYlYCYdt}^;yvlam~WUQ+XA{CWAT8DW|^HZD=xxAy&r{&eM?w5RHf=z_K**g;XY`wqn^^aEiiAu5!doJ^b{-aQVM zf~3jNiQBW7H13g0;Cu|CEdJwYfzTAr?6`@-1n=#MLkl7|JG`k~w0zz?lGTJ;)x((w zI@AGU<9>h(2&{6(E2vL!I|;iMaWD>oSE4tCVjqtmQA^=Tqj>iRSsufi6ORWl??Ggr z0zFBcz~3l+p{6)00nd-X5xhhLCM+^p*tMMC^94pDm^^7>8tP;9dJCV6 zIP7JorwQKH2SRZGwVVPl=5_Mk-f(ycwYEOLVB~^oYB@yL+VQjCs}w+J#Wx{9b2aDo z!pPpn6DsgU2mq$UsrSPj-Ujhc*93VIhJ9Dtz*W|#>SFi;@qS>j~jJ2=q$ER^lMH(!V$jp ziSjDV$tN}Xe7&He8J!oNKy(yZnXjm*(?`%f$eTfBBD_uLGO!OJ?I}QIN)Gz~8v(Wo zr-9Dh$gcocd`js|dH~K&-4=dtOuRndB?Iy+ zSLRcuMnn0Lq{FyKZJI)i^%6;EYT;HS#K-?;Ingfd=cvRSRAm<6&339pe*p0yAtfa+ xZ=x)3UHMUTu3QcOUvl+tkM+M64N-jYu(xw|t?*2f!l^-&-8%Z(_qHE7|DT@fCENf2 literal 0 HcmV?d00001 diff --git a/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-y-brush-selection-1-snap.png b/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-y-brush-selection-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..c340d383f2bb645e53bcbcecb22d741c0fa51868 GIT binary patch literal 27139 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 literal 0 HcmV?d00001 diff --git a/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-y-brush-selection-90-degree-1-snap.png b/integration/tests/__image_snapshots__/interactions-test-ts-tooltips-rotation-90-show-y-brush-selection-90-degree-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..139c4b87b79bf7798656359b1c5fcb8e81362fb1 GIT binary patch literal 27664 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 { +describe('Tooltips', () => { describe('rotation 0', () => { it('shows tooltip on first x value - top', async () => { await common.expectChartWithMouseAtUrlToMatchScreenshot( @@ -103,5 +103,48 @@ describe.only('Tooltips', () => { }, ); }); + it('show rectangular brush selection', async () => { + await common.expectChartWithDragAtUrlToMatchScreenshot( + 'http://localhost:9001/?path=/story/interactions--brush-tool', + { x: 100, y: 100 }, + { x: 250, y: 250 }, + ); + }); + it('show y brush selection', async () => { + await common.expectChartWithDragAtUrlToMatchScreenshot( + 'http://localhost:9001/?path=/story/interactions--brush-tool&knob-brush axis=y&knob-chartRotation=0', + { x: 100, y: 100 }, + { x: 250, y: 250 }, + ); + }); + it('show x brush selection', async () => { + await common.expectChartWithDragAtUrlToMatchScreenshot( + 'http://localhost:9001/?path=/story/interactions--brush-tool&knob-brush axis=x&knob-chartRotation=0', + { x: 100, y: 100 }, + { x: 250, y: 250 }, + ); + }); + + it('show rectangular brush selection -90 degree', async () => { + await common.expectChartWithDragAtUrlToMatchScreenshot( + 'http://localhost:9001/?path=/story/interactions--brush-tool&knob-brush axis=both&knob-chartRotation=-90', + { x: 100, y: 100 }, + { x: 250, y: 250 }, + ); + }); + it('show y brush selection -90 degree', async () => { + await common.expectChartWithDragAtUrlToMatchScreenshot( + 'http://localhost:9001/?path=/story/interactions--brush-tool&knob-brush axis=y&knob-chartRotation=-90', + { x: 100, y: 100 }, + { x: 250, y: 250 }, + ); + }); + it('show x brush selection -90 degree', async () => { + await common.expectChartWithDragAtUrlToMatchScreenshot( + 'http://localhost:9001/?path=/story/interactions--brush-tool&knob-brush axis=x&knob-chartRotation=-90', + { x: 100, y: 100 }, + { x: 250, y: 250 }, + ); + }); }); }); diff --git a/src/chart_types/xy_chart/state/selectors/get_brush_area.test.ts b/src/chart_types/xy_chart/state/selectors/get_brush_area.test.ts new file mode 100644 index 0000000000..9ab3b95916 --- /dev/null +++ b/src/chart_types/xy_chart/state/selectors/get_brush_area.test.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ + +import { getBrushForXAxis, getBrushForYAxis, getBrushForBothAxis } from './get_brush_area'; +import { Dimensions } from '../../../../utils/dimensions'; + +describe('getBrushArea Selector', () => { + it('should return the brush area', () => { + const chartDimensions: Dimensions = { left: 0, top: 0, width: 100, height: 110 }; + + const xBrushArea = getBrushForXAxis(chartDimensions, 0, { x: 10, y: 10 }, { x: 30, y: 30 }); + expect(xBrushArea).toEqual({ + top: 0, + left: 10, + width: 20, + height: 110, + }); + const yBrushArea = getBrushForYAxis(chartDimensions, 0, { x: 10, y: 10 }, { x: 30, y: 30 }); + expect(yBrushArea).toEqual({ + top: 10, + left: 0, + width: 100, + height: 20, + }); + + const bothBrushArea = getBrushForBothAxis(chartDimensions, { x: 10, y: 10 }, { x: 30, y: 30 }); + expect(bothBrushArea).toEqual({ + top: 10, + left: 10, + width: 20, + height: 20, + }); + }); + + it('should return the brush area on rotated chart', () => { + const chartDimensions: Dimensions = { left: 0, top: 0, width: 100, height: 110 }; + + const brushArea = getBrushForXAxis(chartDimensions, 90, { x: 10, y: 10 }, { x: 30, y: 30 }); + expect(brushArea).toEqual({ + top: 10, + left: 0, + width: 100, + height: 20, + }); + + const yBrushArea = getBrushForYAxis(chartDimensions, 90, { x: 10, y: 10 }, { x: 30, y: 30 }); + expect(yBrushArea).toEqual({ + top: 0, + left: 10, + width: 20, + height: 110, + }); + + const bothBrushArea = getBrushForBothAxis(chartDimensions, { x: 10, y: 10 }, { x: 30, y: 30 }); + expect(bothBrushArea).toEqual({ + top: 10, + left: 10, + width: 20, + height: 20, + }); + }); +}); 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 index 8fe9d753a0..1a1d9696c5 100644 --- a/src/chart_types/xy_chart/state/selectors/get_brush_area.ts +++ b/src/chart_types/xy_chart/state/selectors/get_brush_area.ts @@ -41,62 +41,55 @@ export const getBrushAreaSelector = createCachedSelector( computeChartDimensionsSelector, getSettingsSpecSelector, ], - (mouseDownPosition, cursorPosition, chartRotation, { chartDimensions }, { brushAxis }): Dimensions | null => { + (mouseDownPosition, end, chartRotation, { chartDimensions }, { brushAxis }): Dimensions | null => { if (!mouseDownPosition) { return null; } - const brushStart = { + const start = { x: mouseDownPosition.position.x, y: mouseDownPosition.position.y, }; switch (brushAxis) { case BrushAxis.Y: - return getBrushForYAxis(chartDimensions, chartRotation, cursorPosition, brushStart); + return getBrushForYAxis(chartDimensions, chartRotation, start, end); case BrushAxis.Both: - return getBrushForBothAxis(chartDimensions, cursorPosition, brushStart); + return getBrushForBothAxis(chartDimensions, start, end); case BrushAxis.X: default: - return getBrushForXAxis(chartDimensions, chartRotation, cursorPosition, brushStart); + return getBrushForXAxis(chartDimensions, chartRotation, start, end); } }, )(getChartIdSelector); -function getBrushForXAxis( - chartDimensions: Dimensions, - chartRotation: Rotation, - cursorPosition: Point, - brushStart: Point, -) { +/** @internal */ +export function getBrushForXAxis(chartDimensions: Dimensions, chartRotation: Rotation, start: Point, end: Point) { const rotated = isRotated(chartRotation); return { - left: rotated ? 0 : getLeftPoint(chartDimensions, brushStart), - top: rotated ? getTopPoint(chartDimensions, brushStart) : 0, - height: rotated ? getHeight(cursorPosition, brushStart) : chartDimensions.height, - width: rotated ? chartDimensions.width : getWidth(cursorPosition, brushStart), + left: rotated ? 0 : getLeftPoint(chartDimensions, start), + top: rotated ? getTopPoint(chartDimensions, start) : 0, + height: rotated ? getHeight(start, end) : chartDimensions.height, + width: rotated ? chartDimensions.width : getWidth(start, end), }; } -function getBrushForYAxis( - chartDimensions: Dimensions, - chartRotation: Rotation, - cursorPosition: Point, - brushStart: Point, -) { +/** @internal */ +export function getBrushForYAxis(chartDimensions: Dimensions, chartRotation: Rotation, start: Point, end: Point) { const rotated = isRotated(chartRotation); return { - left: rotated ? getLeftPoint(chartDimensions, brushStart) : 0, - top: rotated ? 0 : getTopPoint(chartDimensions, brushStart), - height: rotated ? chartDimensions.height : getHeight(cursorPosition, brushStart), - width: rotated ? getWidth(cursorPosition, brushStart) : chartDimensions.width, + left: rotated ? getLeftPoint(chartDimensions, start) : 0, + top: rotated ? 0 : getTopPoint(chartDimensions, start), + height: rotated ? chartDimensions.height : getHeight(start, end), + width: rotated ? getWidth(start, end) : chartDimensions.width, }; } -function getBrushForBothAxis(chartDimensions: Dimensions, cursorPosition: Point, brushStart: Point) { +/** @internal */ +export function getBrushForBothAxis(chartDimensions: Dimensions, start: Point, end: Point) { return { - left: getLeftPoint(chartDimensions, brushStart), - top: getTopPoint(chartDimensions, brushStart), - height: getHeight(cursorPosition, brushStart), - width: getWidth(cursorPosition, brushStart), + left: getLeftPoint(chartDimensions, start), + top: getTopPoint(chartDimensions, start), + height: getHeight(start, end), + width: getWidth(start, end), }; } @@ -109,9 +102,9 @@ export function getLeftPoint({ left }: Dimensions, { x }: Point) { export function getTopPoint({ top }: Dimensions, { y }: Point) { return y - top; } -export function getHeight(cursorPosition: Point, brushStart: Point) { - return cursorPosition.y - brushStart.y; +export function getHeight(start: Point, end: Point) { + return end.y - start.y; } -export function getWidth(cursorPosition: Point, brushStart: Point) { - return cursorPosition.x - brushStart.x; +export function getWidth(start: Point, end: Point) { + return end.x - start.x; } diff --git a/stories/interactions/9a_brush_selection_linear.tsx b/stories/interactions/9a_brush_selection_linear.tsx index 35b3c9eae5..4f65d209cd 100644 --- a/stories/interactions/9a_brush_selection_linear.tsx +++ b/stories/interactions/9a_brush_selection_linear.tsx @@ -23,17 +23,16 @@ import { AreaSeries, Axis, Chart, Position, ScaleType, Settings, BrushAxis } fro import { getChartRotationKnob } from '../utils/knobs'; import { select } from '@storybook/addon-knobs'; -const brushAxisSelect = select( - 'brush axis', - { - x: BrushAxis.X, - y: BrushAxis.Y, - both: BrushAxis.Both, - }, - BrushAxis.Both, -); - export const example = () => { + const brushAxisSelect = select( + 'brush axis', + { + x: BrushAxis.X, + y: BrushAxis.Y, + both: BrushAxis.Both, + }, + BrushAxis.Both, + ); return ( From d4d706b6d5738d786abc79c5db05268c817cd5fd Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 15 Apr 2020 18:03:46 +0200 Subject: [PATCH 4/8] test: add test on interactions --- .../state/chart_state.interactions.test.ts | 156 +++++++++++++++++- .../state/selectors/get_brush_area.ts | 17 +- .../state/selectors/on_brush_end_caller.ts | 7 +- 3 files changed, 169 insertions(+), 11 deletions(-) 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 index 0555437932..39a8e8a90a 100644 --- a/src/chart_types/xy_chart/state/chart_state.interactions.test.ts +++ b/src/chart_types/xy_chart/state/chart_state.interactions.test.ts @@ -21,7 +21,7 @@ import { BarSeriesSpec, BasicSeriesSpec, AxisSpec, SeriesTypes } from '../utils/ import { Position } from '../../../utils/commons'; import { ScaleType } from '../../../scales'; import { chartStoreReducer, GlobalChartState } from '../../../state/chart_state'; -import { SettingsSpec, DEFAULT_SETTINGS_SPEC, SpecTypes, TooltipType, XYBrushArea } from '../../../specs'; +import { SettingsSpec, DEFAULT_SETTINGS_SPEC, SpecTypes, TooltipType, XYBrushArea, BrushAxis } from '../../../specs'; import { computeSeriesGeometriesSelector } from './selectors/compute_series_geometries'; import { getProjectedPointerPositionSelector } from './selectors/get_projected_pointer_position'; import { @@ -941,5 +941,159 @@ function mouseOverTestSuite(scaleType: ScaleType) { expect(brushEndListener.mock.calls[3][0]).toEqual({ x: [0, 0] }); } }); + test('can respond to a Y brush', () => { + const brushEndListener = jest.fn((): void => { + return; + }); + const onBrushCaller = createOnBrushEndCaller(); + store.subscribe(() => { + onBrushCaller(store.getState()); + }); + const settings = getSettingsSpecSelector(store.getState()); + const updatedSettings: SettingsSpec = { + ...settings, + brushAxis: BrushAxis.Y, + theme: { + ...settings.theme, + chartMargins: { + left: 0, + right: 0, + top: 0, + bottom: 0, + }, + }, + onBrushEnd: brushEndListener, + }; + store.dispatch(upsertSpec(updatedSettings)); + store.dispatch( + upsertSpec({ + ...spec, + data: [ + [0, 1], + [1, 1], + [2, 2], + [3, 3], + ], + } as BarSeriesSpec), + ); + store.dispatch(specParsed()); + + const start1 = { x: 0, y: 0 }; + const end1 = { x: 0, y: 75 }; + + store.dispatch(onMouseDown(start1, 0)); + store.dispatch(onPointerMove(end1, 1)); + store.dispatch(onMouseUp(end1, 3)); + if (scaleType === ScaleType.Ordinal) { + expect(brushEndListener).not.toBeCalled(); + } else { + expect(brushEndListener).toBeCalled(); + expect(brushEndListener.mock.calls[0][0]).toEqual({ + y: [ + { + groupId: spec.groupId, + extent: [0.75, 3], + }, + ], + }); + } + const start2 = { x: 0, y: 75 }; + const end2 = { x: 0, y: 100 }; + + store.dispatch(onMouseDown(start2, 4)); + store.dispatch(onPointerMove(end2, 5)); + store.dispatch(onMouseUp(end2, 6)); + if (scaleType === ScaleType.Ordinal) { + expect(brushEndListener).not.toBeCalled(); + } else { + expect(brushEndListener).toBeCalled(); + expect(brushEndListener.mock.calls[1][0]).toEqual({ + y: [ + { + groupId: spec.groupId, + extent: [0, 0.75], + }, + ], + }); + } + }); + test('can respond to rectangular brush', () => { + const brushEndListener = jest.fn((): void => { + return; + }); + const onBrushCaller = createOnBrushEndCaller(); + store.subscribe(() => { + onBrushCaller(store.getState()); + }); + const settings = getSettingsSpecSelector(store.getState()); + const updatedSettings: SettingsSpec = { + ...settings, + brushAxis: BrushAxis.Both, + theme: { + ...settings.theme, + chartMargins: { + left: 0, + right: 0, + top: 0, + bottom: 0, + }, + }, + onBrushEnd: brushEndListener, + }; + store.dispatch(upsertSpec(updatedSettings)); + store.dispatch( + upsertSpec({ + ...spec, + data: [ + [0, 1], + [1, 1], + [2, 2], + [3, 3], + ], + } as BarSeriesSpec), + ); + store.dispatch(specParsed()); + + const start1 = { x: 0, y: 0 }; + const end1 = { x: 75, y: 75 }; + + store.dispatch(onMouseDown(start1, 0)); + store.dispatch(onPointerMove(end1, 1)); + store.dispatch(onMouseUp(end1, 3)); + if (scaleType === ScaleType.Ordinal) { + expect(brushEndListener).not.toBeCalled(); + } else { + expect(brushEndListener).toBeCalled(); + expect(brushEndListener.mock.calls[0][0]).toEqual({ + x: [0, 2.5], + y: [ + { + groupId: spec.groupId, + extent: [0.75, 3], + }, + ], + }); + } + const start2 = { x: 75, y: 75 }; + const end2 = { x: 100, y: 100 }; + + store.dispatch(onMouseDown(start2, 4)); + store.dispatch(onPointerMove(end2, 5)); + store.dispatch(onMouseUp(end2, 6)); + if (scaleType === ScaleType.Ordinal) { + expect(brushEndListener).not.toBeCalled(); + } else { + expect(brushEndListener).toBeCalled(); + expect(brushEndListener.mock.calls[1][0]).toEqual({ + x: [2.5, 3], + y: [ + { + groupId: spec.groupId, + extent: [0, 0.75], + }, + ], + }); + } + }); }); } 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 index 1a1d9696c5..2e6dd11fbe 100644 --- a/src/chart_types/xy_chart/state/selectors/get_brush_area.ts +++ b/src/chart_types/xy_chart/state/selectors/get_brush_area.ts @@ -17,6 +17,7 @@ * under the License. */ import createCachedSelector from 're-reselect'; +import { isVerticalRotation } from '../utils'; import { GlobalChartState } from '../../../../state/chart_state'; import { Dimensions } from '../../../../utils/dimensions'; import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation'; @@ -63,7 +64,7 @@ export const getBrushAreaSelector = createCachedSelector( /** @internal */ export function getBrushForXAxis(chartDimensions: Dimensions, chartRotation: Rotation, start: Point, end: Point) { - const rotated = isRotated(chartRotation); + const rotated = isVerticalRotation(chartRotation); return { left: rotated ? 0 : getLeftPoint(chartDimensions, start), top: rotated ? getTopPoint(chartDimensions, start) : 0, @@ -74,7 +75,7 @@ export function getBrushForXAxis(chartDimensions: Dimensions, chartRotation: Rot /** @internal */ export function getBrushForYAxis(chartDimensions: Dimensions, chartRotation: Rotation, start: Point, end: Point) { - const rotated = isRotated(chartRotation); + const rotated = isVerticalRotation(chartRotation); return { left: rotated ? getLeftPoint(chartDimensions, start) : 0, top: rotated ? 0 : getTopPoint(chartDimensions, start), @@ -93,18 +94,20 @@ export function getBrushForBothAxis(chartDimensions: Dimensions, start: Point, e }; } -export function isRotated(chartRotation: Rotation) { - return chartRotation === -90 || chartRotation === 90; -} +/** @internal */ export function getLeftPoint({ left }: Dimensions, { x }: Point) { return x - left; } + +/** @internal */ export function getTopPoint({ top }: Dimensions, { y }: Point) { return y - top; } -export function getHeight(start: Point, end: Point) { + +function getHeight(start: Point, end: Point) { return end.y - start.y; } -export function getWidth(start: Point, end: Point) { + +function getWidth(start: Point, end: Point) { return end.x - start.x; } 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 index d2c98c1c2e..0d96b09097 100644 --- 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 @@ -30,7 +30,8 @@ import { Scale } from '../../../../scales'; import { Dimensions } from '../../../../utils/dimensions'; import { GroupId } from '../../../../utils/ids'; import { Rotation } from '../../../../utils/commons'; -import { getLeftPoint, getTopPoint, isRotated } from './get_brush_area'; +import { getLeftPoint, getTopPoint } from './get_brush_area'; +import { isVerticalRotation } from '../utils'; const getLastDragSelector = (state: GlobalChartState) => state.interactions.pointer.lastDrag; @@ -127,7 +128,7 @@ function getXBrushExtent( let endPos = getLeftPoint(chartDimensions, lastDrag.end.position); let chartMax = chartDimensions.width; - if (isRotated(rotation)) { + if (isVerticalRotation(rotation)) { startPos = getTopPoint(chartDimensions, lastDrag.start.position); endPos = getTopPoint(chartDimensions, lastDrag.end.position); chartMax = chartDimensions.height; @@ -163,7 +164,7 @@ function getYBrushExtents( let startPos = getTopPoint(chartDimensions, lastDrag.start.position); let endPos = getTopPoint(chartDimensions, lastDrag.end.position); let chartMax = chartDimensions.height; - if (isRotated(rotation)) { + if (isVerticalRotation(rotation)) { startPos = getLeftPoint(chartDimensions, lastDrag.start.position); endPos = getLeftPoint(chartDimensions, lastDrag.end.position); chartMax = chartDimensions.width; From 289d5290bd82165f43a756c67a7d9b9a8d165ee7 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Fri, 17 Apr 2020 11:41:51 +0200 Subject: [PATCH 5/8] refactor: extract min,max bounded functions --- .../state/selectors/on_brush_end_caller.ts | 18 +++++++------- src/scales/scale_band.ts | 4 ++-- src/scales/scale_continuous.ts | 4 ++-- src/utils/commons.test.ts | 24 ++++++++++++------- src/utils/commons.ts | 23 +++++++++++++++--- 5 files changed, 49 insertions(+), 24 deletions(-) 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 index 0d96b09097..3474d043cf 100644 --- 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 @@ -29,7 +29,7 @@ import { isBrushAvailableSelector } from './is_brush_available'; import { Scale } from '../../../../scales'; import { Dimensions } from '../../../../utils/dimensions'; import { GroupId } from '../../../../utils/ids'; -import { Rotation } from '../../../../utils/commons'; +import { Rotation, minValueWithLowerLimit, maxValueWithUpperLimit } from '../../../../utils/commons'; import { getLeftPoint, getTopPoint } from './get_brush_area'; import { isVerticalRotation } from '../utils'; @@ -134,8 +134,8 @@ function getXBrushExtent( chartMax = chartDimensions.height; } - let minPos = Math.max(Math.min(startPos, endPos), 0); - let maxPos = Math.min(Math.max(startPos, endPos), chartMax); + let minPos = minValueWithLowerLimit(startPos, endPos, 0); + let maxPos = maxValueWithUpperLimit(startPos, endPos, chartMax); if (rotation === -90 || rotation === 180) { minPos = chartMax - minPos; maxPos = chartMax - maxPos; @@ -148,8 +148,8 @@ function getXBrushExtent( const offset = histogramMode ? 0 : -(xScale.bandwidth + xScale.bandwidthPadding) / 2; const minPosScaled = xScale.invert(minPos + offset); const maxPosScaled = xScale.invert(maxPos + offset); - const minValue = Math.max(Math.min(minPosScaled, maxPosScaled), xScale.domain[0]); - const maxValue = Math.min(Math.max(minPosScaled, maxPosScaled), xScale.domain[1]); + const minValue = minValueWithLowerLimit(minPosScaled, maxPosScaled, xScale.domain[0]); + const maxValue = maxValueWithUpperLimit(minPosScaled, maxPosScaled, xScale.domain[1]); return [minValue, maxValue]; } @@ -169,8 +169,8 @@ function getYBrushExtents( endPos = getLeftPoint(chartDimensions, lastDrag.end.position); chartMax = chartDimensions.width; } - let minPos = Math.max(Math.min(startPos, endPos), 0); - let maxPos = Math.min(Math.max(startPos, endPos), chartMax); + let minPos = minValueWithLowerLimit(startPos, endPos, 0); + let maxPos = maxValueWithUpperLimit(startPos, endPos, chartMax); if (rotation === -90 || rotation === 180) { minPos = chartMax - minPos; maxPos = chartMax - maxPos; @@ -182,8 +182,8 @@ function getYBrushExtents( const minPosScaled = yScale.invert(minPos); const maxPosScaled = yScale.invert(maxPos); - const minValue = Math.max(Math.min(minPosScaled, maxPosScaled), yScale.domain[0]); - const maxValue = Math.min(Math.max(minPosScaled, maxPosScaled), yScale.domain[1]); + const minValue = minValueWithLowerLimit(minPosScaled, maxPosScaled, yScale.domain[0]); + const maxValue = maxValueWithUpperLimit(minPosScaled, maxPosScaled, yScale.domain[1]); yValues.push({ extent: [minValue, maxValue], groupId }); }); return yValues.length === 0 ? undefined : yValues; diff --git a/src/scales/scale_band.ts b/src/scales/scale_band.ts index 953fe74405..2967f0691d 100644 --- a/src/scales/scale_band.ts +++ b/src/scales/scale_band.ts @@ -17,7 +17,7 @@ * under the License. */ import { scaleBand, scaleQuantize, ScaleQuantize } from 'd3-scale'; -import { clamp } from '../utils/commons'; +import { maxValueWithUpperLimit } from '../utils/commons'; import { ScaleType, Scale } from '.'; /** * Categorical scale @@ -51,7 +51,7 @@ export class ScaleBand implements Scale { this.d3Scale = scaleBand(); this.d3Scale.domain(domain); this.d3Scale.range(range); - const safeBarPadding = clamp(barsPadding, 0, 1); + const safeBarPadding = maxValueWithUpperLimit(barsPadding, 0, 1); this.barsPadding = safeBarPadding; this.d3Scale.paddingInner(safeBarPadding); this.d3Scale.paddingOuter(safeBarPadding / 2); diff --git a/src/scales/scale_continuous.ts b/src/scales/scale_continuous.ts index ad83ffa626..b46c8f149b 100644 --- a/src/scales/scale_continuous.ts +++ b/src/scales/scale_continuous.ts @@ -28,7 +28,7 @@ import { ScaleTime, } from 'd3-scale'; -import { clamp, mergePartial } from '../utils/commons'; +import { maxValueWithUpperLimit, mergePartial } from '../utils/commons'; import { ScaleContinuousType, ScaleType, Scale } from '.'; import { getMomentWithTz } from '../utils/data/date_time'; @@ -190,7 +190,7 @@ export class ScaleContinuous implements Scale { this.domain = cleanDomain; this.d3Scale.domain(cleanDomain); - const safeBarPadding = clamp(barsPadding, 0, 1); + const safeBarPadding = maxValueWithUpperLimit(barsPadding, 0, 1); this.barsPadding = safeBarPadding; this.bandwidth = bandwidth * (1 - safeBarPadding); this.bandwidthPadding = bandwidth * safeBarPadding; diff --git a/src/utils/commons.test.ts b/src/utils/commons.test.ts index 1521459be5..15ee72f19c 100644 --- a/src/utils/commons.test.ts +++ b/src/utils/commons.test.ts @@ -17,7 +17,7 @@ * under the License. */ import { - clamp, + maxValueWithUpperLimit, compareByValueAsc, identity, hasPartialObjectToMerge, @@ -26,18 +26,26 @@ import { getPartialValue, getAllKeys, shallowClone, + minValueWithLowerLimit, } from './commons'; describe('commons utilities', () => { - test('can clamp a value to min max', () => { - expect(clamp(0, 0, 1)).toBe(0); - expect(clamp(1, 0, 1)).toBe(1); + test('return value bounded above', () => { + expect(maxValueWithUpperLimit(0, 0, 1)).toBe(0); + expect(maxValueWithUpperLimit(1, 0, 1)).toBe(1); - expect(clamp(1.1, 0, 1)).toBe(1); - expect(clamp(-0.1, 0, 1)).toBe(0); + expect(maxValueWithUpperLimit(1.1, 0, 1)).toBe(1); + expect(maxValueWithUpperLimit(-0.1, 0, 1)).toBe(0); - expect(clamp(0.1, 0, 1)).toBe(0.1); - expect(clamp(0.8, 0, 1)).toBe(0.8); + expect(maxValueWithUpperLimit(0.1, 0, 1)).toBe(0.1); + expect(maxValueWithUpperLimit(0.8, 0, 1)).toBe(0.8); + }); + test('return value bounded below', () => { + expect(minValueWithLowerLimit(10, 20, 0)).toBe(10); + expect(minValueWithLowerLimit(20, 10, 0)).toBe(10); + + expect(minValueWithLowerLimit(10, -20, 0)).toBe(0); + expect(minValueWithLowerLimit(-20, 10, 0)).toBe(0); }); test('identity', () => { diff --git a/src/utils/commons.ts b/src/utils/commons.ts index 3838e64f8e..f54e558de0 100644 --- a/src/utils/commons.ts +++ b/src/utils/commons.ts @@ -45,9 +45,26 @@ export function compareByValueAsc(firstEl: number, secondEl: number): number { return firstEl - secondEl; } -/** @internal */ -export function clamp(value: number, min: number, max: number): number { - return Math.min(Math.max(value, min), max); +/** + * Return the minimum value between val1 and val2. The value is bounded from below by lowerLimit + * @param val1 a numeric value + * @param val2 a numeric value + * @param lowerLimit the lower limit + * @internal + */ +export function minValueWithLowerLimit(val1: number, val2: number, lowerLimit: number) { + return Math.max(Math.min(val1, val2), lowerLimit); +} + +/** + * Return the maximum value between val1 and val2. The value is bounded from above by upperLimit + * @param val1 a numeric value + * @param val2 a numeric value + * @param upperLimit the upper limit + * @internal + */ +export function maxValueWithUpperLimit(val1: number, val2: number, upperLimit: number) { + return Math.min(Math.max(val1, val2), upperLimit); } /** From 7de873988b8d713999f7734fba30db385967d47d Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Fri, 17 Apr 2020 12:00:42 +0200 Subject: [PATCH 6/8] feat: add minBrushDelta Changing the minBrushDelta value in the Settings component will deny any brush event with less than the specified number of pixel --- .../state/selectors/on_brush_end_caller.ts | 25 +++++++++++++++---- src/specs/settings.tsx | 10 +++++++- 2 files changed, 29 insertions(+), 6 deletions(-) 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 index 3474d043cf..72f5cba142 100644 --- 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 @@ -83,7 +83,13 @@ export function createOnBrushEndCaller(): (state: GlobalChartState) => void { computeChartDimensionsSelector, isHistogramModeEnabledSelector, ], - (lastDrag, { onBrushEnd, rotation, brushAxis }, computedScales, { chartDimensions }, histogramMode): void => { + ( + lastDrag, + { onBrushEnd, rotation, brushAxis, minBrushDelta }, + computedScales, + { chartDimensions }, + histogramMode, + ): void => { const nextProps = { lastDrag, onBrushEnd, @@ -95,10 +101,17 @@ export function createOnBrushEndCaller(): (state: GlobalChartState) => void { const { yScales, xScale } = computedScales; if (brushAxis === BrushAxis.X || brushAxis === BrushAxis.Both) { - brushArea.x = getXBrushExtent(chartDimensions, lastDrag, rotation, histogramMode, xScale); + brushArea.x = getXBrushExtent( + chartDimensions, + lastDrag, + rotation, + histogramMode, + xScale, + minBrushDelta, + ); } if (brushAxis === BrushAxis.Y || brushAxis === BrushAxis.Both) { - brushArea.y = getYBrushExtents(chartDimensions, lastDrag, rotation, yScales); + brushArea.y = getYBrushExtents(chartDimensions, lastDrag, rotation, yScales, minBrushDelta); } if (brushArea.x !== undefined || brushArea.y !== undefined) { onBrushEnd(brushArea); @@ -123,6 +136,7 @@ function getXBrushExtent( rotation: Rotation, histogramMode: boolean, xScale: Scale, + minBrushDelta?: number, ): [number, number] | undefined { let startPos = getLeftPoint(chartDimensions, lastDrag.start.position); let endPos = getLeftPoint(chartDimensions, lastDrag.end.position); @@ -140,7 +154,7 @@ function getXBrushExtent( minPos = chartMax - minPos; maxPos = chartMax - maxPos; } - if (maxPos === minPos) { + if (minBrushDelta !== undefined ? Math.abs(maxPos - minPos) < minBrushDelta : maxPos === minPos) { // if 0 size brush, avoid computing the value return; } @@ -158,6 +172,7 @@ function getYBrushExtents( lastDrag: DragState, rotation: Rotation, yScales: Map, + minBrushDelta?: number, ): GroupBrushExtent[] | undefined { const yValues: GroupBrushExtent[] = []; yScales.forEach((yScale, groupId) => { @@ -175,7 +190,7 @@ function getYBrushExtents( minPos = chartMax - minPos; maxPos = chartMax - maxPos; } - if (maxPos === minPos) { + if (minBrushDelta !== undefined ? Math.abs(maxPos - minPos) < minBrushDelta : maxPos === minPos) { // if 0 size brush, avoid computing the value return; } diff --git a/src/specs/settings.tsx b/src/specs/settings.tsx index c2268d4b7b..6a10736ecb 100644 --- a/src/specs/settings.tsx +++ b/src/specs/settings.tsx @@ -247,6 +247,12 @@ export interface SettingsSpec extends Spec { * @default BrushAxis.X */ brushAxis?: BrushAxis; + /** + * The minimum number of pixel to consider for a valid brush event (in both axis if brushAxis prop is BrushAxis.Both). + * E.g. a min value of 2 means that the brush area needs to be at least 2 pixel wide and 2 pixel tall. + * @default 2 + */ + minBrushDelta?: number; } export type DefaultSettingsProps = @@ -264,7 +270,8 @@ export type DefaultSettingsProps = | 'theme' | 'legendPosition' | 'hideDuplicateAxes' - | 'brushAxis'; + | 'brushAxis' + | 'minBrushDelta'; export const DEFAULT_TOOLTIP_TYPE = TooltipType.VerticalCursor; export const DEFAULT_TOOLTIP_SNAP = true; @@ -297,6 +304,7 @@ export const DEFAULT_SETTINGS_SPEC: SettingsSpec = { hideDuplicateAxes: false, theme: LIGHT_THEME, brushAxis: BrushAxis.X, + minBrushDelta: 2, }; export type SettingsSpecProps = Partial>; From 7020b3d43ade32d08e90dc322518c03ceca3b728 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Mon, 27 Apr 2020 18:04:39 +0200 Subject: [PATCH 7/8] fix: add min area size --- .../state/selectors/get_brush_area.ts | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) 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 index 2e6dd11fbe..5847d2ff6b 100644 --- a/src/chart_types/xy_chart/state/selectors/get_brush_area.ts +++ b/src/chart_types/xy_chart/state/selectors/get_brush_area.ts @@ -28,6 +28,8 @@ import { BrushAxis } from '../../../../specs'; import { Rotation } from '../../../../utils/commons'; import { Point } from '../../../../utils/point'; +const MIN_AREA_SIZE = 1; + const getMouseDownPosition = (state: GlobalChartState) => state.interactions.pointer.down; const getCurrentPointerPosition = (state: GlobalChartState) => { return state.interactions.pointer.current.position; @@ -68,8 +70,8 @@ export function getBrushForXAxis(chartDimensions: Dimensions, chartRotation: Rot return { left: rotated ? 0 : getLeftPoint(chartDimensions, start), top: rotated ? getTopPoint(chartDimensions, start) : 0, - height: rotated ? getHeight(start, end) : chartDimensions.height, - width: rotated ? chartDimensions.width : getWidth(start, end), + height: rotated ? getMinimalHeight(start, end) : chartDimensions.height, + width: rotated ? chartDimensions.width : getMinimalWidth(start, end), }; } @@ -79,8 +81,8 @@ export function getBrushForYAxis(chartDimensions: Dimensions, chartRotation: Rot return { left: rotated ? getLeftPoint(chartDimensions, start) : 0, top: rotated ? 0 : getTopPoint(chartDimensions, start), - height: rotated ? chartDimensions.height : getHeight(start, end), - width: rotated ? getWidth(start, end) : chartDimensions.width, + height: rotated ? chartDimensions.height : getMinimalHeight(start, end), + width: rotated ? getMinimalWidth(start, end) : chartDimensions.width, }; } @@ -89,8 +91,8 @@ export function getBrushForBothAxis(chartDimensions: Dimensions, start: Point, e return { left: getLeftPoint(chartDimensions, start), top: getTopPoint(chartDimensions, start), - height: getHeight(start, end), - width: getWidth(start, end), + height: getMinimalHeight(start, end), + width: getMinimalWidth(start, end), }; } @@ -104,10 +106,18 @@ export function getTopPoint({ top }: Dimensions, { y }: Point) { return y - top; } -function getHeight(start: Point, end: Point) { - return end.y - start.y; +function getMinimalHeight(start: Point, end: Point, min = MIN_AREA_SIZE) { + const height = end.y - start.y; + if (Math.abs(height) < min) { + return min; + } + return height; } -function getWidth(start: Point, end: Point) { - return end.x - start.x; +function getMinimalWidth(start: Point, end: Point, min = MIN_AREA_SIZE) { + const width = end.x - start.x; + if (Math.abs(width) < min) { + return min; + } + return width; } From d09b78302e5c33d992d0c8c9d6b617732bc982fe Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Tue, 28 Apr 2020 19:25:15 +0200 Subject: [PATCH 8/8] fix(brush): align brush canvas to underlying canvas fix #620 --- src/chart_types/xy_chart/renderer/dom/_brush.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/chart_types/xy_chart/renderer/dom/_brush.scss b/src/chart_types/xy_chart/renderer/dom/_brush.scss index f6f6f8fc20..2401d5bf74 100644 --- a/src/chart_types/xy_chart/renderer/dom/_brush.scss +++ b/src/chart_types/xy_chart/renderer/dom/_brush.scss @@ -1,5 +1,9 @@ .echBrushTool { position: absolute; + top: 0; + left: 0; + margin: 0; + padding: 0; box-sizing: border-box; overflow: hidden; pointer-events: none;