UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

190 lines (189 loc) 6.44 kB
"use client"; import { styles } from "../../Menu/sharedStyle.mjs"; import { styles as styles$1, triggerVariants } from "./style.mjs"; import { SelectPositioner } from "./atoms.mjs"; import { isValueEmpty } from "./helpers.mjs"; import { usePortalContainer, useSelectOpen, useSelectSearch, useSelectValue, useSelectVirtual } from "./hooks.mjs"; import { EmptyContent, SelectListSection, SelectSearchInput, SelectTriggerSuffix, createTriggerValueRenderer, resolveIconNode, resolveSuffixIcon } from "./parts.mjs"; import { renderOptions } from "./renderOptions.mjs"; import { memo, useCallback, useEffect, useMemo, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import { cx, useThemeMode } from "antd-style"; import { Select } from "@base-ui/react/select"; //#region src/base-ui/Select/Select.tsx const Select$1 = memo(({ allowClear, autoFocus, className, classNames, defaultOpen, defaultValue, disabled, id, labelRender, listHeight = 512, listItemHeight, loading, mode, name, onChange, onOpenChange, onSelect, open, optionRender, options, placeholder, popupClassName, popupMatchSelectWidth, prefix, readOnly, required, behaviorVariant = "default", selectedIndicatorVariant = "check", shadow, showSearch, size = "middle", style, suffixIcon, suffixIconProps, tokenSeparators, value, variant, virtual }) => { const { isDarkMode } = useThemeMode(); const resolvedVariant = variant ?? (isDarkMode ? "filled" : "outlined"); const isMultiple = mode === "multiple" || mode === "tags"; const isItemAligned = behaviorVariant === "item-aligned"; const [extraOptions, setExtraOptions] = useState([]); useEffect(() => { if (mode !== "tags" && extraOptions.length > 0) setExtraOptions([]); }, [mode, extraOptions.length]); const { appendTagValues, getOption, handleValueChange, normalizedValue, normalizeValue, resolvedOptions, valueArray } = useSelectValue({ defaultValue, extraOptions, isMultiple, onChange, onSelect, options, setExtraOptions, value }); const { handleOpenChange, mergedOpen } = useSelectOpen({ defaultOpen, onOpenChange, open }); const { filteredOptions, handleSearchChange, handleSearchKeyDown, searchValue, shouldShowSearch, stopSearchPropagation } = useSelectSearch({ appendTagValues, handleOpenChange, mergedOpen, mode, resolvedOptions, showSearch, tokenSeparators }); const virtualState = useSelectVirtual({ filteredOptions, listItemHeight, size, valueArray, virtual }); const portalContainer = usePortalContainer(); const renderValue = useMemo(() => createTriggerValueRenderer({ getOption, isMultiple, labelRender, normalizeValue, placeholder }), [ getOption, isMultiple, labelRender, normalizeValue, placeholder ]); const hasValue = isMultiple ? valueArray.length > 0 : !isValueEmpty(normalizedValue); const showClear = Boolean(allowClear && hasValue && !disabled && !readOnly); const handleClear = useCallback((event) => { event.preventDefault(); event.stopPropagation(); handleValueChange(isMultiple ? [] : null); }, [handleValueChange, isMultiple]); const prefixNode = useMemo(() => resolveIconNode(prefix), [prefix]); const suffixIconNode = useMemo(() => resolveSuffixIcon(suffixIcon, suffixIconProps, loading), [ loading, suffixIcon, suffixIconProps ]); const popupStyle = useMemo(() => { const maxHeight = isItemAligned ? "80vh" : `${listHeight}px`; const baseStyle = { maxHeight, maxWidth: "var(--available-width)", minWidth: "var(--anchor-width)", ["--lobe-select-popup-max-height"]: maxHeight }; if (popupMatchSelectWidth === void 0 || popupMatchSelectWidth === true) return baseStyle; if (typeof popupMatchSelectWidth === "number") return { ...baseStyle, minWidth: popupMatchSelectWidth, width: popupMatchSelectWidth }; return { ...baseStyle, minWidth: "max-content" }; }, [ isItemAligned, listHeight, popupMatchSelectWidth ]); const triggerClassName = cx(triggerVariants({ shadow, size, variant: resolvedVariant }), className, classNames?.root, classNames?.trigger); const isBoldIndicator = selectedIndicatorVariant === "bold"; const itemTextClassName = cx(optionRender ? styles.itemContent : styles.label, styles$1.itemText, classNames?.itemText); const isEmpty = filteredOptions.length === 0; const listContent = isEmpty ? /* @__PURE__ */ jsx(EmptyContent, { classNames }) : renderOptions({ classNames, isBoldIndicator, items: filteredOptions, itemTextClassName, listItemHeight, optionRender, renderVirtualItem: virtualState.renderVirtualItem, virtual }); return /* @__PURE__ */ jsxs(Select.Root, { disabled, id, modal: isItemAligned, multiple: isMultiple, name, open: mergedOpen, readOnly, required, value: normalizedValue, onOpenChange: handleOpenChange, onValueChange: handleValueChange, children: [/* @__PURE__ */ jsxs(Select.Trigger, { autoFocus, className: triggerClassName, disabled, style, children: [ prefixNode !== null && prefixNode !== void 0 && /* @__PURE__ */ jsx("span", { className: cx(styles$1.prefix, classNames?.prefix), children: prefixNode }), /* @__PURE__ */ jsx(Select.Value, { className: cx(styles$1.value, classNames?.value), children: renderValue }), /* @__PURE__ */ jsx(SelectTriggerSuffix, { classNames, showClear, suffixIconNode, onClear: handleClear }) ] }), /* @__PURE__ */ jsx(Select.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx(SelectPositioner, { align: "start", alignItemWithTrigger: isItemAligned, className: styles$1.positioner, side: "bottom", sideOffset: 6, children: /* @__PURE__ */ jsxs(Select.Popup, { style: popupStyle, className: cx(styles.popup, styles$1.popup, popupClassName, classNames?.popup, classNames?.dropdown), children: [shouldShowSearch && /* @__PURE__ */ jsx(SelectSearchInput, { classNames, placeholder, stopPropagation: stopSearchPropagation, value: searchValue, onChange: handleSearchChange, onKeyDown: handleSearchKeyDown }), /* @__PURE__ */ jsx(SelectListSection, { classNames, isEmpty, listContent, listItemHeight, virtual, virtualState })] }) }) })] }); }); Select$1.displayName = "Select"; //#endregion export { Select$1 as default }; //# sourceMappingURL=Select.mjs.map