Files
Dwinzo_Demo/app/src/components/ui/inputs/DataDetailedDropdown.tsx

124 lines
4.9 KiB
TypeScript

import React, { useState, useMemo, useRef, useEffect } from "react";
import { EyeDroperIcon, SearchIcon } from "../../icons/ExportCommonIcons";
export type DropdownItem = {
id: string;
label: string;
icon?: React.ReactNode;
};
type DataDetailedDropdownProps = {
title: string;
placeholder?: string;
sections: {
title?: string;
items: DropdownItem[];
}[];
value?: DropdownItem | null;
onChange?: (item: DropdownItem) => void;
dropDownHeader?: string;
eyedroper?: boolean;
eyeDropperActive?: boolean;
onEyeDrop?: () => void;
};
const DataDetailedDropdown: React.FC<DataDetailedDropdownProps> = ({ title, placeholder = "Select value", sections, value, onChange, dropDownHeader, eyedroper, eyeDropperActive, onEyeDrop }) => {
const [open, setOpen] = useState(false);
const [search, setSearch] = useState("");
const [isEyeDroperActiveLocal, setIsEyeDroperActiveLocal] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const isEyeActive = eyeDropperActive !== undefined ? eyeDropperActive : isEyeDroperActiveLocal;
const handleEyeClick = () => {
if (onEyeDrop) {
onEyeDrop();
} else {
setIsEyeDroperActiveLocal(!isEyeDroperActiveLocal);
}
};
// Close dropdown on outside click
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
setOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
const filteredSections = useMemo(() => {
if (!search) return sections;
return sections
.map((section) => ({
...section,
items: section.items.filter((item) => item.label.toLowerCase().includes(search.toLowerCase())),
}))
.filter((section) => section.items.length > 0);
}, [search, sections]);
return (
<div className="data-detailed-dropdown" ref={containerRef}>
<div className="title">{title}</div>
<div className="input-container">
<div className="input-wrapper">
<div className="input" onClick={() => setOpen((v) => !v)}>
<div className="key">{value?.label || placeholder}</div>
<div className="icon"></div>
</div>
{open && (
<div className="dropdown-panel">
{dropDownHeader && <div className="heading">{dropDownHeader}</div>}
<div className="search">
<div className="icon">
<SearchIcon />
</div>
<input placeholder="Search Assets" value={search} onChange={(e) => setSearch(e.target.value)} />
</div>
{filteredSections.map((section, index) => (
<div key={index} className="data-section">
{section.title && (
<div className="data-header">
<div className="data-section-title">{section.title}</div>
<div className="data-section-count">{section.items.length}</div>
</div>
)}
{section.items.map((item) => (
<div
key={item.id}
className="item"
onClick={() => {
onChange?.(item);
setOpen(false);
}}
>
{item.icon && <span className="icon">{item.icon}</span>}
<span>{item.label}</span>
</div>
))}
</div>
))}
</div>
)}
</div>
{eyedroper && (
<div className={`add-icon ${isEyeActive ? "active" : ""}`} onClick={handleEyeClick}>
<EyeDroperIcon isActive={isEyeActive} />
</div>
)}
</div>
</div>
);
};
export default DataDetailedDropdown;