import React, { HTMLAttributes, forwardRef } from "react";
import type { AkselStatusColorRole } from "@navikt/ds-tokens/types";
import { AkselColor } from "../types";
import { BodyLong, HeadingProps } from "../typography";
import { cl } from "../utils/helpers";
import Bubble, { type ChatBubbleProps } from "./Bubble";
export const VARIANTS = ["subtle", "info", "neutral"] as const;
export const POSITIONS = ["left", "right"] as const;
export const SIZES = ["medium", "small"] as const;
interface ChatProps extends HTMLAttributes {
/**
* Children of type ``.
*/
children: React.ReactNode;
/**
* Name/sender on first bubble.
*/
name?: string;
/**
* Timestamp on first bubble.
*/
timestamp?: string;
/**
* We recommend using an SVG or plain text initials as avatar.
*
* **Hidden for screen readers.**
*/
avatar?: React.ReactNode;
/**
* @deprecated Use `data-color` prop instead.
*/
variant?: (typeof VARIANTS)[number];
/**
* Positions avatar and bubbles.
* @default "left"
*/
position?: (typeof POSITIONS)[number];
/**
* Horizontal position of toptext.
* @default Same as position
*/
toptextPosition?: (typeof POSITIONS)[number];
/**
* Affects padding and font size in bubbles.
* @default "medium"
*/
size?: (typeof SIZES)[number];
/**
* The heading level for the toptext.
* @default "3"
*/
toptextHeadingLevel?: Exclude;
/**
* Overrides inherited color.
*
* We have disallowed status-colors.
* @see 🏷️ {@link AkselColor}
* @see [📝 Documentation](https://aksel.nav.no/grunnleggende/styling/farger-tokens)
*/
"data-color"?: Exclude;
}
interface ChatComponent extends React.ForwardRefExoticComponent<
ChatProps & React.RefAttributes
> {
/**
* @see 🏷️ {@link ChatBubbleProps}
*/
Bubble: typeof Bubble;
}
/**
* A component for communicating a dialog between two or more parties.
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/chat)
* @see 🏷️ {@link ChatProps}
*
* @example
* ```jsx
*
* Hello!
* How can I help you?
*
*
* Hi there!
*
* ```
*/
export const Chat = forwardRef(
(
{
children,
className,
name,
timestamp,
avatar,
position = "left",
variant = "neutral",
toptextPosition,
size = "medium",
toptextHeadingLevel = "3",
"data-color": color,
...rest
}: ChatProps,
ref,
) => {
return (
{avatar && (
{avatar}
)}
{React.Children.map(children, (child, i) => {
if (!React.isValidElement(child)) {
return null;
}
return React.cloneElement(child, {
name: name && i === 0 ? name : undefined,
timestamp: timestamp && i === 0 ? timestamp : undefined,
toptextHeadingLevel,
...child.props,
});
})}
);
},
) as ChatComponent;
function variantToColor(variant: ChatProps["variant"]): AkselColor {
switch (variant) {
case "neutral":
return "neutral";
case "subtle":
return "neutral";
case "info":
return "info";
default:
return "neutral";
}
}
Chat.Bubble = Bubble;
export default Chat;
export { Bubble as ChatBubble };
export type { ChatProps, ChatBubbleProps };