import React, { useMemo, useState } from "react"; import classNames from "classnames"; import { ControlledProps, useDefaultValue } from "../form/controlled"; import { Omit } from "../_type"; import { DropdownProps, Dropdown, CommonDropdownProps } from "../dropdown"; import { RegionOption, RegionOptionContext } from "./RegionOption"; import { getPropsFromChildrenByType } from "../_util/get-props-from-children-by-type"; import { useConfig } from "../_util/config-context"; import { forwardRefWithStatics } from "../_util/forward-ref-with-statics"; import { useTranslation } from "../i18n"; import { RegionPanel } from "./RegionPanel"; import { callBoth } from "../_util/call-both"; export interface RegionSelectShortcutOptions { /** * 快捷选择标题 * @default "最近访问" (已处理国际化) */ title?: React.ReactNode; /** * 缓存 Key * * **缓存最近点击的项至 localStorage** * @since 2.7.2 */ cacheKey?: string; /** * 自定义快捷选择可选项 */ options?: string[]; } export interface RegionSelectProps extends ControlledProps, Omit { /** * 下拉内容,应该使用 `RegionPanel` */ children?: React.ReactNode; /** * 在下拉按钮显示的额外信息 */ moreInfo?: React.ReactNode; /** * 是否禁用 * @default false * @since 2.4.1 */ disabled?: boolean; /** * 快捷选择(最近访问)区域配置 * * 选项设置方式: * - 设置 `cacheKey` 使用默认缓存方式记录最近访问选项 * - 设置 `options` 自定义该区域可选项 * * @since 2.5.0 */ shortcut?: RegionSelectShortcutOptions; } export const RegionSelect = forwardRefWithStatics( function RegionSelect( props: RegionSelectProps, ref: React.Ref ) { const t = useTranslation(); const { classPrefix } = useConfig(); const [open, setOpen] = useState(false); // eslint-disable-next-line react/destructuring-assignment const options = useMemo( () => getPropsFromChildrenByType(props.children, RegionOption), [props.children] ); const columns = useMemo( () => getPropsFromChildrenByType(props.children, RegionPanel.Column), [props.children] ); const { value, onChange, moreInfo, children, disabled, shortcut, ...dropdownProps } = useDefaultValue(props, options[0]?.value); const shortcutContent = useMemo(() => { if (shortcut?.cacheKey) { let shortcutOptions = []; try { shortcutOptions = JSON.parse( localStorage.getItem(shortcut.cacheKey) || "[]" ); } catch (_) { // ignore } return { title: t.recentlyVisited, ...shortcut, options: shortcutOptions .map(value => options.find(x => x && x.value === value)) .filter(Boolean) .slice(0, columns?.length || 1), }; } if (shortcut?.options) { return { title: t.recentlyVisited, ...shortcut, options: shortcut.options .map(value => options.find(x => x && x.value === value)) .filter(Boolean), }; } return null; // eslint-disable-next-line react-hooks/exhaustive-deps }, [columns, options, shortcut, t.recentlyVisited, open]); const selectedOption = options.find(x => x && x.value === value) || options[0]; return ( setOpen(open) )} button={ <> {selectedOption && } {moreInfo && (
{moreInfo}
)} } > {close => ( i !== props.value), ].slice(0, 12) ) ); } catch (_) { // ignore } } }, }; }, shortcut: shortcutContent, }} > {children} )}
); }, { defaultLabelAlign: "middle", } ); RegionSelect.displayName = "RegionSelect";