{React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
// Clone the element and pass the `onSelect` prop only if it's expected
return React.cloneElement(child as React.ReactElement, { onSelect });
}
return child; // Return non-element children as-is
})}
)}
);
};
// Recursive Function to Render Nested Data
const renderNestedData = (
data: Record,
onSelect: (selectedLabel: string) => void
) => {
return Object.entries(data).map(([key, value]) => {
if (typeof value === "object" && !Array.isArray(value)) {
// If the value is an object, render it as a nested dropdown
return (
{renderNestedData(value, onSelect)}
);
} else if (Array.isArray(value)) {
// If the value is an array, render each item as a dropdown item
return value.map((item, index) => (
onSelect(item)} />
));
} else {
// If the value is a simple string, render it as a dropdown item
return (
onSelect(value)} />
);
}
});
};
// Main Multi-Level Dropdown Component
const MultiLevelDropdown = ({ data }: { data: Record }) => {
const [open, setOpen] = useState(false);
const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
const dropdownRef = useRef(null);
// Handle outer click to close the dropdown
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
// Handle selection of an item
const handleSelect = (selectedLabel: string) => {
setSelectedLabel(selectedLabel); // Update the dropdown trigger text
setOpen(false); // Close the dropdown
};
return (