= ({
children,
className,
fullWidth,
+ compressed,
}) => {
const classes = classNames(
'euiRangeWrapper',
{
'euiRangeWrapper--fullWidth': fullWidth,
+ 'euiRangeWrapper--compressed': compressed,
},
className
);
From db0e01645c20d4a9c789dc5523b268ab9b314e3f Mon Sep 17 00:00:00 2001
From: cchaos
Date: Wed, 14 Aug 2019 15:57:11 -0400
Subject: [PATCH 12/24] Fix full-width delimited
---
.../form_control_layout/_form_control_layout_delimited.scss | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/src/components/form/form_control_layout/_form_control_layout_delimited.scss
index 824785c0d1d..2537b7df614 100644
--- a/src/components/form/form_control_layout/_form_control_layout_delimited.scss
+++ b/src/components/form/form_control_layout/_form_control_layout_delimited.scss
@@ -31,8 +31,10 @@
}
}
- &[class*='--fullWidth'] .euiFormControlLayout__childrenWrapper {
+ &[class*='--fullWidth'] .euiFormControlLayout__childrenWrapper,
+ &[class*='--fullWidth'] input {
width: 100%;
+ max-width: none;
}
&[class*='--readOnly'] {
From b29fe1d1212a7f699ef6e23666eb788f8be45d33 Mon Sep 17 00:00:00 2001
From: cchaos
Date: Wed, 14 Aug 2019 16:36:23 -0400
Subject: [PATCH 13/24] Added `controlOnly` prop to EuiFieldNumber
---
.../__snapshots__/field_number.test.js.snap | 9 ++++
.../form/field_number/field_number.js | 44 ++++++++++++-------
.../form/field_number/field_number.test.js | 6 +++
3 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/src/components/form/field_number/__snapshots__/field_number.test.js.snap b/src/components/form/field_number/__snapshots__/field_number.test.js.snap
index 15a4aa9df41..70fd3227055 100644
--- a/src/components/form/field_number/__snapshots__/field_number.test.js.snap
+++ b/src/components/form/field_number/__snapshots__/field_number.test.js.snap
@@ -24,6 +24,15 @@ exports[`EuiFieldNumber is rendered 1`] = `
`;
+exports[`EuiFieldNumber props controlOnly is rendered 1`] = `
+
+
+
+`;
+
exports[`EuiFieldNumber props fullWidth is rendered 1`] = `
{
const classes = classNames('euiFieldNumber', className, {
@@ -33,6 +34,28 @@ export const EuiFieldNumber = ({
'euiFieldNumber-isLoading': isLoading,
});
+ const control = (
+
+
+
+ );
+
+ if (controlOnly) {
+ return control;
+ }
+
return (
-
-
-
+ {control}
);
};
@@ -113,6 +122,11 @@ EuiFieldNumber.propTypes = {
PropTypes.node,
PropTypes.arrayOf(PropTypes.node),
]),
+ /**
+ * Completely removes form control layout wrapper and ignores
+ * icon, prepend, and append. Best used inside EuiFormControlLayoutDelimited.
+ */
+ controlOnly: PropTypes.bool,
};
EuiFieldNumber.defaultProps = {
diff --git a/src/components/form/field_number/field_number.test.js b/src/components/form/field_number/field_number.test.js
index a1082c3c986..939f1b317a3 100644
--- a/src/components/form/field_number/field_number.test.js
+++ b/src/components/form/field_number/field_number.test.js
@@ -59,6 +59,12 @@ describe('EuiFieldNumber', () => {
expect(component).toMatchSnapshot();
});
+ test('controlOnly is rendered', () => {
+ const component = render( );
+
+ expect(component).toMatchSnapshot();
+ });
+
describe('value', () => {
test('value is number', () => {
const component = render(
From e8a6d82007ee9e1ba6e86fc8d49b7f33a3628722 Mon Sep 17 00:00:00 2001
From: cchaos
Date: Wed, 14 Aug 2019 16:37:22 -0400
Subject: [PATCH 14/24] Finalize styles of input only ranges
- Needed some fixes to EuiFormControlLayoutDelimited
---
.../range/{compressed.js => input_only.js} | 1 +
src-docs/src/views/range/range_example.js | 80 +++++++------------
.../_form_control_layout_delimited.scss | 5 ++
.../__snapshots__/dual_range.test.js.snap | 48 +++++++++++
.../range/__snapshots__/range.test.js.snap | 30 +++++++
src/components/form/range/dual_range.js | 35 ++++----
src/components/form/range/dual_range.test.js | 17 ++++
src/components/form/range/range.js | 23 ++----
src/components/form/range/range.test.js | 17 ++++
9 files changed, 173 insertions(+), 83 deletions(-)
rename src-docs/src/views/range/{compressed.js => input_only.js} (98%)
diff --git a/src-docs/src/views/range/compressed.js b/src-docs/src/views/range/input_only.js
similarity index 98%
rename from src-docs/src/views/range/compressed.js
rename to src-docs/src/views/range/input_only.js
index eb34dfb062d..bca1e3410bf 100644
--- a/src-docs/src/views/range/compressed.js
+++ b/src-docs/src/views/range/input_only.js
@@ -87,6 +87,7 @@ export default class extends Component {
showInput="only"
showLabels
levels={this.levels}
+ readOnly
/>
);
diff --git a/src-docs/src/views/range/range_example.js b/src-docs/src/views/range/range_example.js
index 36aeb889d99..71792e6eb76 100644
--- a/src-docs/src/views/range/range_example.js
+++ b/src-docs/src/views/range/range_example.js
@@ -45,9 +45,9 @@ import StatesExample from './states';
const statesSource = require('!!raw-loader!./states');
const statesHtml = renderToHtml(StatesExample);
-import CompressedExample from './compressed';
-const compressedSource = require('!!raw-loader!./compressed');
-const compressedHtml = renderToHtml(CompressedExample);
+import InputOnlyExample from './input_only';
+const inputOnlySource = require('!!raw-loader!./input_only');
+const inputOnlyHtml = renderToHtml(InputOnlyExample);
export const RangeControlExample = {
title: 'Range sliders',
@@ -116,16 +116,16 @@ export const RangeControlExample = {
EuiRange,
},
demo: ,
- snippet: `
-
-// Show tooltip
+/>`,
+ `// Show tooltip
-
-// Show thickened range and prepend a string to the tooltip
+/>`,
+ `// Show thickened range and prepend a string to the tooltip
`,
+ ],
},
{
title: 'Dual range',
@@ -228,9 +228,7 @@ export const RangeControlExample = {
],
demo: ,
props: { EuiRangeInput },
- snippet: `
-
- `,
+ snippet: [' ', ' '],
},
{
title: 'Tick marks',
@@ -269,17 +267,17 @@ export const RangeControlExample = {
],
demo: ,
props: { EuiRangeTicks },
- snippet: `
-
-
-
- ',
+ ' ',
+ ` `,
+ ],
},
{
title: 'Levels',
@@ -340,45 +338,28 @@ export const RangeControlExample = {
source: [
{
type: GuideSectionTypes.JS,
- code: compressedSource,
+ code: inputOnlySource,
},
{
type: GuideSectionTypes.HTML,
- code: compressedHtml,
+ code: inputOnlyHtml,
},
],
- demo: ,
- snippet: ` ,
+ snippet: [
+ ` {}}
- compressed
- fullWidth
- disabled
- showTicks
- showInput
- showLabels
- showValue
- showRange
- tickInterval={}
- levels={[]}
- aria-describedBy={replaceWithID}
-/>
-
- `,
+ ` {}}
- compressed
- fullWidth
- disabled
- showLabels
- showInput
- showTicks
- ticks={[]}
- levels={[]}
- aria-describedBy={replaceWithID}
+ showInput="only"
/>`,
+ ],
},
{
title: 'Kitchen sink',
@@ -401,7 +382,8 @@ export const RangeControlExample = {
},
],
demo: ,
- snippet: ` {}}
@@ -415,9 +397,8 @@ export const RangeControlExample = {
tickInterval={}
levels={[]}
aria-describedBy={replaceWithID}
-/>
-
- `,
+ ` {}}
@@ -430,6 +411,7 @@ export const RangeControlExample = {
levels={[]}
aria-describedBy={replaceWithID}
/>`,
+ ],
},
],
};
diff --git a/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/src/components/form/form_control_layout/_form_control_layout_delimited.scss
index 2537b7df614..61a9f2c03e4 100644
--- a/src/components/form/form_control_layout/_form_control_layout_delimited.scss
+++ b/src/components/form/form_control_layout/_form_control_layout_delimited.scss
@@ -11,6 +11,7 @@
> .euiFormControlLayout__childrenWrapper {
display: flex;
align-items: center;
+ width: 100%;
}
&[class*='--compressed'] {
@@ -37,6 +38,10 @@
max-width: none;
}
+ &[class*='-isDisabled'] {
+ @include euiFormControlDisabledStyle;
+ }
+
&[class*='--readOnly'] {
@include euiFormControlReadOnlyStyle;
diff --git a/src/components/form/range/__snapshots__/dual_range.test.js.snap b/src/components/form/range/__snapshots__/dual_range.test.js.snap
index 63f9b377f05..4128662c12e 100644
--- a/src/components/form/range/__snapshots__/dual_range.test.js.snap
+++ b/src/components/form/range/__snapshots__/dual_range.test.js.snap
@@ -366,6 +366,54 @@ exports[`EuiDualRange props levels should render 1`] = `
`;
+exports[`EuiDualRange props only input should render 1`] = `
+
+`;
+
exports[`EuiDualRange props range should render 1`] = `
`;
+exports[`EuiRange props input only should render 1`] = `
+
+`;
+
exports[`EuiRange props input should render 1`] = `
) : (
undefined
@@ -302,8 +305,10 @@ export class EuiDualRange extends Component {
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
onClick={this.onInputClick}
+ readOnly={readOnly}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
+ controlOnly={showInputOnly}
/>
) : (
undefined
@@ -404,30 +409,23 @@ export class EuiDualRange extends Component {
);
const thePopover = showInputOnly ? (
-
}
+ fullWidth={fullWidth}
isOpen={this.state.isPopoverOpen}
- closePopover={this.closePopover}
- // zIndex={popoverZIndex}
- className={classNames('euiRange__popover', {
- 'euiRange__popover--fullWidth': fullWidth,
- })}
- anchorClassName="euiRange__popoverAnchor"
- display="block"
- // panelClassName={panelClasses}
- // attachToAnchor={button ? false : true}
- anchorPosition="downLeft"
- panelPaddingSize="s">
+ closePopover={this.closePopover}>
{theRange}
-
+
) : (
undefined
);
@@ -451,6 +449,7 @@ EuiDualRange.propTypes = {
fullWidth: PropTypes.bool,
compressed: PropTypes.bool,
disabled: PropTypes.bool,
+ readOnly: PropTypes.bool,
/**
* Shows static min/max labels on the sides of the range slider
*/
diff --git a/src/components/form/range/dual_range.test.js b/src/components/form/range/dual_range.test.js
index cc010c8b06d..4b96afebd01 100644
--- a/src/components/form/range/dual_range.test.js
+++ b/src/components/form/range/dual_range.test.js
@@ -86,6 +86,23 @@ describe('EuiDualRange', () => {
expect(component).toMatchSnapshot();
});
+ test('only input should render', () => {
+ const component = render(
+
{}}
+ showInput="only"
+ {...requiredProps}
+ />
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+
test('levels should render', () => {
const component = render(
+ closePopover={this.closePopover}>
{theRange}
-
+
) : (
undefined
);
diff --git a/src/components/form/range/range.test.js b/src/components/form/range/range.test.js
index 652a6c104be..b645f82bcbf 100644
--- a/src/components/form/range/range.test.js
+++ b/src/components/form/range/range.test.js
@@ -99,6 +99,23 @@ describe('EuiRange', () => {
expect(component).toMatchSnapshot();
});
+ test('input only should render', () => {
+ const component = render(
+ {}}
+ showInput="only"
+ {...requiredProps}
+ />
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+
test('levels should render', () => {
const component = render(
Date: Mon, 19 Aug 2019 17:42:57 -0400
Subject: [PATCH 15/24] Some cleanup
---
src-docs/src/views/range/input_only.js | 7 +------
src-docs/src/views/range/range_example.js | 9 +++++----
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/src-docs/src/views/range/input_only.js b/src-docs/src/views/range/input_only.js
index bca1e3410bf..43a33d7c124 100644
--- a/src-docs/src/views/range/input_only.js
+++ b/src-docs/src/views/range/input_only.js
@@ -1,11 +1,6 @@
import React, { Component, Fragment } from 'react';
-import {
- EuiRange,
- EuiSpacer,
- // EuiFormHelpText,
- EuiDualRange,
-} from '../../../../src/components';
+import { EuiRange, EuiSpacer, EuiDualRange } from '../../../../src/components';
import makeId from '../../../../src/components/form/form_row/make_id';
diff --git a/src-docs/src/views/range/range_example.js b/src-docs/src/views/range/range_example.js
index 71792e6eb76..7bdbde3d1f0 100644
--- a/src-docs/src/views/range/range_example.js
+++ b/src-docs/src/views/range/range_example.js
@@ -307,21 +307,22 @@ export const RangeControlExample = {
],
demo: ,
props: { EuiRangeLevels },
- snippet: `
-
- `,
+ ` `,
+ ],
},
{
title: 'Inputs with range in a dropdown',
From 8ded06a8aca62ff4b2d624e2c0d6ce5a767fdd0a Mon Sep 17 00:00:00 2001
From: cchaos
Date: Thu, 29 Aug 2019 12:00:00 -0400
Subject: [PATCH 16/24] Use tooltip background variable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Can’t use mixin, too many overrides/differences
---
src/components/form/range/_range_tooltip.scss | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/components/form/range/_range_tooltip.scss b/src/components/form/range/_range_tooltip.scss
index 406acc8c092..77cab4b0ea3 100644
--- a/src/components/form/range/_range_tooltip.scss
+++ b/src/components/form/range/_range_tooltip.scss
@@ -1,3 +1,5 @@
+@import '../../tool_tip/variables';
+
.euiRangeTooltip {
// Keeps tooltip (value) aligned to percentage of actual slider
display: block;
@@ -11,15 +13,14 @@
}
.euiRangeTooltip__value {
- // TODO: Use the new tooltip mixin
// Indentation for legibility in transition
// sass-lint:disable-block indentation
@include euiFontSizeS;
- border: 1px solid transparentize($euiColorDarkestShade, .8);
+ border: 1px solid $euiTooltipBackgroundColor;
position: absolute;
border-radius: $euiBorderRadius;
padding: ($euiSizeXS / 2) $euiSizeS;
- background-color: tintOrShade($euiColorFullShade, 25%, 90%);
+ background-color: $euiTooltipBackgroundColor;
color: $euiColorGhost;
max-width: 256px;
top: 50%;
@@ -38,14 +39,14 @@
bottom: -$arrowSize / 2;
left: 50%;
transform-origin: center;
- background-color: tintOrShade($euiColorFullShade, 25%, 90%);
+ background-color: $euiTooltipBackgroundColor;
width: $arrowSize;
height: $arrowSize;
border-radius: 2px;
}
&::before {
- background-color: transparentize($euiColorDarkestShade, .8);
+ background-color: $euiTooltipBackgroundColor;
}
// Positions the arrow
From b9937a53cf2afb10a2898b016b4684077bdc4f69 Mon Sep 17 00:00:00 2001
From: cchaos
Date: Thu, 29 Aug 2019 12:20:33 -0400
Subject: [PATCH 17/24] Open popover on focus
---
.../__snapshots__/dual_range.test.js.snap | 56 ++++++++++---------
.../range/__snapshots__/range.test.js.snap | 32 ++++++-----
src/components/form/range/_range.scss | 6 --
src/components/form/range/dual_range.js | 7 ++-
src/components/form/range/range.js | 7 ++-
5 files changed, 55 insertions(+), 53 deletions(-)
diff --git a/src/components/form/range/__snapshots__/dual_range.test.js.snap b/src/components/form/range/__snapshots__/dual_range.test.js.snap
index 4128662c12e..d6cc79d08b0 100644
--- a/src/components/form/range/__snapshots__/dual_range.test.js.snap
+++ b/src/components/form/range/__snapshots__/dual_range.test.js.snap
@@ -373,41 +373,43 @@ exports[`EuiDualRange props only input should render 1`] = `
-
diff --git a/src/components/form/range/__snapshots__/range.test.js.snap b/src/components/form/range/__snapshots__/range.test.js.snap
index f7db9774fc4..a4369a479ca 100644
--- a/src/components/form/range/__snapshots__/range.test.js.snap
+++ b/src/components/form/range/__snapshots__/range.test.js.snap
@@ -176,23 +176,25 @@ exports[`EuiRange props input only should render 1`] = `
-
diff --git a/src/components/form/range/_range.scss b/src/components/form/range/_range.scss
index a36ea335235..e69de29bb2d 100644
--- a/src/components/form/range/_range.scss
+++ b/src/components/form/range/_range.scss
@@ -1,6 +0,0 @@
-@import '../mixins';
-
-// Specificity needed to override .euiPopover max-width
-.euiPopover.euiRange__popover {
- @include euiFormControlSize(auto, $includeAlternates: true);
-}
diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js
index a3b8b014574..927da0d2332 100644
--- a/src/components/form/range/dual_range.js
+++ b/src/components/form/range/dual_range.js
@@ -224,7 +224,7 @@ export class EuiDualRange extends Component {
});
};
- onInputClick = () => {
+ onInputFocus = () => {
this.setState({
isPopoverOpen: true,
});
@@ -263,6 +263,7 @@ export class EuiDualRange extends Component {
const digitTolerance = Math.max(String(min).length, String(max).length);
const showInputOnly = showInput === 'only';
+ const canShowDropdown = showInputOnly && !readOnly && !disabled;
const minInput = !!showInput ? (
{
+ onInputFocus = () => {
this.setState({
isPopoverOpen: true,
});
@@ -52,6 +52,7 @@ export class EuiRange extends Component {
compressed,
disabled,
fullWidth,
+ readOnly,
id,
max,
min,
@@ -76,6 +77,7 @@ export class EuiRange extends Component {
const digitTolerance = Math.max(String(min).length, String(max).length);
const showInputOnly = showInput === 'only';
+ const canShowDropdown = showInputOnly && !readOnly && !disabled;
const theInput = !!showInput ? (
Date: Wed, 4 Sep 2019 14:11:52 -0500
Subject: [PATCH 18/24] focus direction
---
.../__snapshots__/dual_range.test.js.snap | 10 ++++++++++
.../range/__snapshots__/range.test.js.snap | 11 +++++++++++
src/components/form/range/dual_range.js | 19 +++++++++++++++++--
src/components/form/range/dual_range.test.js | 2 ++
src/components/form/range/range.js | 18 ++++++++++++++++--
src/components/form/range/range.test.js | 2 ++
src/components/popover/input_popover.tsx | 9 ++++++---
7 files changed, 64 insertions(+), 7 deletions(-)
diff --git a/src/components/form/range/__snapshots__/dual_range.test.js.snap b/src/components/form/range/__snapshots__/dual_range.test.js.snap
index d6cc79d08b0..d9bdf8df45b 100644
--- a/src/components/form/range/__snapshots__/dual_range.test.js.snap
+++ b/src/components/form/range/__snapshots__/dual_range.test.js.snap
@@ -10,6 +10,7 @@ exports[`EuiDualRange allows value prop to accept empty strings 1`] = `
{
+ // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
+ const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
+ if (!relatedTarget || relatedTarget.id !== this.state.id) {
+ this.closePopover();
+ }
+ };
+
closePopover = () => {
this.setState({
isPopoverOpen: false,
@@ -243,7 +253,7 @@ export class EuiDualRange extends Component {
disabled,
fullWidth,
readOnly,
- id,
+ id: propsId,
max,
min,
name,
@@ -261,6 +271,8 @@ export class EuiDualRange extends Component {
...rest
} = this.props;
+ const { id } = this.state;
+
const digitTolerance = Math.max(String(min).length, String(max).length);
const showInputOnly = showInput === 'only';
const canShowDropdown = showInputOnly && !readOnly && !disabled;
@@ -281,6 +293,7 @@ export class EuiDualRange extends Component {
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
+ onBlur={canShowDropdown ? this.onInputBlur : undefined}
readOnly={readOnly}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
@@ -306,6 +319,7 @@ export class EuiDualRange extends Component {
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
+ onBlur={canShowDropdown ? this.onInputBlur : undefined}
readOnly={readOnly}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
@@ -424,7 +438,8 @@ export class EuiDualRange extends Component {
}
fullWidth={fullWidth}
isOpen={this.state.isPopoverOpen}
- closePopover={this.closePopover}>
+ closePopover={this.closePopover}
+ disableFocusTrap={true}>
{theRange}
) : (
diff --git a/src/components/form/range/dual_range.test.js b/src/components/form/range/dual_range.test.js
index 4b96afebd01..39c9a2cb947 100644
--- a/src/components/form/range/dual_range.test.js
+++ b/src/components/form/range/dual_range.test.js
@@ -4,6 +4,8 @@ import { requiredProps } from '../../../test/required_props';
import { EuiDualRange } from './dual_range';
+jest.mock('../form_row/make_id', () => () => 'generated-id');
+
describe('EuiDualRange', () => {
test('is rendered', () => {
const component = render(
diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js
index b760ecefec1..7be1b7dcc57 100644
--- a/src/components/form/range/range.js
+++ b/src/components/form/range/range.js
@@ -4,6 +4,7 @@ import classNames from 'classnames';
import { isWithinRange } from '../../../services/number';
import { EuiInputPopover } from '../../popover';
+import makeId from '../form_row/make_id';
import { EuiRangeHighlight } from './range_highlight';
import { EuiRangeInput } from './range_input';
@@ -17,6 +18,7 @@ export class EuiRange extends Component {
constructor(props) {
super(props);
this.state = {
+ id: props.id || makeId(),
isPopoverOpen: false,
};
}
@@ -40,6 +42,14 @@ export class EuiRange extends Component {
});
};
+ onInputBlur = e => {
+ // Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
+ const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
+ if (!relatedTarget || relatedTarget.id !== this.state.id) {
+ this.closePopover();
+ }
+ };
+
closePopover = () => {
this.setState({
isPopoverOpen: false,
@@ -53,7 +63,7 @@ export class EuiRange extends Component {
disabled,
fullWidth,
readOnly,
- id,
+ id: propsId,
max,
min,
name,
@@ -75,6 +85,8 @@ export class EuiRange extends Component {
...rest
} = this.props;
+ const { id } = this.state;
+
const digitTolerance = Math.max(String(min).length, String(max).length);
const showInputOnly = showInput === 'only';
const canShowDropdown = showInputOnly && !readOnly && !disabled;
@@ -92,6 +104,7 @@ export class EuiRange extends Component {
onChange={this.handleOnChange}
name={name}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
+ onBlur={canShowDropdown ? this.onInputBlur : undefined}
fullWidth={showInputOnly && fullWidth}
autoSize={!showInputOnly}
{...rest}
@@ -180,7 +193,8 @@ export class EuiRange extends Component {
input={theInput}
fullWidth={fullWidth}
isOpen={this.state.isPopoverOpen}
- closePopover={this.closePopover}>
+ closePopover={this.closePopover}
+ disableFocusTrap={true}>
{theRange}
) : (
diff --git a/src/components/form/range/range.test.js b/src/components/form/range/range.test.js
index b645f82bcbf..33495ea665d 100644
--- a/src/components/form/range/range.test.js
+++ b/src/components/form/range/range.test.js
@@ -4,6 +4,8 @@ import { requiredProps } from '../../../test/required_props';
import { EuiRange } from './range';
+jest.mock('../form_row/make_id', () => () => 'generated-id');
+
describe('EuiRange', () => {
test('is rendered', () => {
const component = render(
diff --git a/src/components/popover/input_popover.tsx b/src/components/popover/input_popover.tsx
index 6659708b0aa..8145f91dfb4 100644
--- a/src/components/popover/input_popover.tsx
+++ b/src/components/popover/input_popover.tsx
@@ -15,6 +15,7 @@ import { cascadingMenuKeyCodes } from '../../services';
interface EuiInputPopoverProps
extends Omit {
+ disableFocusTrap?: boolean;
fullWidth?: boolean;
input: EuiPopoverProps['button'];
inputRef?: EuiPopoverProps['buttonRef'];
@@ -27,6 +28,7 @@ type Props = CommonProps &
export const EuiInputPopover: FunctionComponent = ({
children,
className,
+ disableFocusTrap = false,
input,
fullWidth = false,
...props
@@ -68,8 +70,9 @@ export const EuiInputPopover: FunctionComponent = ({
);
});
if (
- tabbableItems.length &&
- tabbableItems[tabbableItems.length - 1] === document.activeElement
+ disableFocusTrap ||
+ (tabbableItems.length &&
+ tabbableItems[tabbableItems.length - 1] === document.activeElement)
) {
props.closePopover();
}
@@ -96,7 +99,7 @@ export const EuiInputPopover: FunctionComponent = ({
panelRef={panelRef}
className={classes}
{...props}>
-
+
{children}
From ac953175239966e7ec6526c98eaaa9982512ed18 Mon Sep 17 00:00:00 2001
From: Greg Thompson
Date: Thu, 5 Sep 2019 11:56:06 -0500
Subject: [PATCH 19/24] dual range respond to resize events when in
showInputOnly mode
---
src/components/form/range/dual_range.js | 28 ++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js
index 984991a176a..60e5a14c0d7 100644
--- a/src/components/form/range/dual_range.js
+++ b/src/components/form/range/dual_range.js
@@ -6,6 +6,7 @@ import { keyCodes } from '../../../services';
import { isWithinRange } from '../../../services/number';
import { EuiInputPopover } from '../../popover';
import { EuiFormControlLayoutDelimited } from '../form_control_layout';
+import { EuiResizeObserver } from '../../observer/resize_observer';
import makeId from '../form_row/make_id';
import { EuiRangeHighlight } from './range_highlight';
@@ -22,6 +23,7 @@ export class EuiDualRange extends Component {
hasFocus: false,
rangeSliderRefAvailable: false,
isPopoverOpen: false,
+ rangeWidth: null,
};
rangeSliderRef = null;
@@ -29,6 +31,7 @@ export class EuiDualRange extends Component {
this.rangeSliderRef = ref;
this.setState({
rangeSliderRefAvailable: !!ref,
+ rangeWidth: !!ref ? ref.clientWidth : null,
});
};
@@ -206,7 +209,7 @@ export class EuiDualRange extends Component {
this._handleOnChange(this.lowerValue, upper, e);
};
- calculateThumbPositionStyle = value => {
+ calculateThumbPositionStyle = (value, width) => {
// Calculate the left position based on value
const decimal =
(value - this.props.min) / (this.props.max - this.props.min);
@@ -215,7 +218,8 @@ export class EuiDualRange extends Component {
valuePosition = valuePosition >= 0 ? valuePosition : 0;
const EUI_THUMB_SIZE = 16;
- const thumbToTrackRatio = EUI_THUMB_SIZE / this.rangeSliderRef.clientWidth;
+ const trackWidth = width || this.rangeSliderRef.clientWidth;
+ const thumbToTrackRatio = EUI_THUMB_SIZE / trackWidth;
const trackPositionScale = (1 - thumbToTrackRatio) * 100;
return { left: `${valuePosition * trackPositionScale}%` };
};
@@ -246,6 +250,12 @@ export class EuiDualRange extends Component {
});
};
+ onResize = ({ width }) => {
+ this.setState({
+ rangeWidth: width,
+ });
+ };
+
render() {
const {
className,
@@ -397,7 +407,10 @@ export class EuiDualRange extends Component {
onKeyDown={this.handleLowerKeyDown}
onFocus={() => this.toggleHasFocus(true)}
onBlur={() => this.toggleHasFocus(false)}
- style={this.calculateThumbPositionStyle(this.lowerValue || min)}
+ style={this.calculateThumbPositionStyle(
+ this.lowerValue || min,
+ showInputOnly ? this.state.rangeWidth : null
+ )}
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
/>
@@ -411,7 +424,10 @@ export class EuiDualRange extends Component {
onKeyDown={this.handleUpperKeyDown}
onFocus={() => this.toggleHasFocus(true)}
onBlur={() => this.toggleHasFocus(false)}
- style={this.calculateThumbPositionStyle(this.upperValue || max)}
+ style={this.calculateThumbPositionStyle(
+ this.upperValue || max,
+ showInputOnly ? this.state.rangeWidth : null
+ )}
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
/>
@@ -440,7 +456,9 @@ export class EuiDualRange extends Component {
isOpen={this.state.isPopoverOpen}
closePopover={this.closePopover}
disableFocusTrap={true}>
- {theRange}
+
+ {resizeRef => {theRange}
}
+
) : (
undefined
From 1b58cdf736d83e224a8488e00857b0f4d67dab35 Mon Sep 17 00:00:00 2001
From: Greg Thompson
Date: Thu, 5 Sep 2019 12:02:06 -0500
Subject: [PATCH 20/24] clean up
---
src/components/form/range/dual_range.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js
index 60e5a14c0d7..1aa5658369d 100644
--- a/src/components/form/range/dual_range.js
+++ b/src/components/form/range/dual_range.js
@@ -218,7 +218,10 @@ export class EuiDualRange extends Component {
valuePosition = valuePosition >= 0 ? valuePosition : 0;
const EUI_THUMB_SIZE = 16;
- const trackWidth = width || this.rangeSliderRef.clientWidth;
+ const trackWidth =
+ this.props.showInput === 'only' && !!width
+ ? width
+ : this.rangeSliderRef.clientWidth;
const thumbToTrackRatio = EUI_THUMB_SIZE / trackWidth;
const trackPositionScale = (1 - thumbToTrackRatio) * 100;
return { left: `${valuePosition * trackPositionScale}%` };
@@ -409,7 +412,7 @@ export class EuiDualRange extends Component {
onBlur={() => this.toggleHasFocus(false)}
style={this.calculateThumbPositionStyle(
this.lowerValue || min,
- showInputOnly ? this.state.rangeWidth : null
+ this.state.rangeWidth
)}
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
@@ -426,7 +429,7 @@ export class EuiDualRange extends Component {
onBlur={() => this.toggleHasFocus(false)}
style={this.calculateThumbPositionStyle(
this.upperValue || max,
- showInputOnly ? this.state.rangeWidth : null
+ this.state.rangeWidth
)}
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
From e132f7e75eb8e5b9c50e2aa8a2ac318919cd93d3 Mon Sep 17 00:00:00 2001
From: cchaos
Date: Fri, 6 Sep 2019 16:02:06 -0400
Subject: [PATCH 21/24] PR Feedback
---
src-docs/src/views/range/input_only.js | 8 ++++----
src-docs/src/views/range/range_example.js | 12 ++++++------
.../_form_control_layout_delimited.scss | 4 ++++
src/components/form/range/_index.scss | 1 -
src/components/form/range/_range.scss | 0
src/components/form/range/_range_highlight.scss | 11 ++++++-----
src/components/form/range/_variables.scss | 2 ++
src/components/form/range/dual_range.js | 6 +++---
src/components/form/range/dual_range.test.js | 2 +-
src/components/form/range/range.js | 6 +++---
src/components/form/range/range.test.js | 2 +-
11 files changed, 30 insertions(+), 24 deletions(-)
delete mode 100644 src/components/form/range/_range.scss
diff --git a/src-docs/src/views/range/input_only.js b/src-docs/src/views/range/input_only.js
index 43a33d7c124..f6e1cd08463 100644
--- a/src-docs/src/views/range/input_only.js
+++ b/src-docs/src/views/range/input_only.js
@@ -46,7 +46,7 @@ export default class extends Component {
id={makeId()}
value={this.state.value}
onChange={this.onChange}
- showInput="only"
+ showInput="inputWithPopover"
showLabels
/>
@@ -56,7 +56,7 @@ export default class extends Component {
id={makeId()}
value={this.state.dualValue}
onChange={this.onDualChange}
- showInput="only"
+ showInput="inputWithPopover"
showLabels
levels={this.levels}
/>
@@ -68,7 +68,7 @@ export default class extends Component {
value={this.state.value}
onChange={this.onChange}
compressed
- showInput="only"
+ showInput="inputWithPopover"
showLabels
/>
@@ -79,7 +79,7 @@ export default class extends Component {
value={this.state.dualValue}
onChange={this.onDualChange}
compressed
- showInput="only"
+ showInput="inputWithPopover"
showLabels
levels={this.levels}
readOnly
diff --git a/src-docs/src/views/range/range_example.js b/src-docs/src/views/range/range_example.js
index 7bdbde3d1f0..f2d0d37c740 100644
--- a/src-docs/src/views/range/range_example.js
+++ b/src-docs/src/views/range/range_example.js
@@ -329,10 +329,10 @@ export const RangeControlExample = {
text: (
- Passing showInput="only" instead of a
- boolean will only display the inputs until the input is interacted
- with in which case a dropdown will appear displaying the actual
- slider.
+ Passing showInput="inputWithPopover" {' '}
+ instead of a boolean will only display the inputs until the input is
+ interacted with in which case a dropdown will appear displaying the
+ actual slider.
),
@@ -352,13 +352,13 @@ export const RangeControlExample = {
id=""
value={}
onChange={() => {}}
- showInput="only"
+ showInput="inputWithPopover"
/>`,
` {}}
- showInput="only"
+ showInput="inputWithPopover"
/>`,
],
},
diff --git a/src/components/form/form_control_layout/_form_control_layout_delimited.scss b/src/components/form/form_control_layout/_form_control_layout_delimited.scss
index 61a9f2c03e4..17a1c7dbafa 100644
--- a/src/components/form/form_control_layout/_form_control_layout_delimited.scss
+++ b/src/components/form/form_control_layout/_form_control_layout_delimited.scss
@@ -14,6 +14,7 @@
width: 100%;
}
+ // Target when the euiFormControlLayout is compressed without specifying the full class name in case it ever changes
&[class*='--compressed'] {
@include euiFormControlDefaultShadow($borderOnly: true);
border-radius: $euiBorderRadius / 2;
@@ -32,16 +33,19 @@
}
}
+ // Target when the euiFormControlLayout is fullWidth without specifying the full class name in case it ever changes
&[class*='--fullWidth'] .euiFormControlLayout__childrenWrapper,
&[class*='--fullWidth'] input {
width: 100%;
max-width: none;
}
+ // Target when the euiFormControlLayout is disabled without specifying the full class name in case it ever changes
&[class*='-isDisabled'] {
@include euiFormControlDisabledStyle;
}
+ // Target when the euiFormControlLayout is readOnly without specifying the full class name in case it ever changes
&[class*='--readOnly'] {
@include euiFormControlReadOnlyStyle;
diff --git a/src/components/form/range/_index.scss b/src/components/form/range/_index.scss
index b8d4204e060..b118aebe3d7 100644
--- a/src/components/form/range/_index.scss
+++ b/src/components/form/range/_index.scss
@@ -1,7 +1,6 @@
@import 'variables';
@import 'mixins';
-@import 'range';
@import 'range_highlight';
@import 'range_input';
@import 'range_label';
diff --git a/src/components/form/range/_range.scss b/src/components/form/range/_range.scss
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/src/components/form/range/_range_highlight.scss b/src/components/form/range/_range_highlight.scss
index 447e32e3a0f..289478342b5 100644
--- a/src/components/form/range/_range_highlight.scss
+++ b/src/components/form/range/_range_highlight.scss
@@ -1,13 +1,14 @@
+// Calcs account for
.euiRangeHighlight {
position: absolute;
left: 0;
width: 100%;
- top: calc(50% - 2px);
+ top: calc(50% - #{($euiRangeHighlightHeight / 2)});
overflow: hidden;
&__progress {
- height: 4px;
- border-radius: 4px;
+ height: $euiRangeHighlightHeight;
+ border-radius: $euiRangeHighlightHeight;
background-color: $euiRangeTrackColor;
&--hasFocus {
@@ -16,10 +17,10 @@
}
&--hasTicks {
- top: ($euiFormControlHeight / 4) - 2px;
+ top: ($euiFormControlHeight / 4) - ($euiRangeHighlightHeight / 2);
}
&--hasTicks.euiRangeHighlight--compressed {
- top: ($euiFormControlCompressedHeight / 4) - 2px;
+ top: ($euiFormControlCompressedHeight / 4) - ($euiRangeHighlightHeight / 2);
}
}
diff --git a/src/components/form/range/_variables.scss b/src/components/form/range/_variables.scss
index ce6a5cfd8e6..623e58acce8 100644
--- a/src/components/form/range/_variables.scss
+++ b/src/components/form/range/_variables.scss
@@ -12,3 +12,5 @@ $euiRangeTrackBorderColor: $euiRangeTrackColor !default;
$euiRangeTrackRadius: $euiBorderRadius !default;
$euiRangeDisabledOpacity: .25;
+
+$euiRangeHighlightHeight: $euiSizeXS;
diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js
index 927da0d2332..7500d59c6d3 100644
--- a/src/components/form/range/dual_range.js
+++ b/src/components/form/range/dual_range.js
@@ -262,7 +262,7 @@ export class EuiDualRange extends Component {
} = this.props;
const digitTolerance = Math.max(String(min).length, String(max).length);
- const showInputOnly = showInput === 'only';
+ const showInputOnly = showInput === 'inputWithPopover';
const canShowDropdown = showInputOnly && !readOnly && !disabled;
const minInput = !!showInput ? (
@@ -457,9 +457,9 @@ EuiDualRange.propTypes = {
showLabels: PropTypes.bool,
/**
* Pass `true` to displays an extra input control for direct manipulation.
- * Pass `'only'` to only show the input but show the range in a dropdown.
+ * Pass `'inputWithPopover'` to only show the input but show the range in a dropdown.
*/
- showInput: PropTypes.oneOf([true, false, 'only']),
+ showInput: PropTypes.oneOf([true, false, 'inputWithPopover']),
/**
* Shows clickable tick marks and labels at the given interval (`step`/`tickInterval`)
*/
diff --git a/src/components/form/range/dual_range.test.js b/src/components/form/range/dual_range.test.js
index 4b96afebd01..697a337f75a 100644
--- a/src/components/form/range/dual_range.test.js
+++ b/src/components/form/range/dual_range.test.js
@@ -95,7 +95,7 @@ describe('EuiDualRange', () => {
max={10}
value={['1', '8']}
onChange={() => {}}
- showInput="only"
+ showInput="inputWithPopover"
{...requiredProps}
/>
);
diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js
index b760ecefec1..981581035f9 100644
--- a/src/components/form/range/range.js
+++ b/src/components/form/range/range.js
@@ -76,7 +76,7 @@ export class EuiRange extends Component {
} = this.props;
const digitTolerance = Math.max(String(min).length, String(max).length);
- const showInputOnly = showInput === 'only';
+ const showInputOnly = showInput === 'inputWithPopover';
const canShowDropdown = showInputOnly && !readOnly && !disabled;
const theInput = !!showInput ? (
@@ -207,9 +207,9 @@ EuiRange.propTypes = {
showLabels: PropTypes.bool,
/**
* Pass `true` to displays an extra input control for direct manipulation.
- * Pass `'only'` to only show the input but show the range in a dropdown.
+ * Pass `'inputWithPopover'` to only show the input but show the range in a dropdown.
*/
- showInput: PropTypes.oneOf([true, false, 'only']),
+ showInput: PropTypes.oneOf([true, false, 'inputWithPopover']),
/**
* Shows clickable tick marks and labels at the given interval (`step`/`tickInterval`)
*/
diff --git a/src/components/form/range/range.test.js b/src/components/form/range/range.test.js
index b645f82bcbf..46362048558 100644
--- a/src/components/form/range/range.test.js
+++ b/src/components/form/range/range.test.js
@@ -108,7 +108,7 @@ describe('EuiRange', () => {
max={10}
value="8"
onChange={() => {}}
- showInput="only"
+ showInput="inputWithPopover"
{...requiredProps}
/>
);
From 2fd14f42e7182441a1ed0f4b4f3a5fca8176ef04 Mon Sep 17 00:00:00 2001
From: Greg Thompson
Date: Thu, 5 Sep 2019 13:19:13 -0500
Subject: [PATCH 22/24] use callback instead of resizeObserver
---
src/components/form/range/dual_range.js | 10 ++++------
src/components/popover/input_popover.tsx | 5 +++++
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js
index 5c660a78093..8d922a1c634 100644
--- a/src/components/form/range/dual_range.js
+++ b/src/components/form/range/dual_range.js
@@ -6,7 +6,6 @@ import { keyCodes } from '../../../services';
import { isWithinRange } from '../../../services/number';
import { EuiInputPopover } from '../../popover';
import { EuiFormControlLayoutDelimited } from '../form_control_layout';
-import { EuiResizeObserver } from '../../observer/resize_observer';
import makeId from '../form_row/make_id';
import { EuiRangeHighlight } from './range_highlight';
@@ -253,7 +252,7 @@ export class EuiDualRange extends Component {
});
};
- onResize = ({ width }) => {
+ onResize = width => {
this.setState({
rangeWidth: width,
});
@@ -458,10 +457,9 @@ export class EuiDualRange extends Component {
fullWidth={fullWidth}
isOpen={this.state.isPopoverOpen}
closePopover={this.closePopover}
- disableFocusTrap={true}>
-
- {resizeRef => {theRange}
}
-
+ disableFocusTrap={true}
+ onPanelResize={this.onResize}>
+ {theRange}
) : (
undefined
diff --git a/src/components/popover/input_popover.tsx b/src/components/popover/input_popover.tsx
index 8145f91dfb4..a9f4f2df543 100644
--- a/src/components/popover/input_popover.tsx
+++ b/src/components/popover/input_popover.tsx
@@ -19,6 +19,7 @@ interface EuiInputPopoverProps
fullWidth?: boolean;
input: EuiPopoverProps['button'];
inputRef?: EuiPopoverProps['buttonRef'];
+ onPanelResize?: (width?: number) => void;
}
type Props = CommonProps &
@@ -31,6 +32,7 @@ export const EuiInputPopover: FunctionComponent = ({
disableFocusTrap = false,
input,
fullWidth = false,
+ onPanelResize,
...props
}) => {
const [inputEl, setInputEl] = useState();
@@ -44,6 +46,9 @@ export const EuiInputPopover: FunctionComponent = ({
if (panelEl && (!!inputElWidth || !!width)) {
const newWidth = !!width ? width : inputElWidth;
panelEl.style.width = `${newWidth}px`;
+ if (onPanelResize) {
+ onPanelResize(newWidth);
+ }
}
};
const onResize = () => {
From 657e3d8ca07faad96bec92b5f8aabb1a0679c5d3 Mon Sep 17 00:00:00 2001
From: Greg Thompson
Date: Mon, 9 Sep 2019 12:27:43 -0500
Subject: [PATCH 23/24] ie11 focus fix
---
src/components/form/range/dual_range.js | 3 ++-
src/components/form/range/range.js | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js
index 8d922a1c634..ea8cef8872b 100644
--- a/src/components/form/range/dual_range.js
+++ b/src/components/form/range/dual_range.js
@@ -240,7 +240,8 @@ export class EuiDualRange extends Component {
onInputBlur = e => {
// Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
- const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
+ const relatedTarget =
+ e.relatedTarget || e.explicitOriginalTarget || document.activeElement;
if (!relatedTarget || relatedTarget.id !== this.state.id) {
this.closePopover();
}
diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js
index 2cf63aba3b2..df450fb8672 100644
--- a/src/components/form/range/range.js
+++ b/src/components/form/range/range.js
@@ -44,7 +44,8 @@ export class EuiRange extends Component {
onInputBlur = e => {
// Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
- const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
+ const relatedTarget =
+ e.relatedTarget || e.explicitOriginalTarget || document.activeElement;
if (!relatedTarget || relatedTarget.id !== this.state.id) {
this.closePopover();
}
From 418e4e156e7fbfd8078a003f8d3448e06b73b587 Mon Sep 17 00:00:00 2001
From: Greg Thompson
Date: Mon, 9 Sep 2019 14:03:03 -0500
Subject: [PATCH 24/24] use focusout instead of blur
---
src/components/form/range/dual_range.js | 25 ++++++++++++++++++++----
src/components/form/range/range.js | 25 ++++++++++++++++++++----
src/components/form/range/range_input.js | 1 +
3 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/src/components/form/range/dual_range.js b/src/components/form/range/dual_range.js
index ea8cef8872b..8e0b3131bbb 100644
--- a/src/components/form/range/dual_range.js
+++ b/src/components/form/range/dual_range.js
@@ -25,6 +25,8 @@ export class EuiDualRange extends Component {
rangeWidth: null,
};
+ maxNode = null;
+ minNode = null;
rangeSliderRef = null;
handleRangeSliderRefUpdate = ref => {
this.rangeSliderRef = ref;
@@ -240,8 +242,7 @@ export class EuiDualRange extends Component {
onInputBlur = e => {
// Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
- const relatedTarget =
- e.relatedTarget || e.explicitOriginalTarget || document.activeElement;
+ const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
if (!relatedTarget || relatedTarget.id !== this.state.id) {
this.closePopover();
}
@@ -259,6 +260,22 @@ export class EuiDualRange extends Component {
});
};
+ inputRef = (node, ref) => {
+ if (!this.props.showInput !== 'inputWithPopover') return;
+
+ // IE11 doesn't support the `relatedTarget` event property for blur events
+ // but does add it for focusout. React doesn't support `onFocusOut` so here we are.
+ if (this[ref] != null) {
+ this[ref].removeEventListener('focusout', this.onInputBlur);
+ }
+
+ this[ref] = node;
+
+ if (this[ref]) {
+ this[ref].addEventListener('focusout', this.onInputBlur);
+ }
+ };
+
render() {
const {
className,
@@ -306,11 +323,11 @@ export class EuiDualRange extends Component {
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
- onBlur={canShowDropdown ? this.onInputBlur : undefined}
readOnly={readOnly}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
controlOnly={showInputOnly}
+ inputRef={node => this.inputRef(node, 'minNode')}
/>
) : (
undefined
@@ -332,11 +349,11 @@ export class EuiDualRange extends Component {
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
- onBlur={canShowDropdown ? this.onInputBlur : undefined}
readOnly={readOnly}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
controlOnly={showInputOnly}
+ inputRef={node => this.inputRef(node, 'maxNode')}
/>
) : (
undefined
diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js
index df450fb8672..2de1b30db00 100644
--- a/src/components/form/range/range.js
+++ b/src/components/form/range/range.js
@@ -21,6 +21,8 @@ export class EuiRange extends Component {
id: props.id || makeId(),
isPopoverOpen: false,
};
+
+ this.inputNode = null;
}
handleOnChange = e => {
@@ -44,8 +46,7 @@ export class EuiRange extends Component {
onInputBlur = e => {
// Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
- const relatedTarget =
- e.relatedTarget || e.explicitOriginalTarget || document.activeElement;
+ const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
if (!relatedTarget || relatedTarget.id !== this.state.id) {
this.closePopover();
}
@@ -57,6 +58,22 @@ export class EuiRange extends Component {
});
};
+ inputRef = node => {
+ if (!this.props.showInput !== 'inputWithPopover') return;
+
+ // IE11 and Safar don't support the `relatedTarget` event property for blur events
+ // but do add it for focusout. React doesn't support `onFocusOut` so here we are.
+ if (this.inputNode != null) {
+ this.inputNode.removeEventListener('focusout', this.onInputBlur);
+ }
+
+ this.inputNode = node;
+
+ if (this.inputNode) {
+ this.inputNode.addEventListener('focusout', this.onInputBlur);
+ }
+ };
+
render() {
const {
className,
@@ -105,9 +122,9 @@ export class EuiRange extends Component {
onChange={this.handleOnChange}
name={name}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
- onBlur={canShowDropdown ? this.onInputBlur : undefined}
fullWidth={showInputOnly && fullWidth}
autoSize={!showInputOnly}
+ inputRef={this.inputRef}
{...rest}
/>
) : (
@@ -162,7 +179,7 @@ export class EuiRange extends Component {
style={style}
showTicks={showTicks}
showRange={showRange}
- tabIndex={showInput === true ? -1 : tabIndex || null}
+ tabIndex={showInput ? -1 : tabIndex || null}
{...rest}
/>
diff --git a/src/components/form/range/range_input.js b/src/components/form/range/range_input.js
index 5386d4aab68..d7e240f9411 100644
--- a/src/components/form/range/range_input.js
+++ b/src/components/form/range/range_input.js
@@ -55,6 +55,7 @@ EuiRangeInput.propTypes = {
side: PropTypes.oneOf(['min', 'max']),
fullWidth: PropTypes.bool,
autoSize: PropTypes.bool,
+ inputRef: PropTypes.func,
};
EuiRangeInput.defaultProps = {
side: 'max',