{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "context-sources",
  "type": "registry:ui",
  "title": "Context sources",
  "description": "Presents retrieved chunks, provenance, and relevance with focused disclosure.",
  "dependencies": [
    "motion"
  ],
  "categories": [
    "agent"
  ],
  "docs": "https://motion-lexicon.pages.dev/en/components/context-sources/",
  "meta": {
    "engines": [
      "motion"
    ],
    "runtimeCost": "light",
    "signature": "A selected source expands across the reading surface"
  },
  "files": [
    {
      "path": "src/registry/components/context-sources.tsx",
      "type": "registry:ui",
      "target": "components/motion-lexicon/context-sources.tsx",
      "content": "\"use client\";\n\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport { useState } from \"react\";\n\nexport type ContextSource = {\n  id: string;\n  title: string;\n  excerpt: string;\n  kind: string;\n  origin: string;\n  relevance?: number;\n};\nexport type ContextSourcesProps = {\n  sources: readonly ContextSource[];\n  label?: string;\n  countLabel?: (count: number) => string;\n  className?: string;\n};\n\nexport function ContextSources({\n  sources,\n  label = \"Retrieved context\",\n  countLabel = (count) => `${count} sources`,\n  className = \"\",\n}: ContextSourcesProps) {\n  const [active, setActive] = useState(sources[0]?.id ?? \"\");\n  const reduced = useReducedMotion();\n  return (\n    <section\n      className={`w-full rounded-[10px] border border-neutral-200 bg-white p-3 text-neutral-950 dark:border-white/10 dark:bg-[#1b1b1b] dark:text-neutral-50 ${className}`}\n    >\n      <header className=\"flex min-h-10 items-center gap-2 px-1\">\n        <span className=\"text-[11px] font-medium text-neutral-600 dark:text-neutral-300\">\n          {label}\n        </span>\n        <span className=\"ml-auto text-[9px] text-neutral-400\">\n          {countLabel(sources.length)}\n        </span>\n      </header>\n      <div className=\"mt-1 grid gap-2 sm:grid-cols-2\">\n        {sources.map((source, index) => {\n          const open = active === source.id;\n          return (\n            <motion.article\n              layout={!reduced}\n              key={source.id}\n              className={`relative overflow-hidden rounded-lg border p-3 ${open ? \"border-neutral-400 bg-neutral-50 sm:col-span-2 dark:border-white/25 dark:bg-white/[.03]\" : \"border-neutral-100 dark:border-white/8\"}`}\n            >\n              <button\n                type=\"button\"\n                aria-expanded={open}\n                onClick={() => setActive(open ? \"\" : source.id)}\n                className=\"flex min-h-11 w-full items-center gap-3 text-left outline-none focus-visible:ring-2 focus-visible:ring-blue-600\"\n              >\n                <span className=\"grid size-7 shrink-0 place-items-center rounded-lg bg-neutral-100 font-mono text-[9px] text-neutral-500 dark:bg-white/5\">\n                  {String(index + 1).padStart(2, \"0\")}\n                </span>\n                <span className=\"min-w-0 flex-1\">\n                  <strong className=\"block truncate text-[11px]\">\n                    {source.title}\n                  </strong>\n                  <span className=\"block truncate text-[9px] text-neutral-400\">\n                    {source.kind} · {source.origin}\n                  </span>\n                </span>\n                {typeof source.relevance === \"number\" ? (\n                  <code className=\"text-[9px] text-neutral-500 dark:text-neutral-400\">\n                    {source.relevance}%\n                  </code>\n                ) : null}\n              </button>\n              <AnimatePresence initial={false}>\n                {open ? (\n                  <motion.p\n                    initial={reduced ? false : { height: 0, opacity: 0 }}\n                    animate={{ height: \"auto\", opacity: 1 }}\n                    exit={{ height: 0, opacity: 0 }}\n                    className=\"mt-2 overflow-hidden pl-10 text-[10px] leading-5 text-neutral-500 dark:text-neutral-400\"\n                  >\n                    {source.excerpt}\n                  </motion.p>\n                ) : null}\n              </AnimatePresence>\n            </motion.article>\n          );\n        })}\n      </div>\n    </section>\n  );\n}\n"
    }
  ]
}
