From 415db1ca2bfbf077b5a1f8f029442afacd7ff512 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 17 Jan 2020 10:57:11 -0600 Subject: [PATCH 1/2] euifieldsearch to ts --- ...est.js.snap => field_search.test.tsx.snap} | 0 ...d_search.test.js => field_search.test.tsx} | 0 .../{field_search.js => field_search.tsx} | 119 ++++++++++-------- src/components/form/field_search/index.d.ts | 29 ----- src/components/form/field_search/index.js | 1 - src/components/form/field_search/index.ts | 1 + src/components/form/index.d.ts | 3 - .../selectable_search/selectable_search.tsx | 6 +- 8 files changed, 68 insertions(+), 91 deletions(-) rename src/components/form/field_search/__snapshots__/{field_search.test.js.snap => field_search.test.tsx.snap} (100%) rename src/components/form/field_search/{field_search.test.js => field_search.test.tsx} (100%) rename src/components/form/field_search/{field_search.js => field_search.tsx} (63%) delete mode 100644 src/components/form/field_search/index.d.ts delete mode 100644 src/components/form/field_search/index.js create mode 100644 src/components/form/field_search/index.ts diff --git a/src/components/form/field_search/__snapshots__/field_search.test.js.snap b/src/components/form/field_search/__snapshots__/field_search.test.tsx.snap similarity index 100% rename from src/components/form/field_search/__snapshots__/field_search.test.js.snap rename to src/components/form/field_search/__snapshots__/field_search.test.tsx.snap diff --git a/src/components/form/field_search/field_search.test.js b/src/components/form/field_search/field_search.test.tsx similarity index 100% rename from src/components/form/field_search/field_search.test.js rename to src/components/form/field_search/field_search.test.tsx diff --git a/src/components/form/field_search/field_search.js b/src/components/form/field_search/field_search.tsx similarity index 63% rename from src/components/form/field_search/field_search.js rename to src/components/form/field_search/field_search.tsx index 580c36c3520..b88728504b1 100644 --- a/src/components/form/field_search/field_search.js +++ b/src/components/form/field_search/field_search.tsx @@ -1,70 +1,70 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React, { Component, InputHTMLAttributes } from 'react'; import classNames from 'classnames'; import { Browser } from '../../../services/browser'; import { ENTER } from '../../../services/key_codes'; +import { CommonProps } from '../../common'; import { EuiFormControlLayout } from '../form_control_layout'; import { EuiValidatableControl } from '../validatable_control'; -const propTypes = { - name: PropTypes.string, - id: PropTypes.string, - placeholder: PropTypes.string, - value: PropTypes.string, - isInvalid: PropTypes.bool, - fullWidth: PropTypes.bool, - isLoading: PropTypes.bool, - inputRef: PropTypes.func, +export interface EuiFieldSearchProps + extends CommonProps, + InputHTMLAttributes { + name?: string; + id?: string; + placeholder?: string; + value?: string; + isInvalid?: boolean; + fullWidth?: boolean; + isLoading?: boolean; /** * Called when the user presses [Enter] OR on change if the incremental prop is `true`. * If you don't need the on[Enter] functionality, prefer using onChange */ - onSearch: PropTypes.func, + onSearch?: (value: string) => void; /** * When `true` the search will be executed (that is, the `onSearch` will be called) as the * user types. */ - incremental: PropTypes.bool, + incremental?: boolean; /** * when `true` creates a shorter height input */ - compressed: PropTypes.bool, + compressed?: boolean; + inputRef?: (node: HTMLInputElement | null) => void; /** * Shows a button that quickly clears any input */ - isClearable: PropTypes.bool, -}; - -const defaultProps = { - fullWidth: false, - isLoading: false, - incremental: false, - compressed: false, - isClearable: true, -}; - -export class EuiFieldSearch extends Component { - static propTypes = propTypes; - static defaultProps = defaultProps; - - constructor(props) { - super(props); - this.cleanups = []; - } + isClearable?: boolean; +} + +export class EuiFieldSearch extends Component { + static defaultProps = { + fullWidth: false, + isLoading: false, + incremental: false, + compressed: false, + isClearable: true, + }; + + inputElement: HTMLInputElement | null = null; + cleanups: Array<() => void> = []; componentDidMount() { + if (!this.inputElement) return; if (Browser.isEventSupported('search', this.inputElement)) { - const onSearch = event => { + const onSearch = (event?: Event) => { if (this.props.onSearch) { - this.props.onSearch(event.target.value); + if (!event || !event.target) return; + this.props.onSearch((event.target as HTMLInputElement).value); } }; this.inputElement.addEventListener('search', onSearch); - this.cleanups.push(() => - this.inputElement.removeEventListener('search', onSearch) - ); + this.cleanups.push(() => { + if (!this.inputElement) return; + this.inputElement.removeEventListener('search', onSearch); + }); } } @@ -79,42 +79,55 @@ export class EuiFieldSearch extends Component { // only then will React treat the value as different and fire its `change` event // // https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js - const nativeInputValueSetter = Object.getOwnPropertyDescriptor( - window.HTMLInputElement.prototype, + const nativeInputValue = Object.getOwnPropertyDescriptor( + HTMLInputElement.prototype, 'value' - ).set; - nativeInputValueSetter.call(this.inputElement, ''); + ); + const nativeInputValueSetter = nativeInputValue + ? nativeInputValue.set + : undefined; + if (nativeInputValueSetter) { + nativeInputValueSetter.call(this.inputElement, ''); + } // dispatch input event, with IE11 support/fallback + let event; if ('Event' in window && typeof Event === 'function') { - const event = new Event('input', { + event = new Event('input', { bubbles: true, cancelable: false, }); - this.inputElement.dispatchEvent(event); } else { // IE11 - const event = document.createEvent('Event'); + event = document.createEvent('Event'); event.initEvent('input', true, false); - this.inputElement.dispatchEvent(event); } - // set focus on the search field - this.inputElement.focus(); + if (this.inputElement) { + if (event) { + this.inputElement.dispatchEvent(event); + } + // set focus on the search field + this.inputElement.focus(); + } }; componentWillUnmount() { this.cleanups.forEach(cleanup => cleanup()); } - setRef = inputElement => { + setRef = (inputElement: HTMLInputElement | null) => { this.inputElement = inputElement; if (this.props.inputRef) { this.props.inputRef(inputElement); } }; - onKeyUp = (incremental, onSearch, event) => { + onKeyUp = ( + event: React.KeyboardEvent, + incremental?: boolean, + onSearch?: (value: string) => void + ) => { if (this.props.onKeyUp) { this.props.onKeyUp(event); if (event.defaultPrevented) { @@ -122,7 +135,7 @@ export class EuiFieldSearch extends Component { } } if (onSearch && (incremental || event.keyCode === ENTER)) { - onSearch(event.target.value); + onSearch((event.target as HTMLInputElement).value); } }; @@ -162,7 +175,7 @@ export class EuiFieldSearch extends Component { clear={ isClearable && value && !rest.readOnly && !rest.disabled ? { onClick: this.onClear } - : null + : undefined } compressed={compressed}> @@ -173,7 +186,7 @@ export class EuiFieldSearch extends Component { placeholder={placeholder} className={classes} value={value} - onKeyUp={this.onKeyUp.bind(this, incremental, onSearch)} + onKeyUp={e => this.onKeyUp(e, incremental, onSearch)} ref={this.setRef} {...rest} /> diff --git a/src/components/form/field_search/index.d.ts b/src/components/form/field_search/index.d.ts deleted file mode 100644 index 24637df7066..00000000000 --- a/src/components/form/field_search/index.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CommonProps } from '../../common'; - -import { FunctionComponent, InputHTMLAttributes, Ref } from 'react'; - -declare module '@elastic/eui' { - /** - * search field type defs - * - * @see './field_search.js' - */ - - export interface EuiFieldSearchProps { - name?: string; - id?: string; - placeholder?: string; - value?: string; - isInvalid?: boolean; - fullWidth?: boolean; - isLoading?: boolean; - onSearch?: (value: string) => void; - incremental?: boolean; - compressed?: boolean; - inputRef?: Ref; - } - - export const EuiFieldSearch: FunctionComponent< - CommonProps & InputHTMLAttributes & EuiFieldSearchProps - >; -} diff --git a/src/components/form/field_search/index.js b/src/components/form/field_search/index.js deleted file mode 100644 index a8b232bf121..00000000000 --- a/src/components/form/field_search/index.js +++ /dev/null @@ -1 +0,0 @@ -export { EuiFieldSearch } from './field_search'; diff --git a/src/components/form/field_search/index.ts b/src/components/form/field_search/index.ts new file mode 100644 index 00000000000..6ab8c11d855 --- /dev/null +++ b/src/components/form/field_search/index.ts @@ -0,0 +1 @@ +export { EuiFieldSearch, EuiFieldSearchProps } from './field_search'; diff --git a/src/components/form/index.d.ts b/src/components/form/index.d.ts index bcd8f9e672e..fa69f48eb7f 100644 --- a/src/components/form/index.d.ts +++ b/src/components/form/index.d.ts @@ -1,7 +1,4 @@ import { CommonProps } from '../common'; -/// -/// -/// /// import { FunctionComponent, FormHTMLAttributes, ReactNode } from 'react'; diff --git a/src/components/selectable/selectable_search/selectable_search.tsx b/src/components/selectable/selectable_search/selectable_search.tsx index 06f4a08e79a..d6eedc5ee99 100644 --- a/src/components/selectable/selectable_search/selectable_search.tsx +++ b/src/components/selectable/selectable_search/selectable_search.tsx @@ -1,14 +1,10 @@ import React, { Component, InputHTMLAttributes } from 'react'; import classNames from 'classnames'; import { CommonProps } from '../../common'; -// @ts-ignore -import { EuiFieldSearch } from '../../form/field_search'; +import { EuiFieldSearch, EuiFieldSearchProps } from '../../form/field_search'; import { getMatchingOptions } from '../matching_options'; import { Option } from '../types'; -/// -import { EuiFieldSearchProps } from '@elastic/eui'; // eslint-disable-line - export type EuiSelectableSearchProps = Omit< InputHTMLAttributes & EuiFieldSearchProps, 'onChange' From af04c534835e24334a4a0f8ce78e62b5d90493e2 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 17 Jan 2020 11:06:44 -0600 Subject: [PATCH 2/2] CL --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15e977f4419..2a8f664777b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Converted `EuiFormRow` to Typescript ([#2712](https://github.com/elastic/eui/pull/2712)) - Updated `logoAPM`, `logoSecurity` and `logoEnterpriseSearch`. Added `logoWorkplaceSearch` and `logoObservability` ([#2769](https://github.com/elastic/eui/pull/2769)) +- Converted `EuiFieldSearch` to TypeScript ([#2775](https://github.com/elastic/eui/pull/2775)) **Deprecations**