{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "audit-log",
  "title": "Audit Log",
  "description": "Actors, actions, resources, timestamps, filters, and event details.",
  "dependencies": [
    "class-variance-authority",
    "lucide-react"
  ],
  "registryDependencies": [
    "collapsible",
    "https://uaiblocks.dev/r/uai-theme.json",
    "https://uaiblocks.dev/r/uai-utils.json"
  ],
  "files": [
    {
      "path": "src/registry/uai/components/audit-log.tsx",
      "content": "\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { ChevronRight } from \"lucide-react\";\nimport { type ComponentProps, createContext, useContext, useId, useState } from \"react\";\nimport { Collapsible, CollapsibleTrigger } from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/uai-utils\";\n\nexport const AUDIT_LOG_VARIANTS = [\"card\", \"timeline\", \"compact\"] as const;\nexport type AuditLogVariant = (typeof AUDIT_LOG_VARIANTS)[number];\nexport type AuditLogProps = ComponentProps<\"section\"> & { variant?: AuditLogVariant };\n\ntype LogContext = { id: string; variant: AuditLogVariant };\nconst Context = createContext<LogContext | null>(null);\nfunction useLog(part: string) {\n  const context = useContext(Context);\n  if (!context) throw new Error(`${part} must be used within AuditLog`);\n  return context;\n}\nconst auditLogVariants = cva(\"grid min-w-0 rounded-[14px] text-[13px]/[18px] text-foreground\", {\n  variants: {\n    variant: {\n      card: \"gap-3 border bg-card px-3 pt-3.5 pb-2 text-card-foreground\",\n      timeline: \"gap-3 border-0 bg-transparent p-0\",\n      compact: \"gap-2 border-0 bg-transparent p-0\",\n    },\n  },\n});\ntype EventContext = { id: string; open: boolean; setOpen: (open: boolean) => void };\nconst EventCtx = createContext<EventContext | null>(null);\nfunction useEvent(part: string) {\n  const context = useContext(EventCtx);\n  if (!context) throw new Error(`${part} must be used within AuditLogEvent`);\n  return context;\n}\n\nexport function AuditLog({ variant = \"card\", className, children, ...props }: AuditLogProps) {\n  const id = useId();\n  return (\n    <Context.Provider value={{ id, variant }}>\n      <section\n        aria-labelledby={`${id}-title`}\n        data-slot=\"audit-log\"\n        className={cn(auditLogVariants({ variant }), className)}\n        {...props}\n        data-variant={variant}\n      >\n        {children}\n      </section>\n    </Context.Provider>\n  );\n}\n\nexport function AuditLogHeader({ className, ...props }: ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"audit-log-header\"\n      className={cn(\"flex flex-wrap items-center justify-between gap-3 px-1\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function AuditLogTitle({ className, ...props }: ComponentProps<\"h3\">) {\n  const context = useLog(\"AuditLogTitle\");\n  return (\n    <h3\n      data-slot=\"audit-log-title\"\n      className={cn(\"m-0 text-sm/5 font-semibold tracking-[-0.01em]\", className)}\n      {...props}\n      id={`${context.id}-title`}\n    />\n  );\n}\n\nexport function AuditLogFilters({ className, ...props }: ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"audit-log-filters\"\n      className={cn(\"flex flex-wrap items-center gap-2\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function AuditLogList({ className, ...props }: ComponentProps<\"ol\">) {\n  const context = useLog(\"AuditLogList\");\n  return (\n    <ol\n      data-slot=\"audit-log-list\"\n      className={cn(\n        \"m-0 grid list-none p-0\",\n        context.variant === \"compact\" ? \"gap-0.5\" : \"gap-0\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport type AuditLogEventProps = ComponentProps<\"li\"> & {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n};\n\nexport function AuditLogEvent({\n  open,\n  defaultOpen = false,\n  onOpenChange,\n  className,\n  children,\n  ...props\n}: AuditLogEventProps) {\n  const log = useLog(\"AuditLogEvent\");\n  const id = useId();\n  const [internal, setInternal] = useState(defaultOpen);\n  const current = open ?? internal;\n  const setOpen = (next: boolean) => {\n    if (open === undefined) setInternal(next);\n    onOpenChange?.(next);\n  };\n  const timeline = log.variant === \"timeline\";\n  return (\n    <EventCtx.Provider value={{ id, open: current, setOpen }}>\n      <Collapsible asChild open={current} onOpenChange={setOpen}>\n        <li\n          data-slot=\"audit-log-event\"\n          className={cn(\n            \"relative grid min-w-0\",\n            log.variant === \"compact\" ? \"gap-1\" : \"gap-1.5\",\n            log.variant === \"card\" && \"ml-0 border-b py-1 last:border-b-0\",\n            timeline && \"ml-1 border-l pt-0 pr-0 pb-2.5 pl-4 last:border-l-transparent\",\n            log.variant === \"compact\" && \"ml-0 p-0\",\n            className,\n          )}\n          {...props}\n          data-state={current ? \"open\" : \"closed\"}\n        >\n          {timeline ? (\n            <span\n              aria-hidden=\"true\"\n              className={cn(\n                \"absolute top-2.75 -left-1 size-1.75 rounded-full shadow-[0_0_0_3px_var(--background)] transition-colors duration-120 ease-[ease-out]\",\n                current ? \"bg-foreground\" : \"bg-border-strong\",\n              )}\n            />\n          ) : null}\n          {children}\n        </li>\n      </Collapsible>\n    </EventCtx.Provider>\n  );\n}\n\nexport function AuditLogEventSummary({ className, children, ...props }: ComponentProps<\"button\">) {\n  const log = useLog(\"AuditLogEventSummary\");\n  const event = useEvent(\"AuditLogEventSummary\");\n  const compact = log.variant === \"compact\";\n  return (\n    <CollapsibleTrigger\n      data-slot=\"audit-log-event-summary\"\n      className={cn(\n        \"flex w-full cursor-pointer flex-wrap items-baseline gap-x-1.5 gap-y-0.5 border-0 text-left text-inherit [transition:background-color_120ms_ease-out] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring motion-reduce:transition-none\",\n        event.open ? \"bg-accent\" : \"bg-transparent hover:bg-accent/70\",\n        compact\n          ? \"min-h-6.5 rounded-[7px] px-1.5 py-1 text-[12.5px]\"\n          : \"min-h-8 rounded-lg px-2 py-1.75 text-[13px]\",\n        className,\n      )}\n      {...props}\n      type=\"button\"\n      aria-expanded={event.open}\n      aria-controls={`${event.id}-details`}\n    >\n      <ChevronRight\n        size={14}\n        strokeWidth={1.75}\n        aria-hidden=\"true\"\n        className={cn(\n          \"size-3.5\",\n          \"shrink-0 self-center text-subtle-foreground transition-[rotate] duration-180 ease-out-quint motion-reduce:transition-none\",\n          event.open && \"rotate-90\",\n        )}\n      />\n      {children}\n    </CollapsibleTrigger>\n  );\n}\n\nexport function AuditLogActor({ className, ...props }: ComponentProps<\"span\">) {\n  return <span data-slot=\"audit-log-actor\" className={cn(\"font-medium\", className)} {...props} />;\n}\n\nexport function AuditLogAction({ className, ...props }: ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"audit-log-action\"\n      className={cn(\"text-muted-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function AuditLogResource({ className, ...props }: ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"audit-log-resource\"\n      className={cn(\n        \"rounded-md bg-foreground/7 px-1.5 py-px font-mono text-[11.5px]/4 text-foreground wrap-anywhere\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport function AuditLogTimestamp({ className, ...props }: ComponentProps<\"time\">) {\n  return (\n    <time\n      data-slot=\"audit-log-timestamp\"\n      className={cn(\n        \"ml-auto pl-2 text-[12px] whitespace-nowrap text-subtle-foreground tabular-nums\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport function AuditLogEventDetails({ className, ...props }: ComponentProps<\"dl\">) {\n  const log = useLog(\"AuditLogEventDetails\");\n  const event = useEvent(\"AuditLogEventDetails\");\n  const compact = log.variant === \"compact\";\n  return (\n    // Details stay mounted while closed so `aria-controls` always points at an element, and\n    // the row height eases open through `grid-template-rows`. Closed details are inert.\n    <div\n      className={cn(\n        \"grid transition-[grid-template-rows,opacity] duration-300 ease-out-quint motion-reduce:transition-none\",\n        event.open ? \"grid-rows-[1fr] opacity-100\" : \"grid-rows-[0fr] opacity-0\",\n      )}\n    >\n      <div className=\"min-h-0 overflow-hidden\">\n        <dl\n          data-slot=\"audit-log-event-details\"\n          data-state={event.open ? \"open\" : \"closed\"}\n          className={cn(\n            \"grid grid-cols-[minmax(88px,max-content)_minmax(0,1fr)] gap-x-4 gap-y-1.5 bg-background text-xs/4 shadow-[inset_0_0_0_1px_var(--border)]\",\n            compact\n              ? \"mt-0 mr-0 mb-1 ml-6.5 rounded-lg px-2.5 py-2\"\n              : \"mt-0 mr-0 mb-2 ml-7 rounded-[10px] px-3 py-2.5\",\n            className,\n          )}\n          {...props}\n          id={`${event.id}-details`}\n          inert={!event.open}\n        />\n      </div>\n    </div>\n  );\n}\n\nexport function AuditLogDetailLabel({ className, ...props }: ComponentProps<\"dt\">) {\n  return (\n    <dt\n      data-slot=\"audit-log-detail-label\"\n      className={cn(\"text-subtle-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function AuditLogDetailValue({ className, ...props }: ComponentProps<\"dd\">) {\n  return (\n    <dd\n      data-slot=\"audit-log-detail-value\"\n      className={cn(\"m-0 min-w-0 font-medium tabular-nums wrap-anywhere\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function AuditLogEmpty({ className, ...props }: ComponentProps<\"p\">) {\n  return (\n    <p\n      role=\"status\"\n      data-slot=\"audit-log-empty\"\n      className={cn(\n        \"m-0 rounded-[10px] border border-dashed px-3 py-6 text-center text-[12.5px] text-subtle-foreground\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n",
      "type": "registry:ui",
      "target": "@ui/uai/audit-log.tsx"
    }
  ],
  "categories": [
    "data-display"
  ],
  "type": "registry:ui"
}