UNPKG

@lobehub/ui

Version:

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

1 lines 22 kB
{"version":3,"file":"hooks.mjs","names":[],"sources":["../../../src/base-ui/Select/hooks.tsx"],"sourcesContent":["'use client';\n\nimport {\n type ChangeEvent,\n type HTMLAttributes,\n type KeyboardEvent,\n type MutableRefObject,\n type Ref,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { useAppElement } from '@/ThemeProvider';\n\nimport {\n countVirtualItems,\n getOptionSearchText,\n isGroupOption,\n isValueEmpty,\n normalizeValueFor,\n splitBySeparators,\n} from './helpers';\nimport {\n type SelectOption,\n type SelectOptions,\n type SelectProps,\n type SelectRootChangeEventDetails,\n type SelectSize,\n} from './type';\n\ninterface UseSelectValueParams {\n defaultValue: SelectProps['defaultValue'];\n extraOptions: SelectOption<any>[];\n isMultiple: boolean;\n onChange: SelectProps['onChange'];\n onSelect: SelectProps['onSelect'];\n options: SelectOptions<any> | undefined;\n setExtraOptions: React.Dispatch<React.SetStateAction<SelectOption<any>[]>>;\n value: SelectProps['value'];\n}\n\nexport function useSelectValue({\n defaultValue,\n extraOptions,\n isMultiple,\n onChange,\n onSelect,\n options,\n setExtraOptions,\n value,\n}: UseSelectValueParams) {\n const [uncontrolledValue, setUncontrolledValue] = useState<any>(() => {\n if (defaultValue !== undefined) return defaultValue;\n return isMultiple ? [] : null;\n });\n\n const normalizeValue = useMemo(() => normalizeValueFor(isMultiple), [isMultiple]);\n\n const mergedValue = value !== undefined ? value : uncontrolledValue;\n const normalizedValue = useMemo(() => normalizeValue(mergedValue), [mergedValue, normalizeValue]);\n\n const valueArray = useMemo(() => {\n if (isMultiple) return normalizedValue as any[];\n return isValueEmpty(normalizedValue) ? [] : [normalizedValue];\n }, [isMultiple, normalizedValue]);\n\n const { optionMap, resolvedOptions } = useMemo(() => {\n const baseOptions = options ?? [];\n const optionValueMap = new Map<any, SelectOption<any>>();\n\n const addOption = (item: SelectOption<any>) => {\n if (!optionValueMap.has(item.value)) {\n optionValueMap.set(item.value, item);\n }\n };\n\n baseOptions.forEach((item) => {\n if (isGroupOption(item)) {\n item.options.forEach(addOption);\n } else {\n addOption(item);\n }\n });\n\n const filteredExtraOptions = extraOptions.filter((item) => !optionValueMap.has(item.value));\n filteredExtraOptions.forEach(addOption);\n const mergedOptions: SelectOptions<any> = [...baseOptions, ...filteredExtraOptions];\n\n const missingValueOptions: SelectOption<any>[] = valueArray\n .filter((val) => !optionValueMap.has(val))\n .map((val) => ({ label: String(val), value: val }));\n missingValueOptions.forEach(addOption);\n\n return {\n optionMap: optionValueMap,\n resolvedOptions: missingValueOptions.length\n ? [...mergedOptions, ...missingValueOptions]\n : mergedOptions,\n };\n }, [extraOptions, options, valueArray]);\n\n const getOption = useCallback(\n (optionValue: any): SelectOption<any> => {\n const matched = optionMap.get(optionValue);\n if (matched) return matched;\n if (optionValue && typeof optionValue === 'object' && 'label' in optionValue) {\n return { label: (optionValue as any).label, value: optionValue };\n }\n return { label: String(optionValue), value: optionValue };\n },\n [optionMap],\n );\n\n const previousValueRef = useRef<any>(normalizedValue);\n useEffect(() => {\n previousValueRef.current = normalizedValue;\n }, [normalizedValue]);\n\n const handleValueChange = useCallback(\n (nextValue: any) => {\n const normalizedNextValue = normalizeValue(nextValue);\n const previousValue = previousValueRef.current;\n\n if (isMultiple) {\n const prevValues = Array.isArray(previousValue) ? previousValue : [];\n const nextValues = Array.isArray(normalizedNextValue) ? normalizedNextValue : [];\n const addedValues = nextValues.filter(\n (val) => !prevValues.some((prev) => Object.is(prev, val)),\n );\n addedValues.forEach((val) => onSelect?.(val, getOption(val)));\n\n if (value === undefined) setUncontrolledValue(nextValues);\n onChange?.(\n nextValues,\n nextValues.map((val) => getOption(val)),\n );\n } else {\n if (!isValueEmpty(normalizedNextValue) && !Object.is(previousValue, normalizedNextValue)) {\n onSelect?.(normalizedNextValue, getOption(normalizedNextValue));\n }\n if (value === undefined) setUncontrolledValue(normalizedNextValue);\n onChange?.(\n isValueEmpty(normalizedNextValue) ? undefined : normalizedNextValue,\n isValueEmpty(normalizedNextValue) ? undefined : getOption(normalizedNextValue),\n );\n }\n\n previousValueRef.current = normalizedNextValue;\n },\n [getOption, isMultiple, normalizeValue, onChange, onSelect, value],\n );\n\n const appendTagValues = useCallback(\n (rawValues: string[]) => {\n const valuesToAdd = rawValues.map((val) => val.trim()).filter(Boolean);\n if (!valuesToAdd.length) return;\n\n const currentValues = Array.isArray(previousValueRef.current)\n ? previousValueRef.current\n : valueArray;\n const nextValues = [...currentValues];\n const newOptionValues = valuesToAdd.filter((val) => !optionMap.has(val));\n\n if (newOptionValues.length > 0) {\n setExtraOptions((prev) => {\n const existingValues = new Set(prev.map((item) => item.value));\n const merged = [...prev];\n newOptionValues.forEach((val) => {\n if (!existingValues.has(val)) {\n merged.push({ label: val, value: val });\n }\n });\n return merged;\n });\n }\n\n valuesToAdd.forEach((val) => {\n if (!nextValues.some((item) => Object.is(item, val))) {\n nextValues.push(val);\n }\n });\n\n if (nextValues.length !== valueArray.length) {\n handleValueChange(nextValues);\n }\n },\n [handleValueChange, optionMap, setExtraOptions, valueArray],\n );\n\n const removeLastTagValue = useCallback(() => {\n const currentValues = Array.isArray(previousValueRef.current)\n ? previousValueRef.current\n : valueArray;\n if (currentValues.length > 0) handleValueChange(currentValues.slice(0, -1));\n }, [handleValueChange, valueArray]);\n\n return {\n appendTagValues,\n getOption,\n handleValueChange,\n normalizedValue,\n normalizeValue,\n optionMap,\n resolvedOptions,\n removeLastTagValue,\n valueArray,\n };\n}\n\ninterface UseSelectOpenParams {\n defaultOpen: boolean | undefined;\n onOpenChange: SelectProps['onOpenChange'];\n open: boolean | undefined;\n}\n\nexport function useSelectOpen({ defaultOpen, onOpenChange, open }: UseSelectOpenParams) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(Boolean(defaultOpen));\n\n useEffect(() => {\n if (open !== undefined) setUncontrolledOpen(open);\n }, [open]);\n\n const mergedOpen = open ?? uncontrolledOpen;\n\n const handleOpenChange = useCallback(\n (nextOpen: boolean, eventDetails?: SelectRootChangeEventDetails) => {\n onOpenChange?.(nextOpen, eventDetails);\n if (open === undefined) setUncontrolledOpen(nextOpen);\n },\n [onOpenChange, open],\n );\n\n return { handleOpenChange, mergedOpen };\n}\n\ninterface UseSelectSearchParams {\n appendTagValues: (values: string[]) => void;\n handleOpenChange: (nextOpen: boolean) => void;\n mergedOpen: boolean;\n mode: SelectProps['mode'];\n removeLastTagValue: () => void;\n resolvedOptions: SelectOptions;\n showSearch: boolean | undefined;\n tokenSeparators: string[] | undefined;\n}\n\nexport function useSelectSearch({\n appendTagValues,\n handleOpenChange,\n mergedOpen,\n mode,\n removeLastTagValue,\n resolvedOptions,\n showSearch,\n tokenSeparators,\n}: UseSelectSearchParams) {\n const [searchValue, setSearchValue] = useState('');\n const shouldShowSearch = Boolean(showSearch || mode === 'tags');\n\n useEffect(() => {\n if (!mergedOpen) setSearchValue('');\n }, [mergedOpen]);\n\n const handleSearchChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const nextValue = event.target.value;\n if (mode === 'tags') {\n const parts = splitBySeparators(nextValue, tokenSeparators);\n if (parts.length > 1) {\n const pending = parts.pop() ?? '';\n appendTagValues(parts.filter(Boolean));\n setSearchValue(pending);\n return;\n }\n }\n setSearchValue(nextValue);\n },\n [appendTagValues, mode, tokenSeparators],\n );\n\n const handleSearchKeyDown = useCallback(\n (event: KeyboardEvent<HTMLInputElement>) => {\n event.stopPropagation();\n\n if (event.key === 'Escape') {\n handleOpenChange(false);\n return;\n }\n if (mode !== 'tags') return;\n\n if (event.key === 'Backspace' && !searchValue) {\n event.preventDefault();\n removeLastTagValue();\n return;\n }\n\n const isSeparator = tokenSeparators?.includes(event.key);\n if (event.key === 'Enter' || isSeparator) {\n event.preventDefault();\n event.stopPropagation();\n appendTagValues([searchValue]);\n setSearchValue('');\n }\n },\n [appendTagValues, handleOpenChange, mode, removeLastTagValue, searchValue, tokenSeparators],\n );\n\n // Stop propagation in capture phase + on keyup to block base-ui Popup-level\n // `useTypeahead` (and any ancestor typeahead) from hijacking the search\n // input's first-letter focus behavior. Do not remove.\n const stopSearchPropagation = useCallback((event: KeyboardEvent<HTMLInputElement>) => {\n event.stopPropagation();\n }, []);\n\n const filteredOptions = useMemo(() => {\n if (!shouldShowSearch || !searchValue.trim()) return resolvedOptions;\n const query = searchValue.trim().toLowerCase();\n\n return resolvedOptions\n .map((item) => {\n if (isGroupOption(item)) {\n const groupItems = item.options.filter((option) =>\n getOptionSearchText(option).toLowerCase().includes(query),\n );\n if (!groupItems.length) return null;\n return { ...item, options: groupItems };\n }\n return getOptionSearchText(item).toLowerCase().includes(query) ? item : null;\n })\n .filter(Boolean) as SelectOptions;\n }, [resolvedOptions, searchValue, shouldShowSearch]);\n\n return {\n filteredOptions,\n handleSearchChange,\n handleSearchKeyDown,\n searchValue,\n shouldShowSearch,\n stopSearchPropagation,\n };\n}\n\ninterface UseSelectVirtualParams {\n filteredOptions: SelectOptions;\n listItemHeight: number | undefined;\n size: SelectSize;\n valueArray: any[];\n virtual: boolean | undefined;\n}\n\nexport function useSelectVirtual({\n filteredOptions,\n listItemHeight,\n size,\n valueArray,\n virtual,\n}: UseSelectVirtualParams) {\n const listRef = useRef<HTMLDivElement | null>(null);\n const pointerScrollRef = useRef(false);\n const pointerScrollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const renderVirtualItem = useCallback((props: HTMLAttributes<HTMLDivElement>) => {\n const { ref, ...rest } = props as HTMLAttributes<HTMLDivElement> & {\n ref?: Ref<HTMLDivElement>;\n };\n\n return (\n <div\n {...rest}\n ref={(node) => {\n if (node) {\n node.scrollIntoView = (...args) => {\n if (!pointerScrollRef.current) {\n HTMLElement.prototype.scrollIntoView.call(node, ...args);\n }\n };\n }\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref && 'current' in ref) {\n (ref as MutableRefObject<HTMLDivElement | null>).current = node;\n }\n }}\n />\n );\n }, []);\n\n const markPointerScroll = useCallback(() => {\n pointerScrollRef.current = true;\n if (pointerScrollTimeoutRef.current) {\n clearTimeout(pointerScrollTimeoutRef.current);\n }\n pointerScrollTimeoutRef.current = setTimeout(() => {\n pointerScrollRef.current = false;\n }, 120);\n }, []);\n\n const handleListScroll = useCallback(() => {\n if (!virtual || !pointerScrollRef.current) return;\n const listElement = listRef.current;\n const activeElement = document.activeElement;\n if (listElement && activeElement && listElement.contains(activeElement)) {\n listElement.focus({ preventScroll: true });\n }\n }, [virtual]);\n\n useEffect(() => {\n return () => {\n if (pointerScrollTimeoutRef.current) {\n clearTimeout(pointerScrollTimeoutRef.current);\n }\n };\n }, []);\n\n const virtualListStyle = useMemo(() => {\n if (!virtual) return undefined;\n const rowCount = countVirtualItems(filteredOptions);\n const maxVisibleRows = 6;\n const estimatedRowHeight =\n listItemHeight ?? (size === 'large' ? 40 : size === 'small' ? 28 : 32);\n const visibleRows = Math.min(Math.max(rowCount, 1), maxVisibleRows);\n const estimatedHeight = visibleRows * estimatedRowHeight + 8;\n\n return {\n height: `min(${estimatedHeight}px, var(--lobe-select-available-height, var(--available-height)))`,\n };\n }, [filteredOptions, listItemHeight, size, virtual]);\n\n const keepMountedIndices = useMemo(() => {\n if (!virtual || valueArray.length === 0) return undefined;\n const selectedSet = new Set(valueArray);\n const indices: number[] = [];\n let index = 0;\n\n filteredOptions.forEach((item) => {\n if (isGroupOption(item)) {\n if (item.options.some((option) => selectedSet.has(option.value))) {\n indices.push(index);\n }\n index += 1;\n return;\n }\n if (selectedSet.has(item.value)) indices.push(index);\n index += 1;\n });\n\n return indices.length ? indices : undefined;\n }, [filteredOptions, valueArray, virtual]);\n\n return {\n handleListScroll,\n keepMountedIndices,\n listRef,\n markPointerScroll,\n renderVirtualItem,\n virtualListStyle,\n };\n}\n\nexport function usePortalContainer() {\n const appElement = useAppElement();\n // `appElement` is the ThemeProvider wrapper div, which uses `display: contents`\n // so it has no layout box. `@base-ui/react/select` fails to mount its Popup\n // into a `display: contents` container in certain hosts (editor/chat inputs\n // with focus traps). Fall back to `document.body` in that case; keep the\n // original behavior when the wrapper has a real layout (older themes, SSR\n // snapshot, etc.).\n return useMemo(() => {\n if (typeof window === 'undefined') return appElement;\n if (!(appElement instanceof HTMLElement)) return undefined;\n const display = window.getComputedStyle(appElement).display;\n return display === 'contents' ? document.body : appElement;\n }, [appElement]);\n}\n"],"mappings":"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"}