{
  "name": "chat-message",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "chat-message.tsx",
      "content": "\"use client\";\r\n\r\nimport { createVariants, css, themeVars as theme } from \"@yugnex/core\";\r\nimport type { HTMLAttributes, ReactNode } from \"react\";\r\n\r\nexport type ChatRole = \"user\" | \"assistant\" | \"system\";\r\n\r\nconst rowVariants = createVariants({\r\n  base: {\r\n    display: \"flex\",\r\n    gap: theme.space[3],\r\n    alignItems: \"flex-start\",\r\n    width: \"100%\",\r\n  },\r\n  variants: {\r\n    role: {\r\n      user: { flexDirection: \"row-reverse\" },\r\n      assistant: { flexDirection: \"row\" },\r\n      system: { flexDirection: \"row\", justifyContent: \"center\" },\r\n    },\r\n  },\r\n  defaultVariants: { role: \"assistant\" },\r\n});\r\n\r\nconst bubbleVariants = createVariants({\r\n  base: {\r\n    position: \"relative\",\r\n    maxWidth: \"42rem\",\r\n    padding: `${theme.space[3]} ${theme.space[4]}`,\r\n    borderRadius: theme.radius.lg,\r\n    fontFamily: theme.fontFamily.sans,\r\n    fontSize: theme.fontSize.sm,\r\n    lineHeight: theme.lineHeight.base,\r\n    whiteSpace: \"pre-wrap\",\r\n    wordBreak: \"break-word\",\r\n  },\r\n  variants: {\r\n    role: {\r\n      user: {\r\n        backgroundColor: theme.color.primary,\r\n        color: theme.color.primaryForeground,\r\n        borderBottomRightRadius: theme.radius.sm,\r\n      },\r\n      assistant: {\r\n        backgroundColor: theme.color.muted,\r\n        color: theme.color.foreground,\r\n        borderBottomLeftRadius: theme.radius.sm,\r\n      },\r\n      system: {\r\n        backgroundColor: \"transparent\",\r\n        border: `1px dashed ${theme.color.border}`,\r\n        color: theme.color.mutedForeground,\r\n        fontSize: theme.fontSize.xs,\r\n        textAlign: \"center\",\r\n      },\r\n    },\r\n  },\r\n  defaultVariants: { role: \"assistant\" },\r\n});\r\n\r\nconst avatarSlotClass = css({\r\n  flexShrink: 0,\r\n  marginTop: \"2px\",\r\n});\r\n\r\nconst columnClass = css({\r\n  display: \"flex\",\r\n  flexDirection: \"column\",\r\n  gap: theme.space[1],\r\n  minWidth: 0,\r\n});\r\n\r\nconst metaClass = css({\r\n  display: \"flex\",\r\n  alignItems: \"center\",\r\n  gap: theme.space[2],\r\n  fontSize: theme.fontSize.xs,\r\n  color: theme.color.mutedForeground,\r\n});\r\n\r\nconst actionsClass = css({\r\n  display: \"flex\",\r\n  gap: theme.space[1],\r\n  opacity: 0,\r\n  transitionProperty: \"opacity\",\r\n  transitionDuration: theme.duration.fast,\r\n  '[data-nx-chat-message]:hover &, [data-nx-chat-message]:focus-within &': {\r\n    opacity: 1,\r\n  },\r\n});\r\n\r\nexport interface ChatMessageProps extends Omit<HTMLAttributes<HTMLDivElement>, \"role\"> {\r\n  role?: ChatRole;\r\n  children: ReactNode;\r\n  /** Rendered beside the bubble — pass an <Avatar />, an icon, or omit entirely. */\r\n  avatar?: ReactNode;\r\n  /** Small label above the bubble, e.g. a model name. */\r\n  name?: ReactNode;\r\n  timestamp?: ReactNode;\r\n  /** Copy / retry / feedback controls. Revealed on hover or keyboard focus. */\r\n  actions?: ReactNode;\r\n}\r\n\r\n/**\r\n * One turn in a conversation. `role` drives alignment and color: user messages\r\n * sit right in the primary color, assistant messages left in muted, and system\r\n * messages render centered and de-emphasized.\r\n */\r\nexport function ChatMessage({\r\n  role = \"assistant\",\r\n  children,\r\n  avatar,\r\n  name,\r\n  timestamp,\r\n  actions,\r\n  className,\r\n  ...props\r\n}: ChatMessageProps) {\r\n  return (\r\n    <div data-nx-chat-message=\"\" className={rowVariants({ role, className })} {...props}>\r\n      {avatar && role !== \"system\" ? <div className={avatarSlotClass}>{avatar}</div> : null}\r\n      <div className={columnClass}>\r\n        {name || timestamp ? (\r\n          <div className={metaClass}>\r\n            {name ? <span>{name}</span> : null}\r\n            {timestamp ? <time>{timestamp}</time> : null}\r\n          </div>\r\n        ) : null}\r\n        <div className={bubbleVariants({ role })}>{children}</div>\r\n        {actions ? <div className={actionsClass}>{actions}</div> : null}\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n\r\nconst listClass = css({\r\n  display: \"flex\",\r\n  flexDirection: \"column\",\r\n  gap: theme.space[5],\r\n  width: \"100%\",\r\n});\r\n\r\n/** A vertical stack of <ChatMessage>s with consistent spacing, marked up as a live log for screen readers. */\r\nexport function ChatMessageList({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) {\r\n  return (\r\n    <div\r\n      role=\"log\"\r\n      aria-live=\"polite\"\r\n      aria-relevant=\"additions text\"\r\n      className={className ? `${listClass} ${className}` : listClass}\r\n      {...props}\r\n    >\r\n      {children}\r\n    </div>\r\n  );\r\n}\r\n",
      "type": "registry:component"
    }
  ]
}