code refactor
This commit is contained in:
@@ -99,7 +99,7 @@ const Outline: React.FC = () => {
|
||||
</section> */}
|
||||
<section className="outline-section overflow">
|
||||
{/* <DropDownList value="Buildings" items={buildingsList} isOpen={isBuildingsOpen} onToggle={() => setIsBuildingsOpen((prev) => !prev)} showKebabMenu={false} showAddIcon={false} /> */}
|
||||
<DropDownList header="Zones" type="Zones" items={sceneAssetsDataList} isDefaultOpen={true} showKebabMenu={false} showAddIcon={false} />
|
||||
<DropDownList header="Zones" items={sceneAssetsDataList} isDefaultOpen={true} showKebabMenu={false} showAddIcon={false} />
|
||||
</section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -5,7 +5,6 @@ import List from "./OutlineList/ListNew";
|
||||
|
||||
interface DropDownListProps {
|
||||
header?: string;
|
||||
type?: "Zones" | "Assets";
|
||||
items?: { id: string; name: string }[];
|
||||
showFocusIcon?: boolean;
|
||||
onFocusClick?: () => void;
|
||||
@@ -21,7 +20,6 @@ interface DropDownListProps {
|
||||
const DropDownList: React.FC<DropDownListProps> = ({
|
||||
header = "Dropdown",
|
||||
items = [],
|
||||
type = "Assets",
|
||||
showFocusIcon = false,
|
||||
onFocusClick,
|
||||
showAddIcon = true,
|
||||
|
||||
@@ -2,44 +2,40 @@ 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
|
||||
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 [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev);
|
||||
};
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleItemClick = (item: string) => {
|
||||
if (onSelect) {
|
||||
onSelect(item);
|
||||
}
|
||||
setIsOpen(false); // Close menu after selection
|
||||
};
|
||||
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}
|
||||
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>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default KebabMenuList;
|
||||
|
||||
@@ -2,81 +2,66 @@ 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
|
||||
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 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);
|
||||
}
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
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
|
||||
|
||||
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}
|
||||
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>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default KebabMenuListMultiSelect;
|
||||
|
||||
57
app/src/types/uiTypes.d.ts
vendored
57
app/src/types/uiTypes.d.ts
vendored
@@ -78,3 +78,60 @@ interface Tutorial {
|
||||
thumbnail?: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
// Base interface for all list items
|
||||
interface BaseListItem {
|
||||
id: string;
|
||||
name: string;
|
||||
type: "zone" | "asset" | "wall" | "floor" | "point" | "decal";
|
||||
isLocked?: boolean;
|
||||
isVisible?: boolean;
|
||||
isActive?: boolean;
|
||||
canEdit?: boolean;
|
||||
children?: ListItem[]; // For nested relationships
|
||||
metadata?: {
|
||||
position?: [number, number, number];
|
||||
rotation?: [number, number, number];
|
||||
scale?: [number, number, number];
|
||||
color?: string;
|
||||
height?: number;
|
||||
thickness?: number;
|
||||
// ... other type-specific properties
|
||||
};
|
||||
}
|
||||
|
||||
// Extended interfaces for specific types
|
||||
interface ZoneListItem extends BaseListItem {
|
||||
type: "zone";
|
||||
metadata: {
|
||||
zoneHeight: number;
|
||||
zoneColor: string;
|
||||
viewPortPosition: [number, number, number];
|
||||
viewPortTarget: [number, number, number];
|
||||
};
|
||||
}
|
||||
|
||||
interface AssetListItem extends BaseListItem {
|
||||
type: "asset";
|
||||
metadata: {
|
||||
modelUuid: string;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
scale: [number, number, number];
|
||||
isCollidable: boolean;
|
||||
opacity: number;
|
||||
animations?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
interface WallListItem extends BaseListItem {
|
||||
type: "wall";
|
||||
metadata: {
|
||||
wallThickness: number;
|
||||
wallHeight: number;
|
||||
outsideMaterial: string;
|
||||
insideMaterial: string;
|
||||
};
|
||||
}
|
||||
|
||||
type ListItem = ZoneListItem | AssetListItem | WallListItem | BaseListItem;
|
||||
|
||||
Reference in New Issue
Block a user