import React, { useEffect, useRef } from "react"; import classNames from "classnames"; import { DateChangeContext } from "../calendar/DateProps"; import { useConfig } from "../_util/config-context"; import { List } from "../list"; const SCROLL_OFFSET = 80; const SCROLL_DURATION = 120; export interface SelectProps { /** * 当前选择的值 */ value: number; /** * 起始值 */ from?: number; /** * 结束值 */ to: number; /** * 步长 */ step?: number; /** * 禁选范围 */ disabledValues?: number[]; /** * 变化回调 */ onChange: (value: number, context: DateChangeContext) => void; } /** * 滚动到指定元素 */ function scrollTo(element: HTMLElement, to: number, duration: number): void { if (duration <= 0) { element.scrollTop = to; return; } const difference = to - element.scrollTop; const perTick = (difference / duration) * 10; requestAnimationFrame(() => { element.scrollTop += perTick; if (element.scrollTop === to) return; scrollTo(element, to, duration - 10); }); } export function TimeSelect({ value, from = 0, to, step = 1, disabledValues = [], onChange = () => null, }: SelectProps) { const { classPrefix } = useConfig(); const selectRef = useRef(null); useEffect(() => { scrollToSelected(0); }, []); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { scrollToSelected(SCROLL_DURATION); }, [value, from, to, step]); // eslint-disable-line react-hooks/exhaustive-deps /** * 滚动到当前选择元素 */ function scrollToSelected(duration: number): void { const element = selectRef.current; const index = Math.floor(value / step); const topOption = element.children[index] as HTMLElement; const to = topOption.offsetTop - element.offsetTop - SCROLL_OFFSET; scrollTo(element, to, duration); } /** * 根据范围生成列表 */ function genRangeList(): number[] { return Array(Math.floor((to - from + 1) / step)) .fill(0) .map((_, i) => i * step + from); } function handleSelect(event: React.MouseEvent, value: number): void { event.stopPropagation(); onChange(value, { event }); } return ( {genRangeList().map(item => { const disabled = disabledValues.includes(item); return ( !disabled && handleSelect(e, item)} >
{item > 9 ? `${item}` : `0${item}`}
); })}
); } TimeSelect.displayName = "TimeSelect";