{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "agent-source-list",
  "title": "AgentSourceList",
  "description": "Inline collapsible agent-source list with safe external links, derived hostnames, optional descriptions, and observable disclosure state.",
  "type": "registry:ui",
  "meta": {
    "library": "@ds-mo/ui",
    "distribution": "npm",
    "storybook": "https://zainadeel.github.io/compomo/?path=/story/agent-source-list",
    "source": "src/wc/components/AgentSourceList/AgentSourceList.tsx",
    "intentStatus": "complete",
    "intent": {
      "audience": "specialized",
      "status": "experimental",
      "summary": "Inline collapsible agent-source list with safe external links, derived hostnames, optional descriptions, and observable disclosure state.",
      "useWhen": [
        "A stable agent response cites external material readers may inspect inline."
      ],
      "avoidWhen": [
        "The links are ordinary body links, source discovery is still active, or the application expects a source drawer or deduplication behavior."
      ],
      "commonlyComposedWith": [
        "component:ds-agent-response",
        "component:ds-markdown"
      ],
      "patterns": [
        "pattern:agent-chat"
      ],
      "accessibility": [
        "Each interactive source uses descriptive linked text, a visible hostname, supporting context, and an external-link indication.",
        "Malformed and unsafe schemes remain non-interactive text rather than producing executable links.",
        "The native disclosure exposes keyboard and expanded-state semantics, while open-change events let applications observe participant intent."
      ],
      "states": [
        "Applications collect and deduplicate sources, then append the stable list once; active discovery remains an activity or tool state."
      ],
      "responsiveBehavior": [
        "Source titles, hostnames, and descriptions wrap within the response width."
      ],
      "references": [
        {
          "label": "Source safety and disclosure stories",
          "path": "src/wc/components/AgentSourceList/AgentSourceList.stories.ts"
        }
      ]
    },
    "api": {
      "props": {
        "heading": {
          "type": "string",
          "resolvedType": "string",
          "attribute": "heading",
          "default": "'Sources'",
          "required": false,
          "mutable": false
        },
        "items": {
          "type": "AgentSource[]",
          "resolvedType": "AgentSource[]",
          "default": "[]",
          "required": false,
          "mutable": false
        },
        "open": {
          "type": "boolean",
          "resolvedType": "boolean",
          "attribute": "open",
          "default": "false",
          "required": false,
          "mutable": false
        }
      },
      "events": [
        {
          "name": "dsOpenChange",
          "detail": "{ open: boolean }",
          "bubbles": true,
          "cancelable": true,
          "composed": true
        }
      ],
      "methods": [],
      "slots": []
    },
    "props": {
      "heading": {
        "type": "string",
        "resolvedType": "string",
        "attribute": "heading",
        "default": "'Sources'",
        "required": false,
        "mutable": false
      },
      "items": {
        "type": "AgentSource[]",
        "resolvedType": "AgentSource[]",
        "default": "[]",
        "required": false,
        "mutable": false
      },
      "open": {
        "type": "boolean",
        "resolvedType": "boolean",
        "attribute": "open",
        "default": "false",
        "required": false,
        "mutable": false
      }
    },
    "events": [
      {
        "name": "dsOpenChange",
        "detail": "{ open: boolean }",
        "bubbles": true,
        "cancelable": true,
        "composed": true
      }
    ],
    "methods": [],
    "slots": [],
    "exports": {
      "customElement": "ds-agent-source-list",
      "react": "DsAgentSourceList",
      "vue": "DsAgentSourceList",
      "angular": "DsAgentSourceList"
    },
    "consumption": {
      "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
      "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
      "customElements": {
        "import": "import '@ds-mo/ui/dist/components/ds-agent-source-list.js';",
        "example": "<ds-agent-source-list></ds-agent-source-list>"
      },
      "react": {
        "import": "import { DsAgentSourceList } from '@ds-mo/ui/react';",
        "example": "<DsAgentSourceList />"
      },
      "vue": {
        "import": "import { DsAgentSourceList } from '@ds-mo/ui/vue';",
        "example": "<DsAgentSourceList />"
      },
      "angular": {
        "import": "import { DsAgentSourceList } from '@ds-mo/ui/angular/ds-agent-source-list';",
        "example": "<ds-agent-source-list></ds-agent-source-list>"
      },
      "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: items.",
      "peerDependencies": {
        "required": [
          "@ds-mo/tokens ^6.5.0",
          "@ds-mo/icons ^7.0.0"
        ],
        "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
      }
    }
  },
  "dependencies": [
    "@ds-mo/ui",
    "@ds-mo/tokens",
    "@ds-mo/icons"
  ],
  "registryDependencies": [
    "icon",
    "text"
  ],
  "files": [
    {
      "path": "src/wc/components/AgentSourceList/AgentSourceList.css",
      "content": "@import '../../utils/text-decoration.css';\n\n:host { display: block; }\n.agent-sources { border-block-start: var(--dimension-stroke-width-012) solid var(--color-border-tertiary); }\nsummary { align-items: center; cursor: default; display: flex; gap: var(--dimension-space-050); list-style: none; padding-block: var(--dimension-space-075); }\nsummary::-webkit-details-marker { display: none; }\ndetails[open] summary ds-icon { transform: rotate(90deg); }\nol { display: grid; gap: var(--dimension-space-075); margin: 0; padding: 0 0 var(--dimension-space-075) var(--dimension-space-150); }\nli { display: grid; gap: var(--dimension-space-025); }\na { --ds-text-decoration-color: var(--color-foreground-tertiary); align-items: center; color: inherit; display: inline-flex; gap: var(--dimension-space-025); width: fit-content; }\n\n@media (prefers-reduced-motion: no-preference) { summary ds-icon { transition: transform var(--effect-motion-short-2); } }\n",
      "type": "registry:ui"
    },
    {
      "path": "src/wc/components/AgentSourceList/AgentSourceList.tsx",
      "content": "import { Component, Event, EventEmitter, Prop, h, Host } from '@stencil/core';\nimport { resolveSafeUrl } from '../../utils';\nimport type { AgentSource } from '../conversation-types';\n\n@Component({ tag: 'ds-agent-source-list', styleUrl: 'AgentSourceList.css', scoped: true })\nexport class AgentSourceList {\n  @Prop() items: AgentSource[] = [];\n  @Prop() heading: string = 'Sources';\n  @Prop() open: boolean = false;\n\n  @Event() dsOpenChange!: EventEmitter<{ open: boolean }>;\n\n  private hostname(href: string): string {\n    try {\n      return new URL(href).hostname;\n    } catch {\n      return '';\n    }\n  }\n\n  render() {\n    if (!this.items.length) return null;\n    return (\n      <Host>\n        <details\n          class=\"agent-sources\"\n          open={this.open}\n          onToggle={(event: Event) =>\n            this.dsOpenChange.emit({\n              open: (event.currentTarget as HTMLDetailsElement).open,\n            })\n          }\n        >\n          <summary>\n            <ds-icon name=\"ChevronRight\" size=\"xs\" color=\"inherit\" />\n            <ds-text variant=\"text-body-small\" emphasis>{this.heading} · {this.items.length}</ds-text>\n          </summary>\n          <ol>\n            {this.items.map(source => {\n              const href = resolveSafeUrl(source.url);\n              const hostname = href ? this.hostname(href) : '';\n              return <li>\n                {href\n                  ? <a\n                      class=\"ds-text-decoration\"\n                      href={href}\n                      target=\"_blank\"\n                      rel=\"noopener noreferrer\"\n                      aria-label={`${source.title} (${hostname}, opens in a new tab)`}\n                    ><ds-text variant=\"text-body-small\" emphasis>{source.title}</ds-text><ds-icon name=\"ExternalLink\" size=\"xs\" color=\"inherit\" /></a>\n                  : <ds-text variant=\"text-body-small\" emphasis>{source.title}</ds-text>}\n                {hostname ? <ds-text variant=\"text-caption\" color=\"secondary\">{hostname}</ds-text> : null}\n                {source.description ? <ds-text variant=\"text-body-small\" color=\"secondary\">{source.description}</ds-text> : null}\n              </li>;\n            })}\n          </ol>\n        </details>\n      </Host>\n    );\n  }\n}\n",
      "type": "registry:ui"
    }
  ]
}
