Skip to content

Commit

Permalink
Merge pull request #571 from sebgroup/develop
Browse files Browse the repository at this point in the history
dropdown fix release
  • Loading branch information
mario-subo authored Apr 6, 2021
2 parents d8fab69 + 876416c commit f4b566a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 18 deletions.
34 changes: 29 additions & 5 deletions lib/src/Dropdown/Dropdown.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const testOptions: React.ReactElement[] = [
<option key={3} value="3">
Third
</option>,
<option key={4} value="4" disabled>
Disabled
</option>,
];

describe("Component: Dropdown", () => {
Expand Down Expand Up @@ -60,10 +63,10 @@ describe("Component: Dropdown", () => {
render(<Dropdown>{testOptions}</Dropdown>, container);
});

// 3 options + first empty option that is injected
expect(container.querySelector("select").options).toHaveLength(4);
// 4 options + first empty option that is injected
expect(container.querySelector("select").options).toHaveLength(5);
expect(document.body.querySelector(".dropdown-menu")).not.toBeNull();
expect(document.body.querySelectorAll(".custom-control")).toHaveLength(3);
expect(document.body.querySelectorAll(".custom-control")).toHaveLength(4);
});

it("Should render grouped options inside", () => {
Expand All @@ -77,7 +80,7 @@ describe("Component: Dropdown", () => {
);
});

expect(container.querySelector("select").options).toHaveLength(4);
expect(container.querySelector("select").options).toHaveLength(5);
expect(container.querySelector("select").querySelector("optgroup")).not.toBeNull();
expect(document.body.querySelector("label.optgroup-label")).not.toBeNull();
expect(document.body.querySelector("label.optgroup-label").textContent).toEqual(optgroupLabel);
Expand All @@ -93,6 +96,27 @@ describe("Component: Dropdown", () => {
expect(container.querySelector("button.dropdown-toggle").firstElementChild.textContent).toEqual(placeholder);
});

it("Should support disabled options", () => {
const placeholder: string = "My placeholder";
act(() => {
render(<Dropdown placeholder={placeholder}>{testOptions}</Dropdown>, container);
});
expect(container.querySelector("select").options.item(4).disabled).toBeTruthy();
});

it("Should ignore disabled elements when determining if all elements are selected", () => {
const placeholder: string = "My placeholder";
act(() => {
render(
<Dropdown multiple value={["1", "2", "3"]} placeholder={placeholder}>
{testOptions}
</Dropdown>,
container
);
});
expect(document.body.querySelector<HTMLInputElement>(".select-all .custom-control-input").checked).toBeTruthy();
});

it("Should allow padding a dropdown divider", () => {
act(() => {
render(
Expand All @@ -115,7 +139,7 @@ describe("Component: Dropdown", () => {
const searchField = document.body.querySelector("input[type=search]");

expect(searchField).not.toBeNull();
expect(document.body.querySelectorAll(".custom-control")).toHaveLength(3);
expect(document.body.querySelectorAll(".custom-control")).toHaveLength(4);

act(() => Simulate.change(searchField, { target: { value: "second" } as any }));

Expand Down
32 changes: 24 additions & 8 deletions lib/src/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,28 @@ export const Dropdown: React.FC<DropdownProps> = React.forwardRef(({ wrapperProp
[isMobile, props.multiple, onMultipleChange]
);

const selectAll = (forceValue?: boolean | React.ChangeEvent<HTMLInputElement>) => {
Array.from(selectRef.current.options).forEach((option) => {
option.selected = typeof forceValue === "boolean" ? forceValue : !allSelected;
const selectAll = React.useCallback(
(forceValue?: boolean | React.ChangeEvent<HTMLInputElement>) => {
Array.from(selectRef.current.options).forEach((_, i) => {
const option = selectRef.current.options.item(i);
if (!option.disabled) {
option.selected = typeof forceValue === "boolean" ? forceValue : !allSelected;
} else {
option.selected = false;
}
});
typeof forceValue === "boolean" && (selectRef.current.value = "");
selectRef.current.dispatchEvent(new Event("change", { bubbles: true }));
props.multiple && onMultipleChange && onMultipleChange(getValueOfMultipleSelect(selectRef.current));
},
[allSelected, props.multiple]
);

const isAllSelected = (): boolean => {
return Array.from(selectRef.current.options).every((_, i) => {
const option: HTMLOptionElement = selectRef.current.options.item(i);
return option.disabled ? true : option.selected;
});
typeof forceValue === "boolean" && (selectRef.current.value = "");
selectRef.current.dispatchEvent(new Event("change", { bubbles: true }));
setAllSelected(!allSelected);
props.multiple && onMultipleChange && onMultipleChange(getValueOfMultipleSelect(selectRef.current));
};

const toggleMenu = React.useCallback(
Expand Down Expand Up @@ -143,6 +157,7 @@ export const Dropdown: React.FC<DropdownProps> = React.forwardRef(({ wrapperProp
case "option":
return filteredBySearch(Child) ? null : (
<CustomDropdownItem
{...Child.props}
multiple={props.multiple}
name={name}
value={Child.props.value}
Expand All @@ -159,6 +174,7 @@ export const Dropdown: React.FC<DropdownProps> = React.forwardRef(({ wrapperProp
...React.Children.toArray(Child.props.children).map((groupChild: React.ReactElement<any>) => {
return filteredBySearch(groupChild) ? null : (
<CustomDropdownItem
{...groupChild.props}
multiple={props.multiple}
name={name}
value={groupChild.props.value}
Expand All @@ -179,7 +195,7 @@ export const Dropdown: React.FC<DropdownProps> = React.forwardRef(({ wrapperProp
};

React.useEffect(() => {
!isMobile && props.multiple && setAllSelected(Array.from(selectRef.current.options).every((option) => option.selected));
!isMobile && props.multiple && setAllSelected(isAllSelected());
}, [props.value]);

React.useEffect(() => {
Expand Down
18 changes: 13 additions & 5 deletions lib/src/Dropdown/dropdown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@

&::after {
filter: grayscale(1);
transition: none;
transform: none;
}
}
}
Expand Down Expand Up @@ -102,20 +104,26 @@
padding: 0;

> input {
&:checked + label:not(:hover) {
background-color: $blue-darker;
color: white;
}

&[type="radio"] {
&:checked + label {
&:not(:hover) {
background-color: $blue-darker;
color: white;
}
&::before {
content: "\2713";
position: absolute;
left: 10px;
}
}
}

&:disabled + label {
color: $gray-500;
&:hover {
background-color: $gray-300;
}
}
}

> label {
Expand Down

0 comments on commit f4b566a

Please sign in to comment.