diff --git a/CHANGELOG.md b/CHANGELOG.md index 61d33824fe4f..833636571b11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,17 @@ ## [`master`](https://github.com/elastic/eui/tree/master) - Added `spacesApp` logo to `EuiIcon` set ([#1065](https://github.com/elastic/eui/pull/1065)) +- Added `!default` to border SASS props ([#1079](https://github.com/elastic/eui/pull/1079)) +- Added `repositionOnScroll` prop to `EuiPopover` which enables repositioning the popover when the window is scrolled. ([#1064](https://github.com/elastic/eui/pull/1064)) +- Allow `_` and `*` characters to be used in `EuiSearchBar` query terms ([#1058](https://github.com/elastic/eui/pull/1058)) - Added more `status` options for `EuiSteps` ([#1088](https://github.com/elastic/eui/pull/1088)) **Bug fixes** - `EuiMutationObserver`'s `children` prop is no longer marked as required ([#1076](https://github.com/elastic/eui/pull/1076)) +- Fixed large drop shadows so they work on darker backgrounds ([#1079](https://github.com/elastic/eui/pull/1079)) +- Added `resize-observer-polyfill` as a dependency (was previously a devDependency) ([#1085](https://github.com/elastic/eui/pull/1085)) +- Fixed `EuiBasicTable` to inform its parent about a selection change triggered by a different set of `items` ([#1086](https://github.com/elastic/eui/pull/1086)) - Fixed `EuiStepsHorizontal`'s title wrapping in IE ([#1088](https://github.com/elastic/eui/pull/1088)) ## [`3.3.0`](https://github.com/elastic/eui/tree/v3.3.0) diff --git a/package.json b/package.json index 57879b95a0da..92303ee28c0e 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "react-input-autosize": "^2.2.1", "react-virtualized": "^9.18.5", "react-vis": "1.10.2", + "resize-observer-polyfill": "^1.5.0", "tabbable": "^1.1.0", "uuid": "^3.1.0" }, @@ -125,7 +126,6 @@ "react-test-renderer": "^16.2.0", "redux": "^3.7.2", "redux-thunk": "^2.2.0", - "resize-observer-polyfill": "^1.5.0", "rimraf": "^2.6.2", "sass-extract": "^2.1.0", "sass-extract-js": "^0.3.0", diff --git a/src-docs/src/views/popover/popover_example.js b/src-docs/src/views/popover/popover_example.js index 4b86b9d15ed6..ac41ed3dedba 100644 --- a/src-docs/src/views/popover/popover_example.js +++ b/src-docs/src/views/popover/popover_example.js @@ -44,6 +44,9 @@ import PopoverContainer from './popover_container'; const popoverContainerSource = require('!!raw-loader!./popover_container'); const popoverContainerHtml = renderToHtml(PopoverContainer); +import PopoverFixed from './popover_fixed'; +const popoverFixedSource = require('!!raw-loader!./popover_fixed'); +const popoverFixedHtml = renderToHtml(PopoverFixed); export const PopoverExample = { title: 'Popover', @@ -204,5 +207,22 @@ export const PopoverExample = { ), demo: , + }, { + title: 'Popover on a fixed element', + source: [{ + type: GuideSectionTypes.JS, + code: popoverFixedSource, + }, { + type: GuideSectionTypes.HTML, + code: popoverFixedHtml, + }], + text: ( +
+

+ Popover content even works on position: fixed; elements. +

+
+ ), + demo: , }], }; diff --git a/src-docs/src/views/popover/popover_fixed.js b/src-docs/src/views/popover/popover_fixed.js new file mode 100644 index 000000000000..f543a5133531 --- /dev/null +++ b/src-docs/src/views/popover/popover_fixed.js @@ -0,0 +1,67 @@ +import React, { + Component, +} from 'react'; + +import { + EuiButton, + EuiPopover, +} from '../../../../src/components'; + +export default class PopoverContainer extends Component { + constructor(props) { + super(props); + + this.state = { + isExampleShown: false, + isPopoverOpen: false, + }; + } + + toggleExample = () => this.setState(({ isExampleShown }) => ({ isExampleShown: !isExampleShown })) + + onButtonClick = () => { + this.setState({ + isPopoverOpen: !this.state.isPopoverOpen, + }); + } + + closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + } + + setPanelRef = node => this.panel = node; + + render() { + const button = ( + + Show fixed popover + + ); + + return ( + + Toggle Example + {this.state.isExampleShown && ( + +
+ This popover scrolls with the button element! +
+
+ )} +
+ ); + } +} diff --git a/src/components/basic_table/basic_table.js b/src/components/basic_table/basic_table.js index fba26f2c5f4b..fb323ea9e6a5 100644 --- a/src/components/basic_table/basic_table.js +++ b/src/components/basic_table/basic_table.js @@ -199,7 +199,15 @@ export class EuiBasicTable extends Component { nextProps.items.findIndex(item => getItemId(item, itemId) === getItemId(selectedItem, itemId)) !== -1 )); - return { selection }; + if (selection.length !== prevState.selection.length) { + if (nextProps.selection.onSelectionChange) { + nextProps.selection.onSelectionChange(selection); + } + + return { selection }; + } + + return null; } constructor(props) { diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 719b1013b73a..8a0db98038c0 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -153,6 +153,10 @@ export class EuiPopover extends Component { this.setState({ suppressingPopover: false, isOpening: true }); // eslint-disable-line react/no-did-mount-set-state } + if (this.props.repositionOnScroll) { + window.addEventListener('scroll', this.positionPopover); + } + this.updateFocus(); } @@ -169,6 +173,15 @@ export class EuiPopover extends Component { }); } + // update scroll listener + if (prevProps.repositionOnScroll !== this.props.repositionOnScroll) { + if (this.props.repositionOnScroll) { + window.addEventListener('scroll', this.positionPopover); + } else { + window.removeEventListener('scroll', this.positionPopover); + } + } + // The popover is being closed. if (prevProps.isOpen && !this.props.isOpen) { // If the user has just closed the popover, queue up the removal of the content after the @@ -184,6 +197,7 @@ export class EuiPopover extends Component { } componentWillUnmount() { + window.removeEventListener('scroll', this.positionPopover); clearTimeout(this.closingTransitionTimeout); } @@ -420,6 +434,8 @@ EuiPopover.propTypes = { PropTypes.node, PropTypes.instanceOf(HTMLElement) ]), + /** When `true`, the popover's position is re-calculated when the user scrolls, this supports having fixed-position popover anchors. */ + repositionOnScroll: PropTypes.bool, }; EuiPopover.defaultProps = { diff --git a/src/components/search_bar/query/default_syntax.js b/src/components/search_bar/query/default_syntax.js index 0f6ca5835df5..5d7ba1bcf760 100644 --- a/src/components/search_bar/query/default_syntax.js +++ b/src/components/search_bar/query/default_syntax.js @@ -127,7 +127,7 @@ word wordChar = alnum - / [-] + / [-_*] / escapedChar escapedChar diff --git a/src/components/search_bar/query/default_syntax.test.js b/src/components/search_bar/query/default_syntax.test.js index c74b710a3d6f..61251fb79a9b 100644 --- a/src/components/search_bar/query/default_syntax.test.js +++ b/src/components/search_bar/query/default_syntax.test.js @@ -661,6 +661,38 @@ describe('defaultSyntax', () => { expect(clause.value).toBe('truest'); }); + describe('wordChar', () => { + test('alphanumeric characters', () => { + const ast = defaultSyntax.parse('logstash'); + const clauses = ast.getTermClauses(); + expect(clauses).toEqual([{ + type: 'term', + value: 'logstash', + match: 'must', + }]); + }); + + test('escaped characters', () => { + const ast = defaultSyntax.parse('\\-'); + const clauses = ast.getTermClauses(); + expect(clauses).toEqual([{ + type: 'term', + value: '-', + match: 'must', + }]); + }); + + test('special characters', () => { + const ast = defaultSyntax.parse('*_-'); + const clauses = ast.getTermClauses(); + expect(clauses).toEqual([{ + type: 'term', + value: '*_-', + match: 'must', + }]); + }); + }); + test('number range expressions', () => { const query = `num1>6 -num2>=8 num3<4 -num4<=2`;