Skip to content

Commit

Permalink
fix(fuselage): Adjusted PaginatedMultiSelect to keep received/returne…
Browse files Browse the repository at this point in the history
…d values consistent (#994)

Co-authored-by: Tasso Evangelista <[email protected]>
  • Loading branch information
aleksandernsilva and tassoevan authored Mar 1, 2023
1 parent db343e0 commit 057b036
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type OptionsPaginatedProps = Omit<ComponentProps<typeof Box>, 'onSelect'> & {
multiple?: boolean;
options: { value: unknown; label: string; selected?: boolean }[];
cursor: number;
withTitle?: boolean;
renderItem?: ElementType;
renderEmpty?: ElementType;
onSelect: (option: [unknown, string]) => void;
Expand All @@ -42,7 +43,7 @@ export const CheckOption = memo(function CheckOption({
export const OptionsPaginated = forwardRef(
(
{
title,
withTitle,
multiple,
renderEmpty: EmptyComponent = Empty,
options,
Expand All @@ -64,7 +65,7 @@ export const OptionsPaginated = forwardRef(
const { value, label, selected } = data;
return (
<OptionComponent
{...(title && { title: label })}
{...(withTitle && { title: label })}
role='option'
label={label}
onMouseDown={(e: SyntheticEvent) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
// @ts-nocheck
import {
useMutableCallback,
useResizeObserver,
} from '@rocket.chat/fuselage-hooks';
import type { SyntheticEvent, ComponentProps, Ref } from 'react';
import type {
SyntheticEvent,
ComponentProps,
Ref,
ReactElement,
FormEvent,
} from 'react';
import React, { useState, useRef, useCallback, forwardRef, memo } from 'react';

import { prevent } from '../../helpers/prevent';
Expand All @@ -20,22 +25,30 @@ import Position from '../Position';
import SelectAddon from '../Select/SelectAddon';
import SelectFocus from '../Select/SelectFocus';

const SelectedOptions = memo((props) => (
const SelectedOptions = memo<ComponentProps<typeof Chip>>((props) => (
<Chip maxWidth='150px' withTruncatedText {...props} />
));

type PaginatedMultiSelectOption = {
value?: string | number;
label?: string | number;
export type PaginatedMultiSelectOption = {
value: string | number;
label: string;
};

type PaginatedMultiSelectProps = ComponentProps<typeof Box> & {
type PaginatedMultiSelectProps = Omit<
ComponentProps<typeof Box>,
'onChange' | 'value'
> & {
error?: boolean;
options: PaginatedMultiSelectOption[];
withTitle?: boolean;
placeholder: string;
placeholder?: string;
endReached?: (start?: number, end?: number) => void;
value?: PaginatedMultiSelectOption['value'];
value?: PaginatedMultiSelectOption[];
onChange: (values: PaginatedMultiSelectOption[]) => void;
renderOptions?: (
props: ComponentProps<typeof OptionsPaginated>
) => ReactElement | null;
anchor?: any;
};

export const PaginatedMultiSelect = ({
Expand All @@ -55,23 +68,20 @@ export const PaginatedMultiSelect = ({
const [internalValue, setInternalValue] = useState(value || []);

const currentValue = value !== undefined ? value : internalValue;
const option = options.find(
(option: PaginatedMultiSelecOption) => option.value === currentValue

const selectedOptions = options.filter((option) =>
currentValue.some((opt) => opt.value === option.value)
);

const internalChanged = ([value]: PaginatedMultiSelecOption[]) => {
if (
currentValue.some(
(item: PaginatedMultiSelecOption) => item.value === value.value
)
) {
const newValue = currentValue.filter(
(item: PaginatedMultiSelecOption) => item.value !== value.value
);
const internalChanged = (option: PaginatedMultiSelectOption) => {
if (currentValue.some((opt) => opt.value === option.value)) {
const newValue = currentValue.filter((opt) => opt.value !== option.value);

setInternalValue(newValue);
return onChange(newValue);
}
const newValue = [...currentValue, value];

const newValue = [...currentValue, option];
setInternalValue(newValue);
return onChange(newValue);
};
Expand All @@ -90,6 +100,15 @@ export const PaginatedMultiSelect = ({
return show();
}
});

const handleMouseDown = useMutableCallback(
(option: PaginatedMultiSelectOption) => (e: SyntheticEvent) => {
prevent(e);
internalChanged(option);
return false;
}
);

return (
<Box
is='div'
Expand Down Expand Up @@ -121,37 +140,21 @@ export const PaginatedMultiSelect = ({
onBlur={hide}
order={1}
rcx-input-box--undecorated
children={!value ? option || placeholder : null}
children={placeholder ?? null}
/>
{currentValue.map(
(value: PaginatedMultiSelecOption, index: number) => (
<SelectedOptions
{...(withTitle && {
title:
value.label ||
options.find(
(val: PaginatedMultiSelecOption) =>
val.value === value
)?.label,
})}
tabIndex={-1}
role='option'
key={index}
onMouseDown={(e: SyntheticEvent) => {
prevent(e);
internalChanged([value]);
return false;
}}
children={
value.label ||
options.find(
(val: PaginatedMultiSelecOption) =>
val.value === value
)?.label
}
/>
)
)}

{selectedOptions.map((option, index: number) => (
<SelectedOptions
{...(withTitle && {
title: option.label,
})}
tabIndex={-1}
role='option'
key={index}
onMouseDown={handleMouseDown(option)}
children={option.label}
/>
))}
</Margins>
</Box>
</Box>
Expand All @@ -177,25 +180,31 @@ export const PaginatedMultiSelect = ({
<AnimatedVisibility visibility={visible}>
<Position anchor={containerRef}>
<_Options
{...(withTitle && { title: withTitle })}
withTitle={withTitle}
width={borderBoxSize.inlineSize}
onMouseDown={prevent}
multiple
filter={filter}
role='listbox'
options={options}
onSelect={internalChanged}
cursor={-1}
endReached={endReached}
onSelect={([value, label]) =>
internalChanged({ value: value as string, label })
}
/>
</Position>
</AnimatedVisibility>
</Box>
);
};

type PaginatedMultiSelectFilteredProps = PaginatedMultiSelectProps & {
setFilter?: (value: PaginatedMultiSelectOption['value']) => void;
type PaginatedMultiSelectFilteredProps = Omit<
PaginatedMultiSelectProps,
'filter'
> & {
filter?: string;
setFilter?: (value: string) => void;
};

export const PaginatedMultiSelectFiltered = ({
Expand All @@ -205,6 +214,7 @@ export const PaginatedMultiSelectFiltered = ({
placeholder,
...props
}: PaginatedMultiSelectFilteredProps) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
const anchor = useCallback(
forwardRef(
(
Expand All @@ -220,9 +230,8 @@ export const PaginatedMultiSelectFiltered = ({
ref={ref}
placeholder={placeholder}
value={filter}
onInput={(e: SyntheticEvent) =>
setFilter &&
setFilter((e.currentTarget as HTMLInputElement).value)
onInput={(e: FormEvent<HTMLInputElement>) =>
setFilter?.(e.currentTarget.value)
}
{...props}
rcx-input-box--undecorated
Expand All @@ -232,6 +241,7 @@ export const PaginatedMultiSelectFiltered = ({
),
[]
);

return (
<PaginatedMultiSelect
filter={filter}
Expand Down
5 changes: 4 additions & 1 deletion packages/fuselage/src/components/PaginatedSelect/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export { PaginatedSelectFiltered } from './PaginatedSelectFiltered';
export { PaginatedMultiSelectFiltered } from './PaginatedMultiSelect';
export {
PaginatedMultiSelectFiltered,
PaginatedMultiSelectOption,
} from './PaginatedMultiSelect';

0 comments on commit 057b036

Please sign in to comment.