UNPKG

lightswind

Version:

A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.

71 lines 5.6 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExpandableSearchBar = ExpandableSearchBar; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const framer_motion_1 = require("framer-motion"); const lucide_react_1 = require("lucide-react"); const utils_1 = require("@/components/lib/utils"); function ExpandableSearchBar({ placeholder = "Search...", onChange, onSubmit, className, expandedWidth = "18rem", // 288px (w-72) }) { const [isExpanded, setIsExpanded] = (0, react_1.useState)(false); const [value, setValue] = (0, react_1.useState)(""); const inputRef = (0, react_1.useRef)(null); const containerRef = (0, react_1.useRef)(null); // Focus input when expanded (0, react_1.useEffect)(() => { if (isExpanded && inputRef.current) { inputRef.current.focus(); } }, [isExpanded]); // Handle outside click to collapse if empty (0, react_1.useEffect)(() => { const handleClickOutside = (e) => { if (containerRef.current && !containerRef.current.contains(e.target) && value === "") { setIsExpanded(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [value]); const handleSubmit = (e) => { e.preventDefault(); if (onSubmit) onSubmit(value); }; const handleClear = () => { setValue(""); if (onChange) onChange(""); inputRef.current?.focus(); }; return ((0, jsx_runtime_1.jsx)("div", { ref: containerRef, className: (0, utils_1.cn)("relative flex items-center justify-end", className), // Ensures the container takes up the max space when expanded to prevent layout shifts if needed style: { width: isExpanded ? expandedWidth : "2.5rem" }, children: (0, jsx_runtime_1.jsxs)(framer_motion_1.motion.form, { initial: false, animate: { width: isExpanded ? expandedWidth : "2.5rem", backgroundColor: isExpanded ? "var(--background)" : "var(--muted)", }, transition: { type: "spring", stiffness: 400, damping: 30, }, onSubmit: handleSubmit, className: (0, utils_1.cn)("relative flex h-10 items-center overflow-hidden rounded-full border shadow-sm transition-colors focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0", isExpanded ? "border-border/50 bg-background" : "border-transparent bg-muted hover:bg-muted/80 cursor-pointer"), onClick: () => !isExpanded && setIsExpanded(true), children: [(0, jsx_runtime_1.jsx)("button", { type: "button", className: "absolute left-0 flex h-full w-10 items-center justify-center text-muted-foreground transition-colors hover:text-foreground z-10 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0", onClick: () => { if (isExpanded && value === "") { setIsExpanded(false); } else if (!isExpanded) { setIsExpanded(true); } }, "aria-label": "Search", disabled: isExpanded && value !== "", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Search, { className: "h-4 w-4" }) }), (0, jsx_runtime_1.jsx)("input", { ref: inputRef, type: "text", value: value, onChange: (e) => { setValue(e.target.value); if (onChange) onChange(e.target.value); }, placeholder: placeholder, className: "h-full w-full border-none bg-transparent pl-10 pr-10 text-sm outline-none placeholder:text-muted-foreground/60 focus:border-transparent focus:outline-none focus:ring-0 focus-visible:ring-0 focus-visible:outline-none focus:ring-offset-0 focus-visible:ring-offset-0", style: { pointerEvents: isExpanded ? "auto" : "none", opacity: isExpanded ? 1 : 0, boxShadow: "none", }, tabIndex: isExpanded ? 0 : -1 }), (0, jsx_runtime_1.jsxs)(framer_motion_1.AnimatePresence, { children: [isExpanded && value === "" && ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.8 }, transition: { duration: 0.15 }, className: "absolute right-3 flex items-center justify-center pointer-events-none", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex h-5 items-center gap-1 rounded bg-muted px-1.5 text-[10px] font-medium text-muted-foreground", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Command, { className: "h-3 w-3" }), (0, jsx_runtime_1.jsx)("span", { children: "K" })] }) })), isExpanded && value !== "" && ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.button, { type: "button", initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.8 }, transition: { duration: 0.15 }, onClick: handleClear, className: "absolute right-0 flex h-full w-10 items-center justify-center text-muted-foreground hover:text-foreground focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0", "aria-label": "Clear search", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-4 w-4" }) }))] })] }) })); } //# sourceMappingURL=expandable-search-bar.js.map