diff --git a/src/components/molecules/ComponentTree.tsx b/src/components/molecules/ComponentTree.tsx index 5eebde6..1268417 100644 --- a/src/components/molecules/ComponentTree.tsx +++ b/src/components/molecules/ComponentTree.tsx @@ -1,9 +1,9 @@ -import { useState, useCallback } from 'react' import { UIComponent } from '@/types/json-ui' import { ScrollArea } from '@/components/ui/scroll-area' import { ComponentTreeHeader } from '@/components/molecules/component-tree/ComponentTreeHeader' import { ComponentTreeEmptyState } from '@/components/molecules/component-tree/ComponentTreeEmptyState' import { ComponentTreeNodes } from '@/components/molecules/component-tree/ComponentTreeNodes' +import { useComponentTreeExpansion } from '@/hooks/use-component-tree-expansion' interface ComponentTreeProps { components: UIComponent[] @@ -34,42 +34,8 @@ export function ComponentTree({ onDragLeave, onDrop, }: ComponentTreeProps) { - const [expandedIds, setExpandedIds] = useState>(new Set()) - - const getAllComponentIds = useCallback((comps: UIComponent[]): string[] => { - const ids: string[] = [] - const traverse = (nodes: UIComponent[]) => { - nodes.forEach((comp) => { - if (Array.isArray(comp.children) && comp.children.length > 0) { - ids.push(comp.id) - traverse(comp.children) - } - }) - } - traverse(comps) - return ids - }, []) - - const handleExpandAll = useCallback(() => { - const allIds = getAllComponentIds(components) - setExpandedIds(new Set(allIds)) - }, [components, getAllComponentIds]) - - const handleCollapseAll = useCallback(() => { - setExpandedIds(new Set()) - }, []) - - const toggleExpand = useCallback((id: string) => { - setExpandedIds((prev) => { - const next = new Set(prev) - if (next.has(id)) { - next.delete(id) - } else { - next.add(id) - } - return next - }) - }, []) + const { expandedIds, handleExpandAll, handleCollapseAll, toggleExpand } = + useComponentTreeExpansion(components) return (
diff --git a/src/hooks/use-component-tree-expansion.ts b/src/hooks/use-component-tree-expansion.ts new file mode 100644 index 0000000..9fa2ec6 --- /dev/null +++ b/src/hooks/use-component-tree-expansion.ts @@ -0,0 +1,58 @@ +import { useCallback, useMemo, useState } from 'react' +import { UIComponent } from '@/types/json-ui' + +interface ComponentTreeExpansionState { + expandedIds: Set + handleExpandAll: () => void + handleCollapseAll: () => void + toggleExpand: (id: string) => void +} + +const getExpandableIds = (components: UIComponent[]): string[] => { + const ids: string[] = [] + const traverse = (nodes: UIComponent[]) => { + nodes.forEach((component) => { + if (Array.isArray(component.children) && component.children.length > 0) { + ids.push(component.id) + traverse(component.children) + } + }) + } + traverse(components) + return ids +} + +export function useComponentTreeExpansion( + components: UIComponent[], +): ComponentTreeExpansionState { + const [expandedIds, setExpandedIds] = useState>(new Set()) + + const expandableIds = useMemo(() => getExpandableIds(components), [components]) + + const handleExpandAll = useCallback(() => { + setExpandedIds(new Set(expandableIds)) + }, [expandableIds]) + + const handleCollapseAll = useCallback(() => { + setExpandedIds(new Set()) + }, []) + + const toggleExpand = useCallback((id: string) => { + setExpandedIds((prev) => { + const next = new Set(prev) + if (next.has(id)) { + next.delete(id) + } else { + next.add(id) + } + return next + }) + }, []) + + return { + expandedIds, + handleExpandAll, + handleCollapseAll, + toggleExpand, + } +}