Skip to content

Commit

Permalink
Merge pull request #22 from Coaktion/feat/select-all-mutiple-autocomp…
Browse files Browse the repository at this point in the history
…lete

feat: adding select option to multiple autocomplete
  • Loading branch information
MatheusDev20 authored Apr 10, 2024
2 parents 2d9b281 + 479b299 commit d4d2d75
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 57 deletions.
53 changes: 33 additions & 20 deletions __tests__/auto-complete-multiple.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,69 @@ import { fireEvent, render, screen } from '@testing-library/react';
import AktAutoCompleteMultiple from '../src/auto-complete-multiple';

describe('AktAutoCompleteMultiple', () => {
const mockOptions = ['Option1', 'Option2'];
const mockOptions = ['Selecionar Todos', 'Option1', 'Option2'];
const mockOnChange = jest.fn();

beforeEach(() => {
render(
<AktAutoCompleteMultiple rows={mockOptions} onChange={mockOnChange} />
<AktAutoCompleteMultiple
allSelectOption="Selecionar Todos"
rows={mockOptions}
onChange={mockOnChange}
/>
);
});

it('should render the component', () => {
expect(screen.getByTestId('auto-complete-input')).toBeInTheDocument();
});

it('should toggle dropdown on arrow icon click', () => {
const arrowIcon = screen.getByTestId('auto-complete-arrow');
fireEvent.click(arrowIcon);
it('should show the options when the element has focus', () => {
fireEvent.focus(screen.getByTestId('auto-complete-input'));
expect(screen.getByText('Option1')).toBeInTheDocument();
});

it('should call onChange with selected values', () => {
const arrowIcon = screen.getByTestId('auto-complete-arrow');
fireEvent.click(arrowIcon);

fireEvent.focus(screen.getByTestId('auto-complete-input'));
const option = screen.getByText('Option1');
fireEvent.click(option);

expect(mockOnChange).toHaveBeenCalledWith(['Option1']);
});

it('should display chips for selected values', () => {
const arrowIcon = screen.getByTestId('auto-complete-arrow');
fireEvent.click(arrowIcon);

fireEvent.focus(screen.getByTestId('auto-complete-input'));
const option1 = screen.getByText('Option1');
fireEvent.click(option1);

fireEvent.click(arrowIcon);

const option2 = screen.getByText('Option2');
fireEvent.click(option2);

fireEvent.blur(screen.getByTestId('auto-complete'));
expect(screen.getByText('Option1')).toBeInTheDocument();
expect(screen.getByText('Option2')).toBeInTheDocument();
});

it('should close the list when clicking outside', () => {
fireEvent.click(screen.getByTestId('auto-complete-arrow'));
fireEvent.focus(screen.getByTestId('auto-complete-input'));
fireEvent.blur(screen.getByTestId('auto-complete'));
expect(
screen.queryByTestId('auto-complete-option')
).not.toBeInTheDocument();
});

it('Should select all the values when clicing on allSelect Option', () => {
fireEvent.focus(screen.getByTestId('auto-complete-input'));
const allSelectOption = screen.getByText('Selecionar Todos');
fireEvent.click(allSelectOption);
expect(mockOnChange).toHaveBeenCalledWith(['Option1', 'Option2']);
});

it('Should clear all the values when clicing on allSelect Option and all values are selected', () => {
fireEvent.focus(screen.getByTestId('auto-complete-input'));
const allSelectOption = screen.getByText('Selecionar Todos');
const option1 = screen.getByText('Option1');
const option2 = screen.getByText('Option2');
fireEvent.click(allSelectOption);
fireEvent.blur(screen.getByTestId('auto-complete'));
fireEvent.focus(screen.getByTestId('auto-complete-input'));
fireEvent.click(allSelectOption);

expect(option1).not.toBeInTheDocument();
expect(option2).not.toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
"pre-commit:prepare": "husky install",
"release:major": "standard-version --release-as major",
"release:minor": "standard-version --release-as minor",
"release:patch": "standard-version --release-as patch"
"release:patch": "standard-version --release-as patch",
"prepackpackage": "npm run build",
"packpackage": "npm pack"
},
"keywords": [],
"author": "",
Expand Down
90 changes: 55 additions & 35 deletions src/auto-complete-multiple.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import CheckBoxIcon from '@mui/icons-material/CheckBox';
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
import DoneAllIcon from '@mui/icons-material/DoneAll';
import { Checkbox } from '@mui/material';
import Autocomplete from '@mui/material/Autocomplete';
import Chip from '@mui/material/Chip';
import TextField from '@mui/material/TextField';
Expand All @@ -24,32 +27,79 @@ interface AktAutoCompleteMultipleProps {
limitTags?: number;
iconColor?: string;
onChange: (data: any) => void;
allSelectOption: string;
}

const optionStyles = {
display: 'flex',
alignItems: 'center',
width: '100%',
gap: '8px'
};

const AktAutoCompleteMultiple: React.FC<AktAutoCompleteMultipleProps> = ({
rows,
value,
title,
iconColor = '#6b6b6b',
limitTags,
onChange
onChange,
allSelectOption
}: AktAutoCompleteMultipleProps) => {
const [isOpen, setIsOpen] = useState(false);

const handleChange = (value: any) => {
setIsOpen(false);
if (value.includes(allSelectOption)) {
// value = value.length === rows.length ? [] : rows.filter((item) => item !== allSelectOption)
value = rows.filter((item) => item !== allSelectOption);
setIsOpen(false);
}

onChange(value);
};

const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;

type OptionProps = {
props: React.HTMLAttributes<HTMLLIElement>;
option: any;
selected: boolean;
};
const Option = ({ props, option, selected }: OptionProps) => {
return (
<li {...props}>
{option === allSelectOption ? (
<div style={optionStyles}>
<DoneAllIcon style={{ color: '#48BB30' }} />
{option}
</div>
) : (
<div>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option}
</div>
)}
</li>
);
};
return (
<>
<Autocomplete
multiple
open={isOpen}
limitTags={limitTags || -1}
title={title}
onFocus={() => setIsOpen(true)}
onBlur={() => setIsOpen(false)}
options={rows}
renderOption={(props, option, { selected }) => (
<Option props={props} option={option} selected={selected} />
)}
disableCloseOnSelect
value={value}
data-testid="auto-complete"
Expand All @@ -66,37 +116,7 @@ const AktAutoCompleteMultiple: React.FC<AktAutoCompleteMultipleProps> = ({
))
}
renderInput={(params) => (
<TextField
{...params}
fullWidth
data-testid="auto-complete-input"
InputProps={{
...params.InputProps,
endAdornment: (
<div
style={{
position: 'absolute',
display: 'flex',
justifyContent: 'flex-end',
right: 10,
top: '50%',
transform: 'translateY(-50%)'
}}
data-testid="auto-complete-end-adornment"
onClick={() => setIsOpen(!isOpen)}
>
<ArrowDropDownIcon
style={{
color: `${iconColor}`,
cursor: 'pointer'
}}
data-testid="auto-complete-arrow"
onClick={() => setIsOpen(!isOpen)}
/>
</div>
)
}}
/>
<TextField {...params} fullWidth data-testid="auto-complete-input" />
)}
/>
</>
Expand Down
1 change: 1 addition & 0 deletions src/auto-complete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const AktAutoComplete: React.FC<AktAutoCompleteProps> = ({
<Autocomplete
open={isOpen}
onBlur={() => setIsOpen(false)}
onFocus={() => setIsOpen(true)}
options={rows}
disabled={disabled}
title={title}
Expand Down

0 comments on commit d4d2d75

Please sign in to comment.