syncing sidebar

This commit is contained in:
wass08
2026-01-21 11:57:31 +09:00
parent 67f9111d03
commit 48f7d7ffa4
5 changed files with 33 additions and 9 deletions
@@ -1,4 +1,5 @@
import { BuildingNode, LevelNode, useScene } from "@pascal-app/core"; import { BuildingNode, LevelNode, useScene } from "@pascal-app/core";
import { useViewer } from "@pascal-app/viewer";
import { Building2, Plus } from "lucide-react"; import { Building2, Plus } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { TreeNode, TreeNodeWrapper } from "./tree-node"; import { TreeNode, TreeNodeWrapper } from "./tree-node";
@@ -16,9 +17,12 @@ interface BuildingTreeNodeProps {
export function BuildingTreeNode({ node, depth }: BuildingTreeNodeProps) { export function BuildingTreeNode({ node, depth }: BuildingTreeNodeProps) {
const [expanded, setExpanded] = useState(true); const [expanded, setExpanded] = useState(true);
const createNode = useScene((state) => state.createNode); const createNode = useScene((state) => state.createNode);
const isSelected = useViewer((state) => state.selection.buildingId === node.id);
const isHovered = useViewer((state) => state.hoveredId === node.id);
const setSelection = useViewer((state) => state.setSelection);
const handleClick = () => { const handleClick = () => {
// Handle building selection setSelection({ buildingId: node.id });
}; };
const handleAddLevel = (e: React.MouseEvent) => { const handleAddLevel = (e: React.MouseEvent) => {
@@ -40,6 +44,8 @@ export function BuildingTreeNode({ node, depth }: BuildingTreeNodeProps) {
expanded={expanded} expanded={expanded}
onToggle={() => setExpanded(!expanded)} onToggle={() => setExpanded(!expanded)}
onClick={handleClick} onClick={handleClick}
isSelected={isSelected}
isHovered={isHovered}
actions={ actions={
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
@@ -1,4 +1,5 @@
import { ItemNode } from "@pascal-app/core"; import { ItemNode } from "@pascal-app/core";
import { useViewer } from "@pascal-app/viewer";
import { Box } from "lucide-react"; import { Box } from "lucide-react";
import { TreeNodeWrapper } from "./tree-node"; import { TreeNodeWrapper } from "./tree-node";
@@ -8,8 +9,12 @@ interface ItemTreeNodeProps {
} }
export function ItemTreeNode({ node, depth }: ItemTreeNodeProps) { export function ItemTreeNode({ node, depth }: ItemTreeNodeProps) {
const isSelected = useViewer((state) => state.selection.selectedIds.includes(node.id));
const isHovered = useViewer((state) => state.hoveredId === node.id);
const setSelection = useViewer((state) => state.setSelection);
const handleClick = () => { const handleClick = () => {
// Handle item selection setSelection({ selectedIds: [node.id] });
}; };
return ( return (
@@ -21,6 +26,8 @@ export function ItemTreeNode({ node, depth }: ItemTreeNodeProps) {
expanded={false} expanded={false}
onToggle={() => {}} onToggle={() => {}}
onClick={handleClick} onClick={handleClick}
isSelected={isSelected}
isHovered={isHovered}
/> />
); );
} }
@@ -11,15 +11,14 @@ interface LevelTreeNodeProps {
export function LevelTreeNode({ node, depth }: LevelTreeNodeProps) { export function LevelTreeNode({ node, depth }: LevelTreeNodeProps) {
const [expanded, setExpanded] = useState(true); const [expanded, setExpanded] = useState(true);
const currentLevelId = useViewer((state) => state.selection.levelId); const isSelected = useViewer((state) => state.selection.levelId === node.id);
const isHovered = useViewer((state) => state.hoveredId === node.id);
const setSelection = useViewer((state) => state.setSelection); const setSelection = useViewer((state) => state.setSelection);
const handleClick = () => { const handleClick = () => {
setSelection({ levelId: node.id }); setSelection({ levelId: node.id });
}; };
const isSelected = currentLevelId === node.id;
return ( return (
<TreeNodeWrapper <TreeNodeWrapper
icon={<Layers className="w-3.5 h-3.5" />} icon={<Layers className="w-3.5 h-3.5" />}
@@ -30,6 +29,7 @@ export function LevelTreeNode({ node, depth }: LevelTreeNodeProps) {
onToggle={() => setExpanded(!expanded)} onToggle={() => setExpanded(!expanded)}
onClick={handleClick} onClick={handleClick}
isSelected={isSelected} isSelected={isSelected}
isHovered={isHovered}
> >
{node.children.map((childId) => ( {node.children.map((childId) => (
<TreeNode key={childId} nodeId={childId} depth={depth + 1} /> <TreeNode key={childId} nodeId={childId} depth={depth + 1} />
@@ -41,6 +41,7 @@ interface TreeNodeWrapperProps {
actions?: React.ReactNode; actions?: React.ReactNode;
children?: React.ReactNode; children?: React.ReactNode;
isSelected?: boolean; isSelected?: boolean;
isHovered?: boolean;
} }
export function TreeNodeWrapper({ export function TreeNodeWrapper({
@@ -54,6 +55,7 @@ export function TreeNodeWrapper({
actions, actions,
children, children,
isSelected, isSelected,
isHovered,
}: TreeNodeWrapperProps) { }: TreeNodeWrapperProps) {
return ( return (
<div> <div>
@@ -61,7 +63,11 @@ export function TreeNodeWrapper({
className={cn( className={cn(
"flex items-center h-7 hover:bg-accent/50 cursor-pointer group", "flex items-center h-7 hover:bg-accent/50 cursor-pointer group",
"text-sm", "text-sm",
isSelected ? "text-primary-foreground bg-primary/80" : "text-muted-foreground" isSelected
? "text-primary-foreground bg-primary/80"
: isHovered
? "bg-accent/70 text-foreground"
: "text-muted-foreground"
)} )}
style={{ paddingLeft: depth * 12 + 4 }} style={{ paddingLeft: depth * 12 + 4 }}
> >
@@ -1,4 +1,5 @@
import { WallNode, useScene } from "@pascal-app/core"; import { WallNode } from "@pascal-app/core";
import { useViewer } from "@pascal-app/viewer";
import { Square } from "lucide-react"; import { Square } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { TreeNode, TreeNodeWrapper } from "./tree-node"; import { TreeNode, TreeNodeWrapper } from "./tree-node";
@@ -10,10 +11,12 @@ interface WallTreeNodeProps {
export function WallTreeNode({ node, depth }: WallTreeNodeProps) { export function WallTreeNode({ node, depth }: WallTreeNodeProps) {
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const isSelected = useViewer((state) => state.selection.selectedIds.includes(node.id));
const isHovered = useViewer((state) => state.hoveredId === node.id);
const setSelection = useViewer((state) => state.setSelection);
const handleClick = () => { const handleClick = () => {
// Handle wall selection setSelection({ selectedIds: [node.id] });
useScene.getState().markDirty(node.id);
}; };
const wallLength = Math.sqrt( const wallLength = Math.sqrt(
@@ -30,6 +33,8 @@ export function WallTreeNode({ node, depth }: WallTreeNodeProps) {
expanded={expanded} expanded={expanded}
onToggle={() => setExpanded(!expanded)} onToggle={() => setExpanded(!expanded)}
onClick={handleClick} onClick={handleClick}
isSelected={isSelected}
isHovered={isHovered}
> >
{node.children.map((childId) => ( {node.children.map((childId) => (
<TreeNode key={childId} nodeId={childId} depth={depth + 1} /> <TreeNode key={childId} nodeId={childId} depth={depth + 1} />