'use client'
import * as React from 'react'
import Link from '../../embed-shims/next-link'
import { cn } from '../../utils/cn'
import { AssigneeDropdown, type AssigneeDropdownProps } from './assignee-dropdown'
import { SquareAvatar } from './square-avatar'
import { TicketStatusTag, type TicketStatusTagProps } from './ticket-status-tag'
/** A plain-text value, optionally with a trailing image (avatar), leading icon, or click action. */
export interface InfoSectionTextValue {
type?: 'text'
text: string
/** Image shown after the text (e.g. a user or organization avatar). */
imageSrc?: string
/** Initials shown when the image is missing or fails to load. Defaults to `text`. */
imageFallback?: string
/** Avatar shape. Defaults to `round`. */
imageVariant?: 'square' | 'round'
/** Icon shown before the text. */
icon?: React.ReactNode
/** Renders the text as a button; on hover it takes the accent color. */
onClick?: () => void
/**
* Renders the text as a link (Next.js `Link`). Takes precedence over `onClick`.
* A regular click navigates in the same tab; the browser's native new-tab
* affordances (cmd/ctrl-click, "open in new tab") work as usual.
*/
href?: string
/** Force the link to always open in a new tab (sets `target="_blank"`). */
openInNewTab?: boolean
}
/** An inline assignee picker (autocomplete with search). Defaults to the `compact` variant. */
export type InfoSectionAssigneeValue = { type: 'assignee' } & AssigneeDropdownProps
/** An inline status changer (dropdown). Pass `options` + `onSelect` to make it interactive. */
export type InfoSectionStatusValue = { type: 'status' } & TicketStatusTagProps
/** Arbitrary value content. */
export interface InfoSectionCustomValue {
type: 'custom'
content: React.ReactNode
}
export type InfoSectionValue =
| InfoSectionTextValue
| InfoSectionAssigneeValue
| InfoSectionStatusValue
| InfoSectionCustomValue
export interface InfoSectionRow {
/** Stable key for the row. */
id: string
/** Left-side label. */
label: string
/** Right-side value: text (with optional image), assignee picker, status dropdown, or custom node. */
value: InfoSectionValue
}
export interface InfoSectionProps {
/** Optional caption rendered above the card (e.g. "Ticket Details"). */
title?: string
rows: InfoSectionRow[]
className?: string
}
function TextValue({ value }: { value: InfoSectionTextValue }) {
const { text, imageSrc, imageFallback, imageVariant = 'round', icon, onClick, href, openInNewTab } = value
const hasImage = imageSrc !== undefined || imageFallback !== undefined
const interactiveClass = 'truncate text-left text-h4 text-ods-text-primary transition-colors hover:text-ods-accent'
return (
<>
{icon && (
{icon}
)}
{href ? (
{text}
) : onClick ? (
) : (
{text}
)}
{hasImage && (
{title}
}