@humain/ui 2.1.62 → 2.1.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/dist/components/organisms/ai/AIToolCall/AIToolCall.d.ts +9 -3
  2. package/dist/components/organisms/ai/AIToolRun/index.d.ts +1 -1
  3. package/dist/components/organisms/ai/AIToolRun/validation.d.ts +24 -3
  4. package/dist/components/organisms/ai/_shared/format-ai-duration.d.ts +1 -0
  5. package/dist/components/organisms/ai/_shared/workflow-step-renderer.d.ts +1 -0
  6. package/dist/index.js +52 -52
  7. package/dist/index151.js +1 -1
  8. package/dist/index174.js +10 -333
  9. package/dist/index174.js.map +1 -1
  10. package/dist/index175.js +310 -137
  11. package/dist/index175.js.map +1 -1
  12. package/dist/index176.js +148 -174
  13. package/dist/index176.js.map +1 -1
  14. package/dist/index177.js +186 -78
  15. package/dist/index177.js.map +1 -1
  16. package/dist/index178.js +74 -124
  17. package/dist/index178.js.map +1 -1
  18. package/dist/index179.js +133 -1
  19. package/dist/index179.js.map +1 -0
  20. package/dist/index180.js +2 -201
  21. package/dist/index181.js +201 -0
  22. package/dist/{index180.js.map → index181.js.map} +1 -1
  23. package/dist/index183.js +130 -166
  24. package/dist/index183.js.map +1 -1
  25. package/dist/index184.js +195 -983
  26. package/dist/index184.js.map +1 -1
  27. package/dist/index185.js +1069 -369
  28. package/dist/index185.js.map +1 -1
  29. package/dist/index186.js +395 -197
  30. package/dist/index186.js.map +1 -1
  31. package/dist/index187.js +198 -243
  32. package/dist/index187.js.map +1 -1
  33. package/dist/index188.js +263 -3
  34. package/dist/index188.js.map +1 -1
  35. package/dist/index189.js +3 -209
  36. package/dist/index189.js.map +1 -1
  37. package/dist/index190.js +190 -777
  38. package/dist/index190.js.map +1 -1
  39. package/dist/index191.js +771 -252
  40. package/dist/index191.js.map +1 -1
  41. package/dist/index192.js +250 -65
  42. package/dist/index192.js.map +1 -1
  43. package/dist/index193.js +72 -523
  44. package/dist/index193.js.map +1 -1
  45. package/dist/index194.js +537 -144
  46. package/dist/index194.js.map +1 -1
  47. package/dist/index195.js +139 -720
  48. package/dist/index195.js.map +1 -1
  49. package/dist/index196.js +707 -167
  50. package/dist/index196.js.map +1 -1
  51. package/dist/index197.js +175 -151
  52. package/dist/index197.js.map +1 -1
  53. package/dist/index198.js +152 -487
  54. package/dist/index198.js.map +1 -1
  55. package/dist/index199.js +472 -225
  56. package/dist/index199.js.map +1 -1
  57. package/dist/index200.js +236 -260
  58. package/dist/index200.js.map +1 -1
  59. package/dist/index201.js +265 -215
  60. package/dist/index201.js.map +1 -1
  61. package/dist/index202.js +207 -307
  62. package/dist/index202.js.map +1 -1
  63. package/dist/index203.js +302 -135
  64. package/dist/index203.js.map +1 -1
  65. package/dist/index204.js +140 -271
  66. package/dist/index204.js.map +1 -1
  67. package/dist/index205.js +263 -253
  68. package/dist/index205.js.map +1 -1
  69. package/dist/index206.js +244 -137
  70. package/dist/index206.js.map +1 -1
  71. package/dist/index207.js +100 -238
  72. package/dist/index207.js.map +1 -1
  73. package/dist/index208.js +278 -74
  74. package/dist/index208.js.map +1 -1
  75. package/dist/index209.js +56 -97
  76. package/dist/index209.js.map +1 -1
  77. package/dist/index210.js +142 -47
  78. package/dist/index210.js.map +1 -1
  79. package/dist/index211.js +38 -84
  80. package/dist/index211.js.map +1 -1
  81. package/dist/index212.js +72 -252
  82. package/dist/index212.js.map +1 -1
  83. package/dist/index213.js +274 -26
  84. package/dist/index213.js.map +1 -1
  85. package/dist/index214.js +29 -94
  86. package/dist/index214.js.map +1 -1
  87. package/dist/index215.js +98 -25
  88. package/dist/index215.js.map +1 -1
  89. package/dist/index216.js +20 -565
  90. package/dist/index216.js.map +1 -1
  91. package/dist/index217.js +564 -17
  92. package/dist/index217.js.map +1 -1
  93. package/dist/index218.js +20 -23
  94. package/dist/index218.js.map +1 -1
  95. package/dist/index219.js +20 -95
  96. package/dist/index219.js.map +1 -1
  97. package/dist/index220.js +92 -88
  98. package/dist/index220.js.map +1 -1
  99. package/dist/index221.js +97 -29
  100. package/dist/index221.js.map +1 -1
  101. package/dist/index222.js +24 -470
  102. package/dist/index222.js.map +1 -1
  103. package/dist/index223.js +446 -196
  104. package/dist/index223.js.map +1 -1
  105. package/dist/index224.js +199 -729
  106. package/dist/index224.js.map +1 -1
  107. package/dist/index225.js +750 -61
  108. package/dist/index225.js.map +1 -1
  109. package/dist/index226.js +58 -181
  110. package/dist/index226.js.map +1 -1
  111. package/dist/index227.js +175 -259
  112. package/dist/index227.js.map +1 -1
  113. package/dist/index228.js +246 -172
  114. package/dist/index228.js.map +1 -1
  115. package/dist/index229.js +195 -32
  116. package/dist/index229.js.map +1 -1
  117. package/dist/index230.js +12 -40
  118. package/dist/index230.js.map +1 -1
  119. package/dist/index231.js +23 -26
  120. package/dist/index231.js.map +1 -1
  121. package/dist/index232.js +45 -22
  122. package/dist/index232.js.map +1 -1
  123. package/dist/index233.js +27 -48
  124. package/dist/index233.js.map +1 -1
  125. package/dist/index234.js +52 -26
  126. package/dist/index234.js.map +1 -1
  127. package/dist/index235.js +40 -225
  128. package/dist/index235.js.map +1 -1
  129. package/dist/index236.js +217 -39
  130. package/dist/index236.js.map +1 -1
  131. package/dist/index237.js +50 -0
  132. package/dist/index237.js.map +1 -0
  133. package/dist/styles.css +1 -1
  134. package/dist/wc/AIToolCall.js +218 -0
  135. package/dist/wc/AIToolCall.js.map +1 -0
  136. package/dist/wc/hf-ai-tool-call.js +34 -219
  137. package/dist/wc/hf-ai-tool-call.js.map +1 -1
  138. package/dist/wc/hf-ai-tool-run.js +673 -576
  139. package/dist/wc/hf-ai-tool-run.js.map +1 -1
  140. package/dist/wc/workflow-step-renderer.js +94 -86
  141. package/dist/wc/workflow-step-renderer.js.map +1 -1
  142. package/dist/wc-react/AIToolCall.js +218 -0
  143. package/dist/wc-react/AIToolCall.js.map +1 -0
  144. package/dist/wc-react/hf-ai-tool-call.js +32 -217
  145. package/dist/wc-react/hf-ai-tool-call.js.map +1 -1
  146. package/dist/wc-react/hf-ai-tool-run.js +698 -601
  147. package/dist/wc-react/hf-ai-tool-run.js.map +1 -1
  148. package/dist/wc-react/workflow-step-renderer.js +76 -68
  149. package/dist/wc-react/workflow-step-renderer.js.map +1 -1
  150. package/package.json +1 -1
  151. package/skills/humain-ui/SKILL.md +1 -1
  152. package/skills/humain-ui-wc/SKILL.md +1 -1
  153. package/skills/humain-ui-wc.skill +0 -0
  154. package/skills/humain-ui.skill +0 -0
  155. package/dist/index182.js +0 -143
  156. package/dist/index182.js.map +0 -1
  157. package/dist/wc/wrench.js +0 -10
  158. package/dist/wc/wrench.js.map +0 -1
  159. package/dist/wc-react/wrench.js +0 -10
  160. package/dist/wc-react/wrench.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index174.js","names":[],"sources":["../src/components/organisms/ai/_shared/workflow-step-renderer.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport {\n AlertCircle,\n Check,\n ChevronDown,\n ChevronRight,\n Loader,\n Pause,\n} from 'lucide-react';\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react';\nimport * as React from 'react';\nimport { assertNever, cn } from '@/lib/utils';\n\nexport type WorkflowStepStatus =\n | 'pending'\n | 'running'\n | 'suspended'\n | 'completed'\n | 'error';\n\nexport type WorkflowStepAppearance = 'contained' | 'embedded' | 'timeline';\n\nexport interface WorkflowStepViewModel {\n id: string;\n title: string;\n description?: string;\n status: WorkflowStepStatus;\n content?: React.ReactNode;\n durationMs?: number;\n error?: string;\n}\n\nexport interface WorkflowStepRendererProps {\n steps: readonly WorkflowStepViewModel[];\n appearance?: WorkflowStepAppearance;\n itemSlot?: string;\n expandable?: boolean;\n activeStepId?: string;\n expandedStepIds?: readonly string[];\n defaultExpandedStepIds?: readonly string[];\n onExpandedStepIdsChange?: (ids: readonly string[]) => void;\n className?: string;\n}\n\ninterface PrivateWorkflowStepRendererProps extends WorkflowStepRendererProps {\n renderItems?: boolean;\n}\n\nconst workflowStepItemStatusClasses = {\n pending: 'text-muted-foreground',\n running: 'text-primary',\n suspended: 'text-warning',\n completed: 'text-success',\n error: 'text-destructive',\n} as const satisfies Record<WorkflowStepStatus, string>;\n\nconst workflowStepIconStatusClasses = {\n pending: 'bg-accent text-muted-foreground',\n running: 'bg-primary/20 text-primary',\n suspended: 'bg-warning/20 text-warning',\n completed: 'bg-success/20 text-success',\n error: 'bg-destructive/20 text-destructive',\n} as const satisfies Record<WorkflowStepStatus, string>;\n\nexport const workflowStepItemVariants = cva(\n 'flex items-start gap-3 px-4 py-3 transition-colors motion-reduce:transition-none',\n {\n variants: {\n status: workflowStepItemStatusClasses,\n },\n defaultVariants: {\n status: 'pending',\n },\n },\n);\n\nexport const workflowStepIconVariants = cva(\n 'size-5 shrink-0 flex items-center justify-center rounded-full',\n {\n variants: {\n status: workflowStepIconStatusClasses,\n },\n defaultVariants: {\n status: 'pending',\n },\n },\n);\n\nconst workflowStepAppearanceConfig = {\n contained: {\n rootClassName: 'relative',\n hasDivider: true,\n hasConnector: false,\n },\n embedded: {\n rootClassName: 'relative',\n hasDivider: true,\n hasConnector: false,\n },\n timeline: {\n rootClassName: 'relative',\n hasDivider: false,\n hasConnector: true,\n },\n} as const satisfies Record<\n WorkflowStepAppearance,\n { rootClassName: string; hasDivider: boolean; hasConnector: boolean }\n>;\n\nexport function normalizeExpandedWorkflowStepIds(\n ids: readonly string[],\n steps: readonly WorkflowStepViewModel[],\n): string[] {\n const requested = new Set(ids);\n return steps.flatMap((step) => (requested.has(step.id) ? [step.id] : []));\n}\n\nfunction areWorkflowStepIdsEqual(\n left: readonly string[],\n right: readonly string[],\n): boolean {\n return (\n left.length === right.length &&\n left.every((id, index) => id === right[index])\n );\n}\n\nfunction formatWorkflowStepDuration(durationMs: number): string {\n if (durationMs < 1000) return `${durationMs}ms`;\n return `${(durationMs / 1000).toFixed(1)}s`;\n}\n\nfunction isIterableWorkflowStepContent(\n content: React.ReactNode,\n): content is Iterable<React.ReactNode> {\n return (\n typeof content === 'object' &&\n content !== null &&\n Symbol.iterator in content &&\n typeof (content as Iterable<React.ReactNode>)[Symbol.iterator] ===\n 'function'\n );\n}\n\nfunction isIteratorWorkflowStepContent(\n content: unknown,\n): content is Iterator<React.ReactNode> {\n return (\n typeof (content as Partial<Iterator<React.ReactNode>>).next === 'function'\n );\n}\n\ninterface NormalizedWorkflowStepContent {\n content: React.ReactNode;\n hasRenderableContent: boolean;\n changed: boolean;\n}\n\nconst normalizedOneShotWorkflowStepContent = new WeakMap<\n object,\n NormalizedWorkflowStepContent\n>();\n\nfunction normalizeIterableWorkflowStepContent(\n content: Iterable<React.ReactNode>,\n iterator: Iterator<React.ReactNode>,\n): NormalizedWorkflowStepContent {\n const normalizedChildren: React.ReactNode[] = [];\n let hasRenderableContent = false;\n let changed = !Array.isArray(content);\n\n for (let result = iterator.next(); !result.done; result = iterator.next()) {\n const normalizedChild = normalizeWorkflowStepContent(result.value);\n normalizedChildren.push(normalizedChild.content);\n hasRenderableContent ||= normalizedChild.hasRenderableContent;\n changed ||= normalizedChild.changed;\n }\n\n return {\n content: changed ? normalizedChildren : content,\n hasRenderableContent,\n changed,\n };\n}\n\nfunction normalizeWorkflowStepContent(\n content: React.ReactNode,\n): NormalizedWorkflowStepContent {\n if (\n content === null ||\n content === undefined ||\n typeof content === 'boolean' ||\n content === ''\n ) {\n return { content, hasRenderableContent: false, changed: false };\n }\n\n if (\n typeof content === 'string' ||\n typeof content === 'number' ||\n typeof content === 'bigint'\n ) {\n return { content, hasRenderableContent: true, changed: false };\n }\n\n if (React.isValidElement<{ children?: React.ReactNode }>(content)) {\n if (content.type !== React.Fragment) {\n return { content, hasRenderableContent: true, changed: false };\n }\n\n const normalizedChildren = normalizeWorkflowStepContent(\n content.props.children,\n );\n return {\n content: normalizedChildren.changed\n ? React.cloneElement(content, undefined, normalizedChildren.content)\n : content,\n hasRenderableContent: normalizedChildren.hasRenderableContent,\n changed: normalizedChildren.changed,\n };\n }\n\n if (isIterableWorkflowStepContent(content)) {\n const iterator = content[Symbol.iterator]();\n const oneShotCacheKey = isIteratorWorkflowStepContent(iterator)\n ? (iterator as object)\n : null;\n\n if (oneShotCacheKey !== null) {\n const cached = normalizedOneShotWorkflowStepContent.get(oneShotCacheKey);\n if (cached !== undefined) return cached;\n }\n\n const normalized = normalizeIterableWorkflowStepContent(content, iterator);\n if (oneShotCacheKey !== null) {\n normalizedOneShotWorkflowStepContent.set(oneShotCacheKey, normalized);\n }\n return normalized;\n }\n\n return { content, hasRenderableContent: true, changed: false };\n}\n\nfunction getNonBlankWorkflowStepError(\n error: string | undefined,\n): string | undefined {\n return error?.trim() ? error : undefined;\n}\n\nfunction getWorkflowStepStatusLabel(status: WorkflowStepStatus): string {\n switch (status) {\n case 'pending':\n return 'Pending';\n case 'running':\n return 'Running';\n case 'suspended':\n return 'Paused';\n case 'completed':\n return 'Completed';\n case 'error':\n return 'Error';\n default:\n return assertNever(status);\n }\n}\n\nexport interface WorkflowStepStatusIconProps {\n status: WorkflowStepStatus;\n index: number;\n className?: string;\n}\n\nexport function WorkflowStepStatusIcon({\n status,\n index,\n className,\n}: WorkflowStepStatusIconProps) {\n const iconClass = cn(workflowStepIconVariants({ status }), className);\n\n switch (status) {\n case 'pending':\n return (\n <div data-slot=\"workflow-step-icon\" className={iconClass}>\n <span className=\"text-xs font-medium\">{index + 1}</span>\n </div>\n );\n case 'running':\n return (\n <div\n data-slot=\"workflow-step-icon\"\n className={cn(\n iconClass,\n 'delight-status-pulse motion-reduce:!animate-none',\n )}\n >\n <Loader className=\"size-3 animate-spin motion-reduce:animate-none\" />\n </div>\n );\n case 'suspended':\n return (\n <div data-slot=\"workflow-step-icon\" className={iconClass}>\n <Pause className=\"size-3\" />\n </div>\n );\n case 'completed':\n return (\n <div\n data-slot=\"workflow-step-icon\"\n className={cn(\n iconClass,\n 'delight-check-bounce motion-reduce:!animate-none',\n )}\n >\n <Check className=\"size-3\" />\n </div>\n );\n case 'error':\n return (\n <div\n data-slot=\"workflow-step-icon\"\n className={cn(iconClass, 'delight-shake motion-reduce:!animate-none')}\n >\n <AlertCircle className=\"size-3\" />\n </div>\n );\n default:\n return assertNever(status);\n }\n}\n\nWorkflowStepStatusIcon.displayName = 'WorkflowStepStatusIcon';\n\nexport interface WorkflowStepItemProps {\n step: WorkflowStepViewModel;\n index: number;\n isLast: boolean;\n appearance?: WorkflowStepAppearance;\n itemSlot?: string;\n expandable?: boolean;\n expanded: boolean;\n active?: boolean;\n onExpandedChange: () => void;\n}\n\nexport function WorkflowStepItem({\n step,\n index,\n isLast,\n appearance = 'contained',\n itemSlot = 'workflow-step-item',\n expandable = true,\n expanded,\n active = false,\n onExpandedChange,\n}: WorkflowStepItemProps) {\n const contentId = React.useId();\n const errorDescriptionId = React.useId();\n const normalizedContent = normalizeWorkflowStepContent(step.content);\n const hasContent = normalizedContent.hasRenderableContent;\n const error = getNonBlankWorkflowStepError(step.error);\n const hasError = error !== undefined;\n const hasExpandableDetails = hasContent || hasError;\n const isDisclosureControl = hasExpandableDetails && expandable;\n const prefersReducedMotion = useReducedMotion();\n const appearanceConfig = workflowStepAppearanceConfig[appearance];\n const disclosureTransition = {\n duration: prefersReducedMotion ? 0 : 0.2,\n };\n const stepContent = (\n <>\n <WorkflowStepStatusIcon status={step.status} index={index} />\n\n <div className=\"min-w-0 flex-1 text-start\">\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'text-sm font-medium',\n step.status === 'pending'\n ? 'text-text-quaternary'\n : 'text-foreground',\n )}\n >\n {step.title}\n </span>\n <span className=\"text-xs text-secondary-foreground\">\n {getWorkflowStepStatusLabel(step.status)}\n </span>\n {step.durationMs !== undefined && (\n <span className=\"text-xs text-muted-foreground\">\n {formatWorkflowStepDuration(step.durationMs)}\n </span>\n )}\n </div>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-text-quaternary\">\n {step.description}\n </p>\n )}\n </div>\n\n {isDisclosureControl && (\n <div className=\"shrink-0\">\n {expanded ? (\n <ChevronDown className=\"size-4 text-muted-foreground\" />\n ) : (\n <ChevronRight className=\"size-4 text-muted-foreground rtl:rotate-180\" />\n )}\n </div>\n )}\n </>\n );\n\n return (\n <div\n data-slot={itemSlot}\n data-step-status={step.status}\n data-appearance={appearance}\n className={cn(\n appearanceConfig.rootClassName,\n appearanceConfig.hasDivider && !isLast && 'border-b border-border',\n )}\n >\n {isDisclosureControl ? (\n <button\n type=\"button\"\n onClick={onExpandedChange}\n aria-current={active ? 'step' : undefined}\n aria-expanded={expanded}\n aria-controls={contentId}\n aria-describedby={hasError ? errorDescriptionId : undefined}\n className={cn(\n workflowStepItemVariants({ status: step.status }),\n 'w-full cursor-pointer hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring',\n )}\n >\n {stepContent}\n </button>\n ) : (\n <div\n aria-current={active ? 'step' : undefined}\n aria-describedby={hasError ? errorDescriptionId : undefined}\n className={cn(\n workflowStepItemVariants({ status: step.status }),\n 'w-full',\n )}\n >\n {stepContent}\n </div>\n )}\n\n <AnimatePresence initial={false}>\n {expanded && hasExpandableDetails && (\n <motion.div\n id={contentId}\n data-slot=\"workflow-step-panel\"\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={disclosureTransition}\n className=\"overflow-hidden motion-reduce:transition-none\"\n >\n <div className=\"px-4 pb-3 ps-12\">\n {hasError && (\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-3\">\n <div className=\"flex items-start gap-2\">\n <AlertCircle className=\"mt-0.5 size-4 shrink-0 text-destructive\" />\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n </div>\n )}\n {hasContent && (\n <div className={hasError ? 'mt-3' : undefined}>\n {normalizedContent.content}\n </div>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {hasError && (\n <span id={errorDescriptionId} className=\"sr-only\">\n {error}\n </span>\n )}\n\n {appearanceConfig.hasConnector && !isLast && (\n <div\n data-slot=\"workflow-step-connector\"\n aria-hidden=\"true\"\n className=\"absolute top-8 -bottom-3 start-6 w-px bg-border\"\n />\n )}\n </div>\n );\n}\n\nWorkflowStepItem.displayName = 'WorkflowStepItem';\n\nexport function WorkflowStepRenderer({\n steps,\n appearance = 'contained',\n itemSlot = 'workflow-step-item',\n expandable = true,\n activeStepId,\n expandedStepIds: controlledExpandedStepIds,\n defaultExpandedStepIds = [],\n onExpandedStepIdsChange,\n className,\n renderItems = true,\n}: PrivateWorkflowStepRendererProps) {\n const isControlled = controlledExpandedStepIds !== undefined;\n const controlledSnapshot = isControlled\n ? [...controlledExpandedStepIds]\n : undefined;\n const [uncontrolledExpandedStepIds, setUncontrolledExpandedStepIds] =\n React.useState<readonly string[]>(() =>\n normalizeExpandedWorkflowStepIds(defaultExpandedStepIds, steps),\n );\n const lastControlledExpandedStepIdsRef = React.useRef<readonly string[]>(\n controlledSnapshot ?? [],\n );\n const wasControlledRef = React.useRef(isControlled);\n const rawExpandedStepIds = isControlled\n ? controlledExpandedStepIds\n : uncontrolledExpandedStepIds;\n const visibleExpandedStepIds = normalizeExpandedWorkflowStepIds(\n rawExpandedStepIds,\n steps,\n );\n const expandedSet = new Set(visibleExpandedStepIds);\n\n React.useLayoutEffect(() => {\n if (controlledSnapshot !== undefined) {\n lastControlledExpandedStepIdsRef.current = controlledSnapshot;\n }\n }, [controlledSnapshot]);\n\n React.useLayoutEffect(() => {\n const wasControlled = wasControlledRef.current;\n wasControlledRef.current = isControlled;\n if (isControlled) return;\n\n setUncontrolledExpandedStepIds((current) => {\n const source = wasControlled\n ? lastControlledExpandedStepIdsRef.current\n : current;\n const reconciled = normalizeExpandedWorkflowStepIds(source, steps);\n return areWorkflowStepIdsEqual(reconciled, current)\n ? current\n : reconciled;\n });\n }, [isControlled, steps]);\n\n const toggleStep = (id: string) => {\n const next = new Set(visibleExpandedStepIds);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n const normalizedNext = normalizeExpandedWorkflowStepIds([...next], steps);\n if (!isControlled) {\n setUncontrolledExpandedStepIds([...normalizedNext]);\n }\n onExpandedStepIdsChange?.([...normalizedNext]);\n };\n\n if (!renderItems) return null;\n\n return (\n <ol\n data-slot=\"workflow-step-list\"\n data-appearance={appearance}\n className={cn('m-0 list-none p-0', className)}\n >\n {steps.map((step, index) => (\n <li key={step.id}>\n <WorkflowStepItem\n step={step}\n index={index}\n isLast={index === steps.length - 1}\n appearance={appearance}\n itemSlot={itemSlot}\n expandable={expandable}\n expanded={expandedSet.has(step.id)}\n active={activeStepId === step.id}\n onExpandedChange={() => toggleStep(step.id)}\n />\n </li>\n ))}\n </ol>\n );\n}\n\nWorkflowStepRenderer.displayName = 'WorkflowStepRenderer';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index174.js","names":[],"sources":["../src/components/organisms/ai/_shared/format-ai-duration.ts"],"sourcesContent":["export function formatAIDuration(durationMs: number): string {\n const totalSeconds = Math.max(0, Math.round(durationMs / 1000));\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return [hours ? `${hours}h` : '', minutes ? `${minutes}m` : '']\n .filter(Boolean)\n .join(' ');\n }\n if (minutes > 0) {\n return `${minutes}m${seconds ? ` ${seconds}s` : ''}`;\n }\n return `${totalSeconds}s`;\n}\n"],"mappings":";AAAA,SAAgB,iBAAiB,YAA4B;CAC3D,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,GAAI,CAAC;CAC9D,MAAM,QAAQ,KAAK,MAAM,eAAe,IAAI;CAC5C,MAAM,UAAU,KAAK,MAAO,eAAe,OAAQ,EAAE;CACrD,MAAM,UAAU,eAAe;CAE/B,IAAI,QAAQ,GACV,OAAO,CAAC,QAAQ,GAAG,MAAM,KAAK,IAAI,UAAU,GAAG,QAAQ,KAAK,EAAE,CAAC,CAC5D,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;CAEb,IAAI,UAAU,GACZ,OAAO,GAAG,QAAQ,GAAG,UAAU,IAAI,QAAQ,KAAK;CAElD,OAAO,GAAG,aAAa;AACzB"}
package/dist/index175.js CHANGED
@@ -1,166 +1,339 @@
1
- import { cn } from "./index2.js";
2
- import { WorkflowStepItem, WorkflowStepRenderer, WorkflowStepStatusIcon } from "./index174.js";
1
+ import { assertNever, cn } from "./index2.js";
2
+ import { formatAIDuration } from "./index174.js";
3
3
  import { cva } from "class-variance-authority";
4
- import { AlertCircle, Check, ChevronDown, ChevronRight, Clock } from "lucide-react";
4
+ import { AlertCircle, Check, ChevronDown, ChevronRight, Loader, Pause } from "lucide-react";
5
5
  import * as React from "react";
6
- import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { AnimatePresence, motion, useReducedMotion } from "motion/react";
8
- //#region src/components/organisms/ai/AISteps/AISteps.tsx
9
- var stepsContainerVariants = cva("overflow-hidden rounded-xl border", {
10
- variants: { variant: {
11
- default: "border-border bg-background",
12
- subtle: "border-border bg-muted"
13
- } },
14
- defaultVariants: { variant: "default" }
15
- });
16
- var stepItemVariants = cva("flex items-start gap-3 px-4 py-3 transition-colors", {
17
- variants: { status: {
18
- pending: "text-muted-foreground",
19
- running: "text-primary",
20
- completed: "text-success",
21
- error: "text-destructive"
22
- } },
8
+ //#region src/components/organisms/ai/_shared/workflow-step-renderer.tsx
9
+ var workflowStepItemStatusClasses = {
10
+ pending: "text-muted-foreground",
11
+ running: "text-primary",
12
+ suspended: "text-warning",
13
+ completed: "text-success",
14
+ error: "text-destructive"
15
+ };
16
+ var workflowStepIconStatusClasses = {
17
+ pending: "bg-accent text-muted-foreground",
18
+ running: "bg-primary/20 text-primary",
19
+ suspended: "bg-warning/20 text-warning",
20
+ completed: "bg-success/20 text-success",
21
+ error: "bg-destructive/20 text-destructive"
22
+ };
23
+ var workflowStepItemVariants = cva("flex items-start gap-3 px-4 py-3 transition-colors motion-reduce:transition-none", {
24
+ variants: { status: workflowStepItemStatusClasses },
23
25
  defaultVariants: { status: "pending" }
24
26
  });
25
- var stepIconVariants = cva("size-5 shrink-0 flex items-center justify-center rounded-full", {
26
- variants: { status: {
27
- pending: "bg-accent text-muted-foreground",
28
- running: "bg-primary/20 text-primary",
29
- completed: "bg-success/20 text-success",
30
- error: "bg-destructive/20 text-destructive"
31
- } },
27
+ var workflowStepIconVariants = cva("size-5 shrink-0 flex items-center justify-center rounded-full", {
28
+ variants: { status: workflowStepIconStatusClasses },
32
29
  defaultVariants: { status: "pending" }
33
30
  });
34
- var WORKFLOW_STATUS_BY_STEP_STATUS = {
35
- pending: "pending",
36
- running: "running",
37
- completed: "completed",
38
- error: "error"
31
+ var workflowStepAppearanceConfig = {
32
+ contained: {
33
+ rootClassName: "relative",
34
+ hasDivider: true,
35
+ hasConnector: false
36
+ },
37
+ embedded: {
38
+ rootClassName: "relative",
39
+ hasDivider: true,
40
+ hasConnector: false
41
+ },
42
+ timeline: {
43
+ rootClassName: "relative",
44
+ hasDivider: false,
45
+ hasConnector: true
46
+ }
39
47
  };
40
- function toWorkflowStepStatus(status) {
41
- return WORKFLOW_STATUS_BY_STEP_STATUS[status];
48
+ function normalizeExpandedWorkflowStepIds(ids, steps) {
49
+ const requested = new Set(ids);
50
+ return steps.flatMap((step) => requested.has(step.id) ? [step.id] : []);
51
+ }
52
+ function areWorkflowStepIdsEqual(left, right) {
53
+ return left.length === right.length && left.every((id, index) => id === right[index]);
54
+ }
55
+ function isIterableWorkflowStepContent(content) {
56
+ return typeof content === "object" && content !== null && Symbol.iterator in content && typeof content[Symbol.iterator] === "function";
57
+ }
58
+ function isIteratorWorkflowStepContent(content) {
59
+ return typeof content.next === "function";
42
60
  }
43
- function toWorkflowStep(step) {
44
- const error = step.error?.trim() ? step.error : void 0;
61
+ var normalizedOneShotWorkflowStepContent = /* @__PURE__ */ new WeakMap();
62
+ function normalizeIterableWorkflowStepContent(content, iterator) {
63
+ const normalizedChildren = [];
64
+ let hasRenderableContent = false;
65
+ let changed = !Array.isArray(content);
66
+ for (let result = iterator.next(); !result.done; result = iterator.next()) {
67
+ const normalizedChild = normalizeWorkflowStepContent(result.value);
68
+ normalizedChildren.push(normalizedChild.content);
69
+ hasRenderableContent ||= normalizedChild.hasRenderableContent;
70
+ changed ||= normalizedChild.changed;
71
+ }
45
72
  return {
46
- id: step.id,
47
- title: step.title,
48
- description: step.description,
49
- status: toWorkflowStepStatus(step.status),
50
- content: error === void 0 ? step.content : void 0,
51
- durationMs: step.status === "completed" ? step.duration : void 0,
52
- error
73
+ content: changed ? normalizedChildren : content,
74
+ hasRenderableContent,
75
+ changed
53
76
  };
54
77
  }
55
- function StepIcon({ status, index, className }) {
56
- return /* @__PURE__ */ jsx(WorkflowStepStatusIcon, {
57
- status: toWorkflowStepStatus(status),
58
- index,
59
- className
60
- });
78
+ function normalizeWorkflowStepContent(content) {
79
+ if (content === null || content === void 0 || typeof content === "boolean" || content === "") return {
80
+ content,
81
+ hasRenderableContent: false,
82
+ changed: false
83
+ };
84
+ if (typeof content === "string" || typeof content === "number" || typeof content === "bigint") return {
85
+ content,
86
+ hasRenderableContent: true,
87
+ changed: false
88
+ };
89
+ if (React.isValidElement(content)) {
90
+ if (content.type !== React.Fragment) return {
91
+ content,
92
+ hasRenderableContent: true,
93
+ changed: false
94
+ };
95
+ const normalizedChildren = normalizeWorkflowStepContent(content.props.children);
96
+ return {
97
+ content: normalizedChildren.changed ? React.cloneElement(content, void 0, normalizedChildren.content) : content,
98
+ hasRenderableContent: normalizedChildren.hasRenderableContent,
99
+ changed: normalizedChildren.changed
100
+ };
101
+ }
102
+ if (isIterableWorkflowStepContent(content)) {
103
+ const iterator = content[Symbol.iterator]();
104
+ const oneShotCacheKey = isIteratorWorkflowStepContent(iterator) ? iterator : null;
105
+ if (oneShotCacheKey !== null) {
106
+ const cached = normalizedOneShotWorkflowStepContent.get(oneShotCacheKey);
107
+ if (cached !== void 0) return cached;
108
+ }
109
+ const normalized = normalizeIterableWorkflowStepContent(content, iterator);
110
+ if (oneShotCacheKey !== null) normalizedOneShotWorkflowStepContent.set(oneShotCacheKey, normalized);
111
+ return normalized;
112
+ }
113
+ return {
114
+ content,
115
+ hasRenderableContent: true,
116
+ changed: false
117
+ };
61
118
  }
62
- StepIcon.displayName = "StepIcon";
63
- function AIStepItem({ step, index, isLast, expandable = true, defaultExpanded = false }) {
64
- const [expanded, setExpanded] = React.useState(defaultExpanded);
65
- return /* @__PURE__ */ jsx(WorkflowStepItem, {
66
- step: toWorkflowStep(step),
67
- index,
68
- isLast,
69
- appearance: "contained",
70
- itemSlot: "ai-step-item",
71
- expandable,
72
- expanded,
73
- onExpandedChange: () => setExpanded((value) => !value)
74
- });
119
+ function getNonBlankWorkflowStepError(error) {
120
+ return error?.trim() ? error : void 0;
121
+ }
122
+ function getWorkflowStepStatusLabel(status) {
123
+ switch (status) {
124
+ case "pending": return "Pending";
125
+ case "running": return "Running";
126
+ case "suspended": return "Paused";
127
+ case "completed": return "Completed";
128
+ case "error": return "Error";
129
+ default: return assertNever(status);
130
+ }
131
+ }
132
+ function WorkflowStepStatusIcon({ status, index, className }) {
133
+ const iconClass = cn(workflowStepIconVariants({ status }), className);
134
+ switch (status) {
135
+ case "pending": return /* @__PURE__ */ jsx("div", {
136
+ "data-slot": "workflow-step-icon",
137
+ className: iconClass,
138
+ children: /* @__PURE__ */ jsx("span", {
139
+ className: "text-xs font-medium",
140
+ children: index + 1
141
+ })
142
+ });
143
+ case "running": return /* @__PURE__ */ jsx("div", {
144
+ "data-slot": "workflow-step-icon",
145
+ className: cn(iconClass, "delight-status-pulse motion-reduce:!animate-none"),
146
+ children: /* @__PURE__ */ jsx(Loader, { className: "size-3 animate-spin motion-reduce:animate-none" })
147
+ });
148
+ case "suspended": return /* @__PURE__ */ jsx("div", {
149
+ "data-slot": "workflow-step-icon",
150
+ className: iconClass,
151
+ children: /* @__PURE__ */ jsx(Pause, { className: "size-3" })
152
+ });
153
+ case "completed": return /* @__PURE__ */ jsx("div", {
154
+ "data-slot": "workflow-step-icon",
155
+ className: cn(iconClass, "delight-check-bounce motion-reduce:!animate-none"),
156
+ children: /* @__PURE__ */ jsx(Check, { className: "size-3" })
157
+ });
158
+ case "error": return /* @__PURE__ */ jsx("div", {
159
+ "data-slot": "workflow-step-icon",
160
+ className: cn(iconClass, "delight-shake motion-reduce:!animate-none"),
161
+ children: /* @__PURE__ */ jsx(AlertCircle, { className: "size-3" })
162
+ });
163
+ default: return assertNever(status);
164
+ }
75
165
  }
76
- AIStepItem.displayName = "AIStepItem";
77
- /**
78
- * AISteps displays a multi-step progress indicator for AI workflows.
79
- * Shows step status (pending, running, complete, error) with expandable details and timing.
80
- *
81
- * @llms Multi-step AI progress with status icons, timing, expandable details
82
- * @example
83
- * ```tsx
84
- * <AISteps
85
- * title="Processing"
86
- * steps={[
87
- * { label: 'Analyzing', status: 'complete', duration: '2s' },
88
- * { label: 'Generating', status: 'running' },
89
- * ]}
90
- * />
91
- * ```
92
- */
93
- function AISteps({ steps, title, variant, collapsible = true, defaultExpanded = true, stepsExpandable = true, className }) {
94
- const [isExpanded, setIsExpanded] = React.useState(defaultExpanded);
166
+ WorkflowStepStatusIcon.displayName = "WorkflowStepStatusIcon";
167
+ function WorkflowStepItem({ step, index, isLast, appearance = "contained", itemSlot = "workflow-step-item", expandable = true, expanded, active = false, onExpandedChange }) {
168
+ const contentId = React.useId();
169
+ const errorDescriptionId = React.useId();
170
+ const normalizedContent = normalizeWorkflowStepContent(step.content);
171
+ const hasContent = normalizedContent.hasRenderableContent;
172
+ const error = getNonBlankWorkflowStepError(step.error);
173
+ const hasError = error !== void 0;
174
+ const hasExpandableDetails = hasContent || hasError;
175
+ const isDisclosureControl = hasExpandableDetails && expandable;
95
176
  const prefersReducedMotion = useReducedMotion();
96
- const completedCount = steps.filter((s) => s.status === "completed").length;
97
- const totalCount = steps.length;
98
- const hasError = steps.some((s) => s.status === "error");
99
- const isRunning = steps.some((s) => s.status === "running");
100
- return /* @__PURE__ */ jsxs("section", {
101
- "data-slot": "ai-steps",
102
- "aria-label": title || "Steps",
103
- className: cn(stepsContainerVariants({ variant }), className),
104
- children: [(title || collapsible) && /* @__PURE__ */ jsxs("button", {
105
- type: "button",
106
- onClick: () => collapsible && setIsExpanded(!isExpanded),
107
- disabled: !collapsible,
108
- "aria-expanded": collapsible ? isExpanded : void 0,
109
- className: cn("flex items-center justify-between w-full px-4 py-3 border-b border-border", collapsible && "hover:bg-muted cursor-pointer", "focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring"),
177
+ const appearanceConfig = workflowStepAppearanceConfig[appearance];
178
+ const disclosureTransition = { duration: prefersReducedMotion ? 0 : .2 };
179
+ const stepContent = /* @__PURE__ */ jsxs(Fragment, { children: [
180
+ /* @__PURE__ */ jsx(WorkflowStepStatusIcon, {
181
+ status: step.status,
182
+ index
183
+ }),
184
+ /* @__PURE__ */ jsxs("div", {
185
+ className: "min-w-0 flex-1 text-start",
110
186
  children: [/* @__PURE__ */ jsxs("div", {
111
- className: "flex items-center gap-2",
187
+ className: "flex flex-wrap items-center gap-2",
112
188
  children: [
113
- isRunning && /* @__PURE__ */ jsx(Clock, { className: "size-4 text-primary animate-pulse motion-reduce:animate-none" }),
114
- hasError && !isRunning && /* @__PURE__ */ jsx(AlertCircle, { className: "size-4 text-destructive" }),
115
- !isRunning && !hasError && completedCount === totalCount && /* @__PURE__ */ jsx(Check, { className: "size-4 text-success" }),
189
+ step.contextLabel && /* @__PURE__ */ jsx("span", {
190
+ "data-slot": "workflow-step-context",
191
+ className: "rounded-full border border-border px-2 py-0.5 text-[0.6875rem] font-medium leading-none text-secondary-foreground",
192
+ children: step.contextLabel
193
+ }),
116
194
  /* @__PURE__ */ jsx("span", {
117
- className: "text-sm font-medium text-foreground",
118
- children: title || "Steps"
195
+ className: cn("text-sm font-medium", step.status === "pending" ? "text-text-quaternary" : "text-foreground"),
196
+ children: step.title
119
197
  }),
120
- /* @__PURE__ */ jsxs("span", {
121
- className: "text-xs text-text-quaternary",
122
- children: [
123
- "(",
124
- completedCount,
125
- "/",
126
- totalCount,
127
- ")"
128
- ]
198
+ /* @__PURE__ */ jsx("span", {
199
+ className: "text-xs text-secondary-foreground",
200
+ children: getWorkflowStepStatusLabel(step.status)
201
+ }),
202
+ step.durationMs !== void 0 && /* @__PURE__ */ jsx("span", {
203
+ className: "text-xs text-muted-foreground",
204
+ children: formatAIDuration(step.durationMs)
129
205
  })
130
206
  ]
131
- }), collapsible && /* @__PURE__ */ jsx("div", {
132
- className: "shrink-0",
133
- children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-muted-foreground" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 text-muted-foreground rtl:rotate-180" })
207
+ }), step.description && /* @__PURE__ */ jsx("p", {
208
+ className: "mt-0.5 text-xs text-text-quaternary",
209
+ children: step.description
134
210
  })]
135
- }), /* @__PURE__ */ jsx(AnimatePresence, {
136
- initial: false,
137
- children: isExpanded && /* @__PURE__ */ jsx(motion.div, {
138
- initial: {
139
- height: 0,
140
- opacity: 0
141
- },
142
- animate: {
143
- height: "auto",
144
- opacity: 1
145
- },
146
- exit: {
147
- height: 0,
148
- opacity: 0
149
- },
150
- transition: { duration: prefersReducedMotion ? 0 : .2 },
151
- className: "overflow-hidden",
152
- children: /* @__PURE__ */ jsx(WorkflowStepRenderer, {
153
- appearance: "contained",
154
- steps: steps.map(toWorkflowStep),
155
- itemSlot: "ai-step-item",
156
- expandable: stepsExpandable
211
+ }),
212
+ isDisclosureControl && /* @__PURE__ */ jsx("div", {
213
+ className: "shrink-0",
214
+ children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-muted-foreground" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 text-muted-foreground rtl:rotate-180" })
215
+ })
216
+ ] });
217
+ return /* @__PURE__ */ jsxs("div", {
218
+ "data-slot": itemSlot,
219
+ "data-step-status": step.status,
220
+ "data-appearance": appearance,
221
+ className: cn(appearanceConfig.rootClassName, appearanceConfig.hasDivider && !isLast && "border-b border-border"),
222
+ children: [
223
+ isDisclosureControl ? /* @__PURE__ */ jsx("button", {
224
+ type: "button",
225
+ onClick: onExpandedChange,
226
+ "aria-current": active ? "step" : void 0,
227
+ "aria-expanded": expanded,
228
+ "aria-controls": contentId,
229
+ "aria-describedby": hasError ? errorDescriptionId : void 0,
230
+ className: cn(workflowStepItemVariants({ status: step.status }), "w-full cursor-pointer hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring"),
231
+ children: stepContent
232
+ }) : /* @__PURE__ */ jsx("div", {
233
+ "aria-current": active ? "step" : void 0,
234
+ "aria-describedby": hasError ? errorDescriptionId : void 0,
235
+ className: cn(workflowStepItemVariants({ status: step.status }), "w-full"),
236
+ children: stepContent
237
+ }),
238
+ /* @__PURE__ */ jsx(AnimatePresence, {
239
+ initial: false,
240
+ children: expanded && hasExpandableDetails && /* @__PURE__ */ jsx(motion.div, {
241
+ id: contentId,
242
+ "data-slot": "workflow-step-panel",
243
+ initial: {
244
+ height: 0,
245
+ opacity: 0
246
+ },
247
+ animate: {
248
+ height: "auto",
249
+ opacity: 1
250
+ },
251
+ exit: {
252
+ height: 0,
253
+ opacity: 0
254
+ },
255
+ transition: disclosureTransition,
256
+ className: "overflow-hidden motion-reduce:transition-none",
257
+ children: /* @__PURE__ */ jsxs("div", {
258
+ className: "px-4 pb-3 ps-12",
259
+ children: [hasError && /* @__PURE__ */ jsx("div", {
260
+ className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3",
261
+ children: /* @__PURE__ */ jsxs("div", {
262
+ className: "flex items-start gap-2",
263
+ children: [/* @__PURE__ */ jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0 text-destructive" }), /* @__PURE__ */ jsx("p", {
264
+ className: "text-sm text-destructive",
265
+ children: error
266
+ })]
267
+ })
268
+ }), hasContent && /* @__PURE__ */ jsx("div", {
269
+ className: hasError ? "mt-3" : void 0,
270
+ children: normalizedContent.content
271
+ })]
272
+ })
157
273
  })
274
+ }),
275
+ hasError && /* @__PURE__ */ jsx("span", {
276
+ id: errorDescriptionId,
277
+ className: "sr-only",
278
+ children: error
279
+ }),
280
+ appearanceConfig.hasConnector && !isLast && /* @__PURE__ */ jsx("div", {
281
+ "data-slot": "workflow-step-connector",
282
+ "aria-hidden": "true",
283
+ className: "absolute top-8 -bottom-3 start-6 w-px bg-border"
158
284
  })
159
- })]
285
+ ]
286
+ });
287
+ }
288
+ WorkflowStepItem.displayName = "WorkflowStepItem";
289
+ function WorkflowStepRenderer({ steps, appearance = "contained", itemSlot = "workflow-step-item", expandable = true, activeStepId, expandedStepIds: controlledExpandedStepIds, defaultExpandedStepIds = [], onExpandedStepIdsChange, className, renderItems = true }) {
290
+ const isControlled = controlledExpandedStepIds !== void 0;
291
+ const controlledSnapshot = isControlled ? [...controlledExpandedStepIds] : void 0;
292
+ const [uncontrolledExpandedStepIds, setUncontrolledExpandedStepIds] = React.useState(() => normalizeExpandedWorkflowStepIds(defaultExpandedStepIds, steps));
293
+ const lastControlledExpandedStepIdsRef = React.useRef(controlledSnapshot ?? []);
294
+ const wasControlledRef = React.useRef(isControlled);
295
+ const visibleExpandedStepIds = normalizeExpandedWorkflowStepIds(isControlled ? controlledExpandedStepIds : uncontrolledExpandedStepIds, steps);
296
+ const expandedSet = new Set(visibleExpandedStepIds);
297
+ React.useLayoutEffect(() => {
298
+ if (controlledSnapshot !== void 0) lastControlledExpandedStepIdsRef.current = controlledSnapshot;
299
+ }, [controlledSnapshot]);
300
+ React.useLayoutEffect(() => {
301
+ const wasControlled = wasControlledRef.current;
302
+ wasControlledRef.current = isControlled;
303
+ if (isControlled) return;
304
+ setUncontrolledExpandedStepIds((current) => {
305
+ const reconciled = normalizeExpandedWorkflowStepIds(wasControlled ? lastControlledExpandedStepIdsRef.current : current, steps);
306
+ return areWorkflowStepIdsEqual(reconciled, current) ? current : reconciled;
307
+ });
308
+ }, [isControlled, steps]);
309
+ const toggleStep = (id) => {
310
+ const next = new Set(visibleExpandedStepIds);
311
+ if (next.has(id)) next.delete(id);
312
+ else next.add(id);
313
+ const normalizedNext = normalizeExpandedWorkflowStepIds([...next], steps);
314
+ if (!isControlled) setUncontrolledExpandedStepIds([...normalizedNext]);
315
+ onExpandedStepIdsChange?.([...normalizedNext]);
316
+ };
317
+ if (!renderItems) return null;
318
+ return /* @__PURE__ */ jsx("ol", {
319
+ "data-slot": "workflow-step-list",
320
+ "data-appearance": appearance,
321
+ className: cn("m-0 list-none p-0", className),
322
+ children: steps.map((step, index) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(WorkflowStepItem, {
323
+ step,
324
+ index,
325
+ isLast: index === steps.length - 1,
326
+ appearance,
327
+ itemSlot,
328
+ expandable,
329
+ expanded: expandedSet.has(step.id),
330
+ active: activeStepId === step.id,
331
+ onExpandedChange: () => toggleStep(step.id)
332
+ }) }, step.id))
160
333
  });
161
334
  }
162
- AISteps.displayName = "AISteps";
335
+ WorkflowStepRenderer.displayName = "WorkflowStepRenderer";
163
336
  //#endregion
164
- export { AIStepItem, AISteps, StepIcon, stepIconVariants, stepItemVariants, stepsContainerVariants };
337
+ export { WorkflowStepItem, WorkflowStepRenderer, WorkflowStepStatusIcon, normalizeExpandedWorkflowStepIds, workflowStepIconVariants, workflowStepItemVariants };
165
338
 
166
339
  //# sourceMappingURL=index175.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index175.js","names":[],"sources":["../src/components/organisms/ai/AISteps/AISteps.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport {\n AlertCircle,\n Check,\n ChevronDown,\n ChevronRight,\n Clock,\n} from 'lucide-react';\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react';\nimport * as React from 'react';\nimport { cn } from '@/lib/utils';\nimport {\n WorkflowStepItem,\n WorkflowStepRenderer,\n type WorkflowStepStatus,\n WorkflowStepStatusIcon,\n type WorkflowStepViewModel,\n} from '../_shared/workflow-step-renderer';\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nconst stepsContainerVariants = cva('overflow-hidden rounded-xl border', {\n variants: {\n variant: {\n default: 'border-border bg-background',\n subtle: 'border-border bg-muted',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nconst stepItemVariants = cva(\n 'flex items-start gap-3 px-4 py-3 transition-colors',\n {\n variants: {\n status: {\n pending: 'text-muted-foreground',\n running: 'text-primary',\n completed: 'text-success',\n error: 'text-destructive',\n },\n },\n defaultVariants: {\n status: 'pending',\n },\n },\n);\n\nconst stepIconVariants = cva(\n 'size-5 shrink-0 flex items-center justify-center rounded-full',\n {\n variants: {\n status: {\n pending: 'bg-accent text-muted-foreground',\n running: 'bg-primary/20 text-primary',\n completed: 'bg-success/20 text-success',\n error: 'bg-destructive/20 text-destructive',\n },\n },\n defaultVariants: {\n status: 'pending',\n },\n },\n);\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type StepStatus = 'pending' | 'running' | 'completed' | 'error';\n\nexport interface StepData {\n /** Unique step ID */\n id: string;\n /** Step title */\n title: string;\n /** Step description */\n description?: string;\n /** Step status */\n status: StepStatus;\n /** Optional content to show when expanded */\n content?: React.ReactNode;\n /** Duration in ms (for completed steps) */\n duration?: number;\n /** Error message if status is error */\n error?: string;\n}\n\ntype AIStepsWorkflowStatus = Exclude<WorkflowStepStatus, 'suspended'>;\n\nconst WORKFLOW_STATUS_BY_STEP_STATUS = {\n pending: 'pending',\n running: 'running',\n completed: 'completed',\n error: 'error',\n} as const satisfies Record<StepStatus, AIStepsWorkflowStatus>;\n\nfunction toWorkflowStepStatus(status: StepStatus): AIStepsWorkflowStatus {\n return WORKFLOW_STATUS_BY_STEP_STATUS[status];\n}\n\nfunction toWorkflowStep(step: StepData): WorkflowStepViewModel {\n const error = step.error?.trim() ? step.error : undefined;\n\n return {\n id: step.id,\n title: step.title,\n description: step.description,\n status: toWorkflowStepStatus(step.status),\n content: error === undefined ? step.content : undefined,\n durationMs: step.status === 'completed' ? step.duration : undefined,\n error,\n };\n}\n\n// =============================================================================\n// Step Icon Component\n// =============================================================================\n\ninterface StepIconProps {\n status: StepStatus;\n index: number;\n className?: string;\n}\n\nfunction StepIcon({ status, index, className }: StepIconProps) {\n return (\n <WorkflowStepStatusIcon\n status={toWorkflowStepStatus(status)}\n index={index}\n className={className}\n />\n );\n}\n\nStepIcon.displayName = 'StepIcon';\n\n// =============================================================================\n// Single Step Item\n// =============================================================================\n\ninterface AIStepItemProps {\n step: StepData;\n index: number;\n isLast: boolean;\n expandable?: boolean;\n defaultExpanded?: boolean;\n}\n\nfunction AIStepItem({\n step,\n index,\n isLast,\n expandable = true,\n defaultExpanded = false,\n}: AIStepItemProps) {\n const [expanded, setExpanded] = React.useState(defaultExpanded);\n\n return (\n <WorkflowStepItem\n step={toWorkflowStep(step)}\n index={index}\n isLast={isLast}\n appearance=\"contained\"\n itemSlot=\"ai-step-item\"\n expandable={expandable}\n expanded={expanded}\n onExpandedChange={() => setExpanded((value) => !value)}\n />\n );\n}\n\nAIStepItem.displayName = 'AIStepItem';\n\n// =============================================================================\n// Main AISteps Component\n// =============================================================================\n\nexport interface AIStepsProps\n extends VariantProps<typeof stepsContainerVariants> {\n /** Array of steps */\n steps: StepData[];\n /** Title for the steps container */\n title?: string;\n /** Whether the container is collapsible */\n collapsible?: boolean;\n /** Whether the container is expanded by default */\n defaultExpanded?: boolean;\n /** Whether individual steps are expandable */\n stepsExpandable?: boolean;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * AISteps displays a multi-step progress indicator for AI workflows.\n * Shows step status (pending, running, complete, error) with expandable details and timing.\n *\n * @llms Multi-step AI progress with status icons, timing, expandable details\n * @example\n * ```tsx\n * <AISteps\n * title=\"Processing\"\n * steps={[\n * { label: 'Analyzing', status: 'complete', duration: '2s' },\n * { label: 'Generating', status: 'running' },\n * ]}\n * />\n * ```\n */\nexport function AISteps({\n steps,\n title,\n variant,\n collapsible = true,\n defaultExpanded = true,\n stepsExpandable = true,\n className,\n}: AIStepsProps) {\n const [isExpanded, setIsExpanded] = React.useState(defaultExpanded);\n const prefersReducedMotion = useReducedMotion();\n\n // Calculate summary stats\n const completedCount = steps.filter((s) => s.status === 'completed').length;\n const totalCount = steps.length;\n const hasError = steps.some((s) => s.status === 'error');\n const isRunning = steps.some((s) => s.status === 'running');\n\n return (\n <section\n data-slot=\"ai-steps\"\n aria-label={title || 'Steps'}\n className={cn(stepsContainerVariants({ variant }), className)}\n >\n {/* Header */}\n {(title || collapsible) && (\n <button\n type=\"button\"\n onClick={() => collapsible && setIsExpanded(!isExpanded)}\n disabled={!collapsible}\n aria-expanded={collapsible ? isExpanded : undefined}\n className={cn(\n 'flex items-center justify-between w-full px-4 py-3 border-b border-border',\n collapsible && 'hover:bg-muted cursor-pointer',\n 'focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring',\n )}\n >\n <div className=\"flex items-center gap-2\">\n {isRunning && (\n <Clock className=\"size-4 text-primary animate-pulse motion-reduce:animate-none\" />\n )}\n {hasError && !isRunning && (\n <AlertCircle className=\"size-4 text-destructive\" />\n )}\n {!isRunning && !hasError && completedCount === totalCount && (\n <Check className=\"size-4 text-success\" />\n )}\n <span className=\"text-sm font-medium text-foreground\">\n {title || 'Steps'}\n </span>\n <span className=\"text-xs text-text-quaternary\">\n ({completedCount}/{totalCount})\n </span>\n </div>\n\n {collapsible && (\n <div className=\"shrink-0\">\n {isExpanded ? (\n <ChevronDown className=\"size-4 text-muted-foreground\" />\n ) : (\n <ChevronRight className=\"size-4 text-muted-foreground rtl:rotate-180\" />\n )}\n </div>\n )}\n </button>\n )}\n\n {/* Steps List */}\n <AnimatePresence initial={false}>\n {isExpanded && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={{ duration: prefersReducedMotion ? 0 : 0.2 }}\n className=\"overflow-hidden\"\n >\n <WorkflowStepRenderer\n appearance=\"contained\"\n steps={steps.map(toWorkflowStep)}\n itemSlot=\"ai-step-item\"\n expandable={stepsExpandable}\n />\n </motion.div>\n )}\n </AnimatePresence>\n </section>\n );\n}\n\nAISteps.displayName = 'AISteps';\n\nexport {\n AIStepItem,\n StepIcon,\n stepIconVariants,\n stepItemVariants,\n stepsContainerVariants,\n};\n"],"mappings":";;;;;;;;AAuBA,IAAM,yBAAyB,IAAI,qCAAqC;CACtE,UAAU,EACR,SAAS;EACP,SAAS;EACT,QAAQ;CACV,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAED,IAAM,mBAAmB,IACvB,sDACA;CACE,UAAU,EACR,QAAQ;EACN,SAAS;EACT,SAAS;EACT,WAAW;EACX,OAAO;CACT,EACF;CACA,iBAAiB,EACf,QAAQ,UACV;AACF,CACF;AAEA,IAAM,mBAAmB,IACvB,iEACA;CACE,UAAU,EACR,QAAQ;EACN,SAAS;EACT,SAAS;EACT,WAAW;EACX,OAAO;CACT,EACF;CACA,iBAAiB,EACf,QAAQ,UACV;AACF,CACF;AA2BA,IAAM,iCAAiC;CACrC,SAAS;CACT,SAAS;CACT,WAAW;CACX,OAAO;AACT;AAEA,SAAS,qBAAqB,QAA2C;CACvE,OAAO,+BAA+B;AACxC;AAEA,SAAS,eAAe,MAAuC;CAC7D,MAAM,QAAQ,KAAK,OAAO,KAAK,IAAI,KAAK,QAAQ,KAAA;CAEhD,OAAO;EACL,IAAI,KAAK;EACT,OAAO,KAAK;EACZ,aAAa,KAAK;EAClB,QAAQ,qBAAqB,KAAK,MAAM;EACxC,SAAS,UAAU,KAAA,IAAY,KAAK,UAAU,KAAA;EAC9C,YAAY,KAAK,WAAW,cAAc,KAAK,WAAW,KAAA;EAC1D;CACF;AACF;AAYA,SAAS,SAAS,EAAE,QAAQ,OAAO,aAA4B;CAC7D,OACE,oBAAC,wBAAD;EACE,QAAQ,qBAAqB,MAAM;EAC5B;EACI;CACZ,CAAA;AAEL;AAEA,SAAS,cAAc;AAcvB,SAAS,WAAW,EAClB,MACA,OACA,QACA,aAAa,MACb,kBAAkB,SACA;CAClB,MAAM,CAAC,UAAU,eAAe,MAAM,SAAS,eAAe;CAE9D,OACE,oBAAC,kBAAD;EACE,MAAM,eAAe,IAAI;EAClB;EACC;EACR,YAAW;EACX,UAAS;EACG;EACF;EACV,wBAAwB,aAAa,UAAU,CAAC,KAAK;CACtD,CAAA;AAEL;AAEA,WAAW,cAAc;;;;;;;;;;;;;;;;;AAsCzB,SAAgB,QAAQ,EACtB,OACA,OACA,SACA,cAAc,MACd,kBAAkB,MAClB,kBAAkB,MAClB,aACe;CACf,MAAM,CAAC,YAAY,iBAAiB,MAAM,SAAS,eAAe;CAClE,MAAM,uBAAuB,iBAAiB;CAG9C,MAAM,iBAAiB,MAAM,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC,CAAC;CACrE,MAAM,aAAa,MAAM;CACzB,MAAM,WAAW,MAAM,MAAM,MAAM,EAAE,WAAW,OAAO;CACvD,MAAM,YAAY,MAAM,MAAM,MAAM,EAAE,WAAW,SAAS;CAE1D,OACE,qBAAC,WAAD;EACE,aAAU;EACV,cAAY,SAAS;EACrB,WAAW,GAAG,uBAAuB,EAAE,QAAQ,CAAC,GAAG,SAAS;YAH9D,EAMI,SAAS,gBACT,qBAAC,UAAD;GACE,MAAK;GACL,eAAe,eAAe,cAAc,CAAC,UAAU;GACvD,UAAU,CAAC;GACX,iBAAe,cAAc,aAAa,KAAA;GAC1C,WAAW,GACT,6EACA,eAAe,iCACf,wFACF;aATF,CAWE,qBAAC,OAAD;IAAK,WAAU;cAAf;KACG,aACC,oBAAC,OAAD,EAAO,WAAU,+DAAgE,CAAA;KAElF,YAAY,CAAC,aACZ,oBAAC,aAAD,EAAa,WAAU,0BAA2B,CAAA;KAEnD,CAAC,aAAa,CAAC,YAAY,mBAAmB,cAC7C,oBAAC,OAAD,EAAO,WAAU,sBAAuB,CAAA;KAE1C,oBAAC,QAAD;MAAM,WAAU;gBACb,SAAS;KACN,CAAA;KACN,qBAAC,QAAD;MAAM,WAAU;gBAAhB;OAA+C;OAC3C;OAAe;OAAE;OAAW;MAC1B;;IACH;OAEJ,eACC,oBAAC,OAAD;IAAK,WAAU;cACZ,aACC,oBAAC,aAAD,EAAa,WAAU,+BAAgC,CAAA,IAEvD,oBAAC,cAAD,EAAc,WAAU,8CAA+C,CAAA;GAEtE,CAAA,CAED;MAIV,oBAAC,iBAAD;GAAiB,SAAS;aACvB,cACC,oBAAC,OAAO,KAAR;IACE,SAAS;KAAE,QAAQ;KAAG,SAAS;IAAE;IACjC,SAAS;KAAE,QAAQ;KAAQ,SAAS;IAAE;IACtC,MAAM;KAAE,QAAQ;KAAG,SAAS;IAAE;IAC9B,YAAY,EAAE,UAAU,uBAAuB,IAAI,GAAI;IACvD,WAAU;cAEV,oBAAC,sBAAD;KACE,YAAW;KACX,OAAO,MAAM,IAAI,cAAc;KAC/B,UAAS;KACT,YAAY;IACb,CAAA;GACS,CAAA;EAEC,CAAA,CACV;;AAEb;AAEA,QAAQ,cAAc"}
1
+ {"version":3,"file":"index175.js","names":[],"sources":["../src/components/organisms/ai/_shared/workflow-step-renderer.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport {\n AlertCircle,\n Check,\n ChevronDown,\n ChevronRight,\n Loader,\n Pause,\n} from 'lucide-react';\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react';\nimport * as React from 'react';\nimport { assertNever, cn } from '@/lib/utils';\nimport { formatAIDuration } from './format-ai-duration';\n\nexport type WorkflowStepStatus =\n | 'pending'\n | 'running'\n | 'suspended'\n | 'completed'\n | 'error';\n\nexport type WorkflowStepAppearance = 'contained' | 'embedded' | 'timeline';\n\nexport interface WorkflowStepViewModel {\n id: string;\n title: string;\n description?: string;\n contextLabel?: string;\n status: WorkflowStepStatus;\n content?: React.ReactNode;\n durationMs?: number;\n error?: string;\n}\n\nexport interface WorkflowStepRendererProps {\n steps: readonly WorkflowStepViewModel[];\n appearance?: WorkflowStepAppearance;\n itemSlot?: string;\n expandable?: boolean;\n activeStepId?: string;\n expandedStepIds?: readonly string[];\n defaultExpandedStepIds?: readonly string[];\n onExpandedStepIdsChange?: (ids: readonly string[]) => void;\n className?: string;\n}\n\ninterface PrivateWorkflowStepRendererProps extends WorkflowStepRendererProps {\n renderItems?: boolean;\n}\n\nconst workflowStepItemStatusClasses = {\n pending: 'text-muted-foreground',\n running: 'text-primary',\n suspended: 'text-warning',\n completed: 'text-success',\n error: 'text-destructive',\n} as const satisfies Record<WorkflowStepStatus, string>;\n\nconst workflowStepIconStatusClasses = {\n pending: 'bg-accent text-muted-foreground',\n running: 'bg-primary/20 text-primary',\n suspended: 'bg-warning/20 text-warning',\n completed: 'bg-success/20 text-success',\n error: 'bg-destructive/20 text-destructive',\n} as const satisfies Record<WorkflowStepStatus, string>;\n\nexport const workflowStepItemVariants = cva(\n 'flex items-start gap-3 px-4 py-3 transition-colors motion-reduce:transition-none',\n {\n variants: {\n status: workflowStepItemStatusClasses,\n },\n defaultVariants: {\n status: 'pending',\n },\n },\n);\n\nexport const workflowStepIconVariants = cva(\n 'size-5 shrink-0 flex items-center justify-center rounded-full',\n {\n variants: {\n status: workflowStepIconStatusClasses,\n },\n defaultVariants: {\n status: 'pending',\n },\n },\n);\n\nconst workflowStepAppearanceConfig = {\n contained: {\n rootClassName: 'relative',\n hasDivider: true,\n hasConnector: false,\n },\n embedded: {\n rootClassName: 'relative',\n hasDivider: true,\n hasConnector: false,\n },\n timeline: {\n rootClassName: 'relative',\n hasDivider: false,\n hasConnector: true,\n },\n} as const satisfies Record<\n WorkflowStepAppearance,\n { rootClassName: string; hasDivider: boolean; hasConnector: boolean }\n>;\n\nexport function normalizeExpandedWorkflowStepIds(\n ids: readonly string[],\n steps: readonly WorkflowStepViewModel[],\n): string[] {\n const requested = new Set(ids);\n return steps.flatMap((step) => (requested.has(step.id) ? [step.id] : []));\n}\n\nfunction areWorkflowStepIdsEqual(\n left: readonly string[],\n right: readonly string[],\n): boolean {\n return (\n left.length === right.length &&\n left.every((id, index) => id === right[index])\n );\n}\n\nfunction isIterableWorkflowStepContent(\n content: React.ReactNode,\n): content is Iterable<React.ReactNode> {\n return (\n typeof content === 'object' &&\n content !== null &&\n Symbol.iterator in content &&\n typeof (content as Iterable<React.ReactNode>)[Symbol.iterator] ===\n 'function'\n );\n}\n\nfunction isIteratorWorkflowStepContent(\n content: unknown,\n): content is Iterator<React.ReactNode> {\n return (\n typeof (content as Partial<Iterator<React.ReactNode>>).next === 'function'\n );\n}\n\ninterface NormalizedWorkflowStepContent {\n content: React.ReactNode;\n hasRenderableContent: boolean;\n changed: boolean;\n}\n\nconst normalizedOneShotWorkflowStepContent = new WeakMap<\n object,\n NormalizedWorkflowStepContent\n>();\n\nfunction normalizeIterableWorkflowStepContent(\n content: Iterable<React.ReactNode>,\n iterator: Iterator<React.ReactNode>,\n): NormalizedWorkflowStepContent {\n const normalizedChildren: React.ReactNode[] = [];\n let hasRenderableContent = false;\n let changed = !Array.isArray(content);\n\n for (let result = iterator.next(); !result.done; result = iterator.next()) {\n const normalizedChild = normalizeWorkflowStepContent(result.value);\n normalizedChildren.push(normalizedChild.content);\n hasRenderableContent ||= normalizedChild.hasRenderableContent;\n changed ||= normalizedChild.changed;\n }\n\n return {\n content: changed ? normalizedChildren : content,\n hasRenderableContent,\n changed,\n };\n}\n\nfunction normalizeWorkflowStepContent(\n content: React.ReactNode,\n): NormalizedWorkflowStepContent {\n if (\n content === null ||\n content === undefined ||\n typeof content === 'boolean' ||\n content === ''\n ) {\n return { content, hasRenderableContent: false, changed: false };\n }\n\n if (\n typeof content === 'string' ||\n typeof content === 'number' ||\n typeof content === 'bigint'\n ) {\n return { content, hasRenderableContent: true, changed: false };\n }\n\n if (React.isValidElement<{ children?: React.ReactNode }>(content)) {\n if (content.type !== React.Fragment) {\n return { content, hasRenderableContent: true, changed: false };\n }\n\n const normalizedChildren = normalizeWorkflowStepContent(\n content.props.children,\n );\n return {\n content: normalizedChildren.changed\n ? React.cloneElement(content, undefined, normalizedChildren.content)\n : content,\n hasRenderableContent: normalizedChildren.hasRenderableContent,\n changed: normalizedChildren.changed,\n };\n }\n\n if (isIterableWorkflowStepContent(content)) {\n const iterator = content[Symbol.iterator]();\n const oneShotCacheKey = isIteratorWorkflowStepContent(iterator)\n ? (iterator as object)\n : null;\n\n if (oneShotCacheKey !== null) {\n const cached = normalizedOneShotWorkflowStepContent.get(oneShotCacheKey);\n if (cached !== undefined) return cached;\n }\n\n const normalized = normalizeIterableWorkflowStepContent(content, iterator);\n if (oneShotCacheKey !== null) {\n normalizedOneShotWorkflowStepContent.set(oneShotCacheKey, normalized);\n }\n return normalized;\n }\n\n return { content, hasRenderableContent: true, changed: false };\n}\n\nfunction getNonBlankWorkflowStepError(\n error: string | undefined,\n): string | undefined {\n return error?.trim() ? error : undefined;\n}\n\nfunction getWorkflowStepStatusLabel(status: WorkflowStepStatus): string {\n switch (status) {\n case 'pending':\n return 'Pending';\n case 'running':\n return 'Running';\n case 'suspended':\n return 'Paused';\n case 'completed':\n return 'Completed';\n case 'error':\n return 'Error';\n default:\n return assertNever(status);\n }\n}\n\nexport interface WorkflowStepStatusIconProps {\n status: WorkflowStepStatus;\n index: number;\n className?: string;\n}\n\nexport function WorkflowStepStatusIcon({\n status,\n index,\n className,\n}: WorkflowStepStatusIconProps) {\n const iconClass = cn(workflowStepIconVariants({ status }), className);\n\n switch (status) {\n case 'pending':\n return (\n <div data-slot=\"workflow-step-icon\" className={iconClass}>\n <span className=\"text-xs font-medium\">{index + 1}</span>\n </div>\n );\n case 'running':\n return (\n <div\n data-slot=\"workflow-step-icon\"\n className={cn(\n iconClass,\n 'delight-status-pulse motion-reduce:!animate-none',\n )}\n >\n <Loader className=\"size-3 animate-spin motion-reduce:animate-none\" />\n </div>\n );\n case 'suspended':\n return (\n <div data-slot=\"workflow-step-icon\" className={iconClass}>\n <Pause className=\"size-3\" />\n </div>\n );\n case 'completed':\n return (\n <div\n data-slot=\"workflow-step-icon\"\n className={cn(\n iconClass,\n 'delight-check-bounce motion-reduce:!animate-none',\n )}\n >\n <Check className=\"size-3\" />\n </div>\n );\n case 'error':\n return (\n <div\n data-slot=\"workflow-step-icon\"\n className={cn(iconClass, 'delight-shake motion-reduce:!animate-none')}\n >\n <AlertCircle className=\"size-3\" />\n </div>\n );\n default:\n return assertNever(status);\n }\n}\n\nWorkflowStepStatusIcon.displayName = 'WorkflowStepStatusIcon';\n\nexport interface WorkflowStepItemProps {\n step: WorkflowStepViewModel;\n index: number;\n isLast: boolean;\n appearance?: WorkflowStepAppearance;\n itemSlot?: string;\n expandable?: boolean;\n expanded: boolean;\n active?: boolean;\n onExpandedChange: () => void;\n}\n\nexport function WorkflowStepItem({\n step,\n index,\n isLast,\n appearance = 'contained',\n itemSlot = 'workflow-step-item',\n expandable = true,\n expanded,\n active = false,\n onExpandedChange,\n}: WorkflowStepItemProps) {\n const contentId = React.useId();\n const errorDescriptionId = React.useId();\n const normalizedContent = normalizeWorkflowStepContent(step.content);\n const hasContent = normalizedContent.hasRenderableContent;\n const error = getNonBlankWorkflowStepError(step.error);\n const hasError = error !== undefined;\n const hasExpandableDetails = hasContent || hasError;\n const isDisclosureControl = hasExpandableDetails && expandable;\n const prefersReducedMotion = useReducedMotion();\n const appearanceConfig = workflowStepAppearanceConfig[appearance];\n const disclosureTransition = {\n duration: prefersReducedMotion ? 0 : 0.2,\n };\n const stepContent = (\n <>\n <WorkflowStepStatusIcon status={step.status} index={index} />\n\n <div className=\"min-w-0 flex-1 text-start\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {step.contextLabel && (\n <span\n data-slot=\"workflow-step-context\"\n className=\"rounded-full border border-border px-2 py-0.5 text-[0.6875rem] font-medium leading-none text-secondary-foreground\"\n >\n {step.contextLabel}\n </span>\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n step.status === 'pending'\n ? 'text-text-quaternary'\n : 'text-foreground',\n )}\n >\n {step.title}\n </span>\n <span className=\"text-xs text-secondary-foreground\">\n {getWorkflowStepStatusLabel(step.status)}\n </span>\n {step.durationMs !== undefined && (\n <span className=\"text-xs text-muted-foreground\">\n {formatAIDuration(step.durationMs)}\n </span>\n )}\n </div>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-text-quaternary\">\n {step.description}\n </p>\n )}\n </div>\n\n {isDisclosureControl && (\n <div className=\"shrink-0\">\n {expanded ? (\n <ChevronDown className=\"size-4 text-muted-foreground\" />\n ) : (\n <ChevronRight className=\"size-4 text-muted-foreground rtl:rotate-180\" />\n )}\n </div>\n )}\n </>\n );\n\n return (\n <div\n data-slot={itemSlot}\n data-step-status={step.status}\n data-appearance={appearance}\n className={cn(\n appearanceConfig.rootClassName,\n appearanceConfig.hasDivider && !isLast && 'border-b border-border',\n )}\n >\n {isDisclosureControl ? (\n <button\n type=\"button\"\n onClick={onExpandedChange}\n aria-current={active ? 'step' : undefined}\n aria-expanded={expanded}\n aria-controls={contentId}\n aria-describedby={hasError ? errorDescriptionId : undefined}\n className={cn(\n workflowStepItemVariants({ status: step.status }),\n 'w-full cursor-pointer hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring',\n )}\n >\n {stepContent}\n </button>\n ) : (\n <div\n aria-current={active ? 'step' : undefined}\n aria-describedby={hasError ? errorDescriptionId : undefined}\n className={cn(\n workflowStepItemVariants({ status: step.status }),\n 'w-full',\n )}\n >\n {stepContent}\n </div>\n )}\n\n <AnimatePresence initial={false}>\n {expanded && hasExpandableDetails && (\n <motion.div\n id={contentId}\n data-slot=\"workflow-step-panel\"\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={disclosureTransition}\n className=\"overflow-hidden motion-reduce:transition-none\"\n >\n <div className=\"px-4 pb-3 ps-12\">\n {hasError && (\n <div className=\"rounded-lg border border-destructive/50 bg-destructive/10 p-3\">\n <div className=\"flex items-start gap-2\">\n <AlertCircle className=\"mt-0.5 size-4 shrink-0 text-destructive\" />\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n </div>\n )}\n {hasContent && (\n <div className={hasError ? 'mt-3' : undefined}>\n {normalizedContent.content}\n </div>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {hasError && (\n <span id={errorDescriptionId} className=\"sr-only\">\n {error}\n </span>\n )}\n\n {appearanceConfig.hasConnector && !isLast && (\n <div\n data-slot=\"workflow-step-connector\"\n aria-hidden=\"true\"\n className=\"absolute top-8 -bottom-3 start-6 w-px bg-border\"\n />\n )}\n </div>\n );\n}\n\nWorkflowStepItem.displayName = 'WorkflowStepItem';\n\nexport function WorkflowStepRenderer({\n steps,\n appearance = 'contained',\n itemSlot = 'workflow-step-item',\n expandable = true,\n activeStepId,\n expandedStepIds: controlledExpandedStepIds,\n defaultExpandedStepIds = [],\n onExpandedStepIdsChange,\n className,\n renderItems = true,\n}: PrivateWorkflowStepRendererProps) {\n const isControlled = controlledExpandedStepIds !== undefined;\n const controlledSnapshot = isControlled\n ? [...controlledExpandedStepIds]\n : undefined;\n const [uncontrolledExpandedStepIds, setUncontrolledExpandedStepIds] =\n React.useState<readonly string[]>(() =>\n normalizeExpandedWorkflowStepIds(defaultExpandedStepIds, steps),\n );\n const lastControlledExpandedStepIdsRef = React.useRef<readonly string[]>(\n controlledSnapshot ?? [],\n );\n const wasControlledRef = React.useRef(isControlled);\n const rawExpandedStepIds = isControlled\n ? controlledExpandedStepIds\n : uncontrolledExpandedStepIds;\n const visibleExpandedStepIds = normalizeExpandedWorkflowStepIds(\n rawExpandedStepIds,\n steps,\n );\n const expandedSet = new Set(visibleExpandedStepIds);\n\n React.useLayoutEffect(() => {\n if (controlledSnapshot !== undefined) {\n lastControlledExpandedStepIdsRef.current = controlledSnapshot;\n }\n }, [controlledSnapshot]);\n\n React.useLayoutEffect(() => {\n const wasControlled = wasControlledRef.current;\n wasControlledRef.current = isControlled;\n if (isControlled) return;\n\n setUncontrolledExpandedStepIds((current) => {\n const source = wasControlled\n ? lastControlledExpandedStepIdsRef.current\n : current;\n const reconciled = normalizeExpandedWorkflowStepIds(source, steps);\n return areWorkflowStepIdsEqual(reconciled, current)\n ? current\n : reconciled;\n });\n }, [isControlled, steps]);\n\n const toggleStep = (id: string) => {\n const next = new Set(visibleExpandedStepIds);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n const normalizedNext = normalizeExpandedWorkflowStepIds([...next], steps);\n if (!isControlled) {\n setUncontrolledExpandedStepIds([...normalizedNext]);\n }\n onExpandedStepIdsChange?.([...normalizedNext]);\n };\n\n if (!renderItems) return null;\n\n return (\n <ol\n data-slot=\"workflow-step-list\"\n data-appearance={appearance}\n className={cn('m-0 list-none p-0', className)}\n >\n {steps.map((step, index) => (\n <li key={step.id}>\n <WorkflowStepItem\n step={step}\n index={index}\n isLast={index === steps.length - 1}\n appearance={appearance}\n itemSlot={itemSlot}\n expandable={expandable}\n expanded={expandedSet.has(step.id)}\n active={activeStepId === step.id}\n onExpandedChange={() => toggleStep(step.id)}\n />\n </li>\n ))}\n </ol>\n );\n}\n\nWorkflowStepRenderer.displayName = 'WorkflowStepRenderer';\n"],"mappings":"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"}