Merge conflicts remote-tracking branch 'origin/main' into ui
This commit is contained in:
@@ -1,99 +1,220 @@
|
||||
// import React, { useState, useRef, useEffect } from "react";
|
||||
|
||||
// // Dropdown Item Component
|
||||
// const DropdownItem = ({
|
||||
// label,
|
||||
// href,
|
||||
// onClick,
|
||||
// }: {
|
||||
// label: string;
|
||||
// href?: string;
|
||||
// onClick?: () => void;
|
||||
// }) => (
|
||||
// <a
|
||||
// href={href || "#"}
|
||||
// className="dropdown-item"
|
||||
// onClick={(e) => {
|
||||
// e.preventDefault();
|
||||
// onClick?.();
|
||||
// }}
|
||||
// >
|
||||
// {label}
|
||||
// </a>
|
||||
// );
|
||||
|
||||
// // Nested Dropdown Component
|
||||
// const NestedDropdown = ({
|
||||
// label,
|
||||
// children,
|
||||
// onSelect,
|
||||
// }: {
|
||||
// label: string;
|
||||
// children: React.ReactNode;
|
||||
// onSelect: (selectedLabel: string) => void;
|
||||
// }) => {
|
||||
// const [open, setOpen] = useState(false);
|
||||
|
||||
// return (
|
||||
// <div className="nested-dropdown">
|
||||
// {/* Dropdown Trigger */}
|
||||
// <div
|
||||
// className={`dropdown-trigger ${open ? "open" : ""}`}
|
||||
// onClick={() => setOpen(!open)} // Toggle submenu on click
|
||||
// >
|
||||
// {label} <span className="icon">{open ? "▼" : "▶"}</span>
|
||||
// </div>
|
||||
|
||||
// {/* Submenu */}
|
||||
// {open && (
|
||||
// <div className="submenu">
|
||||
// {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<any>, { onSelect });
|
||||
// }
|
||||
// return child; // Return non-element children as-is
|
||||
// })}
|
||||
// </div>
|
||||
// )}
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// // Recursive Function to Render Nested Data
|
||||
// const renderNestedData = (
|
||||
// data: Record<string, any>,
|
||||
// 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 (
|
||||
// <NestedDropdown key={key} label={key} onSelect={onSelect}>
|
||||
// {renderNestedData(value, onSelect)}
|
||||
// </NestedDropdown>
|
||||
// );
|
||||
// } else if (Array.isArray(value)) {
|
||||
// // If the value is an array, render each item as a dropdown item
|
||||
// return value.map((item, index) => (
|
||||
// <DropdownItem key={index} label={item} onClick={() => onSelect(item)} />
|
||||
// ));
|
||||
// } else {
|
||||
// // If the value is a simple string, render it as a dropdown item
|
||||
// return (
|
||||
// <DropdownItem key={key} label={value} onClick={() => onSelect(value)} />
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
|
||||
// // Main Multi-Level Dropdown Component
|
||||
// const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
||||
// const [open, setOpen] = useState(false);
|
||||
// const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
|
||||
// const dropdownRef = useRef<HTMLDivElement>(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 (
|
||||
// <div className="multi-level-dropdown" ref={dropdownRef}>
|
||||
// {/* Dropdown Trigger Button */}
|
||||
// <button
|
||||
// className={`dropdown-button ${open ? "open" : ""}`}
|
||||
// onClick={() => setOpen(!open)} // Toggle main menu on click
|
||||
// >
|
||||
// {selectedLabel} <span className="icon">▾</span>
|
||||
// </button>
|
||||
|
||||
// {/* Dropdown Menu */}
|
||||
// {open && (
|
||||
// <div className="dropdown-menu">
|
||||
// <div className="dropdown-content">
|
||||
// {renderNestedData(data, handleSelect)}
|
||||
// </div>
|
||||
// </div>
|
||||
// )}
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default MultiLevelDropdown;
|
||||
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
||||
|
||||
// Dropdown Item Component
|
||||
const DropdownItem = ({
|
||||
label,
|
||||
href,
|
||||
onClick,
|
||||
}: {
|
||||
label: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
onClick: () => void;
|
||||
}) => (
|
||||
<a
|
||||
href={href || "#"}
|
||||
className="dropdown-item"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onClick?.();
|
||||
}}
|
||||
>
|
||||
<div className="dropdown-item" onClick={onClick}>
|
||||
{label}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
// Nested Dropdown Component
|
||||
const NestedDropdown = ({
|
||||
label,
|
||||
children,
|
||||
fields,
|
||||
onSelect,
|
||||
}: {
|
||||
label: string;
|
||||
children: React.ReactNode;
|
||||
onSelect: (selectedLabel: string) => void;
|
||||
fields: string[];
|
||||
onSelect: (selectedData: { name: string; fields: string }) => void;
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="nested-dropdown">
|
||||
{/* Dropdown Trigger */}
|
||||
<div
|
||||
className={`dropdown-trigger ${open ? "open" : ""}`}
|
||||
onClick={() => setOpen(!open)} // Toggle submenu on click
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
{label} <span className="icon">{open ? "▼" : "▶"}</span>
|
||||
{label}
|
||||
<div
|
||||
className="arrow-container"
|
||||
style={{ rotate: open ? "" : "-90deg" }}
|
||||
>
|
||||
<ArrowIcon />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Submenu */}
|
||||
{open && (
|
||||
<div className="submenu">
|
||||
{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<any>, { onSelect });
|
||||
}
|
||||
return child; // Return non-element children as-is
|
||||
})}
|
||||
{fields.map((field) => (
|
||||
<DropdownItem
|
||||
key={field}
|
||||
label={field}
|
||||
onClick={() => onSelect({ name: label, fields: field })}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Recursive Function to Render Nested Data
|
||||
const renderNestedData = (
|
||||
data: Record<string, any>,
|
||||
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 (
|
||||
<NestedDropdown key={key} label={key} onSelect={onSelect}>
|
||||
{renderNestedData(value, onSelect)}
|
||||
</NestedDropdown>
|
||||
);
|
||||
} else if (Array.isArray(value)) {
|
||||
// If the value is an array, render each item as a dropdown item
|
||||
return value.map((item, index) => (
|
||||
<DropdownItem key={index} label={item} onClick={() => onSelect(item)} />
|
||||
));
|
||||
} else {
|
||||
// If the value is a simple string, render it as a dropdown item
|
||||
return (
|
||||
<DropdownItem key={key} label={value} onClick={() => onSelect(value)} />
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
// Props type for MultiLevelDropdown
|
||||
interface MultiLevelDropdownProps {
|
||||
data: Record<string, any>;
|
||||
onSelect: (selectedData: { name: string; fields: string }) => void;
|
||||
onUnselect: () => void;
|
||||
selectedValue?: { name: string; fields: string };
|
||||
}
|
||||
|
||||
// Main Multi-Level Dropdown Component
|
||||
const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
||||
const MultiLevelDropdown = ({
|
||||
data,
|
||||
onSelect,
|
||||
onUnselect,
|
||||
selectedValue,
|
||||
}: MultiLevelDropdownProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Handle outer click to close the dropdown
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
@@ -103,34 +224,51 @@ const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
||||
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
|
||||
// Handle item selection
|
||||
const handleItemSelect = (selectedData: { name: string; fields: string }) => {
|
||||
onSelect(selectedData);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// Handle unselect
|
||||
const handleItemUnselect = () => {
|
||||
onUnselect();
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// Determine the display label
|
||||
const displayLabel = selectedValue
|
||||
? `${selectedValue.name} - ${selectedValue.fields}`
|
||||
: "Dropdown trigger";
|
||||
|
||||
return (
|
||||
<div className="multi-level-dropdown" ref={dropdownRef}>
|
||||
{/* Dropdown Trigger Button */}
|
||||
<button
|
||||
className={`dropdown-button ${open ? "open" : ""}`}
|
||||
onClick={() => setOpen(!open)} // Toggle main menu on click
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
{selectedLabel} <span className="icon">▾</span>
|
||||
{displayLabel} <span className="icon">▾</span>
|
||||
</button>
|
||||
|
||||
{/* Dropdown Menu */}
|
||||
{open && (
|
||||
<div className="dropdown-menu">
|
||||
<div className="dropdown-content">
|
||||
{renderNestedData(data, handleSelect)}
|
||||
{/* Unselect Option */}
|
||||
<DropdownItem label="Unselect" onClick={handleItemUnselect} />
|
||||
{/* Nested Dropdown Items */}
|
||||
{Object.entries(data).map(([key, value]) => (
|
||||
<NestedDropdown
|
||||
key={key}
|
||||
label={key}
|
||||
fields={Object.keys(value)}
|
||||
onSelect={handleItemSelect}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -138,4 +276,4 @@ const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default MultiLevelDropdown;
|
||||
export default MultiLevelDropdown;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef } from "react";
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
|
||||
interface RenameInputProps {
|
||||
value: string;
|
||||
@@ -9,6 +9,9 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [text, setText] = useState(value);
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
useEffect(() => {
|
||||
setText(value); // Ensure state updates when parent value changes
|
||||
}, [value]);
|
||||
|
||||
const handleDoubleClick = () => {
|
||||
setIsEditing(true);
|
||||
|
||||
Reference in New Issue
Block a user