import React, { useCallback } from 'react'; import { useEditor } from '@craftjs/core'; interface LayerNodeProps { nodeId: string; depth: number; } const LayerNode: React.FC = ({ nodeId, depth }) => { const { node, selectedId, actions } = useEditor((state) => { const n = state.nodes[nodeId]; const selectedIds = state.events.selected; const selId = selectedIds ? Array.from(selectedIds)[0] : null; return { node: n, selectedId: selId, }; }); const handleClick = useCallback((e: React.MouseEvent) => { e.stopPropagation(); actions.selectNode(nodeId); }, [actions, nodeId]); if (!node) return null; const isSelected = selectedId === nodeId; const nodeType = node.data.type; const resolvedName = typeof nodeType === 'object' && nodeType !== null && 'resolvedName' in nodeType ? (nodeType as any).resolvedName : typeof nodeType === 'string' ? nodeType : undefined; const displayName = (node.data.props?.aiName as string) || node.data.displayName || (node.data.type as any)?.resolvedName || 'Node'; const childNodeIds: string[] = node.data.nodes || []; const linkedNodeIds: string[] = Object.values(node.data.linkedNodes || {}) as string[]; const allChildren = [...childNodeIds, ...linkedNodeIds]; const isRoot = nodeId === 'ROOT'; return (
{ if (!isSelected) { (e.currentTarget as HTMLElement).style.background = 'var(--color-bg-hover)'; } }} onMouseLeave={(e) => { if (!isSelected) { (e.currentTarget as HTMLElement).style.background = 'transparent'; } }} > {/* Indentation indicator */} {allChildren.length > 0 && ( ▼ )} {allChildren.length === 0 && ( ▼ )} {/* Component type icon and name */} {isRoot ? 'Canvas (Root)' : displayName}
{/* Render children */} {allChildren.map((childId) => ( ))}
); }; export const LayersPanel: React.FC = () => { const { nodeIds } = useEditor((state) => { return { nodeIds: Object.keys(state.nodes), }; }); const hasRoot = nodeIds.includes('ROOT'); if (!hasRoot) { return (
No content on canvas
); } return (
Component Tree
); };