/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import type React from 'react'; import { useCallback } from 'react'; import { Text } from 'ink'; import { theme } from '../../semantic-colors.js'; import { BaseSelectionList, type RenderItemContext, } from './BaseSelectionList.js'; import type { SelectionListItem } from '../../hooks/useSelectionList.js'; /** * Represents a single option for the RadioButtonSelect. * Requires a label for display and a value to be returned on selection. */ export interface RadioSelectItem extends SelectionListItem { label: string; themeNameDisplay?: string; themeTypeDisplay?: string; } /** * Props for the RadioButtonSelect component. * @template T The type of the value associated with each radio item. * @template TItem The type of the item, extending RadioSelectItem. */ export interface RadioButtonSelectProps< T, TItem extends RadioSelectItem = RadioSelectItem, > { /** An array of items to display as radio options. */ items: TItem[]; /** The initial index selected */ initialIndex?: number; /** Function called when an item is selected. Receives the `value` of the selected item. */ onSelect: (value: T) => void; /** Function called when an item is highlighted. Receives the `value` of the selected item. */ onHighlight?: (value: T) => void; /** Whether this select input is currently focused and should respond to input. */ isFocused?: boolean; /** Whether to show the scroll arrows. */ showScrollArrows?: boolean; /** The maximum number of items to show at once. */ maxItemsToShow?: number; /** Whether to show numbers next to items. */ showNumbers?: boolean; /** Optional custom render function for items. If not provided, uses default rendering. */ renderItem?: (item: TItem, context: RenderItemContext) => React.ReactNode; } /** * A custom component that displays a list of items with radio buttons, * supporting scrolling and keyboard navigation. * * @template T The type of the value associated with each radio item. * @template TItem The type of the item, extending RadioSelectItem. */ export function RadioButtonSelect< T, TItem extends RadioSelectItem = RadioSelectItem, >({ items, initialIndex = 0, onSelect, onHighlight, isFocused = true, showScrollArrows = false, maxItemsToShow = 10, showNumbers = true, renderItem: customRenderItem, }: RadioButtonSelectProps): React.JSX.Element { const defaultRenderItem = useCallback( (item: TItem, { titleColor }: RenderItemContext) => { // Handle special theme display case for ThemeDialog compatibility if (item.themeNameDisplay && item.themeTypeDisplay) { return ( {item.themeNameDisplay}{' '} {item.themeTypeDisplay} ); } // Regular label display return ( {item.label} ); }, [], ); const renderItem = customRenderItem ?? defaultRenderItem; return ( items={items} initialIndex={initialIndex} onSelect={onSelect} onHighlight={onHighlight} isFocused={isFocused} showNumbers={showNumbers} showScrollArrows={showScrollArrows} maxItemsToShow={maxItemsToShow} renderItem={renderItem} /> ); }