import { createContext, useContext, useState, useCallback, useMemo } from 'react' import type { ReactNode } from 'react' import { EyeLine, ArrowRightLine } from '../../basic/icons-inline' import type { ReasoningStepContextValue, ReasoningStepRootProps } from './types' // ===== 样式常量 ===== const eyeClass = 'w-full h-full text-text-tertiary transition-transform duration-200 ease-in-out' const arrowClass = 'w-full h-full transition-transform duration-200 ease-in-out' // ===== Context ===== const ReasoningStepContext = createContext(null) ReasoningStepContext.displayName = 'ReasoningStepContext' export function useReasoningStepContext() { const ctx = useContext(ReasoningStepContext) if (!ctx) throw new Error('ReasoningStep compound components must be used within ReasoningStep.Root') return ctx } // ===== Provider ===== export function ReasoningStepRootProvider({ text, description, status = 'completed', icon, showIcon = true, details, children, detailsChildren, duration = 2, spread = 2, disableExpandAnimation = false, defaultExpanded, expanded: expandedProp, onExpandedChange, eyeIcon, arrowRightIcon, }: ReasoningStepRootProps & { children?: ReactNode; detailsChildren?: ReactNode }) { const isControlled = expandedProp !== undefined const [isExpandedInternal, setIsExpandedInternal] = useState(defaultExpanded ?? false) const isExpanded = isControlled ? expandedProp : isExpandedInternal const [isHovered, setIsHovered] = useState(false) const effectiveExpanded = disableExpandAnimation && defaultExpanded !== undefined ? defaultExpanded : isExpanded const effectiveShowIcon = showIcon && typeof text === 'string' const detailIndent = effectiveShowIcon ? 'var(--spacing-1.5)' : 'var(--spacing-2.5)' const hasDetails = details != null && details.length > 0 const hasExpandableContent = hasDetails || detailsChildren != null const toggleExpanded = useCallback(() => { if (hasExpandableContent) { if (isControlled) onExpandedChange?.(!expandedProp) else setIsExpandedInternal((e) => !e) } }, [hasExpandableContent, isControlled, expandedProp, onExpandedChange]) const [expandedNestedKeys, setExpandedNestedKeys] = useState>(new Set()) const toggleNested = useCallback((pathKey: string) => { setExpandedNestedKeys((prev) => { const next = new Set(prev) if (next.has(pathKey)) next.delete(pathKey) else next.add(pathKey) return next }) }, []) const defaultEye = useMemo( () => eyeIcon ?? , [eyeIcon] ) const defaultArrow = useMemo( () => arrowRightIcon ?? , [arrowRightIcon] ) const ctxValue: ReasoningStepContextValue = { status, isExpanded, isHovered, setIsHovered, toggleExpanded, effectiveExpanded, effectiveShowIcon, hasExpandableContent, text, description, details, detailsChildren, duration, spread, disableExpandAnimation, detailIndent, expandedNestedKeys, toggleNested, icon, eyeIcon: defaultEye, arrowRightIcon: defaultArrow, } return ( {children} ) } ReasoningStepRootProvider.displayName = 'ReasoningStepRoot'