From 20047ac37a2a258795efa9cadffa0854437fb94f Mon Sep 17 00:00:00 2001 From: Theo Date: Mon, 15 Apr 2019 20:41:19 +0100 Subject: [PATCH] `matching_options` code review fixes for `EuiComboBoxOptionProps` --- src/components/combo_box/index.d.ts | 119 ++++++++++-------- .../combo_box/matching_options.test.ts | 14 +-- src/components/combo_box/matching_options.ts | 34 ++--- 3 files changed, 90 insertions(+), 77 deletions(-) diff --git a/src/components/combo_box/index.d.ts b/src/components/combo_box/index.d.ts index 25dd0b601df..76aa5733580 100644 --- a/src/components/combo_box/index.d.ts +++ b/src/components/combo_box/index.d.ts @@ -6,73 +6,84 @@ import { EuiComboBoxOptionsListPosition, EuiComboBoxOptionsListProps, } from '@elastic/eui'; -import { RefCallback } from '../common'; +import { RefCallback, CommonProps } from '../common'; declare module '@elastic/eui' { - export type EuiComboBoxOptionProps = ButtonHTMLAttributes & { - label: string, - isGroupLabelOption?: boolean, - } + export type EuiComboBoxOptionProps = CommonProps & + ButtonHTMLAttributes & { + label: string; + isGroupLabelOption?: boolean; + options?: EuiComboBoxOptionProps[]; + }; - export type EuiComboBoxOptionsListPosition = 'top' | 'bottom' + export type EuiComboBoxOptionsListPosition = 'top' | 'bottom'; export interface EuiComboBoxOption { - option: EuiComboBoxOptionProps, - children?: ReactNode, - className?: string, - optionRef?: RefCallback, - onClick: (option: EuiComboBoxOptionProps) => any, - onEnterKey: (option: EuiComboBoxOptionProps) => any, - disabled?: boolean, + option: EuiComboBoxOptionProps; + children?: ReactNode; + className?: string; + optionRef?: RefCallback; + onClick: (option: EuiComboBoxOptionProps) => any; + onEnterKey: (option: EuiComboBoxOptionProps) => any; + disabled?: boolean; } export interface EuiComboBoxOptionsListProps { - options?: Array, - isLoading?: boolean, - selectedOptions?: Array, - onCreateOption?: any, - searchValue?: string, - matchingOptions?: Array, - optionRef?: EuiComboBoxOption['optionRef'], - onOptionClick?: EuiComboBoxOption['onClick'], - onOptionEnterKey?: EuiComboBoxOption['onEnterKey'], - areAllOptionsSelected?: boolean, - getSelectedOptionForSearchValue?: (searchValue: string, selectedOptions: Array) => EuiComboBoxOptionProps, - updatePosition: (parameter?: UIEvent | EuiPanelProps['panelRef']) => any, - position?: EuiComboBoxOptionsListPosition, - listRef: EuiPanelProps['panelRef'], - renderOption?: (option: EuiComboBoxOptionProps, searchValue: string, OPTION_CONTENT_CLASSNAME: string) => ReactNode, - width?: number, - scrollToIndex?: number, - onScroll?: ListProps['onScroll'], - rowHeight?: number, - fullWidth?: boolean, + options?: EuiComboBoxOptionProps[]; + isLoading?: boolean; + selectedOptions?: any[]; + onCreateOption?: any; + searchValue?: string; + matchingOptions?: EuiComboBoxOptionProps[]; + optionRef?: EuiComboBoxOption['optionRef']; + onOptionClick?: EuiComboBoxOption['onClick']; + onOptionEnterKey?: EuiComboBoxOption['onEnterKey']; + areAllOptionsSelected?: boolean; + getSelectedOptionForSearchValue?: ( + searchValue: string, + selectedOptions: any[] + ) => EuiComboBoxOptionProps; + updatePosition: (parameter?: UIEvent | EuiPanelProps['panelRef']) => any; + position?: EuiComboBoxOptionsListPosition; + listRef: EuiPanelProps['panelRef']; + renderOption?: ( + option: EuiComboBoxOptionProps, + searchValue: string, + OPTION_CONTENT_CLASSNAME: string + ) => ReactNode; + width?: number; + scrollToIndex?: number; + onScroll?: ListProps['onScroll']; + rowHeight?: number; + fullWidth?: boolean; } - export const EuiComboBoxOptionsList: FunctionComponent; + export const EuiComboBoxOptionsList: FunctionComponent< + EuiComboBoxOptionsListProps + >; export type EuiComboBoxSingleSelectionShape = { asPlainText?: boolean; }; export interface EuiComboBoxProps { - id?: string, - isDisabled?: boolean, - className?: string, - placeholder?: string, - isLoading?: boolean, - async?: boolean, - singleSelection?: EuiComboBoxSingleSelectionShape | boolean, - noSuggestions?: boolean, - options?: EuiComboBoxOptionsListProps['options'], - selectedOptions?: EuiComboBoxOptionsListProps['selectedOptions'], - onBlur?: FocusEventHandler, - onChange?: (options: Array) => any, - onFocus?: FocusEventHandler, - onSearchChange?: (searchValue: string) => any, - onCreateOption?: EuiComboBoxOptionsListProps['onCreateOption'], - renderOption?: EuiComboBoxOptionsListProps['renderOption'], - isInvalid?: boolean, - rowHeight?: number, - isClearable?: boolean, - fullWidth?: boolean, + id?: string; + isDisabled?: boolean; + className?: string; + placeholder?: string; + isLoading?: boolean; + async?: boolean; + singleSelection?: EuiComboBoxSingleSelectionShape | boolean; + noSuggestions?: boolean; + options?: EuiComboBoxOptionsListProps['options']; + selectedOptions?: EuiComboBoxOptionsListProps['selectedOptions']; + onBlur?: FocusEventHandler; + onChange?: (options: Array) => any; + onFocus?: FocusEventHandler; + onSearchChange?: (searchValue: string) => any; + onCreateOption?: EuiComboBoxOptionsListProps['onCreateOption']; + renderOption?: EuiComboBoxOptionsListProps['renderOption']; + isInvalid?: boolean; + rowHeight?: number; + isClearable?: boolean; + fullWidth?: boolean; inputRef?: (element: HTMLInputElement) => void; } export const EuiComboBox: FunctionComponent; diff --git a/src/components/combo_box/matching_options.test.ts b/src/components/combo_box/matching_options.test.ts index a4117425411..09ff2c77e7e 100644 --- a/src/components/combo_box/matching_options.test.ts +++ b/src/components/combo_box/matching_options.test.ts @@ -1,11 +1,11 @@ +import { EuiComboBoxOptionProps } from '@elastic/eui'; import { - EuiComboBoxOption, flattenOptionGroups, getSelectedOptionForSearchValue, getMatchingOptions, } from './matching_options'; -const options: EuiComboBoxOption[] = [ +const options: EuiComboBoxOptionProps[] = [ { label: 'Titan', 'data-test-subj': 'titanOption', @@ -51,7 +51,7 @@ describe('flattenOptionGroups', () => { describe('getSelectedOptionForSearchValue', () => { test('gets the first matching selected option for search value', () => { // Assemble - const expected: EuiComboBoxOption = { + const expected: EuiComboBoxOptionProps = { label: 'Saturn', 'data-test-subj': 'saturnOption', }; @@ -71,7 +71,7 @@ describe('getSelectedOptionForSearchValue', () => { }); test('gets the first matching selected option for search value', () => { // Assemble - const expected: EuiComboBoxOption = { + const expected: EuiComboBoxOptionProps = { label: 'Saturn', 'data-test-subj': 'saturnOption', }; @@ -83,12 +83,12 @@ describe('getSelectedOptionForSearchValue', () => { }); interface GetMatchingOptionsTestCase { - options: EuiComboBoxOption[]; - selectedOptions: EuiComboBoxOption[]; + options: EuiComboBoxOptionProps[]; + selectedOptions: EuiComboBoxOptionProps[]; searchValue: string; isPreFiltered: boolean; showPrevSelected: boolean; - expected: EuiComboBoxOption[]; + expected: EuiComboBoxOptionProps[]; } const testCases: GetMatchingOptionsTestCase[] = [ diff --git a/src/components/combo_box/matching_options.ts b/src/components/combo_box/matching_options.ts index 535c7d5fcc4..5dbd44b5f31 100644 --- a/src/components/combo_box/matching_options.ts +++ b/src/components/combo_box/matching_options.ts @@ -1,11 +1,13 @@ -export interface EuiComboBoxOption { - label: string; - [prop: string]: any; -} +import { EuiComboBoxOptionProps } from '@elastic/eui'; -export const flattenOptionGroups = (optionsOrGroups: EuiComboBoxOption[]) => { +export const flattenOptionGroups = ( + optionsOrGroups: EuiComboBoxOptionProps[] +) => { return optionsOrGroups.reduce( - (options: EuiComboBoxOption[], optionOrGroup: EuiComboBoxOption) => { + ( + options: EuiComboBoxOptionProps[], + optionOrGroup: EuiComboBoxOptionProps + ) => { if (optionOrGroup.options) { options.push(...optionOrGroup.options); } else { @@ -19,18 +21,18 @@ export const flattenOptionGroups = (optionsOrGroups: EuiComboBoxOption[]) => { export const getSelectedOptionForSearchValue = ( searchValue: string, - selectedOptions: EuiComboBoxOption[] + selectedOptions: EuiComboBoxOptionProps[] ) => { const normalizedSearchValue = searchValue.toLowerCase(); return selectedOptions.find( - (option: any) => option.label.toLowerCase() === normalizedSearchValue + option => option.label.toLowerCase() === normalizedSearchValue ); }; const collectMatchingOption = ( - accumulator: EuiComboBoxOption[], - option: EuiComboBoxOption, - selectedOptions: EuiComboBoxOption[], + accumulator: EuiComboBoxOptionProps[], + option: EuiComboBoxOptionProps, + selectedOptions: EuiComboBoxOptionProps[], normalizedSearchValue: string, isPreFiltered: boolean, showPrevSelected: boolean @@ -62,19 +64,19 @@ const collectMatchingOption = ( }; export const getMatchingOptions = ( - options: EuiComboBoxOption[], - selectedOptions: EuiComboBoxOption[], + options: EuiComboBoxOptionProps[], + selectedOptions: EuiComboBoxOptionProps[], searchValue: string, isPreFiltered: boolean, showPrevSelected: boolean ) => { const normalizedSearchValue = searchValue.trim().toLowerCase(); - const matchingOptions: EuiComboBoxOption[] = []; + const matchingOptions: EuiComboBoxOptionProps[] = []; options.forEach(option => { if (option.options) { - const matchingOptionsForGroup: EuiComboBoxOption[] = []; - option.options.forEach((groupOption: EuiComboBoxOption) => { + const matchingOptionsForGroup: EuiComboBoxOptionProps[] = []; + option.options.forEach((groupOption: EuiComboBoxOptionProps) => { collectMatchingOption( matchingOptionsForGroup, groupOption,