From 97041bf4bcae1f00f2fce2a24b804f8ec0983741 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 17 Jan 2020 13:16:48 -0600 Subject: [PATCH 1/6] conversion --- .../context_menu/context_menu_item.tsx | 8 +- src/components/context_menu/index.ts | 1 + src/components/form/index.d.ts | 1 - .../__snapshots__/super_select.test.js.snap | 1456 ----------------- ...nap => super_select_control.test.tsx.snap} | 51 - src/components/form/super_select/index.d.ts | 83 - src/components/form/super_select/index.js | 3 - src/components/form/super_select/index.ts | 7 + ...r_select.test.js => super_select.test.tsx} | 2 +- .../{super_select.js => super_select.tsx} | 215 +-- ....test.js => super_select_control.test.tsx} | 3 +- ...ct_control.js => super_select_control.tsx} | 84 +- 12 files changed, 182 insertions(+), 1732 deletions(-) delete mode 100644 src/components/form/super_select/__snapshots__/super_select.test.js.snap rename src/components/form/super_select/__snapshots__/{super_select_control.test.js.snap => super_select_control.test.tsx.snap} (87%) delete mode 100644 src/components/form/super_select/index.d.ts delete mode 100644 src/components/form/super_select/index.js create mode 100644 src/components/form/super_select/index.ts rename src/components/form/super_select/{super_select.test.js => super_select.test.tsx} (98%) rename src/components/form/super_select/{super_select.js => super_select.tsx} (62%) rename src/components/form/super_select/{super_select_control.test.js => super_select_control.test.tsx} (97%) rename src/components/form/super_select/{super_select_control.js => super_select_control.tsx} (65%) diff --git a/src/components/context_menu/context_menu_item.tsx b/src/components/context_menu/context_menu_item.tsx index f9746e01d3a..54d1e648736 100644 --- a/src/components/context_menu/context_menu_item.tsx +++ b/src/components/context_menu/context_menu_item.tsx @@ -17,7 +17,7 @@ import { getSecureRelForTarget } from '../../services'; export type EuiContextMenuItemIcon = ReactElement | string | HTMLElement; -type LayoutAlignment = 'center' | 'top' | 'bottom'; +export type EuiContextMenuItemLayoutAlignment = 'center' | 'top' | 'bottom'; export interface EuiContextMenuItemProps extends CommonProps { icon?: EuiContextMenuItemIcon; @@ -43,14 +43,16 @@ export interface EuiContextMenuItemProps extends CommonProps { /** * How to align icon with content of button */ - layoutAlign?: LayoutAlignment; + layoutAlign?: EuiContextMenuItemLayoutAlignment; } type Props = CommonProps & Omit, 'type'> & EuiContextMenuItemProps; -const layoutAlignToClassNames: { [align in LayoutAlignment]: string | null } = { +const layoutAlignToClassNames: { + [align in EuiContextMenuItemLayoutAlignment]: string | null +} = { center: null, top: 'euiContextMenu__itemLayout--top', bottom: 'euiContextMenu__itemLayout--bottom', diff --git a/src/components/context_menu/index.ts b/src/components/context_menu/index.ts index 0f823dd6699..b414a28e22d 100644 --- a/src/components/context_menu/index.ts +++ b/src/components/context_menu/index.ts @@ -12,4 +12,5 @@ export { export { EuiContextMenuItem, EuiContextMenuItemIcon, + EuiContextMenuItemLayoutAlignment, } from './context_menu_item'; diff --git a/src/components/form/index.d.ts b/src/components/form/index.d.ts index bcd8f9e672e..fd61789c33a 100644 --- a/src/components/form/index.d.ts +++ b/src/components/form/index.d.ts @@ -2,7 +2,6 @@ import { CommonProps } from '../common'; /// /// /// -/// import { FunctionComponent, FormHTMLAttributes, ReactNode } from 'react'; diff --git a/src/components/form/super_select/__snapshots__/super_select.test.js.snap b/src/components/form/super_select/__snapshots__/super_select.test.js.snap deleted file mode 100644 index ea902ef53c2..00000000000 --- a/src/components/form/super_select/__snapshots__/super_select.test.js.snap +++ /dev/null @@ -1,1456 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`EuiSuperSelect is rendered 1`] = ` -
-
- -
-
- - Select an option: , is selected - -
-
-
-
-`; - -exports[`EuiSuperSelect props compressed is rendered 1`] = ` -
-
- -
-
- - Select an option: , is selected - -
-
-
-
-`; - -exports[`EuiSuperSelect props custom display is propagated to dropdown 1`] = ` -
-
- -
-
- - Select an option: , is selected - -
-
-
-
-
-
-
- -
-
-
-`; - -exports[`EuiSuperSelect props fullWidth is rendered 1`] = ` -
-
- -
-
- - Select an option: , is selected - -
-
-
-
-`; - -exports[`EuiSuperSelect props more props are propogated to each option 1`] = ` -
-
- -
-
- - Select an option: Option #1, is selected - - -
- - - -
-
-
-
-
-
-
-
- -
-
-
-`; - -exports[`EuiSuperSelect props more props are propogated to each option 2`] = ` - - - } - className="euiSuperSelect" - closePopover={[Function]} - display="block" - hasArrow={false} - isOpen={true} - ownFocus={false} - panelClassName="euiSuperSelect__popoverPanel" - panelPaddingSize="none" - popoverRef={[Function]} - > - -
-
- - - -
-
- - - - Select an option: Option #1, is selected - - - - - -
- - - - - -
-
-
-
-
-
-
- - - - -
- -
-
-
- - - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - > - - - } - onActivation={[Function]} - onDeactivation={[Function]} - persistentFocus={false} - /> - - -
-
- -
- -

- - You are in a form selector of 2 items and must select a single option. Use the up and down keys to navigate or escape to close. - -

-
-
- - - - - - -
-
-
-
- -
-
- -
- - - - -
- - - -`; - -exports[`EuiSuperSelect props options are rendered when select is open 1`] = ` -
-
- -
-
- - Select an option: , is selected - -
-
-
-
-
-
-
- -
-
-
-`; - -exports[`EuiSuperSelect props select component is rendered 1`] = ` -
-
- -
-
- - Select an option: , is selected - -
-
-
-
-`; - -exports[`EuiSuperSelect props valueSelected is rendered 1`] = ` -
-
- -
-
- - Select an option: Option #2, is selected - - -
- - - -
-
-
-
-
-`; diff --git a/src/components/form/super_select/__snapshots__/super_select_control.test.js.snap b/src/components/form/super_select/__snapshots__/super_select_control.test.tsx.snap similarity index 87% rename from src/components/form/super_select/__snapshots__/super_select_control.test.js.snap rename to src/components/form/super_select/__snapshots__/super_select_control.test.tsx.snap index 7e99f042576..6c8d8b9e9e8 100644 --- a/src/components/form/super_select/__snapshots__/super_select_control.test.js.snap +++ b/src/components/form/super_select/__snapshots__/super_select_control.test.tsx.snap @@ -347,54 +347,3 @@ Array [
, ] `; - -exports[`EuiSuperSelectControl props value option is rendered 1`] = ` -Array [ - , -
-
- - Select an option: Option #1, is selected - - -
- - - -
-
-
, -] -`; diff --git a/src/components/form/super_select/index.d.ts b/src/components/form/super_select/index.d.ts deleted file mode 100644 index 87d75033743..00000000000 --- a/src/components/form/super_select/index.d.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { CommonProps } from '../../common'; - -import { FunctionComponent, ReactNode, ButtonHTMLAttributes } from 'react'; - -declare module '@elastic/eui' { - /** - * @see './super_select.js' - */ - - export type EuiSuperSelectProps = CommonProps & - Omit, 'onChange'> & { - /** - * Pass an array of options that must at least include: - * `value`: storing unique value of item, - * `inputDisplay`: what shows inside the form input when selected - * `dropdownDisplay` (optional): what shows for the item in the dropdown - */ - options: Array<{ - value: T; - inputDisplay?: ReactNode; - dropdownDisplay?: ReactNode; - disabled?: boolean; - 'data-test-subj'?: string; - }>; - - valueOfSelected?: T; - - /** - * Classes for the context menu item - */ - itemClassName?: string; - - /** - * You must pass an `onChange` function to handle the update of the value - */ - onChange?: (value: T) => void; - - /** - * Change to `true` if you want horizontal lines between options. - * This is best used when options are multi-line. - */ - hasDividers?: boolean; - - /** - * Change `EuiContextMenuItem` layout position of icon - */ - itemLayoutAlign?: string; - - /** - * Make it wide. Default: false - */ - fullWidth?: boolean; - - /** - * Provides invalid styling. Default: false - */ - isInvalid?: boolean; - - /** - * Provides a loading indicator. Default: false - */ - isLoading?: boolean; - - /** - * Make it short. Default: false - */ - compressed?: boolean; - - /** - * Applied to the outermost wrapper (popover) - */ - popoverClassName?: string; - - /** - * Controls whether the options are shown. Default: false - */ - isOpen?: boolean; - }; - - export const EuiSuperSelect: ( - props: EuiSuperSelectProps - ) => ReturnType>>; -} diff --git a/src/components/form/super_select/index.js b/src/components/form/super_select/index.js deleted file mode 100644 index 7176a843996..00000000000 --- a/src/components/form/super_select/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export { EuiSuperSelect } from './super_select'; - -export { EuiSuperSelectControl } from './super_select_control'; diff --git a/src/components/form/super_select/index.ts b/src/components/form/super_select/index.ts new file mode 100644 index 00000000000..c203f20d54d --- /dev/null +++ b/src/components/form/super_select/index.ts @@ -0,0 +1,7 @@ +export { EuiSuperSelect, EuiSuperSelectProps } from './super_select'; + +export { + EuiSuperSelectControl, + EuiSuperSelectControlProps, + EuiSuperSelectOption, +} from './super_select_control'; diff --git a/src/components/form/super_select/super_select.test.js b/src/components/form/super_select/super_select.test.tsx similarity index 98% rename from src/components/form/super_select/super_select.test.js rename to src/components/form/super_select/super_select.test.tsx index 62100231382..7eee0e8c2a0 100644 --- a/src/components/form/super_select/super_select.test.js +++ b/src/components/form/super_select/super_select.test.tsx @@ -7,7 +7,7 @@ import { EuiSuperSelect } from './super_select'; jest.mock('../form_row/make_id', () => () => 'generated-id'); jest.mock('../../portal', () => ({ - EuiPortal: ({ children }) => children, + EuiPortal: ({ children }: any) => children, })); // Mock the htmlIdGenerator to generate predictable ids for snapshot tests diff --git a/src/components/form/super_select/super_select.js b/src/components/form/super_select/super_select.tsx similarity index 62% rename from src/components/form/super_select/super_select.js rename to src/components/form/super_select/super_select.tsx index 19ebab80986..1dcae25d37b 100644 --- a/src/components/form/super_select/super_select.js +++ b/src/components/form/super_select/super_select.tsx @@ -1,27 +1,111 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React, { Component, ButtonHTMLAttributes } from 'react'; import classNames from 'classnames'; +import { CommonProps } from '../../common'; + import { EuiScreenReaderOnly } from '../../accessibility'; -import { EuiSuperSelectControl } from './super_select_control'; +import { + EuiSuperSelectControl, + EuiSuperSelectOption, +} from './super_select_control'; import { EuiPopover } from '../../popover'; -import { EuiContextMenuItem } from '../../context_menu'; +import { + EuiContextMenuItem, + EuiContextMenuItemLayoutAlignment, +} from '../../context_menu'; import { keyCodes } from '../../../services'; import { EuiI18n } from '../../i18n'; -const SHIFT_BACK = 'back'; -const SHIFT_FORWARD = 'forward'; +enum ShiftDirection { + BACK = 'back', + FORWARD = 'forward', +} -export class EuiSuperSelect extends Component { - constructor(props) { - super(props); +const SHIFT_BACK = ShiftDirection.BACK as const; +const SHIFT_FORWARD = ShiftDirection.FORWARD as const; + +export type EuiSuperSelectProps = CommonProps & + Omit, 'onChange' | 'value'> & { + /** + * Pass an array of options that must at least include: + * `value`: storing unique value of item, + * `inputDisplay`: what shows inside the form input when selected + * `dropdownDisplay` (optional): what shows for the item in the dropdown + */ + options: Array>; + + valueOfSelected?: T; + + /** + * Classes for the context menu item + */ + itemClassName?: string; + + /** + * You must pass an `onChange` function to handle the update of the value + */ + onChange?: (value: T) => void; + + /** + * Change to `true` if you want horizontal lines between options. + * This is best used when options are multi-line. + */ + hasDividers?: boolean; + + /** + * Change `EuiContextMenuItem` layout position of icon + */ + itemLayoutAlign?: EuiContextMenuItemLayoutAlignment; + + /** + * Make it wide. Default: false + */ + fullWidth?: boolean; + + /** + * Provides invalid styling. Default: false + */ + isInvalid?: boolean; + + /** + * Provides a loading indicator. Default: false + */ + isLoading?: boolean; + + /** + * Make it short. Default: false + */ + compressed?: boolean; + + /** + * Applied to the outermost wrapper (popover) + */ + popoverClassName?: string; + + /** + * Controls whether the options are shown. Default: false + */ + isOpen?: boolean; + }; - this.itemNodes = []; - this.state = { - isPopoverOpen: props.isOpen || false, - menuWidth: null, - }; - } +export class EuiSuperSelect extends Component< + EuiSuperSelectProps +> { + static defaultProps = { + hasDividers: false, + fullWidth: false, + compressed: false, + isInvalid: false, + }; + + private itemNodes: Array = []; + private popoverRef: HTMLDivElement | null = null; + private _isMounted: boolean = false; + + state = { + isPopoverOpen: this.props.isOpen || false, + menuWidth: undefined, + }; componentDidMount() { this._isMounted = true; @@ -31,11 +115,11 @@ export class EuiSuperSelect extends Component { this._isMounted = false; } - setItemNode = (node, index) => { + setItemNode = (node: HTMLButtonElement | null, index: number) => { this.itemNodes[index] = node; }; - setPopoverRef = ref => { + setPopoverRef = (ref: HTMLDivElement | null) => { this.popoverRef = ref; }; @@ -45,8 +129,8 @@ export class EuiSuperSelect extends Component { }); const focusSelected = () => { - const indexOfSelected = this.props.options.reduce( - (indexOfSelected, option, index) => { + const indexOfSelected: number | null = this.props.options.reduce( + (indexOfSelected: number | null, option, index) => { if (indexOfSelected != null) return indexOfSelected; if (option == null) return null; return option.value === this.props.valueOfSelected ? index : null; @@ -59,12 +143,14 @@ export class EuiSuperSelect extends Component { return; } this.setState({ - menuWidth: this.popoverRef.getBoundingClientRect().width - 2, // account for border not inner shadow + menuWidth: this.popoverRef + ? this.popoverRef.getBoundingClientRect().width - 2 // account for border not inner shadow + : undefined, }); if (this.props.valueOfSelected != null) { if (indexOfSelected != null) { - this.focusItemAt(indexOfSelected); + this.focusItemAt(indexOfSelected as number); } else { focusSelected(); } @@ -81,14 +167,16 @@ export class EuiSuperSelect extends Component { }); }; - itemClicked = value => { + itemClicked = (value: T) => { this.setState({ isPopoverOpen: false, }); - this.props.onChange(value); + if (this.props.onChange) { + this.props.onChange(value); + } }; - onSelectKeyDown = e => { + onSelectKeyDown = (e: React.KeyboardEvent) => { if (e.keyCode === keyCodes.UP || e.keyCode === keyCodes.DOWN) { e.preventDefault(); e.stopPropagation(); @@ -96,7 +184,7 @@ export class EuiSuperSelect extends Component { } }; - onItemKeyDown = e => { + onItemKeyDown = (e: React.KeyboardEvent) => { switch (e.keyCode) { case keyCodes.ESCAPE: // close the popover and prevent ancestors from handling @@ -125,16 +213,18 @@ export class EuiSuperSelect extends Component { } }; - focusItemAt(index) { + focusItemAt(index: number) { const targetElement = this.itemNodes[index]; if (targetElement != null) { targetElement.focus(); } } - shiftFocus(direction) { - const currentIndex = this.itemNodes.indexOf(document.activeElement); - let targetElementIndex; + shiftFocus(direction: ShiftDirection) { + const currentIndex = this.itemNodes.indexOf( + document.activeElement as HTMLButtonElement + ); + let targetElementIndex: number; if (currentIndex === -1) { // somehow the select options has lost focus @@ -261,75 +351,10 @@ export class EuiSuperSelect extends Component { role="listbox" aria-activedescendant={valueOfSelected} style={{ width: this.state.menuWidth }} - tabIndex="0"> + tabIndex={0}> {items}
); } } - -EuiSuperSelect.propTypes = { - /** - * Classes (and `...rest`) will be applied to the control - */ - className: PropTypes.string, - /** - * Classes for the context menu item - */ - itemClassName: PropTypes.string, - /** - * You must pass an `onChange` function to handle the update of the value - */ - onChange: PropTypes.func, - /** - * Pass an array of options that must at least include: - * `value`: storing unique value of item, - * `inputDisplay`: what shows inside the form input when selected - * `dropdownDisplay` (optional): what shows for the item in the dropdown - */ - options: PropTypes.arrayOf( - PropTypes.shape({ - value: PropTypes.string.isRequired, - inputDisplay: PropTypes.node, - dropdownDisplay: PropTypes.node, - }) - ).isRequired, - valueOfSelected: PropTypes.string, - /** - * Change to `true` if you want horizontal lines between options. - * This is best used when options are multi-line. - */ - hasDividers: PropTypes.bool, - /** - * Change `EuiContextMenuItem` layout position of icon - */ - itemLayoutAlign: PropTypes.string, - /** - * Make it wide - */ - fullWidth: PropTypes.bool, - /** - * Provides invalid styling - */ - isInvalid: PropTypes.bool, - /** - * Provides loading indictor - */ - isLoading: PropTypes.bool, - /** - * Make it short - */ - compressed: PropTypes.bool, - /** - * Applied to the outermost wrapper (popover) - */ - popoverClassName: PropTypes.string, -}; - -EuiSuperSelect.defaultProps = { - hasDividers: false, - fullWidth: false, - compressed: false, - isInvalid: false, -}; diff --git a/src/components/form/super_select/super_select_control.test.js b/src/components/form/super_select/super_select_control.test.tsx similarity index 97% rename from src/components/form/super_select/super_select_control.test.js rename to src/components/form/super_select/super_select_control.test.tsx index 82a0065416d..5aae913b796 100644 --- a/src/components/form/super_select/super_select_control.test.js +++ b/src/components/form/super_select/super_select_control.test.tsx @@ -67,13 +67,14 @@ describe('EuiSuperSelectControl', () => { }); test('empty value option is rendered', () => { + const value = undefined; const component = render( {}} /> ); diff --git a/src/components/form/super_select/super_select_control.js b/src/components/form/super_select/super_select_control.tsx similarity index 65% rename from src/components/form/super_select/super_select_control.js rename to src/components/form/super_select/super_select_control.tsx index c1670c42cb3..7f015504886 100644 --- a/src/components/form/super_select/super_select_control.js +++ b/src/components/form/super_select/super_select_control.tsx @@ -1,22 +1,56 @@ -import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; +import React, { + Fragment, + FunctionComponent, + ButtonHTMLAttributes, + ReactNode, +} from 'react'; import classNames from 'classnames'; +import { CommonProps } from '../../common'; + import { EuiScreenReaderOnly } from '../../accessibility'; import makeId from '../form_row/make_id'; -import { EuiFormControlLayout } from '../form_control_layout'; +import { + EuiFormControlLayout, + EuiFormControlLayoutProps, +} from '../form_control_layout'; import { EuiI18n } from '../../i18n'; -export const EuiSuperSelectControl = ({ +export interface EuiSuperSelectOption { + value: T; + inputDisplay?: ReactNode; + dropdownDisplay?: ReactNode; + disabled?: boolean; + 'data-test-subj'?: string; +} + +export interface EuiSuperSelectControlProps + extends CommonProps, + Omit, 'value'> { + compressed?: boolean; + fullWidth?: boolean; + isInvalid?: boolean; + isLoading?: boolean; + readOnly?: boolean; + + name?: string; + value?: T; + + options?: Array>; +} + +export const EuiSuperSelectControl: ( + props: EuiSuperSelectControlProps +) => ReturnType>> = ({ className, - options, + options = [], id, name, - fullWidth, - isLoading, - isInvalid, + fullWidth = false, + isLoading = false, + isInvalid = false, defaultValue, - compressed, + compressed = false, value, ...rest }) => { @@ -33,12 +67,12 @@ export const EuiSuperSelectControl = ({ // React HTML input can not have both value and defaultValue properties. // https://reactjs.org/docs/uncontrolled-components.html#default-values - let selectDefaultValue; + let selectDefaultValue: string | number | string[] = ''; if (value == null) { selectDefaultValue = defaultValue || ''; } - let selectedValue = ''; + let selectedValue; if (value) { const selectedOption = options.find(option => option.value === value); selectedValue = selectedOption @@ -46,7 +80,7 @@ export const EuiSuperSelectControl = ({ : selectedValue; } - const icon = { + const icon: EuiFormControlLayoutProps['icon'] = { type: 'arrowDown', side: 'right', }; @@ -96,29 +130,3 @@ export const EuiSuperSelectControl = ({ ); }; - -EuiSuperSelectControl.propTypes = { - name: PropTypes.string, - id: PropTypes.string, - options: PropTypes.arrayOf( - PropTypes.shape({ - value: PropTypes.node.isRequired, - inputDisplay: PropTypes.node.isRequired, - }) - ).isRequired, - isInvalid: PropTypes.bool, - fullWidth: PropTypes.bool, - isLoading: PropTypes.bool, - /** - * when `true` creates a shorter height input - */ - compressed: PropTypes.bool, -}; - -EuiSuperSelectControl.defaultProps = { - options: [], - fullWidth: false, - isLoading: false, - isInvalid: false, - compressed: false, -}; From 91bd2dd985b9ec42e1882c2bb62e4d99312d1a6b Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 17 Jan 2020 13:56:51 -0600 Subject: [PATCH 2/6] tests --- .../__snapshots__/super_select.test.tsx.snap | 1454 +++++++++++++++++ .../super_select_control.test.tsx.snap | 51 + .../super_select/super_select_control.tsx | 2 +- 3 files changed, 1506 insertions(+), 1 deletion(-) create mode 100644 src/components/form/super_select/__snapshots__/super_select.test.tsx.snap diff --git a/src/components/form/super_select/__snapshots__/super_select.test.tsx.snap b/src/components/form/super_select/__snapshots__/super_select.test.tsx.snap new file mode 100644 index 00000000000..8977954bc1d --- /dev/null +++ b/src/components/form/super_select/__snapshots__/super_select.test.tsx.snap @@ -0,0 +1,1454 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiSuperSelect is rendered 1`] = ` +
+
+ +
+
+ + Select an option: , is selected + +
+
+
+
+`; + +exports[`EuiSuperSelect props compressed is rendered 1`] = ` +
+
+ +
+
+ + Select an option: , is selected + +
+
+
+
+`; + +exports[`EuiSuperSelect props custom display is propagated to dropdown 1`] = ` +
+
+ +
+
+ + Select an option: , is selected + +
+
+
+
+
+
+
+ +
+
+
+`; + +exports[`EuiSuperSelect props fullWidth is rendered 1`] = ` +
+
+ +
+
+ + Select an option: , is selected + +
+
+
+
+`; + +exports[`EuiSuperSelect props more props are propogated to each option 1`] = ` +
+
+ +
+
+ + Select an option: Option #1, is selected + + +
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+`; + +exports[`EuiSuperSelect props more props are propogated to each option 2`] = ` + + + } + className="euiSuperSelect" + closePopover={[Function]} + display="block" + hasArrow={false} + isOpen={true} + ownFocus={false} + panelClassName="euiSuperSelect__popoverPanel" + panelPaddingSize="none" + popoverRef={[Function]} + > + +
+
+ + + +
+
+ + + + Select an option: Option #1, is selected + + + + + +
+ + + + + +
+
+
+
+
+
+
+ + + + +
+ +
+
+
+ + + } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + > + + + } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + /> + + +
+
+ +
+ +

+ + You are in a form selector of 2 items and must select a single option. Use the up and down keys to navigate or escape to close. + +

+
+
+ + + + + + +
+
+
+
+ +
+
+ +
+ + + + +
+ + + +`; + +exports[`EuiSuperSelect props options are rendered when select is open 1`] = ` +
+
+ +
+
+ + Select an option: , is selected + +
+
+
+
+
+
+
+ +
+
+
+`; + +exports[`EuiSuperSelect props select component is rendered 1`] = ` +
+
+ +
+
+ + Select an option: , is selected + +
+
+
+
+`; + +exports[`EuiSuperSelect props valueSelected is rendered 1`] = ` +
+
+ +
+
+ + Select an option: Option #2, is selected + + +
+ + + +
+
+
+
+
+`; diff --git a/src/components/form/super_select/__snapshots__/super_select_control.test.tsx.snap b/src/components/form/super_select/__snapshots__/super_select_control.test.tsx.snap index 6c8d8b9e9e8..7e99f042576 100644 --- a/src/components/form/super_select/__snapshots__/super_select_control.test.tsx.snap +++ b/src/components/form/super_select/__snapshots__/super_select_control.test.tsx.snap @@ -347,3 +347,54 @@ Array [
, ] `; + +exports[`EuiSuperSelectControl props value option is rendered 1`] = ` +Array [ + , +
+
+ + Select an option: Option #1, is selected + + +
+ + + +
+
+
, +] +`; diff --git a/src/components/form/super_select/super_select_control.tsx b/src/components/form/super_select/super_select_control.tsx index 7f015504886..b55b26e815c 100644 --- a/src/components/form/super_select/super_select_control.tsx +++ b/src/components/form/super_select/super_select_control.tsx @@ -67,7 +67,7 @@ export const EuiSuperSelectControl: ( // React HTML input can not have both value and defaultValue properties. // https://reactjs.org/docs/uncontrolled-components.html#default-values - let selectDefaultValue: string | number | string[] = ''; + let selectDefaultValue; if (value == null) { selectDefaultValue = defaultValue || ''; } From de9266fbb9189f5f0ecb62c953b4c90bde3a1d98 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 17 Jan 2020 15:45:53 -0600 Subject: [PATCH 3/6] defaultprop --- .../form/super_select/__snapshots__/super_select.test.tsx.snap | 3 +++ src/components/form/super_select/super_select.tsx | 1 + 2 files changed, 4 insertions(+) diff --git a/src/components/form/super_select/__snapshots__/super_select.test.tsx.snap b/src/components/form/super_select/__snapshots__/super_select.test.tsx.snap index 8977954bc1d..3f251ce1c58 100644 --- a/src/components/form/super_select/__snapshots__/super_select.test.tsx.snap +++ b/src/components/form/super_select/__snapshots__/super_select.test.tsx.snap @@ -497,6 +497,7 @@ exports[`EuiSuperSelect props more props are propogated to each option 2`] = ` fullWidth={false} hasDividers={false} isInvalid={false} + isLoading={false} onChange={[Function]} options={ Array [ @@ -523,6 +524,7 @@ exports[`EuiSuperSelect props more props are propogated to each option 2`] = ` data-test-subj="superSelect" fullWidth={false} isInvalid={false} + isLoading={false} onClick={[Function]} onKeyDown={[Function]} options={ @@ -573,6 +575,7 @@ exports[`EuiSuperSelect props more props are propogated to each option 2`] = ` data-test-subj="superSelect" fullWidth={false} isInvalid={false} + isLoading={false} onClick={[Function]} onKeyDown={[Function]} options={ diff --git a/src/components/form/super_select/super_select.tsx b/src/components/form/super_select/super_select.tsx index 1dcae25d37b..a4bff973153 100644 --- a/src/components/form/super_select/super_select.tsx +++ b/src/components/form/super_select/super_select.tsx @@ -96,6 +96,7 @@ export class EuiSuperSelect extends Component< fullWidth: false, compressed: false, isInvalid: false, + isLoading: false, }; private itemNodes: Array = []; From e2c5b7b59267326265169585fee2fb020edbe0c6 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 17 Jan 2020 16:17:23 -0600 Subject: [PATCH 4/6] CL --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84f29b7b639..8d13f040b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Converted `EuiFilterButton` to TypeScript ([#2761](https://github.com/elastic/eui/pull/2761)) - Converted `EuiFilterSelectItem` to TypeScript ([#2761](https://github.com/elastic/eui/pull/2761)) - Converted `EuiFieldSearch` to TypeScript ([#2775](https://github.com/elastic/eui/pull/2775)) +- Converted `EuiSuperSelect` to TypeScript ([#2776](https://github.com/elastic/eui/pull/2776)) **Bug fixes** From 33b71500b46897c25e78dd78810b42c62675c88f Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 24 Jan 2020 14:30:51 -0600 Subject: [PATCH 5/6] review clean up; use EuiSuperSelectControlProps --- .../form/super_select/super_select.tsx | 40 +++++-------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/components/form/super_select/super_select.tsx b/src/components/form/super_select/super_select.tsx index a4bff973153..ca1766d116b 100644 --- a/src/components/form/super_select/super_select.tsx +++ b/src/components/form/super_select/super_select.tsx @@ -1,4 +1,4 @@ -import React, { Component, ButtonHTMLAttributes } from 'react'; +import React, { Component } from 'react'; import classNames from 'classnames'; import { CommonProps } from '../../common'; @@ -6,6 +6,7 @@ import { CommonProps } from '../../common'; import { EuiScreenReaderOnly } from '../../accessibility'; import { EuiSuperSelectControl, + EuiSuperSelectControlProps, EuiSuperSelectOption, } from './super_select_control'; import { EuiPopover } from '../../popover'; @@ -21,11 +22,8 @@ enum ShiftDirection { FORWARD = 'forward', } -const SHIFT_BACK = ShiftDirection.BACK as const; -const SHIFT_FORWARD = ShiftDirection.FORWARD as const; - export type EuiSuperSelectProps = CommonProps & - Omit, 'onChange' | 'value'> & { + Omit, 'onClick' | 'options' | 'value'> & { /** * Pass an array of options that must at least include: * `value`: storing unique value of item, @@ -57,26 +55,6 @@ export type EuiSuperSelectProps = CommonProps & */ itemLayoutAlign?: EuiContextMenuItemLayoutAlignment; - /** - * Make it wide. Default: false - */ - fullWidth?: boolean; - - /** - * Provides invalid styling. Default: false - */ - isInvalid?: boolean; - - /** - * Provides a loading indicator. Default: false - */ - isLoading?: boolean; - - /** - * Make it short. Default: false - */ - compressed?: boolean; - /** * Applied to the outermost wrapper (popover) */ @@ -130,8 +108,8 @@ export class EuiSuperSelect extends Component< }); const focusSelected = () => { - const indexOfSelected: number | null = this.props.options.reduce( - (indexOfSelected: number | null, option, index) => { + const indexOfSelected = this.props.options.reduce( + (indexOfSelected, option, index) => { if (indexOfSelected != null) return indexOfSelected; if (option == null) return null; return option.value === this.props.valueOfSelected ? index : null; @@ -151,7 +129,7 @@ export class EuiSuperSelect extends Component< if (this.props.valueOfSelected != null) { if (indexOfSelected != null) { - this.focusItemAt(indexOfSelected as number); + this.focusItemAt(indexOfSelected); } else { focusSelected(); } @@ -203,13 +181,13 @@ export class EuiSuperSelect extends Component< case keyCodes.UP: e.preventDefault(); e.stopPropagation(); - this.shiftFocus(SHIFT_BACK); + this.shiftFocus(ShiftDirection.BACK); break; case keyCodes.DOWN: e.preventDefault(); e.stopPropagation(); - this.shiftFocus(SHIFT_FORWARD); + this.shiftFocus(ShiftDirection.FORWARD); break; } }; @@ -231,7 +209,7 @@ export class EuiSuperSelect extends Component< // somehow the select options has lost focus targetElementIndex = 0; } else { - if (direction === SHIFT_BACK) { + if (direction === ShiftDirection.BACK) { targetElementIndex = currentIndex === 0 ? this.itemNodes.length - 1 : currentIndex - 1; } else { From eac817f009657936cd5547b417c1cb8a63d49dbe Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 24 Jan 2020 14:40:00 -0600 Subject: [PATCH 6/6] omit onChange --- src/components/form/super_select/super_select.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/form/super_select/super_select.tsx b/src/components/form/super_select/super_select.tsx index ca1766d116b..4f8077e680f 100644 --- a/src/components/form/super_select/super_select.tsx +++ b/src/components/form/super_select/super_select.tsx @@ -23,7 +23,10 @@ enum ShiftDirection { } export type EuiSuperSelectProps = CommonProps & - Omit, 'onClick' | 'options' | 'value'> & { + Omit< + EuiSuperSelectControlProps, + 'onChange' | 'onClick' | 'options' | 'value' + > & { /** * Pass an array of options that must at least include: * `value`: storing unique value of item,