Skip to content

Commit

Permalink
feat: add formatter for select display value
Browse files Browse the repository at this point in the history
  • Loading branch information
abelflopes committed Jul 11, 2024
1 parent a89d5e8 commit 5592dfb
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 10 deletions.
37 changes: 28 additions & 9 deletions packages/components/select/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const Select = ({
value: userValue,
multiple: selectMultiple,
defaultValue,
displayValueFormatter,
...props
}: Readonly<SelectProps>): React.ReactElement => {
const onNextRender = useNextRender();
Expand Down Expand Up @@ -60,7 +61,13 @@ const Select = ({
);

/** Returns the internal value always as an array to facilitate operations */
const selectedValuesList = useMemo(() => valueAsArray(internalValue ?? []), [internalValue]);
const selectedValuesList = useMemo(
() =>
valueAsArray(internalValue ?? []).filter((i) =>
childrenData.map((c) => c.computedValue).includes(i),
),
[childrenData, internalValue],
);

const updateInternalValue = useCallback<ChangeHandler>(
(value, mode) => {
Expand Down Expand Up @@ -121,6 +128,25 @@ const Select = ({
[handleChange, selectedValuesList],
);

/** Compute value label to display */

const displayValue = useMemo(() => {
if (selectedValuesList.length === 0) return undefined;

const displayValue = childrenData
.filter((i) => i.computedValue && selectedValuesList.includes(i.computedValue))
.map((i) => i.textContent)
.join(", ");

return displayValueFormatter
? displayValueFormatter({
selectedValues: selectedValuesList,
childrenData,
displayValue,
})
: displayValue;
}, [childrenData, displayValueFormatter, selectedValuesList]);

/** Actions to do when dropdown opens */
useEffect(() => {
if (!open) return;
Expand Down Expand Up @@ -189,14 +215,7 @@ const Select = ({
handleBlur();
onBlur?.(e);
}}>
{selectedValuesList.length > 0 &&
childrenData
.filter((i) => i.computedValue && selectedValuesList.includes(i.computedValue))
.map((i) => i.textContent)
.join(", ")}
{selectedValuesList.length === 0 && (
<span className={styles.placeholder}>{placeholder}</span>
)}
{displayValue || <span className={styles.placeholder}>{placeholder}</span>}
</div>

<Dropdown
Expand Down
5 changes: 5 additions & 0 deletions packages/components/select/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export interface SelectProps
defaultValue?: UserValue;
name?: React.SelectHTMLAttributes<HTMLSelectElement>["name"];
multiple?: React.SelectHTMLAttributes<HTMLSelectElement>["multiple"];
displayValueFormatter?: (data: {
displayValue: string;
selectedValues: string[];
childrenData: SelectChildrenData[];
}) => React.ReactNode;
}

export interface SelectOptionProps extends Omit<MenuItemProps, "skin"> {
Expand Down
4 changes: 3 additions & 1 deletion packages/docs/stories/src/select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ const meta: Meta<typeof Select> = {

const args: SelectProps = {
placeholder: "Select a fruit",
displayValueFormatter: ({ displayValue }) => displayValue.replace(" 🍋", ""),
children: (
<>
<Select.Option value="Apple" disabled />
<Select.Option>Guaraná</Select.Option>
<Select.Option value="bnn">Banana</Select.Option>
<Select.Option value="orange">Orange</Select.Option>
<Select.Option value="lemon">Lemon</Select.Option>
<Select.Option value="lemon">Lemon 🍋</Select.Option>
<Select.Option>
<span>
<b>Exotic</b> mango
Expand Down

0 comments on commit 5592dfb

Please sign in to comment.