Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(select): auto scroll behavior #2779

Merged
merged 4 commits into from
Feb 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions src/select/base/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import React, {
useEffect,
useMemo,
KeyboardEvent,
WheelEvent,
useRef,
useCallback,
Children,
cloneElement,
isValidElement,
useState,
} from 'react';
import classNames from 'classnames';
import isFunction from 'lodash/isFunction';
import get from 'lodash/get';
import debounce from 'lodash/debounce';
import useControlled from '../../hooks/useControlled';
import { useLocaleReceiver } from '../../locale/LocalReceiver';
import useConfig from '../../hooks/useConfig';
Expand Down Expand Up @@ -99,7 +102,8 @@ const Select = forwardRefWithStatics(
const [value, onChange] = useControlled(props, 'value', props.onChange);
const selectInputRef = useRef(null);
const { classPrefix } = useConfig();
const { overlayClassName, ...restPopupProps } = popupProps || {};
const { overlayClassName, onScroll, onScrollToBottom, ...restPopupProps } = popupProps || {};
const [isScrolling, toggleIsScrolling] = useState(false);

const name = `${classPrefix}-select`; // t-select

Expand All @@ -123,8 +127,9 @@ const Select = forwardRefWithStatics(

const handleShowPopup = (visible: boolean, ctx: PopupVisibleChangeContext) => {
if (disabled) return;
setShowPopup(visible, ctx);
visible && toggleIsScrolling(false);
!visible && onInputChange('', { trigger: 'blur' });
setShowPopup(visible, ctx);
};

// 可以根据触发来源,自由定制标签变化时的筛选器行为
Expand Down Expand Up @@ -375,7 +380,7 @@ const Select = forwardRefWithStatics(

// 将第一个选中的 option 置于列表可见范围的最后一位
const updateScrollTop = (content: HTMLDivElement) => {
if (!content) {
if (!content || isScrolling) {
return;
}
const firstSelectedNode: HTMLDivElement = content.querySelector(`.${classPrefix}-is-selected`);
Expand All @@ -399,6 +404,20 @@ const Select = forwardRefWithStatics(
const handleEnter = (_, context: { inputValue: string; e: KeyboardEvent<HTMLDivElement> }) => {
onEnter?.({ ...context, value });
};

const handleScroll = ({ e }: { e: WheelEvent<HTMLDivElement> }) => {
toggleIsScrolling(true);

onScroll?.({ e });
if (onScrollToBottom) {
const debounceOnScrollBottom = debounce((e) => onScrollToBottom({ e }), 100);

const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLDivElement;
if (clientHeight + Math.floor(scrollTop) === scrollHeight) {
debounceOnScrollBottom(e);
}
}
};
return (
<div
className={classNames(`${name}__wrap`, className)}
Expand Down Expand Up @@ -441,6 +460,7 @@ const Select = forwardRefWithStatics(
updateScrollTop={updateScrollTop}
popupProps={{
overlayClassName: [`${name}__dropdown`, overlayClassName],
onScroll: handleScroll,
...restPopupProps,
}}
popupVisible={showPopup}
Expand Down
Loading