Skip to content

Commit

Permalink
feat: 🎸 [Select] Added onScroll listener and scrollEnd callback
Browse files Browse the repository at this point in the history
It is now possible to attach onScrollEnd callback to onScroll event.

✅ Closes: 207
  • Loading branch information
luciob committed Sep 15, 2021
1 parent e056b46 commit dbf2e88
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 2 deletions.
19 changes: 19 additions & 0 deletions src/components/Select/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,25 @@ describe("Select Single test suite:", () => {
expect(onChangeCallback).toHaveBeenCalledWith(["Sculpture"]);
});

it("onScroll", () => {
const onScrollEndCallback = jest.fn();
const outerWrapperDataCy = getComposedDataCy(DATA_CY_DEFAULT, SUBPARTS_MAP.outerWrapper);
const { wrapper } = getSelectTestable({
dataCy: outerWrapperDataCy,
domNode: "div",
mountOnly: true,
props: { onScrollEnd: onScrollEndCallback },
});

const input = wrapper.find(`input[data-cy='${DATA_CY_DEFAULT}']`);
input.simulate("mousedown");

const listbox = wrapper.find("ul.MuiAutocomplete-listbox");
listbox.simulate("scroll", { clientHeight: 100, scrollHeight: 100, scrollTop: 0 });

expect(onScrollEndCallback).toHaveBeenCalledTimes(1);
});

it("options - default", () => {
const outerWrapperDataCy = getComposedDataCy(DATA_CY_DEFAULT, SUBPARTS_MAP.outerWrapper);
const { wrapper } = getSelectTestable({
Expand Down
26 changes: 24 additions & 2 deletions src/components/Select/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { CSSProperties, Fragment, useCallback, useMemo } from "react";
import React, { CSSProperties, Fragment, SyntheticEvent, useCallback, useMemo } from "react";
import {
ListSubheader as MUIListSubheader,
Popper as MUIPopper,
Expand Down Expand Up @@ -57,6 +57,7 @@ const Select = <T extends any>({
loading = false,
multiple = false,
onChange: externalOnChange,
onScrollEnd,
options: externalOptions,
placeholder,
popperWidth,
Expand Down Expand Up @@ -93,6 +94,21 @@ const Select = <T extends any>({
[externalOnChange]
);

const onScroll = useCallback(
({ currentTarget: listboxNode }: SyntheticEvent) => {
if (!listboxNode || !onScrollEnd) {
return;
}

const { clientHeight, scrollHeight, scrollTop } = listboxNode;
const scrollEnded = clientHeight + scrollTop === scrollHeight;
if (scrollEnded) {
onScrollEnd();
}
},
[onScrollEnd]
);

const options = useMemo(() => {
let options = [...externalOptions];
if (!autoSort && !groupBy) {
Expand Down Expand Up @@ -145,7 +161,13 @@ const Select = <T extends any>({
getOptionLabel={getOptionLabel}
getOptionSelected={isOptionSelected}
groupBy={groupBy}
ListboxProps={{ style: { padding: 0, width: "100%" } }}
ListboxProps={{
onScroll,
style: {
padding: 0,
width: "100%",
},
}}
loading={loading}
multiple={multiple}
onChange={onChange}
Expand Down
1 change: 1 addition & 0 deletions src/types/Select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface IBaseSelect<T> extends ILocalizable, ILoadable, IInput {
getOptionLabel?: (option: T) => string;
getOptionSelected?: (option: T, value: T) => boolean;
groupBy?: (option: T) => string;
onScrollEnd?: () => void;
options: T[];
popperWidth?: number;
}
Expand Down

0 comments on commit dbf2e88

Please sign in to comment.