'use client' import type { BlockEnum } from '@/app/components/workflow/types' import type { WorkflowGenPlan } from '@/service/workflow-generator' import { memo } from 'react' import { useTranslation } from 'react-i18next' import { SkeletonContainer, SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton' import BlockIcon from '@/app/components/workflow/block-icon' type Props = Readonly<{ /** * The planner result once it has streamed in, or ``null`` while the planner * is still running. Drives the two honest phases of the generation: * "Planning…" (skeleton outline) → plan outline + "Building…". */ plan: WorkflowGenPlan | null }> // Stable keys for the planning skeleton's placeholder rows — avoids array-index // keys while still rendering a fixed-length outline. const SKELETON_ROWS = ['s1', 's2', 's3', 's4'] as const // While the planner runs we render a skeleton shaped like the node list that's // about to arrive, using the shared Skeleton primitives. The pane fills in // place instead of jerking from a centred spinner to a left-aligned list. const PlanningSkeleton = memo(() => { const { t } = useTranslation('workflow') return (