Added outlineListData for asset hierarchy

This commit is contained in:
2025-10-24 15:13:42 +05:30
parent c22fd8ae38
commit 5b4017a7c3
5 changed files with 44 additions and 42 deletions

View File

@@ -3,17 +3,7 @@ import { AddIcon, ChevronIcon, CollapseAllIcon } from "../../icons/ExportIcons";
import { OutlinePanelProps } from "./OutlinePanel"; import { OutlinePanelProps } from "./OutlinePanel";
import TreeNode from "./TreeNode"; import TreeNode from "./TreeNode";
import Search from "./Search"; import Search from "./Search";
import { AssetGroupChild } from "../../data/OutlineListData";
export interface AssetGroupChild {
groupUuid?: string;
groupName?: string;
isExpanded?: boolean;
children?: AssetGroupChild[];
modelUuid?: string;
modelName?: string;
isVisible?: boolean;
isLocked?: boolean;
}
type DropAction = "above" | "child" | "below" | "none"; type DropAction = "above" | "child" | "below" | "none";
@@ -39,19 +29,27 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
height, height,
width, width,
search, search,
data,
}) => { }) => {
const [selectedId, setSelectedId] = useState<string | null>(null); const [selectedId, setSelectedId] = useState<string | null>(null);
const [isPanelOpen, setIsPanelOpen] = useState(true); const [isPanelOpen, setIsPanelOpen] = useState(true);
const [draggedNode, setDraggedNode] = useState<AssetGroupChild | null>(null); const [draggedNode, setDraggedNode] = useState<AssetGroupChild | null>(null);
const [searchValue, setSearchValue] = useState(""); const [searchValue, setSearchValue] = useState("");
const [hierarchy, setHierarchy] = useState<AssetGroupChild[]>([ const [hierarchy, setHierarchy] = useState<AssetGroupChild[]>(data);
{ modelUuid: "a1", modelName: "Asset 1", isVisible: true, isLocked: false, children: [] },
{ modelUuid: "a2", modelName: "Asset 2", isVisible: true, isLocked: false, children: [] }, useEffect(() => {
{ modelUuid: "a3", modelName: "Asset 3", isVisible: true, isLocked: false, children: [] }, const handleClickOutside = (event: MouseEvent): void => {
{ modelUuid: "a4", modelName: "Asset 4", isVisible: true, isLocked: false, children: [] }, const target = event.target as HTMLElement;
{ modelUuid: "a5", modelName: "Asset 5", isVisible: true, isLocked: false, children: [] }, if (!target.closest(".outline-card")) {
{ modelUuid: "a6", modelName: "Asset 6", isVisible: true, isLocked: false, children: [] }, setSelectedId(null);
]); }
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
const handleDragStart = (item: AssetGroupChild) => { const handleDragStart = (item: AssetGroupChild) => {
setDraggedNode(item); setDraggedNode(item);
@@ -120,10 +118,8 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
const updatedHierarchy = [...hierarchy]; const updatedHierarchy = [...hierarchy];
// remove old reference
if (!removeFromHierarchy(draggedItem, updatedHierarchy)) return; if (!removeFromHierarchy(draggedItem, updatedHierarchy)) return;
// insert in new location
if (!insertByDropAction(draggedItem, targetId, dropAction, updatedHierarchy)) { if (!insertByDropAction(draggedItem, targetId, dropAction, updatedHierarchy)) {
updatedHierarchy.push(draggedItem); updatedHierarchy.push(draggedItem);
} }
@@ -215,19 +211,6 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
} }
return false; return false;
}; };
useEffect(() => {
const handleClickOutside = (event: MouseEvent): void => {
const target = event.target as HTMLElement;
if (!target.closest(".outline-card")) {
setSelectedId(null);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
const filterHierarchy = (items: AssetGroupChild[], query: string): AssetGroupChild[] => { const filterHierarchy = (items: AssetGroupChild[], query: string): AssetGroupChild[] => {
if (!query.trim()) return items; if (!query.trim()) return items;
@@ -240,7 +223,6 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
const filteredChildren = item.children ? filterHierarchy(item.children, query) : []; const filteredChildren = item.children ? filterHierarchy(item.children, query) : [];
// If this node or any of its children match, keep it
if (matches || filteredChildren.length > 0) { if (matches || filteredChildren.length > 0) {
return { ...item, children: filteredChildren }; return { ...item, children: filteredChildren };
} }
@@ -248,6 +230,7 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
}) })
.filter(Boolean) as AssetGroupChild[]; .filter(Boolean) as AssetGroupChild[];
}; };
const filteredHierarchy = filterHierarchy(hierarchy, searchValue); const filteredHierarchy = filterHierarchy(hierarchy, searchValue);
const handleRename = (id: string, newName: string) => { const handleRename = (id: string, newName: string) => {
@@ -311,7 +294,6 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
</div> </div>
)} )}
{/* List */}
{isPanelOpen && ( {isPanelOpen && (
<div className="outline-content"> <div className="outline-content">
{filteredHierarchy.map((node) => ( {filteredHierarchy.map((node) => (

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { OutlineList } from "./OutlineList "; import { OutlineList } from "./OutlineList ";
import { AssetGroupChild } from "../../data/OutlineListData";
export interface OutlinePanelProps { export interface OutlinePanelProps {
textColor?: string; textColor?: string;
@@ -11,6 +12,7 @@ export interface OutlinePanelProps {
height?: string; height?: string;
width?: string; width?: string;
search?: boolean; search?: boolean;
data: AssetGroupChild[];
} }
const OutlinePanel: React.FC<OutlinePanelProps> = (props) => { const OutlinePanel: React.FC<OutlinePanelProps> = (props) => {

View File

@@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { AssetGroupChild, DEFAULT_PRAMS } from "./OutlineList "; import { DEFAULT_PRAMS } from "./OutlineList ";
import clsx from "clsx"; import clsx from "clsx";
import { import {
ChevronIcon, ChevronIcon,
@@ -10,6 +10,7 @@ import {
KebebIcon, KebebIcon,
LockIcon, LockIcon,
} from "../../icons/ExportIcons"; } from "../../icons/ExportIcons";
import { AssetGroupChild } from "../../data/OutlineListData";
interface TreeNodeProps { interface TreeNodeProps {
item: AssetGroupChild; item: AssetGroupChild;
@@ -120,15 +121,12 @@ const TreeNode: React.FC<TreeNodeProps> = ({
id={item.modelUuid || item.groupUuid} id={item.modelUuid || item.groupUuid}
onClick={toggleSelect} onClick={toggleSelect}
> >
{/* 👇 Flex container for the entire row */}
<div <div
className="node-wrapper" className="node-wrapper"
style={{ display: "flex", alignItems: "center", width: "100%" }} style={{ display: "flex", alignItems: "center", width: "100%" }}
> >
{/* Indentation spacer — only affects left side */}
<div style={{ width: `${level * 20}px`, flexShrink: 0 }} /> <div style={{ width: `${level * 20}px`, flexShrink: 0 }} />
{/* Expand button (only for groups) */}
{isGroupNode ? ( {isGroupNode ? (
<button <button
className="expand-button" className="expand-button"
@@ -140,7 +138,7 @@ const TreeNode: React.FC<TreeNodeProps> = ({
<ChevronIcon isOpen={isExpanded} /> <ChevronIcon isOpen={isExpanded} />
</button> </button>
) : ( ) : (
<div style={{ width: "20px", flexShrink: 0 }} /> // match expand button width <div style={{ width: "20px", flexShrink: 0 }} />
)} )}
<div className="node-icon" style={{ flexShrink: 0 }}> <div className="node-icon" style={{ flexShrink: 0 }}>
@@ -185,7 +183,6 @@ const TreeNode: React.FC<TreeNodeProps> = ({
)} )}
</div> </div>
{/* Controls (always visible, never shrink) */}
<div <div
className="node-controls" className="node-controls"
style={{ display: "flex", gap: "4px", flexShrink: 0 }} style={{ display: "flex", gap: "4px", flexShrink: 0 }}

View File

@@ -0,0 +1,19 @@
export const OutlineListData = [
{ modelUuid: "a1", modelName: "Asset 1", isVisible: true, isLocked: false, children: [] },
{ modelUuid: "a2", modelName: "Asset 2", isVisible: true, isLocked: false, children: [] },
{ modelUuid: "a3", modelName: "Asset 3", isVisible: true, isLocked: false, children: [] },
{ modelUuid: "a4", modelName: "Asset 4", isVisible: true, isLocked: false, children: [] },
{ modelUuid: "a5", modelName: "Asset 5", isVisible: true, isLocked: false, children: [] },
{ modelUuid: "a6", modelName: "Asset 6", isVisible: true, isLocked: false, children: [] },
];
export interface AssetGroupChild {
groupUuid?: string;
groupName?: string;
isExpanded?: boolean;
children?: AssetGroupChild[];
modelUuid?: string;
modelName?: string;
isVisible?: boolean;
isLocked?: boolean;
}

View File

@@ -1,4 +1,5 @@
import OutlinePanel from "../components/ui/OutlinePanel"; import OutlinePanel from "../components/ui/OutlinePanel";
import { OutlineListData } from "../data/OutlineListData";
const SceneView = () => { const SceneView = () => {
return ( return (
@@ -11,6 +12,7 @@ const SceneView = () => {
// eyeIconColor="" // eyeIconColor=""
// backgroundColor="" // backgroundColor=""
search={true} search={true}
data={OutlineListData}
/> />
); );
}; };