import React from "react"; import { createPortal } from "react-dom"; import { useComboBoxState } from "react-stately"; import { useComboBox } from "react-aria"; import { styled, theme } from "../theme"; import type * as WPDS from "../theme"; import type { ComboBoxState, Key } from "react-stately"; import type { AriaListBoxOptions } from "react-aria"; import type { CollectionChildren } from "@react-types/shared"; type InputSearchContextProps = { state: ComboBoxState; inputRef: React.MutableRefObject; listBoxRef: React.MutableRefObject; popoverRef: React.MutableRefObject; containerRef: React.MutableRefObject; inputProps: React.InputHTMLAttributes; listBoxProps: AriaListBoxOptions; setCollectionChildren: React.Dispatch< React.SetStateAction | undefined> >; setDisabledKeys: React.Dispatch< React.SetStateAction | undefined> >; isDisabled?: boolean; setUsePortal: React.Dispatch>; setPortalDomNode: React.Dispatch>; }; export const InputSearchContext = React.createContext( {} as InputSearchContextProps ); const StyledRoot = styled("div", { width: "100%", position: "relative", variants: { portal: { false: { "&:focus-within::after": { content: "", borderRadius: theme.radii["012"], border: `1px solid ${theme.colors.signal}`, inset: 0, position: "absolute", pointerEvents: "none", zIndex: 1, }, }, }, }, }); export type InputSearchRootProps = { /** Defines a string value that labels the current element. */ "aria-label"?: string; /** Identifies the element (or elements) that labels the current element. */ "aria-labelledby"?: string; /** InputSearch.Root expects to receive InputSearch.Input and InputSearch.Popover as children.*/ children?: React.ReactNode; /** Override CSS */ css?: WPDS.CSS; /** Whether the input field should be disabled or not */ disabled?: boolean; /** If true, the popover opens when focus is on the text box. */ openOnFocus?: boolean; /** Called with the selection value when the user makes a selection from the list. */ onSelect?: (value: string) => void; } & React.ComponentPropsWithoutRef<"div">; export const InputSearchRoot = ({ children, css, disabled, openOnFocus, onSelect, ...props }: InputSearchRootProps) => { const [collectionChildren, setCollectionChildren] = React.useState>(); const [disabledKeys, setDisabledKeys] = React.useState>(); const state = useComboBoxState({ children: collectionChildren, disabledKeys, allowsCustomValue: true, allowsEmptyCollection: true, menuTrigger: openOnFocus ? "focus" : "input", ...props, }); const inputRef = React.useRef(null); const listBoxRef = React.useRef(null); const popoverRef = React.useRef(null); const { inputProps, listBoxProps } = useComboBox( { // Provide aria-label as fallback to satisfy react-aria's accessibility requirements. // When InputText provides a visible