UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

269 lines (267 loc) 9.39 kB
import { DropdownMenuContent, DropdownMenuItem, DropdownMenu_default, createDropdownStore } from "./chunk-DHHHYBOU.mjs"; // src/components/Search/Search.tsx import { XIcon } from "@phosphor-icons/react/dist/csr/X"; import { MagnifyingGlassIcon } from "@phosphor-icons/react/dist/csr/MagnifyingGlass"; import { forwardRef, useState, useId, useMemo, useEffect, useRef } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; var filterOptions = (options, query) => { if (!query || query.length < 1) return []; return options.filter( (option) => option.toLowerCase().includes(query.toLowerCase()) ); }; var updateInputValue = (value, ref, onChange) => { if (!onChange) return; if (ref && "current" in ref && ref.current) { ref.current.value = value; const event = new Event("input", { bubbles: true }); Object.defineProperty(event, "target", { writable: false, value: ref.current }); onChange(event); } else { const event = { target: { value }, currentTarget: { value } }; onChange(event); } }; var Search = forwardRef( ({ options = [], onSelect, onSearch, showDropdown: controlledShowDropdown, onDropdownChange, dropdownMaxHeight = 240, noResultsText = "Nenhum resultado encontrado", className = "", containerClassName = "", disabled, readOnly, id, onClear, value, onChange, placeholder = "Buscar...", onKeyDown: userOnKeyDown, debounceMs = 0, ...props }, ref) => { const [dropdownOpen, setDropdownOpen] = useState(false); const [forceClose, setForceClose] = useState(false); const justSelectedRef = useRef(false); const dropdownStore = useRef(createDropdownStore()).current; const dropdownRef = useRef(null); const inputElRef = useRef(null); const debounceTimer = useRef(null); useEffect(() => { return () => { if (debounceTimer.current) clearTimeout(debounceTimer.current); }; }, []); const filteredOptions = useMemo(() => { if (!options.length) { return []; } const filtered = filterOptions(options, value || ""); return filtered; }, [options, value]); const showDropdown = !forceClose && (controlledShowDropdown ?? (dropdownOpen && value && String(value).length > 0)); const setOpenAndNotify = (open) => { setDropdownOpen(open); dropdownStore.setState({ open }); onDropdownChange?.(open); }; useEffect(() => { if (justSelectedRef.current) { justSelectedRef.current = false; return; } if (forceClose) { setOpenAndNotify(false); return; } const shouldShow = Boolean(value && String(value).length > 0); setOpenAndNotify(shouldShow); }, [value, forceClose, onDropdownChange, dropdownStore]); const handleSelectOption = (option) => { justSelectedRef.current = true; setForceClose(true); onSelect?.(option); setOpenAndNotify(false); updateInputValue(option, ref, onChange); }; useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setOpenAndNotify(false); } }; if (showDropdown) { document.addEventListener("click", handleClickOutside); } return () => { document.removeEventListener("click", handleClickOutside); }; }, [showDropdown, dropdownStore, onDropdownChange]); const generatedId = useId(); const inputId = id ?? `search-${generatedId}`; const dropdownId = `${inputId}-dropdown`; const handleClear = () => { if (debounceTimer.current) { clearTimeout(debounceTimer.current); debounceTimer.current = null; } if (onClear) { onClear(); } else { updateInputValue("", ref, onChange); } }; const handleClearClick = (e) => { e.preventDefault(); e.stopPropagation(); handleClear(); }; const handleSearchIconClick = (e) => { e.preventDefault(); e.stopPropagation(); setTimeout(() => { inputElRef.current?.focus(); }, 0); }; const handleInputChange = (e) => { setForceClose(false); onChange?.(e); if (debounceMs > 0) { if (debounceTimer.current) clearTimeout(debounceTimer.current); const value2 = e.target.value; debounceTimer.current = setTimeout(() => { onSearch?.(value2); }, debounceMs); } else { onSearch?.(e.target.value); } }; const handleKeyDown = (e) => { userOnKeyDown?.(e); if (e.defaultPrevented) return; if (e.key === "Enter") { e.preventDefault(); if (showDropdown && filteredOptions.length > 0) { handleSelectOption(filteredOptions[0]); } else if (value) { onSearch?.(String(value)); setForceClose(true); setOpenAndNotify(false); } } }; const getInputStateClasses = (disabled2, readOnly2) => { if (disabled2) return "cursor-not-allowed opacity-40"; if (readOnly2) return "cursor-default focus:outline-none !text-text-900"; return "hover:border-border-400"; }; const hasValue = String(value ?? "").length > 0; const showClearButton = hasValue && !disabled && !readOnly; const showSearchIcon = !hasValue && !disabled && !readOnly; return /* @__PURE__ */ jsxs( "div", { ref: dropdownRef, className: `w-full max-w-lg md:w-[488px] ${containerClassName}`, children: [ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center", children: [ /* @__PURE__ */ jsx( "input", { ref: (node) => { if (ref) { if (typeof ref === "function") ref(node); else ref.current = node; } inputElRef.current = node; }, id: inputId, type: "text", className: `w-full py-0 px-4 pr-10 font-normal text-text-900 focus:outline-primary-950 border rounded-full bg-background focus:bg-primary-50 border-border-300 focus:border-2 focus:border-primary-950 h-10 placeholder:text-text-600 ${getInputStateClasses(disabled, readOnly)} ${className}`, value, onChange: handleInputChange, onKeyDown: handleKeyDown, disabled, readOnly, placeholder, "aria-expanded": showDropdown ? "true" : void 0, "aria-haspopup": options.length > 0 ? "listbox" : void 0, "aria-controls": showDropdown ? dropdownId : void 0, "aria-autocomplete": "list", role: options.length > 0 ? "combobox" : void 0, ...props } ), showClearButton && /* @__PURE__ */ jsx("div", { className: "absolute right-3 top-1/2 transform -translate-y-1/2", children: /* @__PURE__ */ jsx( "button", { type: "button", className: "p-0 border-0 bg-transparent cursor-pointer", onMouseDown: handleClearClick, "aria-label": "Limpar busca", children: /* @__PURE__ */ jsx("span", { className: "w-6 h-6 text-text-800 flex items-center justify-center hover:text-text-600 transition-colors", children: /* @__PURE__ */ jsx(XIcon, {}) }) } ) }), showSearchIcon && /* @__PURE__ */ jsx("div", { className: "absolute right-3 top-1/2 transform -translate-y-1/2", children: /* @__PURE__ */ jsx( "button", { type: "button", className: "p-0 border-0 bg-transparent cursor-pointer", onMouseDown: handleSearchIconClick, "aria-label": "Buscar", children: /* @__PURE__ */ jsx("span", { className: "w-6 h-6 text-text-800 flex items-center justify-center hover:text-text-600 transition-colors", children: /* @__PURE__ */ jsx(MagnifyingGlassIcon, {}) }) } ) }) ] }), showDropdown && /* @__PURE__ */ jsx(DropdownMenu_default, { open: showDropdown, onOpenChange: setDropdownOpen, children: /* @__PURE__ */ jsx( DropdownMenuContent, { id: dropdownId, className: "w-full mt-1", style: { maxHeight: dropdownMaxHeight }, align: "start", children: filteredOptions.length > 0 ? filteredOptions.map((option) => /* @__PURE__ */ jsx( DropdownMenuItem, { onClick: () => handleSelectOption(option), className: "text-text-700 text-base leading-6 cursor-pointer", children: option }, option )) : /* @__PURE__ */ jsx("div", { className: "px-3 py-3 text-text-700 text-base", children: noResultsText }) } ) }) ] } ); } ); Search.displayName = "Search"; var Search_default = Search; export { Search_default }; //# sourceMappingURL=chunk-YMDK7D7Z.mjs.map