first commit
This commit is contained in:
92
app/src/components/ui/list/DropDownList.tsx
Normal file
92
app/src/components/ui/list/DropDownList.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import React, { useState } from "react";
|
||||
import List from "./List";
|
||||
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
||||
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
||||
|
||||
interface DropDownListProps {
|
||||
value?: string; // Value to display in the DropDownList
|
||||
items?: { id: string; name: string }[]; // Items to display in the dropdown list
|
||||
showFocusIcon?: boolean; // Determines if the FocusIcon should be displayed
|
||||
showAddIcon?: boolean; // Determines if the AddIcon should be displayed
|
||||
showKebabMenu?: boolean; // Determines if the KebabMenuList should be displayed
|
||||
kebabMenuItems?: { id: string; name: string }[]; // Items for the KebabMenuList
|
||||
defaultOpen?: boolean; // Determines if the dropdown list should be open by default
|
||||
listType?: string; // Type of list to display
|
||||
}
|
||||
|
||||
const DropDownList: React.FC<DropDownListProps> = ({
|
||||
value = "Dropdown",
|
||||
items = [],
|
||||
showFocusIcon = false,
|
||||
showAddIcon = true,
|
||||
showKebabMenu = true,
|
||||
kebabMenuItems = [
|
||||
{ id: "Buildings", name: "Buildings" },
|
||||
{ id: "Paths", name: "Paths" },
|
||||
{ id: "Zones", name: "Zones" },
|
||||
],
|
||||
defaultOpen = false,
|
||||
listType = "default",
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
|
||||
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev); // Toggle the state
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="dropdown-list-container">
|
||||
<div className="head">
|
||||
<div className="value" onClick={handleToggle}>
|
||||
{value}
|
||||
</div>
|
||||
<div className="options">
|
||||
{showFocusIcon && (
|
||||
<div className="focus option">
|
||||
<FocusIcon />
|
||||
</div>
|
||||
)}
|
||||
{showAddIcon && (
|
||||
<div className="add option">
|
||||
<AddIcon />
|
||||
</div>
|
||||
)}
|
||||
{showKebabMenu && (
|
||||
<div className="kebab-menu option">
|
||||
<KebabMenuListMultiSelect items={kebabMenuItems} />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="collapse-icon option"
|
||||
style={{ transform: isOpen ? "rotate(0deg)" : "rotate(-90deg)" }}
|
||||
onClick={handleToggle}
|
||||
>
|
||||
<ArrowIcon />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isOpen && (
|
||||
<div className="lists-container">
|
||||
{listType === "default" && <List items={items} />}
|
||||
{listType === "outline" && (
|
||||
<>
|
||||
<DropDownList
|
||||
value="Buildings"
|
||||
showKebabMenu={false}
|
||||
showAddIcon={false}
|
||||
/>
|
||||
<DropDownList
|
||||
value="Zones"
|
||||
showKebabMenu={false}
|
||||
showAddIcon={false}
|
||||
items={[]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DropDownList;
|
||||
45
app/src/components/ui/list/KebebMenuList.tsx
Normal file
45
app/src/components/ui/list/KebebMenuList.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import React, { useState } from "react";
|
||||
import { KebebIcon } from "../../icons/ExportCommonIcons";
|
||||
|
||||
interface KebabMenuListProps {
|
||||
items: string[]; // Array of menu items
|
||||
onSelect?: (item: string) => void; // Callback when a menu item is selected
|
||||
}
|
||||
|
||||
const KebabMenuList: React.FC<KebabMenuListProps> = ({ items, onSelect }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleItemClick = (item: string) => {
|
||||
if (onSelect) {
|
||||
onSelect(item);
|
||||
}
|
||||
setIsOpen(false); // Close menu after selection
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="kebab-menu-container">
|
||||
<div className="kebab-icon" onClick={handleToggle}>
|
||||
<KebebIcon />
|
||||
</div>
|
||||
{isOpen && (
|
||||
<div className="menu-list">
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="menu-item"
|
||||
onClick={() => handleItemClick(item)}
|
||||
>
|
||||
{item}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default KebabMenuList;
|
||||
82
app/src/components/ui/list/KebebMenuListMultiSelect.tsx
Normal file
82
app/src/components/ui/list/KebebMenuListMultiSelect.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { KebebIcon, TickIcon } from "../../icons/ExportCommonIcons";
|
||||
|
||||
interface KebabMenuListMultiSelectProps {
|
||||
items: { id: string; name: string }[]; // Array of menu items with id and name
|
||||
onSelectionChange?: (selectedItems: string[]) => void; // Callback for selected items
|
||||
}
|
||||
|
||||
const KebabMenuListMultiSelect: React.FC<KebabMenuListMultiSelectProps> = ({
|
||||
items,
|
||||
onSelectionChange,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedItems, setSelectedItems] = useState<string[]>([]);
|
||||
const menuRef = useRef<HTMLDivElement>(null); // Ref to track the container
|
||||
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleItemToggle = (id: string) => {
|
||||
setSelectedItems((prevSelected) => {
|
||||
const isAlreadySelected = prevSelected.includes(id);
|
||||
const updatedSelection = isAlreadySelected
|
||||
? prevSelected.filter((item) => item !== id) // Deselect if already selected
|
||||
: [...prevSelected, id]; // Add to selection if not selected
|
||||
|
||||
if (onSelectionChange) {
|
||||
onSelectionChange(updatedSelection);
|
||||
}
|
||||
|
||||
return updatedSelection;
|
||||
});
|
||||
};
|
||||
|
||||
// Close menu if clicked outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="kebab-menu-container" ref={menuRef}>
|
||||
<div className="kebab-icon" onClick={handleToggle}>
|
||||
<KebebIcon />
|
||||
</div>
|
||||
{isOpen && (
|
||||
<div className="menu-list">
|
||||
{items.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className={`menu-item ${
|
||||
selectedItems.includes(item.id) ? "selected" : ""
|
||||
}`}
|
||||
onClick={() => handleItemToggle(item.id)}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedItems.includes(item.id)}
|
||||
onChange={() => handleItemToggle(item.id)}
|
||||
/>
|
||||
<div className="icon-container">
|
||||
{selectedItems.includes(item.id) && <TickIcon />}
|
||||
</div>
|
||||
{item.name}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default KebabMenuListMultiSelect;
|
||||
45
app/src/components/ui/list/List.tsx
Normal file
45
app/src/components/ui/list/List.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import React from "react";
|
||||
import RenameInput from "../inputs/RenameInput";
|
||||
import { EyeIcon, LockIcon, RmoveIcon } from "../../icons/ExportCommonIcons";
|
||||
|
||||
interface ListProps {
|
||||
items?: { id: string; name: string }[]; // Optional array of items to render
|
||||
placeholder?: string; // Optional placeholder text
|
||||
}
|
||||
|
||||
const List: React.FC<ListProps> = ({ items = [] }) => {
|
||||
return (
|
||||
<>
|
||||
{items.length > 0 ? (
|
||||
<ul className="list-wrapper">
|
||||
{items.map((item, index) => (
|
||||
<li key={index} className="list-container">
|
||||
<div className="list-item">
|
||||
<div className="value">
|
||||
<RenameInput value={item.name} />
|
||||
</div>
|
||||
<div className="options-container">
|
||||
<div className="lock option">
|
||||
<LockIcon isLocked />
|
||||
</div>
|
||||
<div className="visibe option">
|
||||
<EyeIcon isClosed />
|
||||
</div>
|
||||
<div className="remove option">
|
||||
<RmoveIcon />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<div className="list-wrapper">
|
||||
<div className="no-item">No items to display</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default List;
|
||||
Reference in New Issue
Block a user