diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/address-form.tsx b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/address-form.tsx index 0d425371a49..84b45a8df64 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/address-form.tsx +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/address-form.tsx @@ -112,6 +112,18 @@ const AddressForm = ( { ); }, [ currentFields, fieldConfig, values.country ] ); + // Clear values for hidden fields. + useEffect( () => { + addressFormFields.forEach( ( field ) => { + if ( field.hidden && values[ field.key ] ) { + onChange( { + ...values, + [ field.key ]: '', + } ); + } + } ); + }, [ addressFormFields, onChange, values ] ); + useEffect( () => { if ( type === 'shipping' ) { validateShippingCountry( @@ -161,8 +173,6 @@ const AddressForm = ( { ...values, country: newValue, state: '', - city: '', - postcode: '', } ) } errorId={ diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/test/index.js b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/test/index.js index 975611cb6d0..252dc376722 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/test/index.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/address-form/test/index.js @@ -21,7 +21,7 @@ const renderInCheckoutProvider = ( ui, options = {} ) => { // Countries used in testing addresses must be in the wcSettings global. // See: tests/js/setup-globals.js const primaryAddress = { - country: 'United Kingdom (UK)', + country: 'United Kingdom', countryKey: 'GB', city: 'London', state: 'Greater London', @@ -46,25 +46,22 @@ const cityRegExp = /city/i; const stateRegExp = /county|province|state/i; const postalCodeRegExp = /postal code|postcode|zip/i; -const inputAddress = ( { +const inputAddress = async ( { country = null, city = null, state = null, postcode = null, } ) => { if ( country ) { - const countryButton = screen.getByRole( 'button', { - name: countryRegExp, - } ); - userEvent.click( countryButton ); - userEvent.click( screen.getByRole( 'option', { name: country } ) ); + const countryInput = screen.getByLabelText( countryRegExp ); + userEvent.type( countryInput, country + '{arrowdown}{enter}' ); } if ( city ) { const cityInput = screen.getByLabelText( cityRegExp ); userEvent.type( cityInput, city ); } if ( state ) { - const stateButton = screen.queryByRole( 'button', { + const stateButton = screen.queryByRole( 'combobox', { name: stateRegExp, } ); // State input might be a select or a text input. @@ -162,17 +159,11 @@ describe( 'AddressForm Component', () => { inputAddress( secondaryAddress ); // Only update `country` to verify other values are reset. inputAddress( { country: primaryAddress.country } ); - - expect( screen.getByLabelText( cityRegExp ).value ).toBe( '' ); expect( screen.getByLabelText( stateRegExp ).value ).toBe( '' ); - expect( screen.getByLabelText( postalCodeRegExp ).value ).toBe( '' ); // Repeat the test with an address which has a select for the state. inputAddress( tertiaryAddress ); inputAddress( { country: primaryAddress.country } ); - - expect( screen.getByLabelText( cityRegExp ).value ).toBe( '' ); expect( screen.getByLabelText( stateRegExp ).value ).toBe( '' ); - expect( screen.getByLabelText( postalCodeRegExp ).value ).toBe( '' ); } ); } ); diff --git a/plugins/woocommerce-blocks/assets/js/base/components/combobox/index.tsx b/plugins/woocommerce-blocks/assets/js/base/components/combobox/index.tsx new file mode 100644 index 00000000000..144ef7fb249 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/combobox/index.tsx @@ -0,0 +1,150 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; +import { __ } from '@wordpress/i18n'; +import { useEffect, useRef } from '@wordpress/element'; +import { withInstanceId } from '@wordpress/compose'; +import { ComboboxControl } from 'wordpress-components'; +import { + ValidationInputError, + useValidationContext, +} from '@woocommerce/base-context'; +import { isObject } from '@woocommerce/types'; + +/** + * Internal dependencies + */ +import './style.scss'; + +export interface ComboboxControlOption { + label: string; + value: string; +} + +/** + * Wrapper for the WordPress ComboboxControl which supports validation. + */ +const Combobox = ( { + id, + className, + label, + onChange, + options, + value, + required = false, + errorMessage = __( + 'Please select a value.', + 'woo-gutenberg-products-block' + ), + errorId: incomingErrorId, + instanceId = '0', + autoComplete = 'off', +}: { + id: string; + className: string; + label: string; + onChange: ( filterValue: string ) => void; + options: ComboboxControlOption[]; + value: string; + required: boolean; + errorMessage: string; + errorId: string; + instanceId: string; + autoComplete: string; +} ): JSX.Element => { + const { + getValidationError, + setValidationErrors, + clearValidationError, + } = useValidationContext(); + + const controlRef = useRef< HTMLDivElement >( null ); + const controlId = id || 'control-' + instanceId; + const errorId = incomingErrorId || controlId; + const error = ( getValidationError( errorId ) || { + message: '', + hidden: false, + } ) as { + message: string; + hidden: boolean; + }; + + useEffect( () => { + if ( ! required || value ) { + clearValidationError( errorId ); + } else { + setValidationErrors( { + [ errorId ]: { + message: errorMessage, + hidden: true, + }, + } ); + } + return () => { + clearValidationError( errorId ); + }; + }, [ + clearValidationError, + value, + errorId, + errorMessage, + required, + setValidationErrors, + ] ); + + // @todo Remove patch for ComboboxControl once https://github.com/WordPress/gutenberg/pull/33928 is released + return ( +
+ { + if ( filterValue.length ) { + // If we have a value and the combobox is not focussed, this could be from browser autofill. + const activeElement = isObject( controlRef.current ) + ? controlRef.current.ownerDocument.activeElement + : undefined; + + if ( + activeElement && + isObject( controlRef.current ) && + controlRef.current.contains( activeElement ) + ) { + return; + } + + // Try to match. + const normalizedFilterValue = filterValue.toLocaleUpperCase(); + const foundOption = options.find( + ( option ) => + option.label + .toLocaleUpperCase() + .startsWith( normalizedFilterValue ) || + option.value.toLocaleUpperCase() === + normalizedFilterValue + ); + if ( foundOption ) { + onChange( foundOption.value ); + } + } + } } + options={ options } + value={ value || '' } + allowReset={ false } + autoComplete={ autoComplete } + /> + +
+ ); +}; + +export default withInstanceId( Combobox ); diff --git a/plugins/woocommerce-blocks/assets/js/base/components/combobox/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/combobox/style.scss new file mode 100644 index 00000000000..83a5d175bde --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/base/components/combobox/style.scss @@ -0,0 +1,156 @@ +.wc-block-components-form .wc-block-components-combobox, +.wc-block-components-combobox { + .wc-block-components-combobox-control { + @include reset-typography(); + @include reset-box(); + + .components-base-control__field { + @include reset-box(); + } + .components-combobox-control__suggestions-container { + @include reset-typography(); + @include reset-box(); + position: relative; + } + input.components-combobox-control__input { + @include reset-typography(); + @include font-size(regular); + + box-sizing: border-box; + outline: inherit; + border: 1px solid $input-border-gray; + background: #fff; + box-shadow: none; + color: $input-text-active; + font-family: inherit; + font-weight: normal; + height: 3em; + letter-spacing: inherit; + line-height: 1; + padding: em($gap-large) $gap em($gap-smallest); + text-align: left; + text-overflow: ellipsis; + text-transform: none; + white-space: nowrap; + width: 100%; + opacity: initial; + border-radius: 4px; + + &[aria-expanded="true"], + &:focus { + background-color: #fff; + color: $input-text-active; + } + + &[aria-expanded="true"] { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + + .has-dark-controls & { + background-color: $input-background-dark; + border-color: $input-border-dark; + color: $input-text-dark; + + &:focus { + background-color: $input-background-dark; + color: $input-text-dark; + } + } + } + .components-form-token-field__suggestions-list { + position: absolute; + z-index: 10; + background-color: $select-dropdown-light; + border: 1px solid $input-border-gray; + border-top: 0; + margin: 3em 0 0 0; + padding: 0; + max-height: 300px; + min-width: 100%; + overflow: auto; + color: $input-text-active; + + .has-dark-controls & { + background-color: $select-dropdown-dark; + color: $input-text-dark; + } + + .components-form-token-field__suggestion { + @include font-size(regular); + color: $gray-700; + cursor: default; + list-style: none; + margin: 0; + padding: em($gap-smallest) $gap; + + &.is-selected { + background-color: $gray-300; + .has-dark-controls & { + background-color: $select-item-dark; + } + } + + &:hover, + &:focus, + &.is-highlighted, + &:active { + background-color: #00669e; + color: #fff; + + } + } + } + + label.components-base-control__label { + @include reset-typography(); + @include font-size(regular); + line-height: 1.375; // =22px when font-size is 16px. + position: absolute; + transform: translateY(0.75em); + transform-origin: top left; + transition: all 200ms ease; + color: $gray-700; + z-index: 1; + margin: 0 0 0 #{$gap + 1px}; + overflow: hidden; + text-overflow: ellipsis; + max-width: calc(100% - #{2 * $gap}); + white-space: nowrap; + + .has-dark-controls & { + color: $input-placeholder-dark; + } + @media screen and (prefers-reduced-motion: reduce) { + transition: none; + } + } + } + + &.is-active, + &:focus-within { + .wc-block-components-combobox-control label.components-base-control__label { + transform: translateY(#{$gap-smallest}) scale(0.75); + } + } + + &.has-error { + .wc-block-components-combobox-control { + label.components-base-control__label { + color: $alert-red; + } + input.components-combobox-control__input { + &, + &:hover, + &:focus, + &:active { + border-color: $alert-red; + } + &:focus { + outline: 1px dotted $alert-red; + outline-offset: 2px; + } + } + } + } +} diff --git a/plugins/woocommerce-blocks/assets/js/base/components/country-input/country-input.tsx b/plugins/woocommerce-blocks/assets/js/base/components/country-input/country-input.tsx index d8f8486d2ed..d8eba8a8e6e 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/country-input/country-input.tsx +++ b/plugins/woocommerce-blocks/assets/js/base/components/country-input/country-input.tsx @@ -9,7 +9,7 @@ import classnames from 'classnames'; /** * Internal dependencies */ -import { ValidatedSelect } from '../select'; +import Combobox from '../combobox'; import './style.scss'; import type { CountryInputWithCountriesProps } from './CountryInputProps'; @@ -31,8 +31,8 @@ const CountryInput = ( { const options = useMemo( () => Object.keys( countries ).map( ( key ) => ( { - key, - name: decodeEntities( countries[ key ] ), + value: key, + label: decodeEntities( countries[ key ] ), } ) ), [ countries ] ); @@ -44,15 +44,16 @@ const CountryInput = ( { 'wc-block-components-country-input' ) } > - option.key === value ) } + value={ value } errorId={ errorId } errorMessage={ errorMessage } required={ required } + autoComplete={ autoComplete } /> { autoComplete !== 'off' && ( { - const textValue = event.target.value; + const textValue = event.target.value.toLocaleUpperCase(); const foundOption = options.find( - ( option ) => option.key === textValue + ( option ) => + ( textValue.length !== 2 && + option.label.toLocaleUpperCase() === + textValue ) || + ( textValue.length === 2 && + option.value.toLocaleUpperCase() === + textValue ) ); - onChange( foundOption ? foundOption.key : '' ); + onChange( foundOption ? foundOption.value : '' ); } } style={ { minHeight: '0', diff --git a/plugins/woocommerce-blocks/assets/js/base/components/select/index.js b/plugins/woocommerce-blocks/assets/js/base/components/select/index.js deleted file mode 100644 index 1fff441e2ac..00000000000 --- a/plugins/woocommerce-blocks/assets/js/base/components/select/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Select } from './select'; -export { default as ValidatedSelect } from './validated'; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/select/select.js b/plugins/woocommerce-blocks/assets/js/base/components/select/select.js deleted file mode 100644 index 75cff2e0dd8..00000000000 --- a/plugins/woocommerce-blocks/assets/js/base/components/select/select.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; -import classnames from 'classnames'; -import { CustomSelectControl } from 'wordpress-components'; - -/** - * Internal dependencies - */ -import './style.scss'; - -const Select = ( { - className, - feedback, - id, - label, - onChange, - options, - value, -} ) => { - return ( -
- { - onChange( selectedItem.key ); - } } - options={ options } - value={ value || null } - /> - { feedback } -
- ); -}; - -Select.propTypes = { - onChange: PropTypes.func.isRequired, - options: PropTypes.arrayOf( - PropTypes.shape( { - key: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - } ).isRequired - ).isRequired, - className: PropTypes.string, - feedback: PropTypes.node, - id: PropTypes.string, - label: PropTypes.string, - value: PropTypes.shape( { - key: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - } ), -}; - -export default Select; diff --git a/plugins/woocommerce-blocks/assets/js/base/components/select/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/select/style.scss deleted file mode 100644 index 0514754d5d6..00000000000 --- a/plugins/woocommerce-blocks/assets/js/base/components/select/style.scss +++ /dev/null @@ -1,162 +0,0 @@ -.wc-block-components-form .wc-block-components-select, -.wc-block-components-select { - height: 3em; - position: relative; - - label.components-custom-select-control__label { - @include reset-typography(); - @include font-size(regular); - line-height: 1.375; // =22px when font-size is 16px. - position: absolute; - transform: translateY(0.75em); - transform-origin: top left; - transition: all 200ms ease; - color: $gray-700; - z-index: 1; - margin: 0 0 0 #{$gap + 1px}; - overflow: hidden; - text-overflow: ellipsis; - max-width: calc(100% - #{2 * $gap}); - white-space: nowrap; - - .has-dark-controls & { - color: $input-placeholder-dark; - } - @media screen and (prefers-reduced-motion: reduce) { - transition: none; - } - } - - &.is-active label { - transform: translateY(#{$gap-smallest}) scale(0.75); - } - - &.has-error { - .components-custom-select-control__button { - &, - &:hover, - &:focus, - &:active { - border-color: $alert-red; - } - &:focus { - outline: 1px dotted $alert-red; - outline-offset: 2px; - } - } - } - - &.has-error label { - color: $alert-red; - } - - .components-custom-select-control__button { - &, - &:hover, - &:focus, - &:active { - @include font-size(regular); - background: #fff; - box-shadow: none; - color: $input-text-active; - font-family: inherit; - font-weight: normal; - height: 3em; - letter-spacing: inherit; - line-height: 1; - overflow: hidden; - padding: em($gap-large) $gap em($gap-smallest); - text-align: left; - text-overflow: ellipsis; - text-transform: none; - white-space: nowrap; - width: 100%; - opacity: initial; - border-radius: 4px; - .has-dark-controls & { - background: $input-background-dark; - border-color: $input-border-dark; - color: $input-text-dark; - } - } - } - - .components-custom-select-control__button-icon { - right: #{$gap - 4px}; - .has-dark-controls & { - fill: $input-text-dark; - } - } - - .components-custom-select-control__menu { - background-color: $select-dropdown-light; - margin: 0; - max-height: 300px; - overflow: auto; - color: $input-text-active; - - // Required by IE11. - &:empty { - display: none; - } - .has-dark-controls & { - background-color: $select-dropdown-dark; - color: $input-text-dark; - } - } - - .components-custom-select-control__item { - @include font-size(regular); - margin-left: 0; - padding-left: $gap; - &:hover, - &:focus, - &.is-highlighted { - .has-dark-controls & { - background-color: $select-item-dark; - } - } - } - - .components-custom-select-control__item-icon { - display: none; - } -} - -.theme-twentytwentyone { - // Extra classes for specificity. - &.theme-twentytwentyone.theme-twentytwentyone .components-custom-select-control__button { - background-color: #fff; - color: $input-text-active; - } - - &.is-dark-theme { - // If the theme is in dark mode, as well as the block, then this selector will match. - .has-dark-controls { - .components-custom-select-control__item { - color: $input-text-dark; - } - } - - // If the theme is in dark mode, but the block isn't, then this selector will match. - .components-custom-select-control__item { - color: $input-text-active; - } - } -} - -.theme-twentyseventeen { - // Extra classes for specificity. - &.theme-twentyseventeen.theme-twentyseventeen { - .components-custom-select-control__button { - background-color: $select-dropdown-light; - color: $input-text-active; - } - .has-dark-controls { - .components-custom-select-control__button { - background-color: $select-dropdown-dark; - color: $input-text-dark; - } - } - } -} diff --git a/plugins/woocommerce-blocks/assets/js/base/components/select/validated.js b/plugins/woocommerce-blocks/assets/js/base/components/select/validated.js deleted file mode 100644 index 22c8bcbb34d..00000000000 --- a/plugins/woocommerce-blocks/assets/js/base/components/select/validated.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * External dependencies - */ -import { __ } from '@wordpress/i18n'; -import { useEffect } from 'react'; -import { useShallowEqual } from '@woocommerce/base-hooks'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; -import { withInstanceId } from '@wordpress/compose'; -import { - ValidationInputError, - useValidationContext, -} from '@woocommerce/base-context'; - -/** - * Internal dependencies - */ -import Select from './select'; -import './style.scss'; - -const ValidatedSelect = ( { - className, - id, - value, - instanceId, - required, - errorId, - errorMessage = __( - 'Please select a value.', - 'woo-gutenberg-products-block' - ), - ...rest -} ) => { - const selectId = id || 'select-' + instanceId; - errorId = errorId || selectId; - - // Prevents re-renders when value is an object, e.g. {key: "NY", name: "New York"} - const currentValue = useShallowEqual( value ); - - const { - getValidationError, - setValidationErrors, - clearValidationError, - } = useValidationContext(); - - useEffect( () => { - if ( ! required || currentValue ) { - clearValidationError( errorId ); - } else { - setValidationErrors( { - [ errorId ]: { - message: errorMessage, - hidden: true, - }, - } ); - } - }, [ - clearValidationError, - currentValue, - errorId, - errorMessage, - required, - setValidationErrors, - ] ); - - // Remove validation errors when unmounted. - useEffect( () => { - return () => { - clearValidationError( errorId ); - }; - }, [ clearValidationError, errorId ] ); - - const error = getValidationError( errorId ) || {}; - - return ( - option.value === value); ++ const currentLabel = (_currentOption$label = currentOption === null || currentOption === void 0 ? void 0 : currentOption.label) !== null && _currentOption$label !== void 0 ? _currentOption$label : ''; ++ const instanceId = useInstanceId(ComboboxControl); ++ const [selectedSuggestion, setSelectedSuggestion] = useState(currentOption || null); ++ const [isExpanded, setIsExpanded] = useState(false); ++ const [inputValue, setInputValue] = useState(''); ++ const inputContainer = useRef(); ++ const matchingSuggestions = useMemo(() => { ++ const startsWithMatch = []; ++ const containsMatch = []; ++ const match = deburr(inputValue.toLocaleLowerCase()); ++ options.forEach(option => { ++ const index = deburr(option.label).toLocaleLowerCase().indexOf(match); + + if (index === 0) { + startsWithMatch.push(option); +@@ -115,7 +75,7 @@ function ComboboxControl(_ref) { + return startsWithMatch.concat(containsMatch); + }, [inputValue, options, value]); + +- var onSuggestionSelected = function onSuggestionSelected(newSelectedSuggestion) { ++ const onSuggestionSelected = newSelectedSuggestion => { + onChange(newSelectedSuggestion.value); + speak(messages.selected, 'assertive'); + setSelectedSuggestion(newSelectedSuggestion); +@@ -123,10 +83,9 @@ function ComboboxControl(_ref) { + setIsExpanded(false); + }; + +- var handleArrowNavigation = function handleArrowNavigation() { +- var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; +- var index = matchingSuggestions.indexOf(selectedSuggestion); +- var nextIndex = index + offset; ++ const handleArrowNavigation = (offset = 1) => { ++ const index = matchingSuggestions.indexOf(selectedSuggestion); ++ let nextIndex = index + offset; + + if (nextIndex < 0) { + nextIndex = matchingSuggestions.length - 1; +@@ -138,8 +97,12 @@ function ComboboxControl(_ref) { + setIsExpanded(true); + }; + +- var onKeyDown = function onKeyDown(event) { +- var preventDefault = false; ++ const onKeyDown = event => { ++ let preventDefault = false; ++ ++ if (event.defaultPrevented) { ++ return; ++ } + + switch (event.keyCode) { + case ENTER: +@@ -164,7 +127,6 @@ function ComboboxControl(_ref) { + setIsExpanded(false); + setSelectedSuggestion(null); + preventDefault = true; +- event.stopPropagation(); + break; + + default: +@@ -176,34 +138,44 @@ function ComboboxControl(_ref) { + } + }; + +- var onFocus = function onFocus() { ++ const onFocus = () => { + setIsExpanded(true); + onFilterValueChange(''); + setInputValue(''); + }; + +- var onFocusOutside = function onFocusOutside() { ++ const onFocusOutside = () => { + setIsExpanded(false); + }; + +- var onInputChange = function onInputChange(event) { +- var text = event.value; ++ const onInputChange = event => { ++ const text = event.value; + setInputValue(text); + onFilterValueChange(text); + setIsExpanded(true); + }; + +- var handleOnReset = function handleOnReset() { ++ const handleOnReset = () => { + onChange(null); + inputContainer.current.input.focus(); +- }; // Announcements ++ }; // Update current selections when the filter input changes. + + +- useEffect(function () { +- var hasMatchingSuggestions = matchingSuggestions.length > 0; ++ useEffect(() => { ++ const hasMatchingSuggestions = matchingSuggestions.length > 0; ++ const hasSelectedMatchingSuggestions = matchingSuggestions.indexOf(selectedSuggestion) > 0; ++ ++ if (hasMatchingSuggestions && !hasSelectedMatchingSuggestions) { ++ // If the current selection isn't present in the list of suggestions, then automatically select the first item from the list of suggestions. ++ setSelectedSuggestion(matchingSuggestions[0]); ++ } ++ }, [matchingSuggestions, selectedSuggestion]); // Announcements ++ ++ useEffect(() => { ++ const hasMatchingSuggestions = matchingSuggestions.length > 0; + + if (isExpanded) { +- var message = hasMatchingSuggestions ? sprintf( ++ const message = hasMatchingSuggestions ? sprintf( + /* translators: %d: number of results. */ + _n('%d result found, use up and down arrow keys to navigate.', '%d results found, use up and down arrow keys to navigate.', matchingSuggestions.length), matchingSuggestions.length) : __('No results.'); + speak(message, 'polite'); +@@ -220,7 +192,7 @@ function ComboboxControl(_ref) { + className: classnames(className, 'components-combobox-control'), + tabIndex: "-1", + label: label, +- id: "components-form-token-input-".concat(instanceId), ++ id: `components-form-token-input-${instanceId}`, + hideLabelFromVision: hideLabelFromVision, + help: help + }, createElement("div", { +@@ -232,7 +204,7 @@ function ComboboxControl(_ref) { + instanceId: instanceId, + ref: inputContainer, + value: isExpanded ? inputValue : currentLabel, +- "aria-label": currentLabel ? "".concat(currentLabel, ", ").concat(label) : null, ++ "aria-label": currentLabel ? `${currentLabel}, ${label}` : null, + onFocus: onFocus, + isExpanded: isExpanded, + selectedSuggestionIndex: matchingSuggestions.indexOf(selectedSuggestion), +@@ -248,9 +220,7 @@ function ComboboxControl(_ref) { + match: { + label: inputValue + }, +- displayTransform: function displayTransform(suggestion) { +- return suggestion.label; +- }, ++ displayTransform: suggestion => suggestion.label, + suggestions: matchingSuggestions, + selectedIndex: matchingSuggestions.indexOf(selectedSuggestion), + onHover: setSelectedSuggestion,