agent-relay-server 0.85.0 → 0.87.0

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 (104) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +2 -2
  3. package/public/assets/{MessageBubble-DqFyach0.js → MessageBubble-DS4Hbn0k.js} +2 -2
  4. package/public/assets/{MessageBubble-DqFyach0.js.map → MessageBubble-DS4Hbn0k.js.map} +1 -1
  5. package/public/assets/{PlanGraphPanel-CCvKbYWe.js → PlanGraphPanel-BYlragEi.js} +2 -2
  6. package/public/assets/{PlanGraphPanel-CCvKbYWe.js.map → PlanGraphPanel-BYlragEi.js.map} +1 -1
  7. package/public/assets/{activity-C6RvknQQ.js → activity-CcGFS_sY.js} +2 -2
  8. package/public/assets/{activity-C6RvknQQ.js.map → activity-CcGFS_sY.js.map} +1 -1
  9. package/public/assets/{agent-profiles-RFCLAgnC.js → agent-profiles-CLJNeVxc.js} +2 -2
  10. package/public/assets/{agent-profiles-RFCLAgnC.js.map → agent-profiles-CLJNeVxc.js.map} +1 -1
  11. package/public/assets/{agents-D7HZJ5eG.js → agents-BTh8SQiP.js} +2 -2
  12. package/public/assets/{agents-D7HZJ5eG.js.map → agents-BTh8SQiP.js.map} +1 -1
  13. package/public/assets/{analytics-2H2z2UNS.js → analytics-C1F28oqr.js} +2 -2
  14. package/public/assets/{analytics-2H2z2UNS.js.map → analytics-C1F28oqr.js.map} +1 -1
  15. package/public/assets/{automation-BUazA3lr.js → automation-izYGpZyQ.js} +2 -2
  16. package/public/assets/{automation-BUazA3lr.js.map → automation-izYGpZyQ.js.map} +1 -1
  17. package/public/assets/{branch-state-badge-DxwNcWr8.js → branch-state-badge-Q4W68jxj.js} +2 -2
  18. package/public/assets/{branch-state-badge-DxwNcWr8.js.map → branch-state-badge-Q4W68jxj.js.map} +1 -1
  19. package/public/assets/{channels-Sh_jdB7y.js → channels-BQbNtrtF.js} +2 -2
  20. package/public/assets/{channels-Sh_jdB7y.js.map → channels-BQbNtrtF.js.map} +1 -1
  21. package/public/assets/{chat-DBTEaf-H.js → chat-ThyPRUPq.js} +2 -2
  22. package/public/assets/{chat-DBTEaf-H.js.map → chat-ThyPRUPq.js.map} +1 -1
  23. package/public/assets/{connectors-C3C4i4Gz.js → connectors-CmARSKoV.js} +2 -2
  24. package/public/assets/{connectors-C3C4i4Gz.js.map → connectors-CmARSKoV.js.map} +1 -1
  25. package/public/assets/display-CWMHll1J.js.map +1 -1
  26. package/public/assets/{formatted-body-impl-KG0iExZ-.js → formatted-body-impl-DEYxGoiw.js} +2 -2
  27. package/public/assets/{formatted-body-impl-KG0iExZ-.js.map → formatted-body-impl-DEYxGoiw.js.map} +1 -1
  28. package/public/assets/index-Bd1NBLyd.js +23 -0
  29. package/public/assets/{index-TZskQfQL.js.map → index-Bd1NBLyd.js.map} +1 -1
  30. package/public/assets/index-BjbvhfFt.css +2 -0
  31. package/public/assets/{insights-JL1s7Uul.js → insights-DAVKQ_SF.js} +2 -2
  32. package/public/assets/{insights-JL1s7Uul.js.map → insights-DAVKQ_SF.js.map} +1 -1
  33. package/public/assets/{integrations-PqWMrPJa.js → integrations-D9Cx-7ma.js} +2 -2
  34. package/public/assets/{integrations-PqWMrPJa.js.map → integrations-D9Cx-7ma.js.map} +1 -1
  35. package/public/assets/{maintenance-CTMfhXFM.js → maintenance-BL4R9076.js} +2 -2
  36. package/public/assets/{maintenance-CTMfhXFM.js.map → maintenance-BL4R9076.js.map} +1 -1
  37. package/public/assets/{managed-agents-C4cb3xQ4.js → managed-agents-C7n1gl7E.js} +2 -2
  38. package/public/assets/{managed-agents-C4cb3xQ4.js.map → managed-agents-C7n1gl7E.js.map} +1 -1
  39. package/public/assets/{markdown-preview-impl-DQIi0O7r.js → markdown-preview-impl-DK0wNWXJ.js} +2 -2
  40. package/public/assets/{markdown-preview-impl-DQIi0O7r.js.map → markdown-preview-impl-DK0wNWXJ.js.map} +1 -1
  41. package/public/assets/{memory-DJPXFdgw.js → memory-BJEkDkwl.js} +2 -2
  42. package/public/assets/{memory-DJPXFdgw.js.map → memory-BJEkDkwl.js.map} +1 -1
  43. package/public/assets/{messages-RSD2g4Wx.js → messages-DBn9tXx2.js} +2 -2
  44. package/public/assets/{messages-RSD2g4Wx.js.map → messages-DBn9tXx2.js.map} +1 -1
  45. package/public/assets/{orchestrators-BGIkULBF.js → orchestrators-Bc1eC16Q.js} +2 -2
  46. package/public/assets/{orchestrators-BGIkULBF.js.map → orchestrators-Bc1eC16Q.js.map} +1 -1
  47. package/public/assets/{overview-ByE9V8pe.js → overview-Bw7zrSqR.js} +2 -2
  48. package/public/assets/{overview-ByE9V8pe.js.map → overview-Bw7zrSqR.js.map} +1 -1
  49. package/public/assets/{pairs-C284ntvD.js → pairs-BSwWnLK2.js} +2 -2
  50. package/public/assets/{pairs-C284ntvD.js.map → pairs-BSwWnLK2.js.map} +1 -1
  51. package/public/assets/{projects-B2-8Eu0e.js → projects-hU5KGW_T.js} +2 -2
  52. package/public/assets/{projects-B2-8Eu0e.js.map → projects-hU5KGW_T.js.map} +1 -1
  53. package/public/assets/{security-vDglScsg.js → security-wTBapq4K.js} +2 -2
  54. package/public/assets/{security-vDglScsg.js.map → security-wTBapq4K.js.map} +1 -1
  55. package/public/assets/{select-DaOiWDBR.js → select-D6HFOeLW.js} +2 -2
  56. package/public/assets/{select-DaOiWDBR.js.map → select-D6HFOeLW.js.map} +1 -1
  57. package/public/assets/{settings-DiLcbSqx.js → settings-CDzp7vqJ.js} +2 -2
  58. package/public/assets/{settings-DiLcbSqx.js.map → settings-CDzp7vqJ.js.map} +1 -1
  59. package/public/assets/{store-DYaQAXRv.js → store-DsqUEZOf.js} +2 -2
  60. package/public/assets/store-DsqUEZOf.js.map +1 -0
  61. package/public/assets/{tasks-DWJdJra3.js → tasks-Bd7Wjy6e.js} +2 -2
  62. package/public/assets/{tasks-DWJdJra3.js.map → tasks-Bd7Wjy6e.js.map} +1 -1
  63. package/public/assets/{teams-FejXkix4.js → teams-l3GUr2XV.js} +2 -2
  64. package/public/assets/{teams-FejXkix4.js.map → teams-l3GUr2XV.js.map} +1 -1
  65. package/public/assets/{terminal-viewer-impl-Bkt1w42o.js → terminal-viewer-impl-BQMMWctd.js} +2 -2
  66. package/public/assets/{terminal-viewer-impl-Bkt1w42o.js.map → terminal-viewer-impl-BQMMWctd.js.map} +1 -1
  67. package/public/assets/{user-avatar-ClE2dMD8.js → user-avatar-DcA69UJK.js} +2 -2
  68. package/public/assets/{user-avatar-ClE2dMD8.js.map → user-avatar-DcA69UJK.js.map} +1 -1
  69. package/public/assets/{work-queue-DZdv9kOb.js → work-queue-BYlFeJ1g.js} +2 -2
  70. package/public/assets/{work-queue-DZdv9kOb.js.map → work-queue-BYlFeJ1g.js.map} +1 -1
  71. package/public/assets/{workspaces-BhblC-Nd.js → workspaces-C740m1ys.js} +2 -2
  72. package/public/assets/{workspaces-BhblC-Nd.js.map → workspaces-C740m1ys.js.map} +1 -1
  73. package/public/index.html +3 -3
  74. package/runner/src/adapter.ts +4 -3
  75. package/src/agent-busy-health.ts +93 -0
  76. package/src/agent-card-projection.ts +4 -1
  77. package/src/agent-lifecycle-events.ts +6 -1
  78. package/src/branch-landed.ts +81 -0
  79. package/src/cli/index.ts +3 -3
  80. package/src/cli/reply.ts +6 -1
  81. package/src/config.ts +9 -0
  82. package/src/db/index.ts +1 -0
  83. package/src/db/migrations.ts +17 -0
  84. package/src/db/provider-quotas.ts +99 -21
  85. package/src/db/terminal-events.ts +56 -0
  86. package/src/maintenance/constants.ts +4 -0
  87. package/src/maintenance/jobs.ts +88 -0
  88. package/src/maintenance/teams.ts +116 -5
  89. package/src/maintenance/workspaces.ts +23 -10
  90. package/src/mcp/index.ts +2 -1
  91. package/src/mcp/tools-spawn.ts +119 -4
  92. package/src/notification-types.ts +6 -0
  93. package/src/provider-catalog-store.ts +3 -0
  94. package/src/routes/workspaces.ts +5 -0
  95. package/src/services/transient-agent-reaper.ts +4 -1
  96. package/src/spawn-targets.ts +8 -2
  97. package/src/steward-identity.ts +50 -0
  98. package/src/steward.ts +12 -4
  99. package/src/team-idle-tracker.ts +19 -0
  100. package/src/workspace-auto-merge.ts +35 -6
  101. package/src/workspace-pr-completion.ts +26 -0
  102. package/public/assets/index-LUIvWcx6.css +0 -2
  103. package/public/assets/index-TZskQfQL.js +0 -23
  104. package/public/assets/store-DYaQAXRv.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"projects-B2-8Eu0e.js","names":[],"sources":["../../dashboard/src/components/views/projects.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react'\nimport { errMessage } from 'agent-relay-sdk/types'\nimport { api } from '@/lib/api'\nimport { useRelayStore } from '@/store'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { CopyButton } from '@/components/shared/copy-button'\nimport { timeAgo } from '@/lib/display'\nimport { Boxes, FileText, FolderGit2, Layers, RefreshCw } from 'lucide-react'\nimport type { Project, ProjectEntryKind, ProjectRoot, ResolvedProjectEntry } from '@/types'\n\n// Projects (#488) — the human's window into the durable Projects scope (epic #403/#405).\n// Read-only: writes go through MCP relay_project_*. Pick a project, see its roots, its\n// entries grouped by kind, what it inherits from umbrella projects, and any ingested\n// CLAUDE.md. Templated on the insights/memory view conventions (zinc/Tailwind, lazy-loaded).\n\ninterface ProjectDetail {\n project: Project\n roots: ProjectRoot[]\n}\n\n// Display order + labels for the entry kinds. Rules first (they're the binding ones),\n// then decisions, facts, and project-native memory.\nconst KIND_ORDER: ProjectEntryKind[] = ['rule', 'decision', 'fact', 'memory']\nconst KIND_LABELS: Record<ProjectEntryKind, string> = {\n rule: 'Rules',\n decision: 'Decisions',\n fact: 'Facts',\n memory: 'Memory',\n}\n\nfunction sourceClass(source: ResolvedProjectEntry['source']): string {\n if (source === 'ingested') return 'bg-blue-500/10 text-blue-400 border-blue-500/30'\n if (source === 'promoted') return 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30'\n return 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30'\n}\n\nconst BODY_CLAMP = 320\n\nfunction EntryRow({ entry, ownerName, now }: { entry: ResolvedProjectEntry; ownerName?: string; now: number }) {\n const [expanded, setExpanded] = useState(false)\n const body = entry.body ?? ''\n const isLong = body.length > BODY_CLAMP\n const shown = expanded || !isLong ? body : body.slice(0, BODY_CLAMP).trimEnd() + '…'\n\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium\">{entry.title}</span>\n <Badge variant=\"outline\" className={`text-[10px] ${sourceClass(entry.source)}`}>{entry.source}</Badge>\n {entry.inherited && (\n <Badge variant=\"outline\" className=\"gap-1 border-amber-500/30 bg-amber-500/10 text-[10px] text-amber-400\">\n <Layers className=\"h-3 w-3\" />\n inherited{ownerName ? ` · ${ownerName}` : ''}\n </Badge>\n )}\n <span className=\"ml-auto text-[10px] text-muted-foreground\">{timeAgo(now, entry.updatedAt)}</span>\n </div>\n {body && (\n <div className=\"mt-2\">\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground\">{shown}</pre>\n {isLong && (\n <button\n type=\"button\"\n className=\"mt-1 text-[11px] font-medium text-primary hover:underline\"\n onClick={() => setExpanded((v) => !v)}\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </div>\n )}\n {entry.tags.length > 0 && (\n <div className=\"mt-2 flex flex-wrap gap-1\">\n {entry.tags.map((tag) => (\n <Badge key={tag} variant=\"secondary\" className=\"h-4 px-1 text-[9px]\">{tag}</Badge>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nexport function ProjectsView() {\n const projectFocusId = useRelayStore((s) => s.projectFocusId)\n const consumeProjectFocus = useRelayStore((s) => s.consumeProjectFocus)\n\n const [projects, setProjects] = useState<Project[]>([])\n const [selectedId, setSelectedId] = useState<string>('')\n const [includeArchived, setIncludeArchived] = useState(false)\n const [detail, setDetail] = useState<ProjectDetail | null>(null)\n const [entries, setEntries] = useState<ResolvedProjectEntry[]>([])\n const [loadingList, setLoadingList] = useState(true)\n const [loadingDetail, setLoadingDetail] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [now, setNow] = useState(() => Date.now())\n\n async function refreshList() {\n setError(null)\n try {\n const res = await api<{ projects: Project[] }>('GET', `/projects${includeArchived ? '?includeArchived=true' : ''}`)\n setProjects(res.projects)\n setNow(Date.now())\n // Selection precedence: a pending deep-link focus → keep current if still present → first.\n const focus = projectFocusId\n const has = (ref: string) => res.projects.some((p) => p.id === ref || p.slug === ref)\n if (focus && has(focus)) { setSelectedId(focus); consumeProjectFocus() }\n else setSelectedId((cur) => (cur && has(cur) ? cur : res.projects[0]?.id ?? ''))\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setLoadingList(false)\n }\n }\n\n // Mount + archived-toggle: sync the project list from the relay (external data source).\n useEffect(() => {\n void refreshList()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [includeArchived])\n\n // A deep-link focus that arrives while this view is already mounted: select it.\n useEffect(() => {\n if (projectFocusId && projects.some((p) => p.id === projectFocusId || p.slug === projectFocusId)) {\n setSelectedId(projectFocusId)\n consumeProjectFocus()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [projectFocusId])\n\n // Selected project changed: pull its roots + resolved entries (own + inherited).\n useEffect(() => {\n if (!selectedId) { setDetail(null); setEntries([]); return }\n let cancelled = false\n setLoadingDetail(true)\n Promise.all([\n api<ProjectDetail>('GET', `/projects/${encodeURIComponent(selectedId)}`),\n api<{ entries: ResolvedProjectEntry[] }>('GET', `/projects/${encodeURIComponent(selectedId)}/entries?includeInherited=true`),\n ])\n .then(([d, e]) => {\n if (cancelled) return\n setDetail(d)\n setEntries(e.entries)\n setNow(Date.now())\n })\n .catch((e) => { if (!cancelled) setError(errMessage(e)) })\n .finally(() => { if (!cancelled) setLoadingDetail(false) })\n return () => { cancelled = true }\n }, [selectedId])\n\n // projectId → display name, so an inherited entry can name the umbrella it came from.\n const nameById = useMemo(() => {\n const map = new Map<string, string>()\n for (const p of projects) map.set(p.id, p.title || p.slug)\n return map\n }, [projects])\n\n const ingested = useMemo(() => entries.filter((e) => e.source === 'ingested'), [entries])\n\n // Group the non-ingested entries by kind; ingested CLAUDE.md gets its own card above,\n // so it's excluded here to avoid listing the same entry twice.\n const byKind = useMemo(() => {\n const groups = new Map<ProjectEntryKind, ResolvedProjectEntry[]>()\n for (const entry of entries) {\n if (entry.source === 'ingested') continue\n const list = groups.get(entry.kind) ?? []\n list.push(entry)\n groups.set(entry.kind, list)\n }\n return groups\n }, [entries])\n const ownCount = entries.filter((e) => !e.inherited).length\n const inheritedCount = entries.length - ownCount\n\n return (\n <div className=\"space-y-4 p-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Boxes className=\"size-5 text-primary\" />\n <h1 className=\"text-lg font-semibold\">Projects</h1>\n <span className=\"text-xs text-muted-foreground\">durable knowledge scope · epic #403</span>\n\n <select\n className=\"ml-auto h-8 rounded-md border border-border bg-card px-2 text-sm text-foreground\"\n value={selectedId}\n onChange={(e) => setSelectedId(e.target.value)}\n disabled={projects.length === 0}\n >\n {projects.length === 0 && <option value=\"\">No projects</option>}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {(p.title || p.slug)}{p.status === 'archived' ? ' (archived)' : ''}\n </option>\n ))}\n </select>\n\n <label className=\"flex items-center gap-1.5 text-xs text-muted-foreground select-none\">\n <input type=\"checkbox\" className=\"rounded\" checked={includeArchived} onChange={(e) => setIncludeArchived(e.target.checked)} />\n Archived\n </label>\n\n <Button variant=\"outline\" size=\"sm\" onClick={() => void refreshList()}>\n <RefreshCw className=\"size-4\" /> Refresh\n </Button>\n </div>\n\n {error && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">{error}</div>\n )}\n\n {!loadingList && projects.length === 0 && (\n <Card>\n <CardContent className=\"py-10 text-center text-sm text-muted-foreground\">\n No projects yet. Projects are created through the relay <code className=\"font-mono text-xs\">relay_project_*</code> MCP tools\n (or bootstrapped from a root's CLAUDE.md).\n </CardContent>\n </Card>\n )}\n\n {detail && (\n <>\n {/* Project header */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2\">\n <span>{detail.project.title || detail.project.slug}</span>\n <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{detail.project.slug}</Badge>\n <Badge variant={detail.project.status === 'active' ? 'secondary' : 'outline'} className=\"text-[10px]\">\n {detail.project.status}\n </Badge>\n <span className=\"ml-auto text-xs font-normal text-muted-foreground\">\n {ownCount} own · {inheritedCount} inherited · updated {timeAgo(now, detail.project.updatedAt)}\n </span>\n </CardTitle>\n </CardHeader>\n {(detail.project.description || detail.project.issueRepo) && (\n <CardContent className=\"space-y-2 pt-0 text-sm text-muted-foreground\">\n {detail.project.description && <div>{detail.project.description}</div>}\n {detail.project.issueRepo && (\n <a\n href={`https://github.com/${detail.project.issueRepo}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1.5 text-primary hover:underline\"\n >\n <FolderGit2 className=\"size-3.5\" />\n <span className=\"font-mono text-xs\">{detail.project.issueRepo}</span>\n </a>\n )}\n </CardContent>\n )}\n </Card>\n\n {/* Roots */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <FolderGit2 className=\"size-4 text-muted-foreground\" /> Roots\n <span className=\"text-xs font-normal text-muted-foreground\">({detail.roots.length})</span>\n </CardTitle>\n </CardHeader>\n <CardContent>\n {detail.roots.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">No roots bound. A project resolves to agents by the repo paths registered here.</div>\n ) : (\n <div className=\"space-y-1.5\">\n {detail.roots.map((root) => (\n <div key={root.rootPath} className=\"flex items-center gap-2 rounded border border-border bg-card/60 px-2 py-1\">\n <span className=\"flex-1 truncate font-mono text-xs text-muted-foreground\" title={root.rootPath}>{root.rootPath}</span>\n <CopyButton value={root.rootPath} label=\"Copy root path\" size=\"icon\" className=\"h-6 w-6\" iconClassName=\"h-3 w-3\" />\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Ingested CLAUDE.md (called out separately — it's the bootstrapped host context) */}\n {ingested.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <FileText className=\"size-4 text-blue-400\" /> Ingested CLAUDE.md\n <span className=\"text-xs font-normal text-muted-foreground\">({ingested.length})</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {ingested.map((entry) => (\n <EntryRow key={entry.id} entry={entry} ownerName={entry.inherited ? nameById.get(entry.projectId) : undefined} now={now} />\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Entries grouped by kind */}\n {loadingDetail && entries.length === 0 ? (\n <div className=\"py-8 text-center text-sm text-muted-foreground\">Loading entries…</div>\n ) : entries.length === 0 ? (\n <Card>\n <CardContent className=\"py-8 text-center text-sm text-muted-foreground\">\n No entries yet. Agents write durable rules, decisions, facts, and memory here via the relay MCP tools.\n </CardContent>\n </Card>\n ) : (\n KIND_ORDER.filter((kind) => byKind.has(kind)).map((kind) => {\n const list = byKind.get(kind)!\n return (\n <Card key={kind}>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n {KIND_LABELS[kind]}\n <span className=\"text-xs font-normal text-muted-foreground\">({list.length})</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {list.map((entry) => (\n <EntryRow key={entry.id} entry={entry} ownerName={entry.inherited ? nameById.get(entry.projectId) : undefined} now={now} />\n ))}\n </CardContent>\n </Card>\n )\n })\n )}\n </>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"projects-hU5KGW_T.js","names":[],"sources":["../../dashboard/src/components/views/projects.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react'\nimport { errMessage } from 'agent-relay-sdk/types'\nimport { api } from '@/lib/api'\nimport { useRelayStore } from '@/store'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { CopyButton } from '@/components/shared/copy-button'\nimport { timeAgo } from '@/lib/display'\nimport { Boxes, FileText, FolderGit2, Layers, RefreshCw } from 'lucide-react'\nimport type { Project, ProjectEntryKind, ProjectRoot, ResolvedProjectEntry } from '@/types'\n\n// Projects (#488) — the human's window into the durable Projects scope (epic #403/#405).\n// Read-only: writes go through MCP relay_project_*. Pick a project, see its roots, its\n// entries grouped by kind, what it inherits from umbrella projects, and any ingested\n// CLAUDE.md. Templated on the insights/memory view conventions (zinc/Tailwind, lazy-loaded).\n\ninterface ProjectDetail {\n project: Project\n roots: ProjectRoot[]\n}\n\n// Display order + labels for the entry kinds. Rules first (they're the binding ones),\n// then decisions, facts, and project-native memory.\nconst KIND_ORDER: ProjectEntryKind[] = ['rule', 'decision', 'fact', 'memory']\nconst KIND_LABELS: Record<ProjectEntryKind, string> = {\n rule: 'Rules',\n decision: 'Decisions',\n fact: 'Facts',\n memory: 'Memory',\n}\n\nfunction sourceClass(source: ResolvedProjectEntry['source']): string {\n if (source === 'ingested') return 'bg-blue-500/10 text-blue-400 border-blue-500/30'\n if (source === 'promoted') return 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30'\n return 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30'\n}\n\nconst BODY_CLAMP = 320\n\nfunction EntryRow({ entry, ownerName, now }: { entry: ResolvedProjectEntry; ownerName?: string; now: number }) {\n const [expanded, setExpanded] = useState(false)\n const body = entry.body ?? ''\n const isLong = body.length > BODY_CLAMP\n const shown = expanded || !isLong ? body : body.slice(0, BODY_CLAMP).trimEnd() + '…'\n\n return (\n <div className=\"rounded-md border border-border bg-card/60 p-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium\">{entry.title}</span>\n <Badge variant=\"outline\" className={`text-[10px] ${sourceClass(entry.source)}`}>{entry.source}</Badge>\n {entry.inherited && (\n <Badge variant=\"outline\" className=\"gap-1 border-amber-500/30 bg-amber-500/10 text-[10px] text-amber-400\">\n <Layers className=\"h-3 w-3\" />\n inherited{ownerName ? ` · ${ownerName}` : ''}\n </Badge>\n )}\n <span className=\"ml-auto text-[10px] text-muted-foreground\">{timeAgo(now, entry.updatedAt)}</span>\n </div>\n {body && (\n <div className=\"mt-2\">\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground\">{shown}</pre>\n {isLong && (\n <button\n type=\"button\"\n className=\"mt-1 text-[11px] font-medium text-primary hover:underline\"\n onClick={() => setExpanded((v) => !v)}\n >\n {expanded ? 'Show less' : 'Show more'}\n </button>\n )}\n </div>\n )}\n {entry.tags.length > 0 && (\n <div className=\"mt-2 flex flex-wrap gap-1\">\n {entry.tags.map((tag) => (\n <Badge key={tag} variant=\"secondary\" className=\"h-4 px-1 text-[9px]\">{tag}</Badge>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nexport function ProjectsView() {\n const projectFocusId = useRelayStore((s) => s.projectFocusId)\n const consumeProjectFocus = useRelayStore((s) => s.consumeProjectFocus)\n\n const [projects, setProjects] = useState<Project[]>([])\n const [selectedId, setSelectedId] = useState<string>('')\n const [includeArchived, setIncludeArchived] = useState(false)\n const [detail, setDetail] = useState<ProjectDetail | null>(null)\n const [entries, setEntries] = useState<ResolvedProjectEntry[]>([])\n const [loadingList, setLoadingList] = useState(true)\n const [loadingDetail, setLoadingDetail] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [now, setNow] = useState(() => Date.now())\n\n async function refreshList() {\n setError(null)\n try {\n const res = await api<{ projects: Project[] }>('GET', `/projects${includeArchived ? '?includeArchived=true' : ''}`)\n setProjects(res.projects)\n setNow(Date.now())\n // Selection precedence: a pending deep-link focus → keep current if still present → first.\n const focus = projectFocusId\n const has = (ref: string) => res.projects.some((p) => p.id === ref || p.slug === ref)\n if (focus && has(focus)) { setSelectedId(focus); consumeProjectFocus() }\n else setSelectedId((cur) => (cur && has(cur) ? cur : res.projects[0]?.id ?? ''))\n } catch (e) {\n setError(errMessage(e))\n } finally {\n setLoadingList(false)\n }\n }\n\n // Mount + archived-toggle: sync the project list from the relay (external data source).\n useEffect(() => {\n void refreshList()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [includeArchived])\n\n // A deep-link focus that arrives while this view is already mounted: select it.\n useEffect(() => {\n if (projectFocusId && projects.some((p) => p.id === projectFocusId || p.slug === projectFocusId)) {\n setSelectedId(projectFocusId)\n consumeProjectFocus()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [projectFocusId])\n\n // Selected project changed: pull its roots + resolved entries (own + inherited).\n useEffect(() => {\n if (!selectedId) { setDetail(null); setEntries([]); return }\n let cancelled = false\n setLoadingDetail(true)\n Promise.all([\n api<ProjectDetail>('GET', `/projects/${encodeURIComponent(selectedId)}`),\n api<{ entries: ResolvedProjectEntry[] }>('GET', `/projects/${encodeURIComponent(selectedId)}/entries?includeInherited=true`),\n ])\n .then(([d, e]) => {\n if (cancelled) return\n setDetail(d)\n setEntries(e.entries)\n setNow(Date.now())\n })\n .catch((e) => { if (!cancelled) setError(errMessage(e)) })\n .finally(() => { if (!cancelled) setLoadingDetail(false) })\n return () => { cancelled = true }\n }, [selectedId])\n\n // projectId → display name, so an inherited entry can name the umbrella it came from.\n const nameById = useMemo(() => {\n const map = new Map<string, string>()\n for (const p of projects) map.set(p.id, p.title || p.slug)\n return map\n }, [projects])\n\n const ingested = useMemo(() => entries.filter((e) => e.source === 'ingested'), [entries])\n\n // Group the non-ingested entries by kind; ingested CLAUDE.md gets its own card above,\n // so it's excluded here to avoid listing the same entry twice.\n const byKind = useMemo(() => {\n const groups = new Map<ProjectEntryKind, ResolvedProjectEntry[]>()\n for (const entry of entries) {\n if (entry.source === 'ingested') continue\n const list = groups.get(entry.kind) ?? []\n list.push(entry)\n groups.set(entry.kind, list)\n }\n return groups\n }, [entries])\n const ownCount = entries.filter((e) => !e.inherited).length\n const inheritedCount = entries.length - ownCount\n\n return (\n <div className=\"space-y-4 p-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Boxes className=\"size-5 text-primary\" />\n <h1 className=\"text-lg font-semibold\">Projects</h1>\n <span className=\"text-xs text-muted-foreground\">durable knowledge scope · epic #403</span>\n\n <select\n className=\"ml-auto h-8 rounded-md border border-border bg-card px-2 text-sm text-foreground\"\n value={selectedId}\n onChange={(e) => setSelectedId(e.target.value)}\n disabled={projects.length === 0}\n >\n {projects.length === 0 && <option value=\"\">No projects</option>}\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {(p.title || p.slug)}{p.status === 'archived' ? ' (archived)' : ''}\n </option>\n ))}\n </select>\n\n <label className=\"flex items-center gap-1.5 text-xs text-muted-foreground select-none\">\n <input type=\"checkbox\" className=\"rounded\" checked={includeArchived} onChange={(e) => setIncludeArchived(e.target.checked)} />\n Archived\n </label>\n\n <Button variant=\"outline\" size=\"sm\" onClick={() => void refreshList()}>\n <RefreshCw className=\"size-4\" /> Refresh\n </Button>\n </div>\n\n {error && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive\">{error}</div>\n )}\n\n {!loadingList && projects.length === 0 && (\n <Card>\n <CardContent className=\"py-10 text-center text-sm text-muted-foreground\">\n No projects yet. Projects are created through the relay <code className=\"font-mono text-xs\">relay_project_*</code> MCP tools\n (or bootstrapped from a root's CLAUDE.md).\n </CardContent>\n </Card>\n )}\n\n {detail && (\n <>\n {/* Project header */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex flex-wrap items-center gap-2\">\n <span>{detail.project.title || detail.project.slug}</span>\n <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{detail.project.slug}</Badge>\n <Badge variant={detail.project.status === 'active' ? 'secondary' : 'outline'} className=\"text-[10px]\">\n {detail.project.status}\n </Badge>\n <span className=\"ml-auto text-xs font-normal text-muted-foreground\">\n {ownCount} own · {inheritedCount} inherited · updated {timeAgo(now, detail.project.updatedAt)}\n </span>\n </CardTitle>\n </CardHeader>\n {(detail.project.description || detail.project.issueRepo) && (\n <CardContent className=\"space-y-2 pt-0 text-sm text-muted-foreground\">\n {detail.project.description && <div>{detail.project.description}</div>}\n {detail.project.issueRepo && (\n <a\n href={`https://github.com/${detail.project.issueRepo}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1.5 text-primary hover:underline\"\n >\n <FolderGit2 className=\"size-3.5\" />\n <span className=\"font-mono text-xs\">{detail.project.issueRepo}</span>\n </a>\n )}\n </CardContent>\n )}\n </Card>\n\n {/* Roots */}\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <FolderGit2 className=\"size-4 text-muted-foreground\" /> Roots\n <span className=\"text-xs font-normal text-muted-foreground\">({detail.roots.length})</span>\n </CardTitle>\n </CardHeader>\n <CardContent>\n {detail.roots.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">No roots bound. A project resolves to agents by the repo paths registered here.</div>\n ) : (\n <div className=\"space-y-1.5\">\n {detail.roots.map((root) => (\n <div key={root.rootPath} className=\"flex items-center gap-2 rounded border border-border bg-card/60 px-2 py-1\">\n <span className=\"flex-1 truncate font-mono text-xs text-muted-foreground\" title={root.rootPath}>{root.rootPath}</span>\n <CopyButton value={root.rootPath} label=\"Copy root path\" size=\"icon\" className=\"h-6 w-6\" iconClassName=\"h-3 w-3\" />\n </div>\n ))}\n </div>\n )}\n </CardContent>\n </Card>\n\n {/* Ingested CLAUDE.md (called out separately — it's the bootstrapped host context) */}\n {ingested.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <FileText className=\"size-4 text-blue-400\" /> Ingested CLAUDE.md\n <span className=\"text-xs font-normal text-muted-foreground\">({ingested.length})</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {ingested.map((entry) => (\n <EntryRow key={entry.id} entry={entry} ownerName={entry.inherited ? nameById.get(entry.projectId) : undefined} now={now} />\n ))}\n </CardContent>\n </Card>\n )}\n\n {/* Entries grouped by kind */}\n {loadingDetail && entries.length === 0 ? (\n <div className=\"py-8 text-center text-sm text-muted-foreground\">Loading entries…</div>\n ) : entries.length === 0 ? (\n <Card>\n <CardContent className=\"py-8 text-center text-sm text-muted-foreground\">\n No entries yet. Agents write durable rules, decisions, facts, and memory here via the relay MCP tools.\n </CardContent>\n </Card>\n ) : (\n KIND_ORDER.filter((kind) => byKind.has(kind)).map((kind) => {\n const list = byKind.get(kind)!\n return (\n <Card key={kind}>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n {KIND_LABELS[kind]}\n <span className=\"text-xs font-normal text-muted-foreground\">({list.length})</span>\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {list.map((entry) => (\n <EntryRow key={entry.id} entry={entry} ownerName={entry.inherited ? nameById.get(entry.projectId) : undefined} now={now} />\n ))}\n </CardContent>\n </Card>\n )\n })\n )}\n </>\n )}\n </div>\n )\n}\n"],"mappings":"ybAwBM,EAAiC,CAAC,OAAQ,WAAY,OAAQ,SAAS,CACvE,EAAgD,CACpD,KAAM,QACN,SAAU,YACV,KAAM,QACN,OAAQ,SACT,CAED,SAAS,EAAY,EAAgD,CAGnE,OAFI,IAAW,WAAmB,kDAC9B,IAAW,WAAmB,2DAC3B,kDAGT,IAAM,EAAa,IAEnB,SAAS,EAAS,CAAE,QAAO,YAAW,OAAyE,CAC7G,GAAM,CAAC,EAAU,IAAA,EAAA,EAAA,UAAwB,GAAM,CACzC,EAAO,EAAM,MAAQ,GACrB,EAAS,EAAK,OAAS,EACvB,EAAQ,GAAY,CAAC,EAAS,EAAO,EAAK,MAAM,EAAG,EAAW,CAAC,SAAS,CAAG,IAEjF,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,0DAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,6CAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,+BAAuB,EAAM,MAAa,CAAA,EAC1D,EAAA,EAAA,KAAC,EAAD,CAAO,QAAQ,UAAU,UAAW,eAAe,EAAY,EAAM,OAAO,YAAK,EAAM,OAAe,CAAA,CACrG,EAAM,YACL,EAAA,EAAA,MAAC,EAAD,CAAO,QAAQ,UAAU,UAAU,gFAAnC,EACE,EAAA,EAAA,KAAC,EAAD,CAAQ,UAAU,UAAY,CAAA,aACpB,EAAY,MAAM,IAAc,GACpC,IAEV,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,qDAA6C,EAAQ,EAAK,EAAM,UAAU,CAAQ,CAAA,CAC9F,GACL,IACC,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,gBAAf,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,mFAA2E,EAAY,CAAA,CACrG,IACC,EAAA,EAAA,KAAC,SAAD,CACE,KAAK,SACL,UAAU,4DACV,YAAe,EAAa,GAAM,CAAC,EAAE,UAEpC,EAAW,YAAc,YACnB,CAAA,CAEP,GAEP,EAAM,KAAK,OAAS,IACnB,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,qCACZ,EAAM,KAAK,IAAK,IACf,EAAA,EAAA,KAAC,EAAD,CAAiB,QAAQ,YAAY,UAAU,+BAAuB,EAAY,CAAtE,EAAsE,CAClF,CACE,CAAA,CAEJ,GAIV,SAAgB,GAAe,CAC7B,IAAM,EAAiB,EAAe,GAAM,EAAE,eAAe,CACvD,EAAsB,EAAe,GAAM,EAAE,oBAAoB,CAEjE,CAAC,EAAU,IAAA,EAAA,EAAA,UAAmC,EAAE,CAAC,CACjD,CAAC,EAAY,IAAA,EAAA,EAAA,UAAkC,GAAG,CAClD,CAAC,EAAiB,IAAA,EAAA,EAAA,UAA+B,GAAM,CACvD,CAAC,EAAQ,IAAA,EAAA,EAAA,UAA4C,KAAK,CAC1D,CAAC,EAAS,IAAA,EAAA,EAAA,UAA+C,EAAE,CAAC,CAC5D,CAAC,EAAa,IAAA,EAAA,EAAA,UAA2B,GAAK,CAC9C,CAAC,EAAe,IAAA,EAAA,EAAA,UAA6B,GAAM,CACnD,CAAC,EAAO,IAAA,EAAA,EAAA,UAAoC,KAAK,CACjD,CAAC,EAAK,IAAA,EAAA,EAAA,cAAyB,KAAK,KAAK,CAAC,CAEhD,eAAe,GAAc,CAC3B,EAAS,KAAK,CACd,GAAI,CACF,IAAM,EAAM,MAAM,EAA6B,MAAO,YAAY,EAAkB,wBAA0B,KAAK,CACnH,EAAY,EAAI,SAAS,CACzB,EAAO,KAAK,KAAK,CAAC,CAElB,IAAM,EAAQ,EACR,EAAO,GAAgB,EAAI,SAAS,KAAM,GAAM,EAAE,KAAO,GAAO,EAAE,OAAS,EAAI,CACjF,GAAS,EAAI,EAAM,EAAI,EAAc,EAAM,CAAE,GAAqB,EACjE,EAAe,GAAS,GAAO,EAAI,EAAI,CAAG,EAAM,EAAI,SAAS,IAAI,IAAM,GAAI,OACzE,EAAG,CACV,EAAS,EAAW,EAAE,CAAC,QACf,CACR,EAAe,GAAM,GAKzB,EAAA,EAAA,eAAgB,CACd,GAAkB,EAEjB,CAAC,EAAgB,CAAC,EAGrB,EAAA,EAAA,eAAgB,CACV,GAAkB,EAAS,KAAM,GAAM,EAAE,KAAO,GAAkB,EAAE,OAAS,EAAe,GAC9F,EAAc,EAAe,CAC7B,GAAqB,GAGtB,CAAC,EAAe,CAAC,EAGpB,EAAA,EAAA,eAAgB,CACd,GAAI,CAAC,EAAY,CAAE,EAAU,KAAK,CAAE,EAAW,EAAE,CAAC,CAAE,OACpD,IAAI,EAAY,GAchB,OAbA,EAAiB,GAAK,CACtB,QAAQ,IAAI,CACV,EAAmB,MAAO,aAAa,mBAAmB,EAAW,GAAG,CACxE,EAAyC,MAAO,aAAa,mBAAmB,EAAW,CAAC,gCAAgC,CAC7H,CAAC,CACC,MAAM,CAAC,EAAG,KAAO,CACZ,IACJ,EAAU,EAAE,CACZ,EAAW,EAAE,QAAQ,CACrB,EAAO,KAAK,KAAK,CAAC,GAClB,CACD,MAAO,GAAM,CAAO,GAAW,EAAS,EAAW,EAAE,CAAC,EAAG,CACzD,YAAc,CAAO,GAAW,EAAiB,GAAM,EAAG,KAChD,CAAE,EAAY,KAC1B,CAAC,EAAW,CAAC,CAGhB,IAAM,GAAA,EAAA,EAAA,aAAyB,CAC7B,IAAM,EAAM,IAAI,IAChB,IAAK,IAAM,KAAK,EAAU,EAAI,IAAI,EAAE,GAAI,EAAE,OAAS,EAAE,KAAK,CAC1D,OAAO,GACN,CAAC,EAAS,CAAC,CAER,GAAA,EAAA,EAAA,aAAyB,EAAQ,OAAQ,GAAM,EAAE,SAAW,WAAW,CAAE,CAAC,EAAQ,CAAC,CAInF,GAAA,EAAA,EAAA,aAAuB,CAC3B,IAAM,EAAS,IAAI,IACnB,IAAK,IAAM,KAAS,EAAS,CAC3B,GAAI,EAAM,SAAW,WAAY,SACjC,IAAM,EAAO,EAAO,IAAI,EAAM,KAAK,EAAI,EAAE,CACzC,EAAK,KAAK,EAAM,CAChB,EAAO,IAAI,EAAM,KAAM,EAAK,CAE9B,OAAO,GACN,CAAC,EAAQ,CAAC,CACP,EAAW,EAAQ,OAAQ,GAAM,CAAC,EAAE,UAAU,CAAC,OAC/C,EAAiB,EAAQ,OAAS,EAExC,OACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,yBAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,6CAAf,EACE,EAAA,EAAA,KAAC,EAAD,CAAO,UAAU,sBAAwB,CAAA,EACzC,EAAA,EAAA,KAAC,KAAD,CAAI,UAAU,iCAAwB,WAAa,CAAA,EACnD,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,yCAAgC,sCAA0C,CAAA,EAE1F,EAAA,EAAA,MAAC,SAAD,CACE,UAAU,mFACV,MAAO,EACP,SAAW,GAAM,EAAc,EAAE,OAAO,MAAM,CAC9C,SAAU,EAAS,SAAW,WAJhC,CAMG,EAAS,SAAW,IAAK,EAAA,EAAA,KAAC,SAAD,CAAQ,MAAM,YAAG,cAAoB,CAAA,CAC9D,EAAS,IAAK,IACb,EAAA,EAAA,MAAC,SAAD,CAAmB,MAAO,EAAE,YAA5B,CACI,EAAE,OAAS,EAAE,KAAO,EAAE,SAAW,WAAa,cAAgB,GACzD,EAFI,EAAE,GAEN,CACT,CACK,IAET,EAAA,EAAA,MAAC,QAAD,CAAO,UAAU,+EAAjB,EACE,EAAA,EAAA,KAAC,QAAD,CAAO,KAAK,WAAW,UAAU,UAAU,QAAS,EAAiB,SAAW,GAAM,EAAmB,EAAE,OAAO,QAAQ,CAAI,CAAA,CAAA,WAExH,IAER,EAAA,EAAA,MAAC,EAAD,CAAQ,QAAQ,UAAU,KAAK,KAAK,YAAe,KAAK,GAAa,UAArE,EACE,EAAA,EAAA,KAAC,EAAD,CAAW,UAAU,SAAW,CAAA,CAAA,WACzB,GACL,GAEL,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,wGAAgG,EAAY,CAAA,CAG5H,CAAC,GAAe,EAAS,SAAW,IACnC,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,MAAC,EAAD,CAAa,UAAU,2DAAvB,CAAyE,4DACf,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,6BAAoB,kBAAsB,CAAA,yDAEtG,GACT,CAAA,CAGR,IACC,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EAEE,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,MAAC,EAAD,CAAW,UAAU,6CAArB,EACE,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAO,QAAQ,OAAS,EAAO,QAAQ,KAAY,CAAA,EAC1D,EAAA,EAAA,KAAC,EAAD,CAAO,QAAQ,UAAU,UAAU,iCAAyB,EAAO,QAAQ,KAAa,CAAA,EACxF,EAAA,EAAA,KAAC,EAAD,CAAO,QAAS,EAAO,QAAQ,SAAW,SAAW,YAAc,UAAW,UAAU,uBACrF,EAAO,QAAQ,OACV,CAAA,EACR,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,6DAAhB,CACG,EAAS,UAAQ,EAAe,wBAAsB,EAAQ,EAAK,EAAO,QAAQ,UAAU,CACxF,GACG,GACD,CAAA,EACX,EAAO,QAAQ,aAAe,EAAO,QAAQ,aAC7C,EAAA,EAAA,MAAC,EAAD,CAAa,UAAU,wDAAvB,CACG,EAAO,QAAQ,cAAe,EAAA,EAAA,KAAC,MAAD,CAAA,SAAM,EAAO,QAAQ,YAAkB,CAAA,CACrE,EAAO,QAAQ,YACd,EAAA,EAAA,MAAC,IAAD,CACE,KAAM,sBAAsB,EAAO,QAAQ,YAC3C,OAAO,SACP,IAAI,aACJ,UAAU,yEAJZ,EAME,EAAA,EAAA,KAAC,EAAD,CAAY,UAAU,WAAa,CAAA,EACnC,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,6BAAqB,EAAO,QAAQ,UAAiB,CAAA,CACnE,GAEM,GAEX,CAAA,CAAA,EAGP,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,MAAC,EAAD,CAAW,UAAU,6CAArB,EACE,EAAA,EAAA,KAAC,EAAD,CAAY,UAAU,+BAAiC,CAAA,WACvD,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,qDAAhB,CAA4D,IAAE,EAAO,MAAM,OAAO,IAAQ,GAChF,GACD,CAAA,EACb,EAAA,EAAA,KAAC,EAAD,CAAA,SACG,EAAO,MAAM,SAAW,GACvB,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,yCAAgC,kFAAqF,CAAA,EAEpI,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,uBACZ,EAAO,MAAM,IAAK,IACjB,EAAA,EAAA,MAAC,MAAD,CAAyB,UAAU,qFAAnC,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,0DAA0D,MAAO,EAAK,kBAAW,EAAK,SAAgB,CAAA,EACtH,EAAA,EAAA,KAAC,EAAD,CAAY,MAAO,EAAK,SAAU,MAAM,iBAAiB,KAAK,OAAO,UAAU,UAAU,cAAc,UAAY,CAAA,CAC/G,EAHI,EAAK,SAGT,CACN,CACE,CAAA,CAEI,CAAA,CACT,CAAA,CAAA,CAGN,EAAS,OAAS,IACjB,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,MAAC,EAAD,CAAW,UAAU,6CAArB,EACE,EAAA,EAAA,KAAC,EAAD,CAAU,UAAU,uBAAyB,CAAA,wBAC7C,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,qDAAhB,CAA4D,IAAE,EAAS,OAAO,IAAQ,GAC5E,GACD,CAAA,EACb,EAAA,EAAA,KAAC,EAAD,CAAa,UAAU,qBACpB,EAAS,IAAK,IACb,EAAA,EAAA,KAAC,EAAD,CAAgC,QAAO,UAAW,EAAM,UAAY,EAAS,IAAI,EAAM,UAAU,CAAG,IAAA,GAAgB,MAAO,CAA5G,EAAM,GAAsG,CAC3H,CACU,CAAA,CACT,CAAA,CAAA,CAIR,GAAiB,EAAQ,SAAW,GACnC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,0DAAiD,mBAAsB,CAAA,CACpF,EAAQ,SAAW,GACrB,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,KAAC,EAAD,CAAa,UAAU,0DAAiD,yGAE1D,CAAA,CACT,CAAA,CAEP,EAAW,OAAQ,GAAS,EAAO,IAAI,EAAK,CAAC,CAAC,IAAK,GAAS,CAC1D,IAAM,EAAO,EAAO,IAAI,EAAK,CAC7B,OACE,EAAA,EAAA,MAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAC,EAAD,CAAA,UACE,EAAA,EAAA,MAAC,EAAD,CAAW,UAAU,6CAArB,CACG,EAAY,IACb,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,qDAAhB,CAA4D,IAAE,EAAK,OAAO,IAAQ,GACxE,GACD,CAAA,EACb,EAAA,EAAA,KAAC,EAAD,CAAa,UAAU,qBACpB,EAAK,IAAK,IACT,EAAA,EAAA,KAAC,EAAD,CAAgC,QAAO,UAAW,EAAM,UAAY,EAAS,IAAI,EAAM,UAAU,CAAG,IAAA,GAAgB,MAAO,CAA5G,EAAM,GAAsG,CAC3H,CACU,CAAA,CACT,CAAA,CAZI,EAYJ,EAET,CAEH,CAAA,CAAA,CAED"}
@@ -1,3 +1,3 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Gn as t,R as n,S as r,Wn as i,h as a,j as o,k as s,rr as c,vt as l}from"./lucide-react-CsPXvXMC.js";import{t as u}from"./badge-CK6ejiOh.js";import{t as d}from"./button-BAwKuRIq.js";import{t as f}from"./input-CLW2gDUM.js";import{t as p}from"./copy-button-D3B_s7J7.js";import{r as m}from"./index-TZskQfQL.js";import{a as h,o as g,r as _,t as v}from"./card-DDxxo-Fo.js";var y=e(c(),1),b=i(),x=[`admin:*`,`token:read`,`token:write`,`agent:read`,`agent:write`,`message:read`,`message:send`,`task:read`,`task:write`,`command:read`,`command:write`,`memory:read`,`memory:write`,`memory:admin`,`mcp:use`,`terminal:attach`,`logs:read`,`integration:read`,`integration:write`,`channel:read`,`channel:write`,`stats:read`,`health:read`,`events:read`],S={agents:``,policies:``,targets:``,channels:``,orchestrators:``,cwdPrefixes:``,memoryScopes:``,spawnRequestIds:``,terminalAttach:!1,logsRead:!1},C={id:``,name:``,description:``,role:`provider`,scope:[`agent:read`,`message:read`,`message:send`],ttlSeconds:`86400`,constraints:{...S}};function w(){let[e,i]=(0,y.useState)([]),[c,w]=(0,y.useState)([]),[k,j]=(0,y.useState)(``),[M,F]=(0,y.useState)(C),[I,L]=(0,y.useState)(``),[R,z]=(0,y.useState)(``),[B,V]=(0,y.useState)({...S}),[H,U]=(0,y.useState)(``),[W,G]=(0,y.useState)(``),[K,q]=(0,y.useState)(`profiles`),J=(0,y.useMemo)(()=>e.find(e=>e.id===k),[e,k]);(0,y.useEffect)(()=>{Y()},[]);async function Y(){let[e,n]=await Promise.all([t(`GET`,`/token-profiles`),t(`GET`,`/tokens`)]);i(e),w(n),!k&&e[0]&&(j(e[0].id),F(D(e[0])),L(e[0].id))}function X(e){j(e.id),F(D(e)),U(``)}function Z(){j(``),F({...C,constraints:{...S}}),G(``)}async function Q(){let e=O(M),n=k?await t(`PATCH`,`/token-profiles/${encodeURIComponent(k)}`,e):await t(`POST`,`/token-profiles`,e);await Y(),j(n.id),F(D(n)),L(n.id),G(`${n.name} saved`)}async function $(e){await t(`DELETE`,`/token-profiles/${encodeURIComponent(e.id)}`),Z(),await Y()}async function ee(){let n=e.find(e=>e.id===I);U((await t(`POST`,`/tokens`,{profileId:I,sub:R||n?.role||`component`,constraints:A(B),createdBy:`dashboard`})).token),z(``),V({...S}),await Y()}async function te(e){await t(`POST`,`/tokens/${encodeURIComponent(e.jti)}/revoke`),await Y()}return(0,b.jsxs)(`div`,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Security`}),(0,b.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Token profiles and scoped component tokens`})]}),(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(`div`,{className:`inline-flex rounded-md border border-border overflow-hidden`,children:[(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`profiles`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm transition-colors ${K===`profiles`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(r,{className:`h-3.5 w-3.5`}),`Profiles`]}),(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`tokens`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm border-l border-border transition-colors ${K===`tokens`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(l,{className:`h-3.5 w-3.5`}),`Tokens`]})]}),(0,b.jsxs)(d,{variant:`outline`,onClick:()=>void Y(),children:[(0,b.jsx)(o,{className:`h-4 w-4`}),`Refresh`]}),K===`profiles`&&(0,b.jsxs)(d,{onClick:Z,children:[(0,b.jsx)(n,{className:`h-4 w-4`}),`New profile`]})]})]}),K===`profiles`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[340px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(r,{className:`h-4 w-4`}),`Profiles`]})}),(0,b.jsx)(_,{className:`space-y-2`,children:e.map(e=>(0,b.jsxs)(`button`,{type:`button`,onClick:()=>X(e),className:`w-full rounded-md border px-3 py-2 text-left transition-colors ${e.id===k?`border-primary bg-primary/10`:`border-border hover:bg-accent`}`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-sm font-medium`,children:e.name}),e.builtIn&&(0,b.jsx)(u,{variant:`secondary`,className:`text-[10px]`,children:`built-in`})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,b.jsx)(`span`,{children:e.role}),(0,b.jsxs)(`span`,{children:[e.scope.length,` scopes`]}),e.ttlSeconds&&(0,b.jsx)(`span`,{children:P(e.ttlSeconds)})]})]},e.id))})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:J?J.name:`New profile`})}),(0,b.jsxs)(_,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[(0,b.jsx)(T,{label:`Profile id`,children:(0,b.jsx)(f,{disabled:!!k,value:M.id,onChange:e=>F({...M,id:e.target.value})})}),(0,b.jsx)(T,{label:`Name`,children:(0,b.jsx)(f,{value:M.name,onChange:e=>F({...M,name:e.target.value})})}),(0,b.jsx)(T,{label:`Role`,children:(0,b.jsx)(f,{value:M.role,onChange:e=>F({...M,role:e.target.value})})}),(0,b.jsx)(T,{label:`TTL seconds`,children:(0,b.jsx)(f,{inputMode:`numeric`,value:M.ttlSeconds,onChange:e=>F({...M,ttlSeconds:e.target.value})})})]}),(0,b.jsx)(T,{label:`Description`,children:(0,b.jsx)(m,{rows:2,value:M.description,onChange:e=>F({...M,description:e.target.value})})}),(0,b.jsxs)(`div`,{className:`space-y-2`,children:[(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Scopes`}),(0,b.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:x.map(e=>(0,b.jsx)(`button`,{type:`button`,onClick:()=>F({...M,scope:N(M.scope,e)}),className:`rounded border px-2 py-1 text-xs ${M.scope.includes(e)?`border-primary/50 bg-primary/15 text-primary`:`border-border text-muted-foreground hover:bg-accent`}`,children:e},e))})]}),(0,b.jsx)(E,{value:M.constraints,onChange:e=>F({...M,constraints:e})}),(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,b.jsxs)(d,{disabled:J?.builtIn,onClick:()=>void Q(),children:[(0,b.jsx)(s,{className:`h-4 w-4`}),`Save`]}),J&&!J.builtIn&&(0,b.jsxs)(d,{variant:`destructive`,onClick:()=>void $(J),children:[(0,b.jsx)(a,{className:`h-4 w-4`}),`Delete`]}),J?.builtIn&&(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Built-in profiles are managed by Relay.`})]})]})]})]}),K===`tokens`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[380px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue token`]})}),(0,b.jsxs)(_,{className:`space-y-3`,children:[(0,b.jsx)(T,{label:`Profile`,children:(0,b.jsx)(`select`,{className:`h-9 w-full rounded-md border border-input bg-background px-3 text-sm`,value:I,onChange:e=>L(e.target.value),children:e.map(e=>(0,b.jsx)(`option`,{value:e.id,children:e.name},e.id))})}),(0,b.jsx)(T,{label:`Subject`,children:(0,b.jsx)(f,{value:R,onChange:e=>z(e.target.value),placeholder:`component id`})}),(0,b.jsx)(E,{compact:!0,value:B,onChange:V}),(0,b.jsxs)(d,{className:`w-full`,disabled:!I,onClick:()=>void ee(),children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue`]}),H&&(0,b.jsxs)(`div`,{className:`rounded-md border border-border bg-muted/30 p-2`,children:[(0,b.jsxs)(`div`,{className:`mb-1 flex items-center justify-between gap-2`,children:[(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`New token`}),(0,b.jsx)(p,{value:H,label:`Copy token`,size:`sm`,variant:`ghost`,onCopied:()=>G(`Copied`)})]}),(0,b.jsx)(`code`,{className:`block max-h-24 overflow-auto break-all text-xs`,children:H})]}),W&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:W})]})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:`Issued tokens`})}),(0,b.jsxs)(_,{className:`space-y-2`,children:[c.length===0&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`No tokens issued yet`}),c.slice(0,20).map(e=>(0,b.jsxs)(`div`,{className:`rounded-md border border-border p-2`,children:[(0,b.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.sub}),(0,b.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[e.role,` `,e.profileId?`· ${e.profileId}`:``]})]}),e.revokedAt?(0,b.jsx)(u,{variant:`destructive`,children:`revoked`}):(0,b.jsx)(d,{variant:`ghost`,size:`sm`,onClick:()=>void te(e),children:(0,b.jsx)(a,{className:`h-3.5 w-3.5`})})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex flex-wrap gap-1`,children:[e.scope.slice(0,4).map(e=>(0,b.jsx)(u,{variant:`outline`,className:`text-[10px]`,children:e},e)),e.scope.length>4&&(0,b.jsxs)(u,{variant:`secondary`,className:`text-[10px]`,children:[`+`,e.scope.length-4]})]})]},e.jti))]})]})]})]})}function T({label:e,children:t}){return(0,b.jsxs)(`label`,{className:`block space-y-1.5 text-sm`,children:[(0,b.jsx)(`span`,{className:`text-muted-foreground`,children:e}),t]})}function E({value:e,onChange:t,compact:n=!1}){return(0,b.jsxs)(`div`,{className:`space-y-3`,children:[!n&&(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Constraints`}),(0,b.jsx)(`div`,{className:`grid gap-3 ${n?``:`md:grid-cols-2`}`,children:[[`agents`,`Agents`],[`policies`,`Policies`],[`targets`,`Targets`],[`channels`,`Channels`],[`orchestrators`,`Orchestrators`],[`cwdPrefixes`,`CWD prefixes`],[`memoryScopes`,`Memory scopes`],[`spawnRequestIds`,`Spawn requests`]].map(([r,i])=>(0,b.jsx)(T,{label:i,children:(0,b.jsx)(m,{rows:n?2:3,value:String(e[r]||``),onChange:n=>t({...e,[r]:n.target.value}),placeholder:`one per line`})},r))}),(0,b.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.terminalAttach,onChange:n=>t({...e,terminalAttach:n.target.checked})}),`Terminal attach`]}),(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.logsRead,onChange:n=>t({...e,logsRead:n.target.checked})}),`Log read`]})]})]})}function D(e){return{id:e.id,name:e.name,description:e.description||``,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?String(e.ttlSeconds):``,constraints:k(e.constraints)}}function O(e){return{id:e.id||void 0,name:e.name,description:e.description||void 0,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?Number(e.ttlSeconds):void 0,constraints:A(e.constraints)}}function k(e){return{agents:M(e?.agents),policies:M(e?.policies),targets:M(e?.targets),channels:M(e?.channels),orchestrators:M(e?.orchestrators),cwdPrefixes:M(e?.cwdPrefixes),memoryScopes:M(e?.memoryScopes),spawnRequestIds:M(e?.spawnRequestIds),terminalAttach:e?.terminalAttach===!0,logsRead:e?.logsRead===!0}}function A(e){let t={};for(let n of[`agents`,`policies`,`targets`,`channels`,`orchestrators`,`cwdPrefixes`,`memoryScopes`,`spawnRequestIds`]){let r=j(String(e[n]||``));r.length&&Object.assign(t,{[n]:r})}return e.terminalAttach&&(t.terminalAttach=!0),e.logsRead&&(t.logsRead=!0),Object.keys(t).length?t:void 0}function j(e){return e.split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)}function M(e){return(e??[]).join(`
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{Gn as t,R as n,S as r,Wn as i,h as a,j as o,k as s,rr as c,vt as l}from"./lucide-react-CsPXvXMC.js";import{t as u}from"./badge-CK6ejiOh.js";import{t as d}from"./button-BAwKuRIq.js";import{t as f}from"./input-CLW2gDUM.js";import{t as p}from"./copy-button-D3B_s7J7.js";import{r as m}from"./index-Bd1NBLyd.js";import{a as h,o as g,r as _,t as v}from"./card-DDxxo-Fo.js";var y=e(c(),1),b=i(),x=[`admin:*`,`token:read`,`token:write`,`agent:read`,`agent:write`,`message:read`,`message:send`,`task:read`,`task:write`,`command:read`,`command:write`,`memory:read`,`memory:write`,`memory:admin`,`mcp:use`,`terminal:attach`,`logs:read`,`integration:read`,`integration:write`,`channel:read`,`channel:write`,`stats:read`,`health:read`,`events:read`],S={agents:``,policies:``,targets:``,channels:``,orchestrators:``,cwdPrefixes:``,memoryScopes:``,spawnRequestIds:``,terminalAttach:!1,logsRead:!1},C={id:``,name:``,description:``,role:`provider`,scope:[`agent:read`,`message:read`,`message:send`],ttlSeconds:`86400`,constraints:{...S}};function w(){let[e,i]=(0,y.useState)([]),[c,w]=(0,y.useState)([]),[k,j]=(0,y.useState)(``),[M,F]=(0,y.useState)(C),[I,L]=(0,y.useState)(``),[R,z]=(0,y.useState)(``),[B,V]=(0,y.useState)({...S}),[H,U]=(0,y.useState)(``),[W,G]=(0,y.useState)(``),[K,q]=(0,y.useState)(`profiles`),J=(0,y.useMemo)(()=>e.find(e=>e.id===k),[e,k]);(0,y.useEffect)(()=>{Y()},[]);async function Y(){let[e,n]=await Promise.all([t(`GET`,`/token-profiles`),t(`GET`,`/tokens`)]);i(e),w(n),!k&&e[0]&&(j(e[0].id),F(D(e[0])),L(e[0].id))}function X(e){j(e.id),F(D(e)),U(``)}function Z(){j(``),F({...C,constraints:{...S}}),G(``)}async function Q(){let e=O(M),n=k?await t(`PATCH`,`/token-profiles/${encodeURIComponent(k)}`,e):await t(`POST`,`/token-profiles`,e);await Y(),j(n.id),F(D(n)),L(n.id),G(`${n.name} saved`)}async function $(e){await t(`DELETE`,`/token-profiles/${encodeURIComponent(e.id)}`),Z(),await Y()}async function ee(){let n=e.find(e=>e.id===I);U((await t(`POST`,`/tokens`,{profileId:I,sub:R||n?.role||`component`,constraints:A(B),createdBy:`dashboard`})).token),z(``),V({...S}),await Y()}async function te(e){await t(`POST`,`/tokens/${encodeURIComponent(e.jti)}/revoke`),await Y()}return(0,b.jsxs)(`div`,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(`h1`,{className:`text-lg font-semibold`,children:`Security`}),(0,b.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Token profiles and scoped component tokens`})]}),(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsxs)(`div`,{className:`inline-flex rounded-md border border-border overflow-hidden`,children:[(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`profiles`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm transition-colors ${K===`profiles`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(r,{className:`h-3.5 w-3.5`}),`Profiles`]}),(0,b.jsxs)(`button`,{type:`button`,onClick:()=>q(`tokens`),className:`flex items-center gap-1.5 px-3 py-1.5 text-sm border-l border-border transition-colors ${K===`tokens`?`bg-primary/15 text-primary`:`text-muted-foreground hover:bg-accent`}`,children:[(0,b.jsx)(l,{className:`h-3.5 w-3.5`}),`Tokens`]})]}),(0,b.jsxs)(d,{variant:`outline`,onClick:()=>void Y(),children:[(0,b.jsx)(o,{className:`h-4 w-4`}),`Refresh`]}),K===`profiles`&&(0,b.jsxs)(d,{onClick:Z,children:[(0,b.jsx)(n,{className:`h-4 w-4`}),`New profile`]})]})]}),K===`profiles`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[340px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(r,{className:`h-4 w-4`}),`Profiles`]})}),(0,b.jsx)(_,{className:`space-y-2`,children:e.map(e=>(0,b.jsxs)(`button`,{type:`button`,onClick:()=>X(e),className:`w-full rounded-md border px-3 py-2 text-left transition-colors ${e.id===k?`border-primary bg-primary/10`:`border-border hover:bg-accent`}`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-sm font-medium`,children:e.name}),e.builtIn&&(0,b.jsx)(u,{variant:`secondary`,className:`text-[10px]`,children:`built-in`})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,b.jsx)(`span`,{children:e.role}),(0,b.jsxs)(`span`,{children:[e.scope.length,` scopes`]}),e.ttlSeconds&&(0,b.jsx)(`span`,{children:P(e.ttlSeconds)})]})]},e.id))})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:J?J.name:`New profile`})}),(0,b.jsxs)(_,{className:`space-y-4`,children:[(0,b.jsxs)(`div`,{className:`grid gap-3 md:grid-cols-2`,children:[(0,b.jsx)(T,{label:`Profile id`,children:(0,b.jsx)(f,{disabled:!!k,value:M.id,onChange:e=>F({...M,id:e.target.value})})}),(0,b.jsx)(T,{label:`Name`,children:(0,b.jsx)(f,{value:M.name,onChange:e=>F({...M,name:e.target.value})})}),(0,b.jsx)(T,{label:`Role`,children:(0,b.jsx)(f,{value:M.role,onChange:e=>F({...M,role:e.target.value})})}),(0,b.jsx)(T,{label:`TTL seconds`,children:(0,b.jsx)(f,{inputMode:`numeric`,value:M.ttlSeconds,onChange:e=>F({...M,ttlSeconds:e.target.value})})})]}),(0,b.jsx)(T,{label:`Description`,children:(0,b.jsx)(m,{rows:2,value:M.description,onChange:e=>F({...M,description:e.target.value})})}),(0,b.jsxs)(`div`,{className:`space-y-2`,children:[(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Scopes`}),(0,b.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:x.map(e=>(0,b.jsx)(`button`,{type:`button`,onClick:()=>F({...M,scope:N(M.scope,e)}),className:`rounded border px-2 py-1 text-xs ${M.scope.includes(e)?`border-primary/50 bg-primary/15 text-primary`:`border-border text-muted-foreground hover:bg-accent`}`,children:e},e))})]}),(0,b.jsx)(E,{value:M.constraints,onChange:e=>F({...M,constraints:e})}),(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,b.jsxs)(d,{disabled:J?.builtIn,onClick:()=>void Q(),children:[(0,b.jsx)(s,{className:`h-4 w-4`}),`Save`]}),J&&!J.builtIn&&(0,b.jsxs)(d,{variant:`destructive`,onClick:()=>void $(J),children:[(0,b.jsx)(a,{className:`h-4 w-4`}),`Delete`]}),J?.builtIn&&(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Built-in profiles are managed by Relay.`})]})]})]})]}),K===`tokens`&&(0,b.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[380px_minmax(0,1fr)]`,children:[(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsxs)(g,{className:`flex items-center gap-2 text-sm`,children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue token`]})}),(0,b.jsxs)(_,{className:`space-y-3`,children:[(0,b.jsx)(T,{label:`Profile`,children:(0,b.jsx)(`select`,{className:`h-9 w-full rounded-md border border-input bg-background px-3 text-sm`,value:I,onChange:e=>L(e.target.value),children:e.map(e=>(0,b.jsx)(`option`,{value:e.id,children:e.name},e.id))})}),(0,b.jsx)(T,{label:`Subject`,children:(0,b.jsx)(f,{value:R,onChange:e=>z(e.target.value),placeholder:`component id`})}),(0,b.jsx)(E,{compact:!0,value:B,onChange:V}),(0,b.jsxs)(d,{className:`w-full`,disabled:!I,onClick:()=>void ee(),children:[(0,b.jsx)(l,{className:`h-4 w-4`}),`Issue`]}),H&&(0,b.jsxs)(`div`,{className:`rounded-md border border-border bg-muted/30 p-2`,children:[(0,b.jsxs)(`div`,{className:`mb-1 flex items-center justify-between gap-2`,children:[(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`New token`}),(0,b.jsx)(p,{value:H,label:`Copy token`,size:`sm`,variant:`ghost`,onCopied:()=>G(`Copied`)})]}),(0,b.jsx)(`code`,{className:`block max-h-24 overflow-auto break-all text-xs`,children:H})]}),W&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:W})]})]}),(0,b.jsxs)(v,{children:[(0,b.jsx)(h,{children:(0,b.jsx)(g,{className:`text-sm`,children:`Issued tokens`})}),(0,b.jsxs)(_,{className:`space-y-2`,children:[c.length===0&&(0,b.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`No tokens issued yet`}),c.slice(0,20).map(e=>(0,b.jsxs)(`div`,{className:`rounded-md border border-border p-2`,children:[(0,b.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`truncate text-sm font-medium`,children:e.sub}),(0,b.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[e.role,` `,e.profileId?`· ${e.profileId}`:``]})]}),e.revokedAt?(0,b.jsx)(u,{variant:`destructive`,children:`revoked`}):(0,b.jsx)(d,{variant:`ghost`,size:`sm`,onClick:()=>void te(e),children:(0,b.jsx)(a,{className:`h-3.5 w-3.5`})})]}),(0,b.jsxs)(`div`,{className:`mt-1 flex flex-wrap gap-1`,children:[e.scope.slice(0,4).map(e=>(0,b.jsx)(u,{variant:`outline`,className:`text-[10px]`,children:e},e)),e.scope.length>4&&(0,b.jsxs)(u,{variant:`secondary`,className:`text-[10px]`,children:[`+`,e.scope.length-4]})]})]},e.jti))]})]})]})]})}function T({label:e,children:t}){return(0,b.jsxs)(`label`,{className:`block space-y-1.5 text-sm`,children:[(0,b.jsx)(`span`,{className:`text-muted-foreground`,children:e}),t]})}function E({value:e,onChange:t,compact:n=!1}){return(0,b.jsxs)(`div`,{className:`space-y-3`,children:[!n&&(0,b.jsx)(`div`,{className:`text-sm text-muted-foreground`,children:`Constraints`}),(0,b.jsx)(`div`,{className:`grid gap-3 ${n?``:`md:grid-cols-2`}`,children:[[`agents`,`Agents`],[`policies`,`Policies`],[`targets`,`Targets`],[`channels`,`Channels`],[`orchestrators`,`Orchestrators`],[`cwdPrefixes`,`CWD prefixes`],[`memoryScopes`,`Memory scopes`],[`spawnRequestIds`,`Spawn requests`]].map(([r,i])=>(0,b.jsx)(T,{label:i,children:(0,b.jsx)(m,{rows:n?2:3,value:String(e[r]||``),onChange:n=>t({...e,[r]:n.target.value}),placeholder:`one per line`})},r))}),(0,b.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.terminalAttach,onChange:n=>t({...e,terminalAttach:n.target.checked})}),`Terminal attach`]}),(0,b.jsxs)(`label`,{className:`flex items-center gap-2 rounded border border-border px-2 py-1 text-xs`,children:[(0,b.jsx)(`input`,{type:`checkbox`,checked:e.logsRead,onChange:n=>t({...e,logsRead:n.target.checked})}),`Log read`]})]})]})}function D(e){return{id:e.id,name:e.name,description:e.description||``,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?String(e.ttlSeconds):``,constraints:k(e.constraints)}}function O(e){return{id:e.id||void 0,name:e.name,description:e.description||void 0,role:e.role,scope:e.scope,ttlSeconds:e.ttlSeconds?Number(e.ttlSeconds):void 0,constraints:A(e.constraints)}}function k(e){return{agents:M(e?.agents),policies:M(e?.policies),targets:M(e?.targets),channels:M(e?.channels),orchestrators:M(e?.orchestrators),cwdPrefixes:M(e?.cwdPrefixes),memoryScopes:M(e?.memoryScopes),spawnRequestIds:M(e?.spawnRequestIds),terminalAttach:e?.terminalAttach===!0,logsRead:e?.logsRead===!0}}function A(e){let t={};for(let n of[`agents`,`policies`,`targets`,`channels`,`orchestrators`,`cwdPrefixes`,`memoryScopes`,`spawnRequestIds`]){let r=j(String(e[n]||``));r.length&&Object.assign(t,{[n]:r})}return e.terminalAttach&&(t.terminalAttach=!0),e.logsRead&&(t.logsRead=!0),Object.keys(t).length?t:void 0}function j(e){return e.split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)}function M(e){return(e??[]).join(`
2
2
  `)}function N(e,t){return e.includes(t)?e.filter(e=>e!==t):[...e,t]}function P(e){return e%86400==0?`${e/86400}d`:e%3600==0?`${e/3600}h`:`${e}s`}export{w as SecurityView};
3
- //# sourceMappingURL=security-vDglScsg.js.map
3
+ //# sourceMappingURL=security-wTBapq4K.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"security-vDglScsg.js","names":[],"sources":["../../dashboard/src/components/views/security.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react'\nimport { api } from '@/lib/api'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { KeyRound, Plus, Save, Shield, Trash2, RotateCcw } from 'lucide-react'\nimport { CopyButton } from '@/components/shared/copy-button'\nimport type { TokenConstraints, TokenProfile, TokenRecord } from '@/types'\n\nconst scopeOptions = [\n 'admin:*',\n 'token:read',\n 'token:write',\n 'agent:read',\n 'agent:write',\n 'message:read',\n 'message:send',\n 'task:read',\n 'task:write',\n 'command:read',\n 'command:write',\n 'memory:read',\n 'memory:write',\n 'memory:admin',\n 'mcp:use',\n 'terminal:attach',\n 'logs:read',\n 'integration:read',\n 'integration:write',\n 'channel:read',\n 'channel:write',\n 'stats:read',\n 'health:read',\n 'events:read',\n]\n\ninterface ProfileForm {\n id: string\n name: string\n description: string\n role: string\n scope: string[]\n ttlSeconds: string\n constraints: ConstraintForm\n}\n\ninterface ConstraintForm {\n agents: string\n policies: string\n targets: string\n channels: string\n orchestrators: string\n cwdPrefixes: string\n memoryScopes: string\n spawnRequestIds: string\n terminalAttach: boolean\n logsRead: boolean\n}\n\nconst emptyConstraints: ConstraintForm = {\n agents: '',\n policies: '',\n targets: '',\n channels: '',\n orchestrators: '',\n cwdPrefixes: '',\n memoryScopes: '',\n spawnRequestIds: '',\n terminalAttach: false,\n logsRead: false,\n}\n\nconst emptyProfile: ProfileForm = {\n id: '',\n name: '',\n description: '',\n role: 'provider',\n scope: ['agent:read', 'message:read', 'message:send'],\n ttlSeconds: '86400',\n constraints: { ...emptyConstraints },\n}\n\nexport function SecurityView() {\n const [profiles, setProfiles] = useState<TokenProfile[]>([])\n const [tokens, setTokens] = useState<TokenRecord[]>([])\n const [selectedId, setSelectedId] = useState('')\n const [form, setForm] = useState<ProfileForm>(emptyProfile)\n const [issueProfileId, setIssueProfileId] = useState('')\n const [issueSub, setIssueSub] = useState('')\n const [issueConstraints, setIssueConstraints] = useState<ConstraintForm>({ ...emptyConstraints })\n const [issuedToken, setIssuedToken] = useState('')\n const [status, setStatus] = useState('')\n const [tab, setTab] = useState<'profiles' | 'tokens'>('profiles')\n\n const selected = useMemo(() => profiles.find((profile) => profile.id === selectedId), [profiles, selectedId])\n\n useEffect(() => { void refresh() }, [])\n\n async function refresh() {\n const [nextProfiles, nextTokens] = await Promise.all([\n api<TokenProfile[]>('GET', '/token-profiles'),\n api<TokenRecord[]>('GET', '/tokens'),\n ])\n setProfiles(nextProfiles)\n setTokens(nextTokens)\n if (!selectedId && nextProfiles[0]) {\n setSelectedId(nextProfiles[0].id)\n setForm(profileToForm(nextProfiles[0]))\n setIssueProfileId(nextProfiles[0].id)\n }\n }\n\n function selectProfile(profile: TokenProfile) {\n setSelectedId(profile.id)\n setForm(profileToForm(profile))\n setIssuedToken('')\n }\n\n function newProfile() {\n setSelectedId('')\n setForm({ ...emptyProfile, constraints: { ...emptyConstraints } })\n setStatus('')\n }\n\n async function saveProfile() {\n const body = formToProfileBody(form)\n const saved = selectedId\n ? await api<TokenProfile>('PATCH', `/token-profiles/${encodeURIComponent(selectedId)}`, body)\n : await api<TokenProfile>('POST', '/token-profiles', body)\n await refresh()\n setSelectedId(saved.id)\n setForm(profileToForm(saved))\n setIssueProfileId(saved.id)\n setStatus(`${saved.name} saved`)\n }\n\n async function deleteProfile(profile: TokenProfile) {\n await api('DELETE', `/token-profiles/${encodeURIComponent(profile.id)}`)\n newProfile()\n await refresh()\n }\n\n async function issueToken() {\n const profile = profiles.find((item) => item.id === issueProfileId)\n const result = await api<{ token: string; record: TokenRecord }>('POST', '/tokens', {\n profileId: issueProfileId,\n sub: issueSub || profile?.role || 'component',\n constraints: constraintsFromForm(issueConstraints),\n createdBy: 'dashboard',\n })\n setIssuedToken(result.token)\n setIssueSub('')\n setIssueConstraints({ ...emptyConstraints })\n await refresh()\n }\n\n async function revokeToken(token: TokenRecord) {\n await api('POST', `/tokens/${encodeURIComponent(token.jti)}/revoke`)\n await refresh()\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-lg font-semibold\">Security</h1>\n <p className=\"text-sm text-muted-foreground\">Token profiles and scoped component tokens</p>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"inline-flex rounded-md border border-border overflow-hidden\">\n <button type=\"button\" onClick={() => setTab('profiles')} className={`flex items-center gap-1.5 px-3 py-1.5 text-sm transition-colors ${tab === 'profiles' ? 'bg-primary/15 text-primary' : 'text-muted-foreground hover:bg-accent'}`}>\n <Shield className=\"h-3.5 w-3.5\" />Profiles\n </button>\n <button type=\"button\" onClick={() => setTab('tokens')} className={`flex items-center gap-1.5 px-3 py-1.5 text-sm border-l border-border transition-colors ${tab === 'tokens' ? 'bg-primary/15 text-primary' : 'text-muted-foreground hover:bg-accent'}`}>\n <KeyRound className=\"h-3.5 w-3.5\" />Tokens\n </button>\n </div>\n <Button variant=\"outline\" onClick={() => void refresh()}><RotateCcw className=\"h-4 w-4\" />Refresh</Button>\n {tab === 'profiles' && <Button onClick={newProfile}><Plus className=\"h-4 w-4\" />New profile</Button>}\n </div>\n </div>\n\n {tab === 'profiles' && (\n <div className=\"grid gap-4 xl:grid-cols-[340px_minmax(0,1fr)]\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\"><Shield className=\"h-4 w-4\" />Profiles</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {profiles.map((profile) => (\n <button\n key={profile.id}\n type=\"button\"\n onClick={() => selectProfile(profile)}\n className={`w-full rounded-md border px-3 py-2 text-left transition-colors ${profile.id === selectedId ? 'border-primary bg-primary/10' : 'border-border hover:bg-accent'}`}\n >\n <div className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">{profile.name}</span>\n {profile.builtIn && <Badge variant=\"secondary\" className=\"text-[10px]\">built-in</Badge>}\n </div>\n <div className=\"mt-1 flex items-center gap-2 text-xs text-muted-foreground\">\n <span>{profile.role}</span>\n <span>{profile.scope.length} scopes</span>\n {profile.ttlSeconds && <span>{formatTtl(profile.ttlSeconds)}</span>}\n </div>\n </button>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">{selected ? selected.name : 'New profile'}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Profile id\"><Input disabled={Boolean(selectedId)} value={form.id} onChange={(e) => setForm({ ...form, id: e.target.value })} /></Field>\n <Field label=\"Name\"><Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} /></Field>\n <Field label=\"Role\"><Input value={form.role} onChange={(e) => setForm({ ...form, role: e.target.value })} /></Field>\n <Field label=\"TTL seconds\"><Input inputMode=\"numeric\" value={form.ttlSeconds} onChange={(e) => setForm({ ...form, ttlSeconds: e.target.value })} /></Field>\n </div>\n <Field label=\"Description\"><Textarea rows={2} value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })} /></Field>\n\n <div className=\"space-y-2\">\n <div className=\"text-sm text-muted-foreground\">Scopes</div>\n <div className=\"flex flex-wrap gap-1.5\">\n {scopeOptions.map((scope) => {\n const active = form.scope.includes(scope)\n return (\n <button\n key={scope}\n type=\"button\"\n onClick={() => setForm({ ...form, scope: toggle(form.scope, scope) })}\n className={`rounded border px-2 py-1 text-xs ${active ? 'border-primary/50 bg-primary/15 text-primary' : 'border-border text-muted-foreground hover:bg-accent'}`}\n >\n {scope}\n </button>\n )\n })}\n </div>\n </div>\n\n <ConstraintEditor value={form.constraints} onChange={(constraints) => setForm({ ...form, constraints })} />\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button disabled={selected?.builtIn} onClick={() => void saveProfile()}><Save className=\"h-4 w-4\" />Save</Button>\n {selected && !selected.builtIn && (\n <Button variant=\"destructive\" onClick={() => void deleteProfile(selected)}><Trash2 className=\"h-4 w-4\" />Delete</Button>\n )}\n {selected?.builtIn && <span className=\"text-xs text-muted-foreground\">Built-in profiles are managed by Relay.</span>}\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {tab === 'tokens' && (\n <div className=\"grid gap-4 xl:grid-cols-[380px_minmax(0,1fr)]\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\"><KeyRound className=\"h-4 w-4\" />Issue token</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <Field label=\"Profile\">\n <select className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm\" value={issueProfileId} onChange={(e) => setIssueProfileId(e.target.value)}>\n {profiles.map((profile) => <option key={profile.id} value={profile.id}>{profile.name}</option>)}\n </select>\n </Field>\n <Field label=\"Subject\"><Input value={issueSub} onChange={(e) => setIssueSub(e.target.value)} placeholder=\"component id\" /></Field>\n <ConstraintEditor compact value={issueConstraints} onChange={setIssueConstraints} />\n <Button className=\"w-full\" disabled={!issueProfileId} onClick={() => void issueToken()}><KeyRound className=\"h-4 w-4\" />Issue</Button>\n {issuedToken && (\n <div className=\"rounded-md border border-border bg-muted/30 p-2\">\n <div className=\"mb-1 flex items-center justify-between gap-2\">\n <span className=\"text-xs text-muted-foreground\">New token</span>\n <CopyButton value={issuedToken} label=\"Copy token\" size=\"sm\" variant=\"ghost\" onCopied={() => setStatus('Copied')} />\n </div>\n <code className=\"block max-h-24 overflow-auto break-all text-xs\">{issuedToken}</code>\n </div>\n )}\n {status && <p className=\"text-xs text-muted-foreground\">{status}</p>}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Issued tokens</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {tokens.length === 0 && <p className=\"text-xs text-muted-foreground\">No tokens issued yet</p>}\n {tokens.slice(0, 20).map((token) => (\n <div key={token.jti} className=\"rounded-md border border-border p-2\">\n <div className=\"flex items-start gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium\">{token.sub}</div>\n <div className=\"text-xs text-muted-foreground\">{token.role} {token.profileId ? `· ${token.profileId}` : ''}</div>\n </div>\n {token.revokedAt ? <Badge variant=\"destructive\">revoked</Badge> : <Button variant=\"ghost\" size=\"sm\" onClick={() => void revokeToken(token)}><Trash2 className=\"h-3.5 w-3.5\" /></Button>}\n </div>\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {token.scope.slice(0, 4).map((scope) => <Badge key={scope} variant=\"outline\" className=\"text-[10px]\">{scope}</Badge>)}\n {token.scope.length > 4 && <Badge variant=\"secondary\" className=\"text-[10px]\">+{token.scope.length - 4}</Badge>}\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n )\n}\n\nfunction Field({ label, children }: { label: string; children: React.ReactNode }) {\n return <label className=\"block space-y-1.5 text-sm\"><span className=\"text-muted-foreground\">{label}</span>{children}</label>\n}\n\nfunction ConstraintEditor({ value, onChange, compact = false }: { value: ConstraintForm; onChange: (value: ConstraintForm) => void; compact?: boolean }) {\n const fields: Array<[keyof ConstraintForm, string]> = [\n ['agents', 'Agents'],\n ['policies', 'Policies'],\n ['targets', 'Targets'],\n ['channels', 'Channels'],\n ['orchestrators', 'Orchestrators'],\n ['cwdPrefixes', 'CWD prefixes'],\n ['memoryScopes', 'Memory scopes'],\n ['spawnRequestIds', 'Spawn requests'],\n ]\n return (\n <div className=\"space-y-3\">\n {!compact && <div className=\"text-sm text-muted-foreground\">Constraints</div>}\n <div className={`grid gap-3 ${compact ? '' : 'md:grid-cols-2'}`}>\n {fields.map(([key, label]) => (\n <Field key={key} label={label}>\n <Textarea\n rows={compact ? 2 : 3}\n value={String(value[key] || '')}\n onChange={(e) => onChange({ ...value, [key]: e.target.value })}\n placeholder=\"one per line\"\n />\n </Field>\n ))}\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <label className=\"flex items-center gap-2 rounded border border-border px-2 py-1 text-xs\">\n <input type=\"checkbox\" checked={value.terminalAttach} onChange={(e) => onChange({ ...value, terminalAttach: e.target.checked })} />\n Terminal attach\n </label>\n <label className=\"flex items-center gap-2 rounded border border-border px-2 py-1 text-xs\">\n <input type=\"checkbox\" checked={value.logsRead} onChange={(e) => onChange({ ...value, logsRead: e.target.checked })} />\n Log read\n </label>\n </div>\n </div>\n )\n}\n\nfunction profileToForm(profile: TokenProfile): ProfileForm {\n return {\n id: profile.id,\n name: profile.name,\n description: profile.description || '',\n role: profile.role,\n scope: profile.scope,\n ttlSeconds: profile.ttlSeconds ? String(profile.ttlSeconds) : '',\n constraints: formFromConstraints(profile.constraints),\n }\n}\n\nfunction formToProfileBody(form: ProfileForm) {\n return {\n id: form.id || undefined,\n name: form.name,\n description: form.description || undefined,\n role: form.role,\n scope: form.scope,\n ttlSeconds: form.ttlSeconds ? Number(form.ttlSeconds) : undefined,\n constraints: constraintsFromForm(form.constraints),\n }\n}\n\nfunction formFromConstraints(constraints: TokenConstraints | undefined): ConstraintForm {\n return {\n agents: linesText(constraints?.agents),\n policies: linesText(constraints?.policies),\n targets: linesText(constraints?.targets),\n channels: linesText(constraints?.channels),\n orchestrators: linesText(constraints?.orchestrators),\n cwdPrefixes: linesText(constraints?.cwdPrefixes),\n memoryScopes: linesText(constraints?.memoryScopes),\n spawnRequestIds: linesText(constraints?.spawnRequestIds),\n terminalAttach: constraints?.terminalAttach === true,\n logsRead: constraints?.logsRead === true,\n }\n}\n\nfunction constraintsFromForm(form: ConstraintForm): TokenConstraints | undefined {\n const constraints: TokenConstraints = {}\n const arrayFields: Array<keyof ConstraintForm> = ['agents', 'policies', 'targets', 'channels', 'orchestrators', 'cwdPrefixes', 'memoryScopes', 'spawnRequestIds']\n for (const field of arrayFields) {\n const values = lines(String(form[field] || ''))\n if (values.length) Object.assign(constraints, { [field]: values })\n }\n if (form.terminalAttach) constraints.terminalAttach = true\n if (form.logsRead) constraints.logsRead = true\n return Object.keys(constraints).length ? constraints : undefined\n}\n\nfunction lines(value: string): string[] {\n return value.split(/\\r?\\n|,/).map((line) => line.trim()).filter(Boolean)\n}\n\nfunction linesText(value: string[] | undefined): string {\n return (value ?? []).join('\\n')\n}\n\nfunction toggle(values: string[], item: string): string[] {\n return values.includes(item) ? values.filter((value) => value !== item) : [...values, item]\n}\n\nfunction formatTtl(seconds: number): string {\n if (seconds % 86400 === 0) return `${seconds / 86400}d`\n if (seconds % 3600 === 0) return `${seconds / 3600}h`\n return `${seconds}s`\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"security-wTBapq4K.js","names":[],"sources":["../../dashboard/src/components/views/security.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react'\nimport { api } from '@/lib/api'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { KeyRound, Plus, Save, Shield, Trash2, RotateCcw } from 'lucide-react'\nimport { CopyButton } from '@/components/shared/copy-button'\nimport type { TokenConstraints, TokenProfile, TokenRecord } from '@/types'\n\nconst scopeOptions = [\n 'admin:*',\n 'token:read',\n 'token:write',\n 'agent:read',\n 'agent:write',\n 'message:read',\n 'message:send',\n 'task:read',\n 'task:write',\n 'command:read',\n 'command:write',\n 'memory:read',\n 'memory:write',\n 'memory:admin',\n 'mcp:use',\n 'terminal:attach',\n 'logs:read',\n 'integration:read',\n 'integration:write',\n 'channel:read',\n 'channel:write',\n 'stats:read',\n 'health:read',\n 'events:read',\n]\n\ninterface ProfileForm {\n id: string\n name: string\n description: string\n role: string\n scope: string[]\n ttlSeconds: string\n constraints: ConstraintForm\n}\n\ninterface ConstraintForm {\n agents: string\n policies: string\n targets: string\n channels: string\n orchestrators: string\n cwdPrefixes: string\n memoryScopes: string\n spawnRequestIds: string\n terminalAttach: boolean\n logsRead: boolean\n}\n\nconst emptyConstraints: ConstraintForm = {\n agents: '',\n policies: '',\n targets: '',\n channels: '',\n orchestrators: '',\n cwdPrefixes: '',\n memoryScopes: '',\n spawnRequestIds: '',\n terminalAttach: false,\n logsRead: false,\n}\n\nconst emptyProfile: ProfileForm = {\n id: '',\n name: '',\n description: '',\n role: 'provider',\n scope: ['agent:read', 'message:read', 'message:send'],\n ttlSeconds: '86400',\n constraints: { ...emptyConstraints },\n}\n\nexport function SecurityView() {\n const [profiles, setProfiles] = useState<TokenProfile[]>([])\n const [tokens, setTokens] = useState<TokenRecord[]>([])\n const [selectedId, setSelectedId] = useState('')\n const [form, setForm] = useState<ProfileForm>(emptyProfile)\n const [issueProfileId, setIssueProfileId] = useState('')\n const [issueSub, setIssueSub] = useState('')\n const [issueConstraints, setIssueConstraints] = useState<ConstraintForm>({ ...emptyConstraints })\n const [issuedToken, setIssuedToken] = useState('')\n const [status, setStatus] = useState('')\n const [tab, setTab] = useState<'profiles' | 'tokens'>('profiles')\n\n const selected = useMemo(() => profiles.find((profile) => profile.id === selectedId), [profiles, selectedId])\n\n useEffect(() => { void refresh() }, [])\n\n async function refresh() {\n const [nextProfiles, nextTokens] = await Promise.all([\n api<TokenProfile[]>('GET', '/token-profiles'),\n api<TokenRecord[]>('GET', '/tokens'),\n ])\n setProfiles(nextProfiles)\n setTokens(nextTokens)\n if (!selectedId && nextProfiles[0]) {\n setSelectedId(nextProfiles[0].id)\n setForm(profileToForm(nextProfiles[0]))\n setIssueProfileId(nextProfiles[0].id)\n }\n }\n\n function selectProfile(profile: TokenProfile) {\n setSelectedId(profile.id)\n setForm(profileToForm(profile))\n setIssuedToken('')\n }\n\n function newProfile() {\n setSelectedId('')\n setForm({ ...emptyProfile, constraints: { ...emptyConstraints } })\n setStatus('')\n }\n\n async function saveProfile() {\n const body = formToProfileBody(form)\n const saved = selectedId\n ? await api<TokenProfile>('PATCH', `/token-profiles/${encodeURIComponent(selectedId)}`, body)\n : await api<TokenProfile>('POST', '/token-profiles', body)\n await refresh()\n setSelectedId(saved.id)\n setForm(profileToForm(saved))\n setIssueProfileId(saved.id)\n setStatus(`${saved.name} saved`)\n }\n\n async function deleteProfile(profile: TokenProfile) {\n await api('DELETE', `/token-profiles/${encodeURIComponent(profile.id)}`)\n newProfile()\n await refresh()\n }\n\n async function issueToken() {\n const profile = profiles.find((item) => item.id === issueProfileId)\n const result = await api<{ token: string; record: TokenRecord }>('POST', '/tokens', {\n profileId: issueProfileId,\n sub: issueSub || profile?.role || 'component',\n constraints: constraintsFromForm(issueConstraints),\n createdBy: 'dashboard',\n })\n setIssuedToken(result.token)\n setIssueSub('')\n setIssueConstraints({ ...emptyConstraints })\n await refresh()\n }\n\n async function revokeToken(token: TokenRecord) {\n await api('POST', `/tokens/${encodeURIComponent(token.jti)}/revoke`)\n await refresh()\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-lg font-semibold\">Security</h1>\n <p className=\"text-sm text-muted-foreground\">Token profiles and scoped component tokens</p>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"inline-flex rounded-md border border-border overflow-hidden\">\n <button type=\"button\" onClick={() => setTab('profiles')} className={`flex items-center gap-1.5 px-3 py-1.5 text-sm transition-colors ${tab === 'profiles' ? 'bg-primary/15 text-primary' : 'text-muted-foreground hover:bg-accent'}`}>\n <Shield className=\"h-3.5 w-3.5\" />Profiles\n </button>\n <button type=\"button\" onClick={() => setTab('tokens')} className={`flex items-center gap-1.5 px-3 py-1.5 text-sm border-l border-border transition-colors ${tab === 'tokens' ? 'bg-primary/15 text-primary' : 'text-muted-foreground hover:bg-accent'}`}>\n <KeyRound className=\"h-3.5 w-3.5\" />Tokens\n </button>\n </div>\n <Button variant=\"outline\" onClick={() => void refresh()}><RotateCcw className=\"h-4 w-4\" />Refresh</Button>\n {tab === 'profiles' && <Button onClick={newProfile}><Plus className=\"h-4 w-4\" />New profile</Button>}\n </div>\n </div>\n\n {tab === 'profiles' && (\n <div className=\"grid gap-4 xl:grid-cols-[340px_minmax(0,1fr)]\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\"><Shield className=\"h-4 w-4\" />Profiles</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {profiles.map((profile) => (\n <button\n key={profile.id}\n type=\"button\"\n onClick={() => selectProfile(profile)}\n className={`w-full rounded-md border px-3 py-2 text-left transition-colors ${profile.id === selectedId ? 'border-primary bg-primary/10' : 'border-border hover:bg-accent'}`}\n >\n <div className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">{profile.name}</span>\n {profile.builtIn && <Badge variant=\"secondary\" className=\"text-[10px]\">built-in</Badge>}\n </div>\n <div className=\"mt-1 flex items-center gap-2 text-xs text-muted-foreground\">\n <span>{profile.role}</span>\n <span>{profile.scope.length} scopes</span>\n {profile.ttlSeconds && <span>{formatTtl(profile.ttlSeconds)}</span>}\n </div>\n </button>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">{selected ? selected.name : 'New profile'}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Profile id\"><Input disabled={Boolean(selectedId)} value={form.id} onChange={(e) => setForm({ ...form, id: e.target.value })} /></Field>\n <Field label=\"Name\"><Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} /></Field>\n <Field label=\"Role\"><Input value={form.role} onChange={(e) => setForm({ ...form, role: e.target.value })} /></Field>\n <Field label=\"TTL seconds\"><Input inputMode=\"numeric\" value={form.ttlSeconds} onChange={(e) => setForm({ ...form, ttlSeconds: e.target.value })} /></Field>\n </div>\n <Field label=\"Description\"><Textarea rows={2} value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })} /></Field>\n\n <div className=\"space-y-2\">\n <div className=\"text-sm text-muted-foreground\">Scopes</div>\n <div className=\"flex flex-wrap gap-1.5\">\n {scopeOptions.map((scope) => {\n const active = form.scope.includes(scope)\n return (\n <button\n key={scope}\n type=\"button\"\n onClick={() => setForm({ ...form, scope: toggle(form.scope, scope) })}\n className={`rounded border px-2 py-1 text-xs ${active ? 'border-primary/50 bg-primary/15 text-primary' : 'border-border text-muted-foreground hover:bg-accent'}`}\n >\n {scope}\n </button>\n )\n })}\n </div>\n </div>\n\n <ConstraintEditor value={form.constraints} onChange={(constraints) => setForm({ ...form, constraints })} />\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button disabled={selected?.builtIn} onClick={() => void saveProfile()}><Save className=\"h-4 w-4\" />Save</Button>\n {selected && !selected.builtIn && (\n <Button variant=\"destructive\" onClick={() => void deleteProfile(selected)}><Trash2 className=\"h-4 w-4\" />Delete</Button>\n )}\n {selected?.builtIn && <span className=\"text-xs text-muted-foreground\">Built-in profiles are managed by Relay.</span>}\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {tab === 'tokens' && (\n <div className=\"grid gap-4 xl:grid-cols-[380px_minmax(0,1fr)]\">\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-sm\"><KeyRound className=\"h-4 w-4\" />Issue token</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <Field label=\"Profile\">\n <select className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm\" value={issueProfileId} onChange={(e) => setIssueProfileId(e.target.value)}>\n {profiles.map((profile) => <option key={profile.id} value={profile.id}>{profile.name}</option>)}\n </select>\n </Field>\n <Field label=\"Subject\"><Input value={issueSub} onChange={(e) => setIssueSub(e.target.value)} placeholder=\"component id\" /></Field>\n <ConstraintEditor compact value={issueConstraints} onChange={setIssueConstraints} />\n <Button className=\"w-full\" disabled={!issueProfileId} onClick={() => void issueToken()}><KeyRound className=\"h-4 w-4\" />Issue</Button>\n {issuedToken && (\n <div className=\"rounded-md border border-border bg-muted/30 p-2\">\n <div className=\"mb-1 flex items-center justify-between gap-2\">\n <span className=\"text-xs text-muted-foreground\">New token</span>\n <CopyButton value={issuedToken} label=\"Copy token\" size=\"sm\" variant=\"ghost\" onCopied={() => setStatus('Copied')} />\n </div>\n <code className=\"block max-h-24 overflow-auto break-all text-xs\">{issuedToken}</code>\n </div>\n )}\n {status && <p className=\"text-xs text-muted-foreground\">{status}</p>}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Issued tokens</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2\">\n {tokens.length === 0 && <p className=\"text-xs text-muted-foreground\">No tokens issued yet</p>}\n {tokens.slice(0, 20).map((token) => (\n <div key={token.jti} className=\"rounded-md border border-border p-2\">\n <div className=\"flex items-start gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium\">{token.sub}</div>\n <div className=\"text-xs text-muted-foreground\">{token.role} {token.profileId ? `· ${token.profileId}` : ''}</div>\n </div>\n {token.revokedAt ? <Badge variant=\"destructive\">revoked</Badge> : <Button variant=\"ghost\" size=\"sm\" onClick={() => void revokeToken(token)}><Trash2 className=\"h-3.5 w-3.5\" /></Button>}\n </div>\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {token.scope.slice(0, 4).map((scope) => <Badge key={scope} variant=\"outline\" className=\"text-[10px]\">{scope}</Badge>)}\n {token.scope.length > 4 && <Badge variant=\"secondary\" className=\"text-[10px]\">+{token.scope.length - 4}</Badge>}\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n )}\n </div>\n )\n}\n\nfunction Field({ label, children }: { label: string; children: React.ReactNode }) {\n return <label className=\"block space-y-1.5 text-sm\"><span className=\"text-muted-foreground\">{label}</span>{children}</label>\n}\n\nfunction ConstraintEditor({ value, onChange, compact = false }: { value: ConstraintForm; onChange: (value: ConstraintForm) => void; compact?: boolean }) {\n const fields: Array<[keyof ConstraintForm, string]> = [\n ['agents', 'Agents'],\n ['policies', 'Policies'],\n ['targets', 'Targets'],\n ['channels', 'Channels'],\n ['orchestrators', 'Orchestrators'],\n ['cwdPrefixes', 'CWD prefixes'],\n ['memoryScopes', 'Memory scopes'],\n ['spawnRequestIds', 'Spawn requests'],\n ]\n return (\n <div className=\"space-y-3\">\n {!compact && <div className=\"text-sm text-muted-foreground\">Constraints</div>}\n <div className={`grid gap-3 ${compact ? '' : 'md:grid-cols-2'}`}>\n {fields.map(([key, label]) => (\n <Field key={key} label={label}>\n <Textarea\n rows={compact ? 2 : 3}\n value={String(value[key] || '')}\n onChange={(e) => onChange({ ...value, [key]: e.target.value })}\n placeholder=\"one per line\"\n />\n </Field>\n ))}\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <label className=\"flex items-center gap-2 rounded border border-border px-2 py-1 text-xs\">\n <input type=\"checkbox\" checked={value.terminalAttach} onChange={(e) => onChange({ ...value, terminalAttach: e.target.checked })} />\n Terminal attach\n </label>\n <label className=\"flex items-center gap-2 rounded border border-border px-2 py-1 text-xs\">\n <input type=\"checkbox\" checked={value.logsRead} onChange={(e) => onChange({ ...value, logsRead: e.target.checked })} />\n Log read\n </label>\n </div>\n </div>\n )\n}\n\nfunction profileToForm(profile: TokenProfile): ProfileForm {\n return {\n id: profile.id,\n name: profile.name,\n description: profile.description || '',\n role: profile.role,\n scope: profile.scope,\n ttlSeconds: profile.ttlSeconds ? String(profile.ttlSeconds) : '',\n constraints: formFromConstraints(profile.constraints),\n }\n}\n\nfunction formToProfileBody(form: ProfileForm) {\n return {\n id: form.id || undefined,\n name: form.name,\n description: form.description || undefined,\n role: form.role,\n scope: form.scope,\n ttlSeconds: form.ttlSeconds ? Number(form.ttlSeconds) : undefined,\n constraints: constraintsFromForm(form.constraints),\n }\n}\n\nfunction formFromConstraints(constraints: TokenConstraints | undefined): ConstraintForm {\n return {\n agents: linesText(constraints?.agents),\n policies: linesText(constraints?.policies),\n targets: linesText(constraints?.targets),\n channels: linesText(constraints?.channels),\n orchestrators: linesText(constraints?.orchestrators),\n cwdPrefixes: linesText(constraints?.cwdPrefixes),\n memoryScopes: linesText(constraints?.memoryScopes),\n spawnRequestIds: linesText(constraints?.spawnRequestIds),\n terminalAttach: constraints?.terminalAttach === true,\n logsRead: constraints?.logsRead === true,\n }\n}\n\nfunction constraintsFromForm(form: ConstraintForm): TokenConstraints | undefined {\n const constraints: TokenConstraints = {}\n const arrayFields: Array<keyof ConstraintForm> = ['agents', 'policies', 'targets', 'channels', 'orchestrators', 'cwdPrefixes', 'memoryScopes', 'spawnRequestIds']\n for (const field of arrayFields) {\n const values = lines(String(form[field] || ''))\n if (values.length) Object.assign(constraints, { [field]: values })\n }\n if (form.terminalAttach) constraints.terminalAttach = true\n if (form.logsRead) constraints.logsRead = true\n return Object.keys(constraints).length ? constraints : undefined\n}\n\nfunction lines(value: string): string[] {\n return value.split(/\\r?\\n|,/).map((line) => line.trim()).filter(Boolean)\n}\n\nfunction linesText(value: string[] | undefined): string {\n return (value ?? []).join('\\n')\n}\n\nfunction toggle(values: string[], item: string): string[] {\n return values.includes(item) ? values.filter((value) => value !== item) : [...values, item]\n}\n\nfunction formatTtl(seconds: number): string {\n if (seconds % 86400 === 0) return `${seconds / 86400}d`\n if (seconds % 3600 === 0) return `${seconds / 3600}h`\n return `${seconds}s`\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Hn as t,Wn as n,dn as r,hn as i,mn as a,rr as o}from"./lucide-react-CsPXvXMC.js";import{t as s}from"./react-dom-CEl58oxP.js";import{o as c,r as l}from"./dist-CL2npVDe.js";import{t as u}from"./dist-CAFUEpK2.js";import{i as d,n as f,t as p}from"./dist-ERYvDMdt.js";import{t as m}from"./dist-DLsSqk6h.js";import{t as h}from"./dist-Dmiv1tSO.js";import{a as g,i as _,n as v,o as y,r as b,s as x,t as S}from"./es2015-Yto-4EBw.js";import{t as C}from"./dist-DyqEeyBI.js";import{t as w}from"./dist-CoRABSO3.js";import{t as T}from"./dist-CIbvPDQV.js";import{a as E,i as D,n as O,r as k,t as A}from"./dist-CnRv0y2x.js";import{t as j}from"./dist-D33pM1xy.js";import{q as M}from"./index-TZskQfQL.js";var N=e(o(),1),P=e(s(),1),F=n(),I=[` `,`Enter`,`ArrowUp`,`ArrowDown`],L=[` `,`Enter`],R=`Select`,[z,B,V]=m(R),[H,U]=d(R,[V,E]),W=E(),[G,K]=H(R),[ee,te]=H(R),q=e=>{let{__scopeSelect:t,children:n,open:r,defaultOpen:i,onOpenChange:a,value:o,defaultValue:s,onValueChange:c,dir:l,name:u,autoComplete:d,disabled:f,required:p,form:m}=e,g=W(t),[_,v]=N.useState(null),[y,b]=N.useState(null),[S,w]=N.useState(!1),T=C(l),[E,O]=h({prop:r,defaultProp:i??!1,onChange:a,caller:R}),[k,A]=h({prop:o,defaultProp:s,onChange:c,caller:R}),j=N.useRef(null),M=_?m||!!_.closest(`form`):!0,[P,I]=N.useState(new Set),L=Array.from(P).map(e=>e.props.value).join(`;`);return(0,F.jsx)(D,{...g,children:(0,F.jsxs)(G,{required:p,scope:t,trigger:_,onTriggerChange:v,valueNode:y,onValueNodeChange:b,valueNodeHasChildren:S,onValueNodeHasChildrenChange:w,contentId:x(),value:k,onValueChange:A,open:E,onOpenChange:O,dir:T,triggerPointerDownPosRef:j,disabled:f,children:[(0,F.jsx)(z.Provider,{scope:t,children:(0,F.jsx)(ee,{scope:e.__scopeSelect,onNativeOptionAdd:N.useCallback(e=>{I(t=>new Set(t).add(e))},[]),onNativeOptionRemove:N.useCallback(e=>{I(t=>{let n=new Set(t);return n.delete(e),n})},[]),children:n})}),M?(0,F.jsxs)(We,{"aria-hidden":!0,required:p,tabIndex:-1,name:u,autoComplete:d,value:k,onChange:e=>A(e.target.value),disabled:f,form:m,children:[k===void 0?(0,F.jsx)(`option`,{value:``}):null,Array.from(P)]},L):null]})})};q.displayName=R;var ne=`SelectTrigger`,re=N.forwardRef((e,t)=>{let{__scopeSelect:n,disabled:r=!1,...i}=e,a=W(n),o=K(ne,n),s=o.disabled||r,l=c(t,o.onTriggerChange),d=B(n),p=N.useRef(`touch`),[m,h,g]=Ke(e=>{let t=d().filter(e=>!e.disabled),n=qe(t,e,t.find(e=>e.value===o.value));n!==void 0&&o.onValueChange(n.value)}),_=e=>{s||(o.onOpenChange(!0),g()),e&&(o.triggerPointerDownPosRef.current={x:Math.round(e.pageX),y:Math.round(e.pageY)})};return(0,F.jsx)(A,{asChild:!0,...a,children:(0,F.jsx)(u.button,{type:`button`,role:`combobox`,"aria-controls":o.contentId,"aria-expanded":o.open,"aria-required":o.required,"aria-autocomplete":`none`,dir:o.dir,"data-state":o.open?`open`:`closed`,disabled:s,"data-disabled":s?``:void 0,"data-placeholder":Ge(o.value)?``:void 0,...i,ref:l,onClick:f(i.onClick,e=>{e.currentTarget.focus(),p.current!==`mouse`&&_(e)}),onPointerDown:f(i.onPointerDown,e=>{p.current=e.pointerType;let t=e.target;t.hasPointerCapture(e.pointerId)&&t.releasePointerCapture(e.pointerId),e.button===0&&e.ctrlKey===!1&&e.pointerType===`mouse`&&(_(e),e.preventDefault())}),onKeyDown:f(i.onKeyDown,e=>{let t=m.current!==``;!(e.ctrlKey||e.altKey||e.metaKey)&&e.key.length===1&&h(e.key),!(t&&e.key===` `)&&I.includes(e.key)&&(_(),e.preventDefault())})})})});re.displayName=ne;var J=`SelectValue`,ie=N.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,children:a,placeholder:o=``,...s}=e,l=K(J,n),{onValueNodeHasChildrenChange:d}=l,f=a!==void 0,m=c(t,l.onValueNodeChange);return p(()=>{d(f)},[d,f]),(0,F.jsx)(u.span,{...s,ref:m,style:{pointerEvents:`none`},children:Ge(l.value)?(0,F.jsx)(F.Fragment,{children:o}):a})});ie.displayName=J;var ae=`SelectIcon`,oe=N.forwardRef((e,t)=>{let{__scopeSelect:n,children:r,...i}=e;return(0,F.jsx)(u.span,{"aria-hidden":!0,...i,ref:t,children:r||`▼`})});oe.displayName=ae;var se=`SelectPortal`,ce=e=>(0,F.jsx)(_,{asChild:!0,...e});ce.displayName=se;var Y=`SelectContent`,le=N.forwardRef((e,t)=>{let n=K(Y,e.__scopeSelect),[r,i]=N.useState();if(p(()=>{i(new DocumentFragment)},[]),!n.open){let t=r;return t?P.createPortal((0,F.jsx)(ue,{scope:e.__scopeSelect,children:(0,F.jsx)(z.Slot,{scope:e.__scopeSelect,children:(0,F.jsx)(`div`,{children:e.children})})}),t):null}return(0,F.jsx)(pe,{...e,ref:t})});le.displayName=Y;var X=10,[ue,Z]=H(Y),de=`SelectContentImpl`,fe=l(`SelectContent.RemoveScroll`),pe=N.forwardRef((e,t)=>{let{__scopeSelect:n,position:r=`item-aligned`,onCloseAutoFocus:i,onEscapeKeyDown:a,onPointerDownOutside:o,side:s,sideOffset:l,align:u,alignOffset:d,arrowPadding:p,collisionBoundary:m,collisionPadding:h,sticky:_,hideWhenDetached:x,avoidCollisions:C,...w}=e,T=K(Y,n),[E,D]=N.useState(null),[O,k]=N.useState(null),A=c(t,e=>D(e)),[j,M]=N.useState(null),[P,I]=N.useState(null),L=B(n),[R,z]=N.useState(!1),V=N.useRef(!1);N.useEffect(()=>{if(E)return S(E)},[E]),b();let H=N.useCallback(e=>{let[t,...n]=L().map(e=>e.ref.current),[r]=n.slice(-1),i=document.activeElement;for(let n of e)if(n===i||(n?.scrollIntoView({block:`nearest`}),n===t&&O&&(O.scrollTop=0),n===r&&O&&(O.scrollTop=O.scrollHeight),n?.focus(),document.activeElement!==i))return},[L,O]),U=N.useCallback(()=>H([j,E]),[H,j,E]);N.useEffect(()=>{R&&U()},[R,U]);let{onOpenChange:W,triggerPointerDownPosRef:G}=T;N.useEffect(()=>{if(E){let e={x:0,y:0},t=t=>{e={x:Math.abs(Math.round(t.pageX)-(G.current?.x??0)),y:Math.abs(Math.round(t.pageY)-(G.current?.y??0))}},n=n=>{e.x<=10&&e.y<=10?n.preventDefault():E.contains(n.target)||W(!1),document.removeEventListener(`pointermove`,t),G.current=null};return G.current!==null&&(document.addEventListener(`pointermove`,t),document.addEventListener(`pointerup`,n,{capture:!0,once:!0})),()=>{document.removeEventListener(`pointermove`,t),document.removeEventListener(`pointerup`,n,{capture:!0})}}},[E,W,G]),N.useEffect(()=>{let e=()=>W(!1);return window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e)}},[W]);let[ee,te]=Ke(e=>{let t=L().filter(e=>!e.disabled),n=qe(t,e,t.find(e=>e.ref.current===document.activeElement));n&&setTimeout(()=>n.ref.current.focus())}),q=N.useCallback((e,t,n)=>{let r=!V.current&&!n;(T.value!==void 0&&T.value===t||r)&&(M(e),r&&(V.current=!0))},[T.value]),ne=N.useCallback(()=>E?.focus(),[E]),re=N.useCallback((e,t,n)=>{let r=!V.current&&!n;(T.value!==void 0&&T.value===t||r)&&I(e)},[T.value]),J=r===`popper`?_e:he,ie=J===_e?{side:s,sideOffset:l,align:u,alignOffset:d,arrowPadding:p,collisionBoundary:m,collisionPadding:h,sticky:_,hideWhenDetached:x,avoidCollisions:C}:{};return(0,F.jsx)(ue,{scope:n,content:E,viewport:O,onViewportChange:k,itemRefCallback:q,selectedItem:j,onItemLeave:ne,itemTextRefCallback:re,focusSelectedItem:U,selectedItemText:P,position:r,isPositioned:R,searchRef:ee,children:(0,F.jsx)(v,{as:fe,allowPinchZoom:!0,children:(0,F.jsx)(g,{asChild:!0,trapped:T.open,onMountAutoFocus:e=>{e.preventDefault()},onUnmountAutoFocus:f(i,e=>{T.trigger?.focus({preventScroll:!0}),e.preventDefault()}),children:(0,F.jsx)(y,{asChild:!0,disableOutsidePointerEvents:!0,onEscapeKeyDown:a,onPointerDownOutside:o,onFocusOutside:e=>e.preventDefault(),onDismiss:()=>T.onOpenChange(!1),children:(0,F.jsx)(J,{role:`listbox`,id:T.contentId,"data-state":T.open?`open`:`closed`,dir:T.dir,onContextMenu:e=>e.preventDefault(),...w,...ie,onPlaced:()=>z(!0),ref:A,style:{display:`flex`,flexDirection:`column`,outline:`none`,...w.style},onKeyDown:f(w.onKeyDown,e=>{let t=e.ctrlKey||e.altKey||e.metaKey;if(e.key===`Tab`&&e.preventDefault(),!t&&e.key.length===1&&te(e.key),[`ArrowUp`,`ArrowDown`,`Home`,`End`].includes(e.key)){let t=L().filter(e=>!e.disabled).map(e=>e.ref.current);if([`ArrowUp`,`End`].includes(e.key)&&(t=t.slice().reverse()),[`ArrowUp`,`ArrowDown`].includes(e.key)){let n=e.target,r=t.indexOf(n);t=t.slice(r+1)}setTimeout(()=>H(t)),e.preventDefault()}})})})})})})});pe.displayName=de;var me=`SelectItemAlignedPosition`,he=N.forwardRef((e,t)=>{let{__scopeSelect:n,onPlaced:r,...i}=e,a=K(Y,n),o=Z(Y,n),[s,l]=N.useState(null),[d,f]=N.useState(null),m=c(t,e=>f(e)),h=B(n),g=N.useRef(!1),_=N.useRef(!0),{viewport:v,selectedItem:y,selectedItemText:b,focusSelectedItem:x}=o,S=N.useCallback(()=>{if(a.trigger&&a.valueNode&&s&&d&&v&&y&&b){let e=a.trigger.getBoundingClientRect(),t=d.getBoundingClientRect(),n=a.valueNode.getBoundingClientRect(),i=b.getBoundingClientRect();if(a.dir!==`rtl`){let r=i.left-t.left,a=n.left-r,o=e.left-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-X,d=j(a,[X,Math.max(X,u-l)]);s.style.minWidth=c+`px`,s.style.left=d+`px`}else{let r=t.right-i.right,a=window.innerWidth-n.right-r,o=window.innerWidth-e.right-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-X,d=j(a,[X,Math.max(X,u-l)]);s.style.minWidth=c+`px`,s.style.right=d+`px`}let o=h(),c=window.innerHeight-X*2,l=v.scrollHeight,u=window.getComputedStyle(d),f=parseInt(u.borderTopWidth,10),p=parseInt(u.paddingTop,10),m=parseInt(u.borderBottomWidth,10),_=parseInt(u.paddingBottom,10),x=f+p+l+_+m,S=Math.min(y.offsetHeight*5,x),C=window.getComputedStyle(v),w=parseInt(C.paddingTop,10),T=parseInt(C.paddingBottom,10),E=e.top+e.height/2-X,D=c-E,O=y.offsetHeight/2,k=y.offsetTop+O,A=f+p+k,M=x-A;if(A<=E){let e=o.length>0&&y===o[o.length-1].ref.current;s.style.bottom=`0px`;let t=d.clientHeight-v.offsetTop-v.offsetHeight,n=A+Math.max(D,O+(e?T:0)+t+m);s.style.height=n+`px`}else{let e=o.length>0&&y===o[0].ref.current;s.style.top=`0px`;let t=Math.max(E,f+v.offsetTop+(e?w:0)+O)+M;s.style.height=t+`px`,v.scrollTop=A-E+v.offsetTop}s.style.margin=`${X}px 0`,s.style.minHeight=S+`px`,s.style.maxHeight=c+`px`,r?.(),requestAnimationFrame(()=>g.current=!0)}},[h,a.trigger,a.valueNode,s,d,v,y,b,a.dir,r]);p(()=>S(),[S]);let[C,w]=N.useState();return p(()=>{d&&w(window.getComputedStyle(d).zIndex)},[d]),(0,F.jsx)(ve,{scope:n,contentWrapper:s,shouldExpandOnScrollRef:g,onScrollButtonChange:N.useCallback(e=>{e&&_.current===!0&&(S(),x?.(),_.current=!1)},[S,x]),children:(0,F.jsx)(`div`,{ref:l,style:{display:`flex`,flexDirection:`column`,position:`fixed`,zIndex:C},children:(0,F.jsx)(u.div,{...i,ref:m,style:{boxSizing:`border-box`,maxHeight:`100%`,...i.style}})})})});he.displayName=me;var ge=`SelectPopperPosition`,_e=N.forwardRef((e,t)=>{let{__scopeSelect:n,align:r=`start`,collisionPadding:i=X,...a}=e,o=W(n);return(0,F.jsx)(k,{...o,...a,ref:t,align:r,collisionPadding:i,style:{boxSizing:`border-box`,...a.style,"--radix-select-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-select-content-available-width":`var(--radix-popper-available-width)`,"--radix-select-content-available-height":`var(--radix-popper-available-height)`,"--radix-select-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-select-trigger-height":`var(--radix-popper-anchor-height)`}})});_e.displayName=ge;var[ve,ye]=H(Y,{}),be=`SelectViewport`,xe=N.forwardRef((e,t)=>{let{__scopeSelect:n,nonce:r,...i}=e,a=Z(be,n),o=ye(be,n),s=c(t,a.onViewportChange),l=N.useRef(0);return(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`style`,{dangerouslySetInnerHTML:{__html:`[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`},nonce:r}),(0,F.jsx)(z.Slot,{scope:n,children:(0,F.jsx)(u.div,{"data-radix-select-viewport":``,role:`presentation`,...i,ref:s,style:{position:`relative`,flex:1,overflow:`hidden auto`,...i.style},onScroll:f(i.onScroll,e=>{let t=e.currentTarget,{contentWrapper:n,shouldExpandOnScrollRef:r}=o;if(r?.current&&n){let e=Math.abs(l.current-t.scrollTop);if(e>0){let r=window.innerHeight-X*2,i=parseFloat(n.style.minHeight),a=parseFloat(n.style.height),o=Math.max(i,a);if(o<r){let i=o+e,a=Math.min(r,i),s=i-a;n.style.height=a+`px`,n.style.bottom===`0px`&&(t.scrollTop=s>0?s:0,n.style.justifyContent=`flex-end`)}}}l.current=t.scrollTop})})})]})});xe.displayName=be;var Se=`SelectGroup`,[Ce,we]=H(Se),Te=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=x();return(0,F.jsx)(Ce,{scope:n,id:i,children:(0,F.jsx)(u.div,{role:`group`,"aria-labelledby":i,...r,ref:t})})});Te.displayName=Se;var Ee=`SelectLabel`,De=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=we(Ee,n);return(0,F.jsx)(u.div,{id:i.id,...r,ref:t})});De.displayName=Ee;var Q=`SelectItem`,[Oe,ke]=H(Q),Ae=N.forwardRef((e,t)=>{let{__scopeSelect:n,value:r,disabled:i=!1,textValue:a,...o}=e,s=K(Q,n),l=Z(Q,n),d=s.value===r,[p,m]=N.useState(a??``),[h,g]=N.useState(!1),_=c(t,e=>l.itemRefCallback?.(e,r,i)),v=x(),y=N.useRef(`touch`),b=()=>{i||(s.onValueChange(r),s.onOpenChange(!1))};if(r===``)throw Error(`A <Select.Item /> must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder.`);return(0,F.jsx)(Oe,{scope:n,value:r,disabled:i,textId:v,isSelected:d,onItemTextChange:N.useCallback(e=>{m(t=>t||(e?.textContent??``).trim())},[]),children:(0,F.jsx)(z.ItemSlot,{scope:n,value:r,disabled:i,textValue:p,children:(0,F.jsx)(u.div,{role:`option`,"aria-labelledby":v,"data-highlighted":h?``:void 0,"aria-selected":d&&h,"data-state":d?`checked`:`unchecked`,"aria-disabled":i||void 0,"data-disabled":i?``:void 0,tabIndex:i?void 0:-1,...o,ref:_,onFocus:f(o.onFocus,()=>g(!0)),onBlur:f(o.onBlur,()=>g(!1)),onClick:f(o.onClick,()=>{y.current!==`mouse`&&b()}),onPointerUp:f(o.onPointerUp,()=>{y.current===`mouse`&&b()}),onPointerDown:f(o.onPointerDown,e=>{y.current=e.pointerType}),onPointerMove:f(o.onPointerMove,e=>{y.current=e.pointerType,i?l.onItemLeave?.():y.current===`mouse`&&e.currentTarget.focus({preventScroll:!0})}),onPointerLeave:f(o.onPointerLeave,e=>{e.currentTarget===document.activeElement&&l.onItemLeave?.()}),onKeyDown:f(o.onKeyDown,e=>{l.searchRef?.current!==``&&e.key===` `||(L.includes(e.key)&&b(),e.key===` `&&e.preventDefault())})})})})});Ae.displayName=Q;var $=`SelectItemText`,je=N.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,...a}=e,o=K($,n),s=Z($,n),l=ke($,n),d=te($,n),[f,m]=N.useState(null),h=c(t,e=>m(e),l.onItemTextChange,e=>s.itemTextRefCallback?.(e,l.value,l.disabled)),g=f?.textContent,_=N.useMemo(()=>(0,F.jsx)(`option`,{value:l.value,disabled:l.disabled,children:g},l.value),[l.disabled,l.value,g]),{onNativeOptionAdd:v,onNativeOptionRemove:y}=d;return p(()=>(v(_),()=>y(_)),[v,y,_]),(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(u.span,{id:l.textId,...a,ref:h}),l.isSelected&&o.valueNode&&!o.valueNodeHasChildren?P.createPortal(a.children,o.valueNode):null]})});je.displayName=$;var Me=`SelectItemIndicator`,Ne=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return ke(Me,n).isSelected?(0,F.jsx)(u.span,{"aria-hidden":!0,...r,ref:t}):null});Ne.displayName=Me;var Pe=`SelectScrollUpButton`,Fe=N.forwardRef((e,t)=>{let n=Z(Pe,e.__scopeSelect),r=ye(Pe,e.__scopeSelect),[i,a]=N.useState(!1),o=c(t,r.onScrollButtonChange);return p(()=>{if(n.viewport&&n.isPositioned){let e=function(){a(t.scrollTop>0)},t=n.viewport;return e(),t.addEventListener(`scroll`,e),()=>t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,F.jsx)(Re,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop-=t.offsetHeight)}}):null});Fe.displayName=Pe;var Ie=`SelectScrollDownButton`,Le=N.forwardRef((e,t)=>{let n=Z(Ie,e.__scopeSelect),r=ye(Ie,e.__scopeSelect),[i,a]=N.useState(!1),o=c(t,r.onScrollButtonChange);return p(()=>{if(n.viewport&&n.isPositioned){let e=function(){let e=t.scrollHeight-t.clientHeight;a(Math.ceil(t.scrollTop)<e)},t=n.viewport;return e(),t.addEventListener(`scroll`,e),()=>t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,F.jsx)(Re,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop+=t.offsetHeight)}}):null});Le.displayName=Ie;var Re=N.forwardRef((e,t)=>{let{__scopeSelect:n,onAutoScroll:r,...i}=e,a=Z(`SelectScrollButton`,n),o=N.useRef(null),s=B(n),c=N.useCallback(()=>{o.current!==null&&(window.clearInterval(o.current),o.current=null)},[]);return N.useEffect(()=>()=>c(),[c]),p(()=>{s().find(e=>e.ref.current===document.activeElement)?.ref.current?.scrollIntoView({block:`nearest`})},[s]),(0,F.jsx)(u.div,{"aria-hidden":!0,...i,ref:t,style:{flexShrink:0,...i.style},onPointerDown:f(i.onPointerDown,()=>{o.current===null&&(o.current=window.setInterval(r,50))}),onPointerMove:f(i.onPointerMove,()=>{a.onItemLeave?.(),o.current===null&&(o.current=window.setInterval(r,50))}),onPointerLeave:f(i.onPointerLeave,()=>{c()})})}),ze=`SelectSeparator`,Be=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return(0,F.jsx)(u.div,{"aria-hidden":!0,...r,ref:t})});Be.displayName=ze;var Ve=`SelectArrow`,He=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=W(n),a=K(Ve,n),o=Z(Ve,n);return a.open&&o.position===`popper`?(0,F.jsx)(O,{...i,...r,ref:t}):null});He.displayName=Ve;var Ue=`SelectBubbleInput`,We=N.forwardRef(({__scopeSelect:e,value:t,...n},r)=>{let i=N.useRef(null),a=c(r,i),o=T(t);return N.useEffect(()=>{let e=i.current;if(!e)return;let n=window.HTMLSelectElement.prototype,r=Object.getOwnPropertyDescriptor(n,`value`).set;if(o!==t&&r){let n=new Event(`change`,{bubbles:!0});r.call(e,t),e.dispatchEvent(n)}},[o,t]),(0,F.jsx)(u.select,{...n,style:{...M,...n.style},ref:a,defaultValue:t})});We.displayName=Ue;function Ge(e){return e===``||e===void 0}function Ke(e){let t=w(e),n=N.useRef(``),r=N.useRef(0),i=N.useCallback(e=>{let i=n.current+e;t(i),(function e(t){n.current=t,window.clearTimeout(r.current),t!==``&&(r.current=window.setTimeout(()=>e(``),1e3))})(i)},[t]),a=N.useCallback(()=>{n.current=``,window.clearTimeout(r.current)},[]);return N.useEffect(()=>()=>window.clearTimeout(r.current),[]),[n,i,a]}function qe(e,t,n){let r=t.length>1&&Array.from(t).every(e=>e===t[0])?t[0]:t,i=n?e.indexOf(n):-1,a=Je(e,Math.max(i,0));r.length===1&&(a=a.filter(e=>e!==n));let o=a.find(e=>e.textValue.toLowerCase().startsWith(r.toLowerCase()));return o===n?void 0:o}function Je(e,t){return e.map((n,r)=>e[(t+r)%e.length])}var Ye=q,Xe=re,Ze=ie,Qe=oe,$e=ce,et=le,tt=xe,nt=Ae,rt=je,it=Ne,at=Fe,ot=Le;function st({...e}){return(0,F.jsx)(Ye,{"data-slot":`select`,...e})}function ct({...e}){return(0,F.jsx)(Ze,{"data-slot":`select-value`,...e})}function lt({className:e,size:n=`default`,children:r,...i}){return(0,F.jsxs)(Xe,{"data-slot":`select-trigger`,"data-size":n,className:t(`flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,e),...i,children:[r,(0,F.jsx)(Qe,{asChild:!0,children:(0,F.jsx)(a,{className:`pointer-events-none size-4 text-muted-foreground`})})]})}function ut({className:e,children:n,position:r=`item-aligned`,align:i=`center`,...a}){return(0,F.jsx)($e,{children:(0,F.jsxs)(et,{"data-slot":`select-content`,"data-align-trigger":r===`item-aligned`,className:t(`relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,r===`popper`&&`data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1`,e),position:r,align:i,...a,children:[(0,F.jsx)(ft,{}),(0,F.jsx)(tt,{"data-position":r,className:t(`data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)`,r===`popper`&&``),children:n}),(0,F.jsx)(pt,{})]})})}function dt({className:e,children:n,...r}){return(0,F.jsxs)(nt,{"data-slot":`select-item`,className:t(`relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2`,e),...r,children:[(0,F.jsx)(`span`,{className:`pointer-events-none absolute right-2 flex size-4 items-center justify-center`,children:(0,F.jsx)(it,{children:(0,F.jsx)(i,{className:`pointer-events-none`})})}),(0,F.jsx)(rt,{children:n})]})}function ft({className:e,...n}){return(0,F.jsx)(at,{"data-slot":`select-scroll-up-button`,className:t(`z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4`,e),...n,children:(0,F.jsx)(r,{})})}function pt({className:e,...n}){return(0,F.jsx)(ot,{"data-slot":`select-scroll-down-button`,className:t(`z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4`,e),...n,children:(0,F.jsx)(a,{})})}export{ct as a,lt as i,ut as n,dt as r,st as t};
2
- //# sourceMappingURL=select-DaOiWDBR.js.map
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{Hn as t,Wn as n,dn as r,hn as i,mn as a,rr as o}from"./lucide-react-CsPXvXMC.js";import{t as s}from"./react-dom-CEl58oxP.js";import{o as c,r as l}from"./dist-CL2npVDe.js";import{t as u}from"./dist-CAFUEpK2.js";import{i as d,n as f,t as p}from"./dist-ERYvDMdt.js";import{t as m}from"./dist-DLsSqk6h.js";import{t as h}from"./dist-Dmiv1tSO.js";import{a as g,i as _,n as v,o as y,r as b,s as x,t as S}from"./es2015-Yto-4EBw.js";import{t as C}from"./dist-DyqEeyBI.js";import{t as w}from"./dist-CoRABSO3.js";import{t as T}from"./dist-CIbvPDQV.js";import{a as E,i as D,n as O,r as k,t as A}from"./dist-CnRv0y2x.js";import{t as j}from"./dist-D33pM1xy.js";import{q as M}from"./index-Bd1NBLyd.js";var N=e(o(),1),P=e(s(),1),F=n(),I=[` `,`Enter`,`ArrowUp`,`ArrowDown`],L=[` `,`Enter`],R=`Select`,[z,B,V]=m(R),[H,U]=d(R,[V,E]),W=E(),[G,K]=H(R),[ee,te]=H(R),q=e=>{let{__scopeSelect:t,children:n,open:r,defaultOpen:i,onOpenChange:a,value:o,defaultValue:s,onValueChange:c,dir:l,name:u,autoComplete:d,disabled:f,required:p,form:m}=e,g=W(t),[_,v]=N.useState(null),[y,b]=N.useState(null),[S,w]=N.useState(!1),T=C(l),[E,O]=h({prop:r,defaultProp:i??!1,onChange:a,caller:R}),[k,A]=h({prop:o,defaultProp:s,onChange:c,caller:R}),j=N.useRef(null),M=_?m||!!_.closest(`form`):!0,[P,I]=N.useState(new Set),L=Array.from(P).map(e=>e.props.value).join(`;`);return(0,F.jsx)(D,{...g,children:(0,F.jsxs)(G,{required:p,scope:t,trigger:_,onTriggerChange:v,valueNode:y,onValueNodeChange:b,valueNodeHasChildren:S,onValueNodeHasChildrenChange:w,contentId:x(),value:k,onValueChange:A,open:E,onOpenChange:O,dir:T,triggerPointerDownPosRef:j,disabled:f,children:[(0,F.jsx)(z.Provider,{scope:t,children:(0,F.jsx)(ee,{scope:e.__scopeSelect,onNativeOptionAdd:N.useCallback(e=>{I(t=>new Set(t).add(e))},[]),onNativeOptionRemove:N.useCallback(e=>{I(t=>{let n=new Set(t);return n.delete(e),n})},[]),children:n})}),M?(0,F.jsxs)(We,{"aria-hidden":!0,required:p,tabIndex:-1,name:u,autoComplete:d,value:k,onChange:e=>A(e.target.value),disabled:f,form:m,children:[k===void 0?(0,F.jsx)(`option`,{value:``}):null,Array.from(P)]},L):null]})})};q.displayName=R;var ne=`SelectTrigger`,re=N.forwardRef((e,t)=>{let{__scopeSelect:n,disabled:r=!1,...i}=e,a=W(n),o=K(ne,n),s=o.disabled||r,l=c(t,o.onTriggerChange),d=B(n),p=N.useRef(`touch`),[m,h,g]=Ke(e=>{let t=d().filter(e=>!e.disabled),n=qe(t,e,t.find(e=>e.value===o.value));n!==void 0&&o.onValueChange(n.value)}),_=e=>{s||(o.onOpenChange(!0),g()),e&&(o.triggerPointerDownPosRef.current={x:Math.round(e.pageX),y:Math.round(e.pageY)})};return(0,F.jsx)(A,{asChild:!0,...a,children:(0,F.jsx)(u.button,{type:`button`,role:`combobox`,"aria-controls":o.contentId,"aria-expanded":o.open,"aria-required":o.required,"aria-autocomplete":`none`,dir:o.dir,"data-state":o.open?`open`:`closed`,disabled:s,"data-disabled":s?``:void 0,"data-placeholder":Ge(o.value)?``:void 0,...i,ref:l,onClick:f(i.onClick,e=>{e.currentTarget.focus(),p.current!==`mouse`&&_(e)}),onPointerDown:f(i.onPointerDown,e=>{p.current=e.pointerType;let t=e.target;t.hasPointerCapture(e.pointerId)&&t.releasePointerCapture(e.pointerId),e.button===0&&e.ctrlKey===!1&&e.pointerType===`mouse`&&(_(e),e.preventDefault())}),onKeyDown:f(i.onKeyDown,e=>{let t=m.current!==``;!(e.ctrlKey||e.altKey||e.metaKey)&&e.key.length===1&&h(e.key),!(t&&e.key===` `)&&I.includes(e.key)&&(_(),e.preventDefault())})})})});re.displayName=ne;var J=`SelectValue`,ie=N.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,children:a,placeholder:o=``,...s}=e,l=K(J,n),{onValueNodeHasChildrenChange:d}=l,f=a!==void 0,m=c(t,l.onValueNodeChange);return p(()=>{d(f)},[d,f]),(0,F.jsx)(u.span,{...s,ref:m,style:{pointerEvents:`none`},children:Ge(l.value)?(0,F.jsx)(F.Fragment,{children:o}):a})});ie.displayName=J;var ae=`SelectIcon`,oe=N.forwardRef((e,t)=>{let{__scopeSelect:n,children:r,...i}=e;return(0,F.jsx)(u.span,{"aria-hidden":!0,...i,ref:t,children:r||`▼`})});oe.displayName=ae;var se=`SelectPortal`,ce=e=>(0,F.jsx)(_,{asChild:!0,...e});ce.displayName=se;var Y=`SelectContent`,le=N.forwardRef((e,t)=>{let n=K(Y,e.__scopeSelect),[r,i]=N.useState();if(p(()=>{i(new DocumentFragment)},[]),!n.open){let t=r;return t?P.createPortal((0,F.jsx)(ue,{scope:e.__scopeSelect,children:(0,F.jsx)(z.Slot,{scope:e.__scopeSelect,children:(0,F.jsx)(`div`,{children:e.children})})}),t):null}return(0,F.jsx)(pe,{...e,ref:t})});le.displayName=Y;var X=10,[ue,Z]=H(Y),de=`SelectContentImpl`,fe=l(`SelectContent.RemoveScroll`),pe=N.forwardRef((e,t)=>{let{__scopeSelect:n,position:r=`item-aligned`,onCloseAutoFocus:i,onEscapeKeyDown:a,onPointerDownOutside:o,side:s,sideOffset:l,align:u,alignOffset:d,arrowPadding:p,collisionBoundary:m,collisionPadding:h,sticky:_,hideWhenDetached:x,avoidCollisions:C,...w}=e,T=K(Y,n),[E,D]=N.useState(null),[O,k]=N.useState(null),A=c(t,e=>D(e)),[j,M]=N.useState(null),[P,I]=N.useState(null),L=B(n),[R,z]=N.useState(!1),V=N.useRef(!1);N.useEffect(()=>{if(E)return S(E)},[E]),b();let H=N.useCallback(e=>{let[t,...n]=L().map(e=>e.ref.current),[r]=n.slice(-1),i=document.activeElement;for(let n of e)if(n===i||(n?.scrollIntoView({block:`nearest`}),n===t&&O&&(O.scrollTop=0),n===r&&O&&(O.scrollTop=O.scrollHeight),n?.focus(),document.activeElement!==i))return},[L,O]),U=N.useCallback(()=>H([j,E]),[H,j,E]);N.useEffect(()=>{R&&U()},[R,U]);let{onOpenChange:W,triggerPointerDownPosRef:G}=T;N.useEffect(()=>{if(E){let e={x:0,y:0},t=t=>{e={x:Math.abs(Math.round(t.pageX)-(G.current?.x??0)),y:Math.abs(Math.round(t.pageY)-(G.current?.y??0))}},n=n=>{e.x<=10&&e.y<=10?n.preventDefault():E.contains(n.target)||W(!1),document.removeEventListener(`pointermove`,t),G.current=null};return G.current!==null&&(document.addEventListener(`pointermove`,t),document.addEventListener(`pointerup`,n,{capture:!0,once:!0})),()=>{document.removeEventListener(`pointermove`,t),document.removeEventListener(`pointerup`,n,{capture:!0})}}},[E,W,G]),N.useEffect(()=>{let e=()=>W(!1);return window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e)}},[W]);let[ee,te]=Ke(e=>{let t=L().filter(e=>!e.disabled),n=qe(t,e,t.find(e=>e.ref.current===document.activeElement));n&&setTimeout(()=>n.ref.current.focus())}),q=N.useCallback((e,t,n)=>{let r=!V.current&&!n;(T.value!==void 0&&T.value===t||r)&&(M(e),r&&(V.current=!0))},[T.value]),ne=N.useCallback(()=>E?.focus(),[E]),re=N.useCallback((e,t,n)=>{let r=!V.current&&!n;(T.value!==void 0&&T.value===t||r)&&I(e)},[T.value]),J=r===`popper`?_e:he,ie=J===_e?{side:s,sideOffset:l,align:u,alignOffset:d,arrowPadding:p,collisionBoundary:m,collisionPadding:h,sticky:_,hideWhenDetached:x,avoidCollisions:C}:{};return(0,F.jsx)(ue,{scope:n,content:E,viewport:O,onViewportChange:k,itemRefCallback:q,selectedItem:j,onItemLeave:ne,itemTextRefCallback:re,focusSelectedItem:U,selectedItemText:P,position:r,isPositioned:R,searchRef:ee,children:(0,F.jsx)(v,{as:fe,allowPinchZoom:!0,children:(0,F.jsx)(g,{asChild:!0,trapped:T.open,onMountAutoFocus:e=>{e.preventDefault()},onUnmountAutoFocus:f(i,e=>{T.trigger?.focus({preventScroll:!0}),e.preventDefault()}),children:(0,F.jsx)(y,{asChild:!0,disableOutsidePointerEvents:!0,onEscapeKeyDown:a,onPointerDownOutside:o,onFocusOutside:e=>e.preventDefault(),onDismiss:()=>T.onOpenChange(!1),children:(0,F.jsx)(J,{role:`listbox`,id:T.contentId,"data-state":T.open?`open`:`closed`,dir:T.dir,onContextMenu:e=>e.preventDefault(),...w,...ie,onPlaced:()=>z(!0),ref:A,style:{display:`flex`,flexDirection:`column`,outline:`none`,...w.style},onKeyDown:f(w.onKeyDown,e=>{let t=e.ctrlKey||e.altKey||e.metaKey;if(e.key===`Tab`&&e.preventDefault(),!t&&e.key.length===1&&te(e.key),[`ArrowUp`,`ArrowDown`,`Home`,`End`].includes(e.key)){let t=L().filter(e=>!e.disabled).map(e=>e.ref.current);if([`ArrowUp`,`End`].includes(e.key)&&(t=t.slice().reverse()),[`ArrowUp`,`ArrowDown`].includes(e.key)){let n=e.target,r=t.indexOf(n);t=t.slice(r+1)}setTimeout(()=>H(t)),e.preventDefault()}})})})})})})});pe.displayName=de;var me=`SelectItemAlignedPosition`,he=N.forwardRef((e,t)=>{let{__scopeSelect:n,onPlaced:r,...i}=e,a=K(Y,n),o=Z(Y,n),[s,l]=N.useState(null),[d,f]=N.useState(null),m=c(t,e=>f(e)),h=B(n),g=N.useRef(!1),_=N.useRef(!0),{viewport:v,selectedItem:y,selectedItemText:b,focusSelectedItem:x}=o,S=N.useCallback(()=>{if(a.trigger&&a.valueNode&&s&&d&&v&&y&&b){let e=a.trigger.getBoundingClientRect(),t=d.getBoundingClientRect(),n=a.valueNode.getBoundingClientRect(),i=b.getBoundingClientRect();if(a.dir!==`rtl`){let r=i.left-t.left,a=n.left-r,o=e.left-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-X,d=j(a,[X,Math.max(X,u-l)]);s.style.minWidth=c+`px`,s.style.left=d+`px`}else{let r=t.right-i.right,a=window.innerWidth-n.right-r,o=window.innerWidth-e.right-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-X,d=j(a,[X,Math.max(X,u-l)]);s.style.minWidth=c+`px`,s.style.right=d+`px`}let o=h(),c=window.innerHeight-X*2,l=v.scrollHeight,u=window.getComputedStyle(d),f=parseInt(u.borderTopWidth,10),p=parseInt(u.paddingTop,10),m=parseInt(u.borderBottomWidth,10),_=parseInt(u.paddingBottom,10),x=f+p+l+_+m,S=Math.min(y.offsetHeight*5,x),C=window.getComputedStyle(v),w=parseInt(C.paddingTop,10),T=parseInt(C.paddingBottom,10),E=e.top+e.height/2-X,D=c-E,O=y.offsetHeight/2,k=y.offsetTop+O,A=f+p+k,M=x-A;if(A<=E){let e=o.length>0&&y===o[o.length-1].ref.current;s.style.bottom=`0px`;let t=d.clientHeight-v.offsetTop-v.offsetHeight,n=A+Math.max(D,O+(e?T:0)+t+m);s.style.height=n+`px`}else{let e=o.length>0&&y===o[0].ref.current;s.style.top=`0px`;let t=Math.max(E,f+v.offsetTop+(e?w:0)+O)+M;s.style.height=t+`px`,v.scrollTop=A-E+v.offsetTop}s.style.margin=`${X}px 0`,s.style.minHeight=S+`px`,s.style.maxHeight=c+`px`,r?.(),requestAnimationFrame(()=>g.current=!0)}},[h,a.trigger,a.valueNode,s,d,v,y,b,a.dir,r]);p(()=>S(),[S]);let[C,w]=N.useState();return p(()=>{d&&w(window.getComputedStyle(d).zIndex)},[d]),(0,F.jsx)(ve,{scope:n,contentWrapper:s,shouldExpandOnScrollRef:g,onScrollButtonChange:N.useCallback(e=>{e&&_.current===!0&&(S(),x?.(),_.current=!1)},[S,x]),children:(0,F.jsx)(`div`,{ref:l,style:{display:`flex`,flexDirection:`column`,position:`fixed`,zIndex:C},children:(0,F.jsx)(u.div,{...i,ref:m,style:{boxSizing:`border-box`,maxHeight:`100%`,...i.style}})})})});he.displayName=me;var ge=`SelectPopperPosition`,_e=N.forwardRef((e,t)=>{let{__scopeSelect:n,align:r=`start`,collisionPadding:i=X,...a}=e,o=W(n);return(0,F.jsx)(k,{...o,...a,ref:t,align:r,collisionPadding:i,style:{boxSizing:`border-box`,...a.style,"--radix-select-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-select-content-available-width":`var(--radix-popper-available-width)`,"--radix-select-content-available-height":`var(--radix-popper-available-height)`,"--radix-select-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-select-trigger-height":`var(--radix-popper-anchor-height)`}})});_e.displayName=ge;var[ve,ye]=H(Y,{}),be=`SelectViewport`,xe=N.forwardRef((e,t)=>{let{__scopeSelect:n,nonce:r,...i}=e,a=Z(be,n),o=ye(be,n),s=c(t,a.onViewportChange),l=N.useRef(0);return(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`style`,{dangerouslySetInnerHTML:{__html:`[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`},nonce:r}),(0,F.jsx)(z.Slot,{scope:n,children:(0,F.jsx)(u.div,{"data-radix-select-viewport":``,role:`presentation`,...i,ref:s,style:{position:`relative`,flex:1,overflow:`hidden auto`,...i.style},onScroll:f(i.onScroll,e=>{let t=e.currentTarget,{contentWrapper:n,shouldExpandOnScrollRef:r}=o;if(r?.current&&n){let e=Math.abs(l.current-t.scrollTop);if(e>0){let r=window.innerHeight-X*2,i=parseFloat(n.style.minHeight),a=parseFloat(n.style.height),o=Math.max(i,a);if(o<r){let i=o+e,a=Math.min(r,i),s=i-a;n.style.height=a+`px`,n.style.bottom===`0px`&&(t.scrollTop=s>0?s:0,n.style.justifyContent=`flex-end`)}}}l.current=t.scrollTop})})})]})});xe.displayName=be;var Se=`SelectGroup`,[Ce,we]=H(Se),Te=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=x();return(0,F.jsx)(Ce,{scope:n,id:i,children:(0,F.jsx)(u.div,{role:`group`,"aria-labelledby":i,...r,ref:t})})});Te.displayName=Se;var Ee=`SelectLabel`,De=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=we(Ee,n);return(0,F.jsx)(u.div,{id:i.id,...r,ref:t})});De.displayName=Ee;var Q=`SelectItem`,[Oe,ke]=H(Q),Ae=N.forwardRef((e,t)=>{let{__scopeSelect:n,value:r,disabled:i=!1,textValue:a,...o}=e,s=K(Q,n),l=Z(Q,n),d=s.value===r,[p,m]=N.useState(a??``),[h,g]=N.useState(!1),_=c(t,e=>l.itemRefCallback?.(e,r,i)),v=x(),y=N.useRef(`touch`),b=()=>{i||(s.onValueChange(r),s.onOpenChange(!1))};if(r===``)throw Error(`A <Select.Item /> must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder.`);return(0,F.jsx)(Oe,{scope:n,value:r,disabled:i,textId:v,isSelected:d,onItemTextChange:N.useCallback(e=>{m(t=>t||(e?.textContent??``).trim())},[]),children:(0,F.jsx)(z.ItemSlot,{scope:n,value:r,disabled:i,textValue:p,children:(0,F.jsx)(u.div,{role:`option`,"aria-labelledby":v,"data-highlighted":h?``:void 0,"aria-selected":d&&h,"data-state":d?`checked`:`unchecked`,"aria-disabled":i||void 0,"data-disabled":i?``:void 0,tabIndex:i?void 0:-1,...o,ref:_,onFocus:f(o.onFocus,()=>g(!0)),onBlur:f(o.onBlur,()=>g(!1)),onClick:f(o.onClick,()=>{y.current!==`mouse`&&b()}),onPointerUp:f(o.onPointerUp,()=>{y.current===`mouse`&&b()}),onPointerDown:f(o.onPointerDown,e=>{y.current=e.pointerType}),onPointerMove:f(o.onPointerMove,e=>{y.current=e.pointerType,i?l.onItemLeave?.():y.current===`mouse`&&e.currentTarget.focus({preventScroll:!0})}),onPointerLeave:f(o.onPointerLeave,e=>{e.currentTarget===document.activeElement&&l.onItemLeave?.()}),onKeyDown:f(o.onKeyDown,e=>{l.searchRef?.current!==``&&e.key===` `||(L.includes(e.key)&&b(),e.key===` `&&e.preventDefault())})})})})});Ae.displayName=Q;var $=`SelectItemText`,je=N.forwardRef((e,t)=>{let{__scopeSelect:n,className:r,style:i,...a}=e,o=K($,n),s=Z($,n),l=ke($,n),d=te($,n),[f,m]=N.useState(null),h=c(t,e=>m(e),l.onItemTextChange,e=>s.itemTextRefCallback?.(e,l.value,l.disabled)),g=f?.textContent,_=N.useMemo(()=>(0,F.jsx)(`option`,{value:l.value,disabled:l.disabled,children:g},l.value),[l.disabled,l.value,g]),{onNativeOptionAdd:v,onNativeOptionRemove:y}=d;return p(()=>(v(_),()=>y(_)),[v,y,_]),(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(u.span,{id:l.textId,...a,ref:h}),l.isSelected&&o.valueNode&&!o.valueNodeHasChildren?P.createPortal(a.children,o.valueNode):null]})});je.displayName=$;var Me=`SelectItemIndicator`,Ne=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return ke(Me,n).isSelected?(0,F.jsx)(u.span,{"aria-hidden":!0,...r,ref:t}):null});Ne.displayName=Me;var Pe=`SelectScrollUpButton`,Fe=N.forwardRef((e,t)=>{let n=Z(Pe,e.__scopeSelect),r=ye(Pe,e.__scopeSelect),[i,a]=N.useState(!1),o=c(t,r.onScrollButtonChange);return p(()=>{if(n.viewport&&n.isPositioned){let e=function(){a(t.scrollTop>0)},t=n.viewport;return e(),t.addEventListener(`scroll`,e),()=>t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,F.jsx)(Re,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop-=t.offsetHeight)}}):null});Fe.displayName=Pe;var Ie=`SelectScrollDownButton`,Le=N.forwardRef((e,t)=>{let n=Z(Ie,e.__scopeSelect),r=ye(Ie,e.__scopeSelect),[i,a]=N.useState(!1),o=c(t,r.onScrollButtonChange);return p(()=>{if(n.viewport&&n.isPositioned){let e=function(){let e=t.scrollHeight-t.clientHeight;a(Math.ceil(t.scrollTop)<e)},t=n.viewport;return e(),t.addEventListener(`scroll`,e),()=>t.removeEventListener(`scroll`,e)}},[n.viewport,n.isPositioned]),i?(0,F.jsx)(Re,{...e,ref:o,onAutoScroll:()=>{let{viewport:e,selectedItem:t}=n;e&&t&&(e.scrollTop+=t.offsetHeight)}}):null});Le.displayName=Ie;var Re=N.forwardRef((e,t)=>{let{__scopeSelect:n,onAutoScroll:r,...i}=e,a=Z(`SelectScrollButton`,n),o=N.useRef(null),s=B(n),c=N.useCallback(()=>{o.current!==null&&(window.clearInterval(o.current),o.current=null)},[]);return N.useEffect(()=>()=>c(),[c]),p(()=>{s().find(e=>e.ref.current===document.activeElement)?.ref.current?.scrollIntoView({block:`nearest`})},[s]),(0,F.jsx)(u.div,{"aria-hidden":!0,...i,ref:t,style:{flexShrink:0,...i.style},onPointerDown:f(i.onPointerDown,()=>{o.current===null&&(o.current=window.setInterval(r,50))}),onPointerMove:f(i.onPointerMove,()=>{a.onItemLeave?.(),o.current===null&&(o.current=window.setInterval(r,50))}),onPointerLeave:f(i.onPointerLeave,()=>{c()})})}),ze=`SelectSeparator`,Be=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e;return(0,F.jsx)(u.div,{"aria-hidden":!0,...r,ref:t})});Be.displayName=ze;var Ve=`SelectArrow`,He=N.forwardRef((e,t)=>{let{__scopeSelect:n,...r}=e,i=W(n),a=K(Ve,n),o=Z(Ve,n);return a.open&&o.position===`popper`?(0,F.jsx)(O,{...i,...r,ref:t}):null});He.displayName=Ve;var Ue=`SelectBubbleInput`,We=N.forwardRef(({__scopeSelect:e,value:t,...n},r)=>{let i=N.useRef(null),a=c(r,i),o=T(t);return N.useEffect(()=>{let e=i.current;if(!e)return;let n=window.HTMLSelectElement.prototype,r=Object.getOwnPropertyDescriptor(n,`value`).set;if(o!==t&&r){let n=new Event(`change`,{bubbles:!0});r.call(e,t),e.dispatchEvent(n)}},[o,t]),(0,F.jsx)(u.select,{...n,style:{...M,...n.style},ref:a,defaultValue:t})});We.displayName=Ue;function Ge(e){return e===``||e===void 0}function Ke(e){let t=w(e),n=N.useRef(``),r=N.useRef(0),i=N.useCallback(e=>{let i=n.current+e;t(i),(function e(t){n.current=t,window.clearTimeout(r.current),t!==``&&(r.current=window.setTimeout(()=>e(``),1e3))})(i)},[t]),a=N.useCallback(()=>{n.current=``,window.clearTimeout(r.current)},[]);return N.useEffect(()=>()=>window.clearTimeout(r.current),[]),[n,i,a]}function qe(e,t,n){let r=t.length>1&&Array.from(t).every(e=>e===t[0])?t[0]:t,i=n?e.indexOf(n):-1,a=Je(e,Math.max(i,0));r.length===1&&(a=a.filter(e=>e!==n));let o=a.find(e=>e.textValue.toLowerCase().startsWith(r.toLowerCase()));return o===n?void 0:o}function Je(e,t){return e.map((n,r)=>e[(t+r)%e.length])}var Ye=q,Xe=re,Ze=ie,Qe=oe,$e=ce,et=le,tt=xe,nt=Ae,rt=je,it=Ne,at=Fe,ot=Le;function st({...e}){return(0,F.jsx)(Ye,{"data-slot":`select`,...e})}function ct({...e}){return(0,F.jsx)(Ze,{"data-slot":`select-value`,...e})}function lt({className:e,size:n=`default`,children:r,...i}){return(0,F.jsxs)(Xe,{"data-slot":`select-trigger`,"data-size":n,className:t(`flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,e),...i,children:[r,(0,F.jsx)(Qe,{asChild:!0,children:(0,F.jsx)(a,{className:`pointer-events-none size-4 text-muted-foreground`})})]})}function ut({className:e,children:n,position:r=`item-aligned`,align:i=`center`,...a}){return(0,F.jsx)($e,{children:(0,F.jsxs)(et,{"data-slot":`select-content`,"data-align-trigger":r===`item-aligned`,className:t(`relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,r===`popper`&&`data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1`,e),position:r,align:i,...a,children:[(0,F.jsx)(ft,{}),(0,F.jsx)(tt,{"data-position":r,className:t(`data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)`,r===`popper`&&``),children:n}),(0,F.jsx)(pt,{})]})})}function dt({className:e,children:n,...r}){return(0,F.jsxs)(nt,{"data-slot":`select-item`,className:t(`relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2`,e),...r,children:[(0,F.jsx)(`span`,{className:`pointer-events-none absolute right-2 flex size-4 items-center justify-center`,children:(0,F.jsx)(it,{children:(0,F.jsx)(i,{className:`pointer-events-none`})})}),(0,F.jsx)(rt,{children:n})]})}function ft({className:e,...n}){return(0,F.jsx)(at,{"data-slot":`select-scroll-up-button`,className:t(`z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4`,e),...n,children:(0,F.jsx)(r,{})})}function pt({className:e,...n}){return(0,F.jsx)(ot,{"data-slot":`select-scroll-down-button`,className:t(`z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4`,e),...n,children:(0,F.jsx)(a,{})})}export{ct as a,lt as i,ut as n,dt as r,st as t};
2
+ //# sourceMappingURL=select-D6HFOeLW.js.map