diff --git a/.changeset/plenty-snails-draw.md b/.changeset/plenty-snails-draw.md
new file mode 100644
index 0000000000..cf206f8d61
--- /dev/null
+++ b/.changeset/plenty-snails-draw.md
@@ -0,0 +1,6 @@
+---
+'@commercetools-uikit/selectable-search-input': minor
+---
+
+We're introducing a **temporary** property to handle an internal case.
+Please do not use it as it will be removed in the near future.
diff --git a/packages/components/inputs/selectable-search-input/src/selectable-search-input.spec.tsx b/packages/components/inputs/selectable-search-input/src/selectable-search-input.spec.tsx
index 2d75e66370..9befc2e331 100644
--- a/packages/components/inputs/selectable-search-input/src/selectable-search-input.spec.tsx
+++ b/packages/components/inputs/selectable-search-input/src/selectable-search-input.spec.tsx
@@ -134,6 +134,35 @@ describe('SelectableSearchInput', () => {
).toHaveTextContent('Bar');
});
+ it('should show the passed experimental value when controlled externally', () => {
+ render(
+
+ );
+ expect(screen.getByLabelText('test-label')).toHaveAttribute(
+ 'value',
+ 'experimental'
+ );
+ expect(
+ screen.getByTestId('selectable-search-input-container')
+ ).toHaveTextContent('Bar');
+ });
+
+ it('should show an empty input when an empty string is passed externally as value', () => {
+ render(
+
+ );
+ expect(screen.getByLabelText('test-label')).toHaveAttribute('value', '');
+ expect(
+ screen.getByTestId('selectable-search-input-container')
+ ).toHaveTextContent('Bar');
+ });
+
it('should call onFocus when the dropdown menu is focused', async () => {
const onFocus = jest.fn();
render(
diff --git a/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js b/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js
index c088a4959f..d349c17290 100644
--- a/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js
+++ b/packages/components/inputs/selectable-search-input/src/selectable-search-input.story.js
@@ -1,4 +1,3 @@
-import { useState } from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { withKnobs, boolean, text, select } from '@storybook/addon-knobs/react';
@@ -88,12 +87,10 @@ storiesOf('Components|Inputs', module)
];
const name = text('name', '') || 'default-name';
- const [dropdownValue, setDropdownValue] = useState();
- const [textInputValue, setTextInputValue] = useState();
const value = {
- text: textInputValue,
- option: dropdownValue,
+ text: '',
+ option: '',
};
return (
@@ -114,12 +111,6 @@ storiesOf('Components|Inputs', module)
value={value}
onChange={(event) => {
action('onChange')(event);
- if (event.target.name.endsWith('.textInput')) {
- setTextInputValue(event.target.value);
- }
- if (event.target.name.endsWith('.dropdown')) {
- setDropdownValue(event.target.value);
- }
}}
isAutofocussed={boolean('isAutofocussed', false)}
isDisabled={boolean('isDisabled', false)}
diff --git a/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx b/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx
index cb99122b8d..8acf6de5eb 100644
--- a/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx
+++ b/packages/components/inputs/selectable-search-input/src/selectable-search-input.tsx
@@ -89,6 +89,7 @@ export type TSelectableSearchInputProps = {
* Value of the input. Consists of text input and selected option.
*/
value: TValue;
+ _experimentalValue?: TValue;
/**
* Called with the event of the input or dropdown when either the selectable dropdown or the text input have changed.
* The change event from the text input has a suffix of `.textInput` and the change event from the dropdown has a suffix of `.dropdown`.
@@ -258,12 +259,15 @@ const transformDataProps = (dataProps?: Record) =>
const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
const [dropdownHasFocus, toggleDropdownHasFocus] = useToggleState(false);
const [searchValue, setSearchValue] = useState(props.value.text || '');
+ const [searchOption, setSearchOption] = useState(props.value.option || '');
const containerRef = useRef(null);
const textInputRef = useRef(null);
const legacyDataProps = filterDataAttributes(props);
const transformedSelectDataProps = transformDataProps(props.selectDataProps);
const transformedInputDataProps = transformDataProps(props.inputDataProps);
+ const searchInputValue = props._experimentalValue?.text ?? searchValue;
+ const searchInputOption = props._experimentalValue?.option ?? searchOption;
const optionsWithoutGroups = props.options.flatMap((option) => {
if (isOptionObject(option)) {
@@ -273,7 +277,7 @@ const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
});
const selectedOption = optionsWithoutGroups.find(
- (option) => option.value === props.value.option
+ (option) => option.value === searchInputOption
);
const selectablSearchInputId = useFieldId(
@@ -324,7 +328,7 @@ const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
}
};
- const handleChange = (event: ChangeEvent) => {
+ const handleTextInputChange = (event: ChangeEvent) => {
setSearchValue(event.target.value);
if (props.onChange) {
props.onChange({
@@ -346,7 +350,7 @@ const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
event.preventDefault();
if (props.onSubmit) {
props.onSubmit({
- text: searchValue,
+ text: searchInputValue,
option: selectedOption?.value ?? '',
});
}
@@ -406,6 +410,23 @@ const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
[onBlur, selectablSearchInputId, name]
);
+ const handleDropdownChange = useCallback(
+ (nextSelectedOptions) => {
+ setSearchOption(nextSelectedOptions.value);
+ if (props.onChange) {
+ props.onChange({
+ target: {
+ id: SelectableSearchInput.getDropdownId(selectablSearchInputId),
+ name: getDropdownName(name),
+ value: nextSelectedOptions.value,
+ },
+ });
+ }
+ textInputRef.current?.focus();
+ },
+ [props.onChange, selectablSearchInputId, name]
+ );
+
return (
{
isCondensed={props.isCondensed ?? false}
handleDropdownFocus={handleDropdownFocus}
handleDropdownBlur={handleDropdownBlur}
+ handleDropdownChange={handleDropdownChange}
textInputRef={textInputRef}
selectedOption={selectedOption}
dataProps={transformedSelectDataProps}
@@ -445,8 +467,8 @@ const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
id={SelectableSearchInput.getTextInputId(selectablSearchInputId)}
name={getTextInputName(props.name)}
type="text"
- value={searchValue}
- onChange={handleChange}
+ value={searchInputValue}
+ onChange={handleTextInputChange}
onBlur={handleTextInputBlur}
onFocus={handleTextInputFocus}
disabled={props.isDisabled}
@@ -470,7 +492,7 @@ const SelectableSearchInput = (props: TSelectableSearchInputProps) => {
}}
/>
{props.isClearable &&
- searchValue &&
+ searchInputValue &&
!props.isDisabled &&
!props.isReadOnly && (
void;
handleDropdownBlur: () => void;
+ handleDropdownChange: ReactSelectProps['onChange'];
textInputRef: React.RefObject;
selectedOption?: TOption;
dataProps?: Record;
@@ -50,23 +51,6 @@ const SelectableSelect = (props: TSelectableSelect) => {
dropdownHasFocus: props.dropdownHasFocus,
}) as ReactSelectProps['styles'];
- const { onChange, name, id, textInputRef } = props;
- const handleDropdownChange = useCallback(
- (nextSelectedOptions) => {
- if (onChange) {
- onChange({
- target: {
- id: id,
- name: name,
- value: (nextSelectedOptions as TOption).value,
- },
- });
- }
- textInputRef.current?.focus();
- },
- [onChange, id, name, textInputRef]
- );
-
return (