UNPKG

@trail-ui/react

Version:
182 lines (179 loc) 6.35 kB
import { ListBox } from "./chunk-O34YT5G7.mjs"; import { _Input } from "./chunk-VGAQK5WY.mjs"; import { _Spinner } from "./chunk-JT3O22CN.mjs"; // src/select/select.tsx import { ChevronDownIcon, ChevronUpIcon, ErrorIcon, SearchIcon } from "@trail-ui/icons"; import { clsx } from "@trail-ui/shared-utils"; import { select } from "@trail-ui/theme"; import { cloneElement, forwardRef, useEffect, useMemo, useRef, useState } from "react"; import { Select as AriaSelect, Button, Label, Popover, SelectValue, Text } from "react-aria-components"; import { jsx, jsxs } from "react/jsx-runtime"; function Select(props, ref) { const [isOpen, setIsOpen] = useState(false); const [noResultsFound, setNoResultsFound] = useState(false); const [filteredResults, setFilteredResults] = useState([]); const searchRef = useRef(null); const { children, className, classNames, label, description, errorMessage, items, placement = "bottom", isLoading = false, isSearchable = true, selectorIcon = isOpen ? /* @__PURE__ */ jsx(ChevronUpIcon, { height: 24, width: 24 }) : /* @__PURE__ */ jsx(ChevronDownIcon, { height: 24, width: 24 }), spinnerProps, popoverProps, listBoxProps, ...otherProps } = props; const onInputChange = (value) => { if (Array.isArray(children)) { const filteredResults2 = children.filter((item) => { return item.props.children.toLowerCase().includes(value.toLowerCase()); }); setFilteredResults(filteredResults2); setNoResultsFound(filteredResults2.length === 0 && value.length > 0); } }; useEffect(() => { setFilteredResults([]); setNoResultsFound(false); requestAnimationFrame(() => { var _a; (_a = searchRef == null ? void 0 : searchRef.current) == null ? void 0 : _a.focus(); }); }, [isOpen]); const slots = useMemo(() => select(), []); const baseStyles = clsx(classNames == null ? void 0 : classNames.base, className); const clonedIcon = cloneElement(selectorIcon, { "aria-hidden": true, className: slots.selectorIcon({ class: classNames == null ? void 0 : classNames.selectorIcon }) }); const renderIndicator = useMemo(() => { if (isLoading) { return /* @__PURE__ */ jsx( _Spinner, { "aria-hidden": true, color: "current", size: "sm", ...spinnerProps, className: slots.spinner({ class: classNames == null ? void 0 : classNames.spinner }) } ); } return clonedIcon; }, [isLoading, clonedIcon, spinnerProps, slots, classNames == null ? void 0 : classNames.spinner]); return /* @__PURE__ */ jsxs( AriaSelect, { ref, isOpen, onOpenChange: setIsOpen, className: slots.base({ class: baseStyles }), ...otherProps, children: [ label && /* @__PURE__ */ jsx(Label, { className: slots.label({ class: classNames == null ? void 0 : classNames.label }), children: label }), /* @__PURE__ */ jsxs( "div", { className: slots.mainWrapper({ class: classNames == null ? void 0 : classNames.mainWrapper }), role: "combobox", "aria-expanded": isOpen, "aria-controls": "listbox-id", children: [ /* @__PURE__ */ jsxs(Button, { className: slots.trigger({ class: classNames == null ? void 0 : classNames.trigger }), children: [ /* @__PURE__ */ jsx(SelectValue, { className: slots.value({ class: classNames == null ? void 0 : classNames.value }) }), renderIndicator ] }), errorMessage ? /* @__PURE__ */ jsxs( Text, { slot: "errorMessage", elementType: "div", className: `${slots.errorMessage({ class: classNames == null ? void 0 : classNames.errorMessage })} flex gap-1`, children: [ /* @__PURE__ */ jsx( ErrorIcon, { height: 16, width: 16, className: "text-red-800 dark:text-red-600", role: "img", "aria-label": "Error", "aria-hidden": "false" } ), /* @__PURE__ */ jsx("span", { children: errorMessage }) ] } ) : description ? /* @__PURE__ */ jsx( Text, { slot: "description", elementType: "div", className: slots.description({ class: classNames == null ? void 0 : classNames.description }), children: /* @__PURE__ */ jsx("span", { children: description }) } ) : null ] } ), /* @__PURE__ */ jsxs( Popover, { placement, className: slots.popover({ class: classNames == null ? void 0 : classNames.popover }), ...popoverProps, children: [ isSearchable && /* @__PURE__ */ jsxs("div", { className: "w-full px-2 pb-2", children: [ /* @__PURE__ */ jsx( _Input, { ref: searchRef, variant: "compact", "aria-label": "Search", placeholder: "Search", startContent: /* @__PURE__ */ jsx(SearchIcon, { height: 16, width: 16 }), onChange: (e) => onInputChange(e.target.value), className: slots.searchInput({ class: classNames == null ? void 0 : classNames.searchInput }) } ), noResultsFound && /* @__PURE__ */ jsx("p", { className: "mt-4 text-center text-sm text-neutral-400", children: "No results found" }) ] }), /* @__PURE__ */ jsx(ListBox, { id: "listbox-id", ...listBoxProps, items, children: (filteredResults == null ? void 0 : filteredResults.length) > 0 ? filteredResults : noResultsFound ? [] : children }) ] } ) ] } ); } var _Select = forwardRef(Select); export { _Select };