UNPKG

@gluestack-ui/select

Version:

A universal headless select component for React Native, Next.js & React

89 lines (88 loc) 3.42 kB
import React, { forwardRef } from 'react'; import { SelectContext } from './SelectContext'; import { useHover } from '@react-native-aria/interactions'; import { useControllableState } from '@gluestack-ui/hooks'; import { useFormControlContext } from '@gluestack-ui/form-control'; import { useFocusRing } from '@react-native-aria/focus'; export const Select = (StyledSelect) => forwardRef(({ children, isDisabled, isInvalid, isReadOnly, isRequired, isHovered: isHoveredProp, isFocused: isFocusedProp, isFocusVisible: isFocusVisibleProp, selectedValue, selectedLabel: selectedLabel, onValueChange, defaultValue, initialLabel, onClose, onOpen, closeOnOverlayClick, ...props }, ref) => { const [placeholderState, setPlaceholderState] = React.useState(''); const [isFocused, setIsFocused] = React.useState(false); const { isFocusVisible, focusProps } = useFocusRing(); const hoverRef = React.useRef(null); const { hoverProps, isHovered } = useHover({ isDisabled }, hoverRef); const [label, setLabel] = React.useState(initialLabel ?? selectedLabel); const [isOpen, setIsOpen] = React.useState(false); const [value, setValue] = useControllableState({ value: selectedValue, defaultValue, onChange: (newValue) => { onValueChange && onValueChange(newValue); }, }); React.useEffect(() => { if (selectedValue === null) { setLabel(initialLabel); } }, [selectedValue, initialLabel]); const handleClose = React.useCallback(() => { setIsOpen(false); onClose && onClose(); }, [onClose, setIsOpen]); const inputProps = useFormControlContext(); const contextValue = React.useMemo(() => { return { isHovered: isHovered || isHoveredProp, isFocused: isFocused || isFocusedProp, isDisabled: isDisabled || inputProps.isDisabled, isInvalid: isInvalid || inputProps.isInvalid, isRequired: isRequired || inputProps.isRequired, isReadOnly: isReadOnly || inputProps.isReadOnly, hoverRef: hoverRef, hoverProps: hoverProps, isFocusVisible: isFocusVisibleProp || isFocusVisible, setIsOpen: setIsOpen, onOpen: onOpen, isOpen: isOpen, onValueChange: setValue, handleClose: handleClose, closeOnOverlayClick: closeOnOverlayClick, value: value, label: label, setLabel: setLabel, placeholder: placeholderState, setPlaceholder: setPlaceholderState, setFocused: setIsFocused, focusProps: focusProps, }; }, [ closeOnOverlayClick, handleClose, hoverProps, isDisabled, isFocusVisible, isFocusVisibleProp, isFocused, isFocusedProp, isHovered, isHoveredProp, isInvalid, isOpen, onOpen, setValue, value, setLabel, label, setIsFocused, focusProps, isRequired, inputProps, isReadOnly, setPlaceholderState, placeholderState, ]); return (<StyledSelect ref={ref} tabIndex={-1} {...props}> <SelectContext.Provider value={contextValue}> {children} </SelectContext.Provider> </StyledSelect>); });