Skip to content

Commit

Permalink
#104 Add valueTransform prop to Autocomplete (#105)
Browse files Browse the repository at this point in the history
* #104 Add valueTransform prop to Autocomplete

* #104 Update Stories

---------

Co-authored-by: imikulec <[email protected]>
  • Loading branch information
ivam5 and imikulec authored Apr 13, 2023
1 parent cba4c12 commit e1b0e4f
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
6 changes: 5 additions & 1 deletion libs/formik-elements/src/AutocompleteField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { isEqual } from "lodash";

import { Autocomplete, AutocompleteProps } from "@tiller-ds/selectors";

import { InputFieldProps } from "./InputField";
import useShouldValidate from "./useShouldValidate";
import useFormikBypass from "./useFormikBypass";

Expand All @@ -48,13 +49,15 @@ export type AutocompleteFieldProps<T> = {
* On by default.
*/
sendOptionValue?: boolean;
} & Omit<AutocompleteProps<T>, AutocompleteOnlyPropsUnion>;
} & Omit<AutocompleteProps<T>, AutocompleteOnlyPropsUnion> &
Pick<InputFieldProps, "valueTransform">;

export default function AutocompleteField<T>({
name,
options,
getOptionValue,
sendOptionValue = true,
valueTransform,
...props
}: AutocompleteFieldProps<T>) {
const [field, meta, helpers] = useField(name);
Expand Down Expand Up @@ -149,6 +152,7 @@ export default function AutocompleteField<T>({
onBlur={onBlur}
onReset={onReset}
error={meta.touched && (initialError.current ? initialError.current : meta.error)}
valueTransform={valueTransform}
/>
);
}
21 changes: 21 additions & 0 deletions libs/selectors/src/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ export type AutocompleteProps<T extends {}> = {
* The value(s) of the field sent on submit and/or retrieved on component render.
*/
value?: T | T[] | null;

/**
* Function or a string that determines how the input value should be transformed when the user types into the input field.
* In case it's a function, it will be called every time the input value changes. The function can then modify the value as needed and return the modified value.
*/
valueTransform?: "uppercase" | "lowercase" | "capitalize" | ((value: string) => string);
} & AutocompleteTokensProps;

type AutocompleteTokensProps = {
Expand Down Expand Up @@ -279,6 +285,7 @@ function Autocomplete<T extends {}>({
className,
children,
onChange,
valueTransform,
...props
}: AutocompleteProps<T>) {
const autocompleteTokens = useTokens("Autocomplete", props.autocompleteTokens);
Expand Down Expand Up @@ -966,6 +973,20 @@ function Autocomplete<T extends {}>({
onBlur: onBlur ? onBlur : undefined,
onKeyDown,
onClick,
onInput: (event) => {
const input = event.target as HTMLInputElement;
let transformedValue = input.value;
if (typeof valueTransform === "function") {
transformedValue = valueTransform(transformedValue);
} else if (valueTransform === "uppercase") {
transformedValue = transformedValue.toUpperCase();
} else if (valueTransform === "lowercase") {
transformedValue = transformedValue.toLowerCase();
} else if (valueTransform === "capitalize") {
transformedValue = transformedValue.charAt(0).toUpperCase() + transformedValue.slice(1);
}
input.value = transformedValue;
},
})}
{...getComboboxProps({}, { suppressRefError: true })}
/>
Expand Down
15 changes: 15 additions & 0 deletions storybook/src/formik-elements/AutocompleteField.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ export default {
useTokens: { name: "Use Tokens", control: "boolean" },
autocompleteTokens: { name: "Autocomplete Tokens", control: "object" },
selectTokens: { name: "Select Tokens", control: "object" },
valueTransform: {
name: "Transform Value",
options: ["uppercase", "lowercase", "capitalize"],
control: { type: "radio" },
},
},
};

Expand Down Expand Up @@ -238,6 +243,7 @@ export const AutocompleteFieldFactory = ({
useTokens,
autocompleteTokens,
selectTokens,
valueTransform,
}) => (
<AutocompleteField
name={name}
Expand Down Expand Up @@ -296,6 +302,7 @@ export const AutocompleteFieldFactory = ({
className={className}
autocompleteTokens={useTokens && autocompleteTokens}
selectTokens={useTokens && selectTokens}
valueTransform={valueTransform}
{...(fetchFrontend ? (tags ? frontendSimpleProps : frontendProps) : tags ? backendSimpleProps : backendProps)}
/>
);
Expand Down Expand Up @@ -323,6 +330,7 @@ AutocompleteFieldFactory.args = {
useTokens: false,
autocompleteTokens: defaultThemeConfig.component["Autocomplete"],
selectTokens: defaultThemeConfig.component["Select"],
valueTransform: "lowercase",
};

AutocompleteFieldFactory.parameters = {
Expand All @@ -341,6 +349,10 @@ export const WithValue = () => (
<AutocompleteField {...backendProps} label={<Intl name="label" />} name={nameWithValue} />
);

export const WithTransformedValue = () => (
<AutocompleteField {...backendProps} label={<Intl name="label" />} name={nameWithValue} valueTransform="uppercase" />
);

export const Disabled = () => (
<AutocompleteField label={<Intl name="label" />} disabled={true} {...backendProps} name={nameWithValue} />
);
Expand Down Expand Up @@ -397,6 +409,7 @@ export const WithMultipleSelectionAndVisibleLabels = () => (
allowMultiple={true}
getMultipleSelectedLabel={(items: Item[]) => items.map((item) => `${item.name} ${item.surname}`).join(", ")}
name={nameWithMultipleValues}
valueTransform="uppercase"
/>
);

Expand Down Expand Up @@ -504,11 +517,13 @@ const HideControls = {
useTokens: { control: { disable: true } },
autocompleteTokens: { control: { disable: true } },
selectTokens: { control: { disable: true } },
valueTransform: { control: { disable: true } },
};

WithLabel.argTypes = HideControls;
WithoutLabel.argTypes = HideControls;
WithValue.argTypes = HideControls;
WithTransformedValue.argTypes = HideControls;
Disabled.argTypes = HideControls;
WithPlaceholder.argTypes = HideControls;
WithHelp.argTypes = HideControls;
Expand Down
14 changes: 14 additions & 0 deletions storybook/src/selectors/Autocomplete.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ export default {
error: { control: false },
tooltip: { control: false },
value: { control: false },
valueTransform: {
name: "Transform Value",
options: ["uppercase", "lowercase", "capitalize"],
control: { type: "radio" },
},
},
};

Expand Down Expand Up @@ -219,6 +224,7 @@ export const AutocompleteFactory = ({
useTokens,
autocompleteTokens,
selectTokens,
valueTransform,
}) => (
<Autocomplete
name={name}
Expand Down Expand Up @@ -277,6 +283,7 @@ export const AutocompleteFactory = ({
className={className}
autocompleteTokens={useTokens && autocompleteTokens}
selectTokens={useTokens && selectTokens}
valueTransform={valueTransform}
{...(fetchFrontend ? (tags ? frontendSimpleProps : frontendProps) : tags ? backendSimpleProps : backendProps)}
/>
);
Expand Down Expand Up @@ -304,6 +311,7 @@ AutocompleteFactory.args = {
useTokens: false,
autocompleteTokens: defaultThemeConfig.component["Autocomplete"],
selectTokens: defaultThemeConfig.component["Select"],
valueTransform: "lowercase",
};

AutocompleteFactory.parameters = {
Expand All @@ -322,6 +330,10 @@ export const WithValue = () => (
<Autocomplete {...backendProps} label={<Intl name="label" />} name={name} value={value} />
);

export const WithTransformedValue = () => (
<Autocomplete {...backendProps} label={<Intl name="label" />} name={name} value={value} valueTransform="uppercase" />
);

export const Disabled = () => (
<Autocomplete label={<Intl name="label" />} disabled={true} {...backendProps} name={name} />
);
Expand Down Expand Up @@ -479,11 +491,13 @@ const HideControls = {
useTokens: { control: { disable: true } },
autocompleteTokens: { control: { disable: true } },
selectTokens: { control: { disable: true } },
valueTransform: { control: { disable: true } },
};

WithLabel.argTypes = HideControls;
WithoutLabel.argTypes = HideControls;
WithValue.argTypes = HideControls;
WithTransformedValue.argTypes = HideControls;
Disabled.argTypes = HideControls;
WithPlaceholder.argTypes = HideControls;
WithHelp.argTypes = HideControls;
Expand Down

0 comments on commit e1b0e4f

Please sign in to comment.