import React, { Fragment, useState } from "react"; import classNames from "classnames"; import { Popover } from "../popover"; import { Input } from "../input"; import { Icon } from "../icon"; import { Text } from "../text"; import { CascaderData, CascaderOption, CascaderSingleProps, } from "./CascaderProps"; import { CascaderBox, getOptions } from "./CascaderBox"; import { CascaderMenuBox } from "./CascadeMenu"; import { CascaderSearch } from "./CascaderSearch"; import { useDefaultValue } from "../form"; import { useTranslation } from "../i18n"; import { useDefault } from "../_util/use-default"; import { useConfig } from "../_util/config-context"; import { noop } from "../_util/noop"; import { mergeEventProps } from "../_util/merge-event-props"; import { forwardRefWithStatics } from "../_util/forward-ref-with-statics"; const defaultValueRender = (options: CascaderOption[]) => options.map(({ label, value }, index) => ( {index !== 0 && " / "} {label || value} )); export const CascaderSingle = forwardRefWithStatics( function CascaderSingle( props: CascaderSingleProps & { data: CascaderData }, ref: React.Ref ) { const t = useTranslation(); const { classPrefix } = useConfig(); const { data, value, onChange, onLoad, disabled, changeOnSelect, style, className, placeholder = t.pleaseSelect, defaultOpen = false, open, onOpenChange = noop, placement = "bottom-start", placementOffset = 5, closeOnScroll = true, escapeWithReference, popupContainer, overlayClassName, overlayStyle, clearable, searchable, filter, type, expandTrigger, valueRender = defaultValueRender, tips, bottomTips, onScrollBottom = noop, onSearch = noop, } = useDefaultValue(props, []); const [hover, setHover] = useState(false); const [isOpened, setIsOpened] = useDefault(open, defaultOpen, onOpenChange); const [focused, setFocused] = useState(false); const [searching, setSearching] = useState(false); const [searchValue, setSearchValue] = useState(""); const options = getOptions(data, value); const Box = type === "menu" ? CascaderMenuBox : CascaderBox; return ( { setSearchValue(""); setSearching(false); }} placement={placement || "bottom-start"} placementOffset={placementOffset} closeOnScroll={closeOnScroll} escapeWithReference={escapeWithReference} popupContainer={popupContainer} overlayClassName={overlayClassName} overlayStyle={overlayStyle} overlay={({ scheduleUpdate }) => { if (searchValue) { return ( { onChange(...args); setIsOpened(false); setSearching(false); }} scheduleUpdate={scheduleUpdate} changeOnSelect={changeOnSelect} tips={tips} bottomTips={bottomTips} onScrollBottom={onScrollBottom} onSearch={onSearch} /> ); } return ( setIsOpened(false)} changeOnSelect={changeOnSelect} scheduleUpdate={scheduleUpdate} expandTrigger={expandTrigger} tips={tips} bottomTips={bottomTips} onScrollBottom={onScrollBottom} /> ); }} >
setHover(true), onMouseLeave: () => setHover(false), })} >
{!searching && (
{valueRender(options)}
)} { if (searchable) { setFocused(true); setIsOpened(true); if (searchValue) { setSearching(true); } } }} onBlur={() => { setFocused(false); setSearching(false); }} onChange={value => { setSearchValue(value); }} onInput={event => { setSearching(!!event.currentTarget.value); }} onClick={event => searchable && event.stopPropagation()} />
{clearable && !disabled && hover && value.length ? ( { event.stopPropagation(); onChange([], { event, options: [] }); setIsOpened(false); }} /> ) : ( )}
); }, { defaultLabelAlign: "middle", } ); CascaderSingle.displayName = "CascaderSingle";