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
JavaScript
;
"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