'use client' import { useState, useRef, useEffect, ReactNode } from 'react' import { Container, Stack, Text, ThemeIcon, Box, rem, Collapse, useMantineTheme, Flex, } from '@pikku/mantine/core' import { asI18n } from '@pikku/react' export interface ExpandableStep { title: string icon: ReactNode content: () => ReactNode } interface ExpandableStepsProps { steps: ExpandableStep[] defaultExpanded?: number[] singleExpand?: boolean containerSize?: string showTitle?: boolean title?: string } export function ExpandableSteps({ steps, defaultExpanded = [0], singleExpand = true, containerSize = 'xl', showTitle = false, title, }: ExpandableStepsProps) { const theme = useMantineTheme() const [expandedSteps, setExpandedSteps] = useState(() => new Set(defaultExpanded)) const contentRefs = useRef<(HTMLDivElement | null)[]>([]) const [heights, setHeights] = useState([]) const CIRCLE_SIZE = 38 const GAP = 8 useEffect(() => { const observers: ResizeObserver[] = [] contentRefs.current.forEach((el, i) => { if (!el) return const observer = new ResizeObserver(() => { setHeights((prev) => { const copy = [...prev] copy[i] = el.offsetHeight return copy }) }) observer.observe(el) observers.push(observer) }) return () => { observers.forEach((observer) => observer.disconnect()) } }, []) const calculateLineHeight = (index: number): number => { if (index === steps.length - 1) return 0 const contentHeight = heights[index] ?? 0 return contentHeight + GAP * 2 } const toggleStep = (index: number) => { if (singleExpand) { setExpandedSteps(() => new Set([index])) } else { setExpandedSteps((prev) => { const newSet = new Set(prev) if (newSet.has(index)) { newSet.delete(index) } else { newSet.add(index) } return newSet }) } } return ( {showTitle && title && ( {asI18n(title)} )} {steps.map((step, index) => { const isActive = expandedSteps.has(index) const lineHeight = isActive && index !== steps.length - 1 ? calculateLineHeight(index) : 0 return ( toggleStep(index)} > {index + 1} {lineHeight > 0 && ( )} toggleStep(index)}> {step.icon} {asI18n(step.title)} { contentRefs.current[index] = el }} id={`step-${index}-content`} p={0} mb="md" > {step.content()} ) })} ) }