{"version":3,"file":"reasoning.cjs","sources":["../../../components/reasoning/reasoning.tsx"],"sourcesContent":["'use client';\n\nimport { useControlled } from '@base-ui/utils/useControlled';\nimport { cx } from 'class-variance-authority';\nimport {\n  ComponentProps,\n  createContext,\n  ReactNode,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef\n} from 'react';\nimport { ChevronRightIcon } from '~/icons';\nimport { Collapsible } from '../collapsible';\nimport styles from './reasoning.module.css';\n\ninterface ReasoningContextValue {\n  streaming: boolean;\n  duration?: number;\n  open: boolean;\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nfunction useReasoningContext(part: string): ReasoningContextValue {\n  const context = useContext(ReasoningContext);\n  if (!context) {\n    throw new Error(`Reasoning.${part} must be used within <Reasoning>`);\n  }\n  return context;\n}\n\nexport interface ReasoningProps\n  extends Omit<ComponentProps<typeof Collapsible>, 'onOpenChange'> {\n  /**\n   * Whether the reasoning is still being produced. While `true` the default\n   * trigger shows a shimmering \"Thinking…\" label and the panel auto-opens;\n   * when it flips back to `false` the panel auto-collapses — unless the user\n   * has toggled it themselves.\n   * @defaultValue false\n   */\n  streaming?: boolean;\n  /**\n   * How long the reasoning took, in seconds. Rendered by the default trigger\n   * label as \"Worked for N seconds\" once `streaming` is over.\n   */\n  duration?: number;\n  /** Called when the panel is opened or closed. */\n  onOpenChange?: (open: boolean) => void;\n}\n\nfunction ReasoningRoot({\n  className,\n  streaming = false,\n  duration,\n  open: openProp,\n  defaultOpen,\n  onOpenChange,\n  children,\n  ...props\n}: ReasoningProps) {\n  const [open, setOpenUnwrapped] = useControlled({\n    controlled: openProp,\n    default: defaultOpen ?? streaming,\n    name: 'Reasoning',\n    state: 'open'\n  });\n\n  const userToggledRef = useRef(false);\n  const onOpenChangeRef = useRef(onOpenChange);\n  onOpenChangeRef.current = onOpenChange;\n\n  const setOpen = (next: boolean) => {\n    setOpenUnwrapped(next);\n    onOpenChangeRef.current?.(next);\n  };\n\n  // Auto-open while streaming and auto-collapse on completion, but hand the\n  // panel over to the user as soon as they toggle it manually.\n  const prevStreamingRef = useRef(streaming);\n  const setOpenRef = useRef(setOpen);\n  setOpenRef.current = setOpen;\n  useEffect(() => {\n    if (prevStreamingRef.current === streaming) return;\n    prevStreamingRef.current = streaming;\n    if (userToggledRef.current) return;\n    setOpenRef.current(streaming);\n  }, [streaming]);\n\n  const contextValue = useMemo<ReasoningContextValue>(\n    () => ({ streaming, duration, open }),\n    [streaming, duration, open]\n  );\n\n  return (\n    <ReasoningContext.Provider value={contextValue}>\n      <Collapsible\n        className={cx(styles.reasoning, className)}\n        open={open}\n        onOpenChange={next => {\n          userToggledRef.current = true;\n          setOpen(next);\n        }}\n        data-slot='reasoning'\n        {...props}\n      >\n        {children}\n      </Collapsible>\n    </ReasoningContext.Provider>\n  );\n}\n\nReasoningRoot.displayName = 'Reasoning';\n\nexport interface ReasoningTriggerProps\n  extends ComponentProps<typeof Collapsible.Trigger> {}\n\nfunction defaultTriggerLabel(streaming: boolean, duration?: number): ReactNode {\n  if (streaming) {\n    return (\n      <span\n        className={styles['reasoning-label-streaming']}\n        data-slot='reasoning-label-streaming'\n      >\n        Thinking…\n      </span>\n    );\n  }\n  if (duration != null) {\n    return `Worked for ${duration} ${duration === 1 ? 'second' : 'seconds'}`;\n  }\n  return 'Reasoning';\n}\n\nexport function ReasoningTrigger({\n  className,\n  children,\n  ...props\n}: ReasoningTriggerProps) {\n  const { streaming, duration } = useReasoningContext('Trigger');\n  return (\n    <Collapsible.Trigger\n      className={cx(styles['reasoning-trigger'], className)}\n      data-slot='reasoning-trigger'\n      {...props}\n    >\n      {children ?? defaultTriggerLabel(streaming, duration)}\n      <ChevronRightIcon\n        className={styles['reasoning-chevron']}\n        aria-hidden='true'\n        data-slot='reasoning-chevron'\n      />\n    </Collapsible.Trigger>\n  );\n}\n\nReasoningTrigger.displayName = 'Reasoning.Trigger';\n\nexport interface ReasoningContentProps\n  extends ComponentProps<typeof Collapsible.Panel> {}\n\nexport function ReasoningContent({\n  className,\n  children,\n  ...props\n}: ReasoningContentProps) {\n  return (\n    <Collapsible.Panel\n      className={cx(styles['reasoning-panel'], className)}\n      data-slot='reasoning-panel'\n      {...props}\n    >\n      <div className={styles['reasoning-body']} data-slot='reasoning-body'>\n        {children}\n      </div>\n    </Collapsible.Panel>\n  );\n}\n\nReasoningContent.displayName = 'Reasoning.Content';\n\nexport interface ReasoningStepProps extends ComponentProps<'div'> {\n  /** Title row of the step, e.g. \"Gathering ticket updates\". */\n  label?: ReactNode;\n}\n\nexport function ReasoningStep({\n  className,\n  label,\n  children,\n  ...props\n}: ReasoningStepProps) {\n  return (\n    <div\n      className={cx(styles['reasoning-step'], className)}\n      data-slot='reasoning-step'\n      {...props}\n    >\n      {label && (\n        <div\n          className={styles['reasoning-step-label']}\n          data-slot='reasoning-step-label'\n        >\n          {label}\n        </div>\n      )}\n      {children && (\n        <div\n          className={styles['reasoning-step-body']}\n          data-slot='reasoning-step-body'\n        >\n          {children}\n        </div>\n      )}\n    </div>\n  );\n}\n\nReasoningStep.displayName = 'Reasoning.Step';\n\nexport const Reasoning = Object.assign(ReasoningRoot, {\n  Trigger: ReasoningTrigger,\n  Content: ReasoningContent,\n  Step: ReasoningStep\n});\n"],"names":[],"mappings":";;;;;;;;;;;;AAuBA;AAEA;AACE;;AAEE;;AAEF;AACF;AAqBA;AAUE;AACE;;AAEA;AACA;AACD;AAED;AACA;AACA;AAEA;;AAEE;AACF;;;AAIA;AACA;AACA;;AAEE;;AACA;;;AAEA;AACF;;AAOA;AAMQ;;;AAUV;AAEA;AAKA;;AAEI;;AASF;AACE;;AAEF;AACF;AAEM;;;AAoBN;AAEA;AAKM;AAKJ;AAWF;AAEA;AAOgB;;AA8BhB;AAEA;;AAGE;AACA;AACA;AACD;;;;;"}