2025-04-22 18:25:03 -07:00
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright 2025 Google LLC
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*/
|
|
|
|
|
|
2025-08-26 00:04:53 +02:00
|
|
|
import type React from 'react';
|
2025-09-22 11:14:41 -04:00
|
|
|
import { Text } from 'ink';
|
2025-09-10 10:57:07 -07:00
|
|
|
import { theme } from '../../semantic-colors.js';
|
2025-09-22 11:14:41 -04:00
|
|
|
import { BaseSelectionList } from './BaseSelectionList.js';
|
2025-04-22 18:25:03 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Represents a single option for the RadioButtonSelect.
|
|
|
|
|
* Requires a label for display and a value to be returned on selection.
|
|
|
|
|
*/
|
|
|
|
|
export interface RadioSelectItem<T> {
|
|
|
|
|
label: string;
|
|
|
|
|
value: T;
|
2025-06-12 02:21:54 +01:00
|
|
|
disabled?: boolean;
|
2025-07-11 18:05:21 -07:00
|
|
|
themeNameDisplay?: string;
|
|
|
|
|
themeTypeDisplay?: string;
|
2025-04-22 18:25:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Props for the RadioButtonSelect component.
|
|
|
|
|
* @template T The type of the value associated with each radio item.
|
|
|
|
|
*/
|
|
|
|
|
export interface RadioButtonSelectProps<T> {
|
|
|
|
|
/** An array of items to display as radio options. */
|
2025-07-11 18:05:21 -07:00
|
|
|
items: Array<RadioSelectItem<T>>;
|
2025-04-22 18:25:03 -07:00
|
|
|
/** The initial index selected */
|
|
|
|
|
initialIndex?: number;
|
|
|
|
|
/** Function called when an item is selected. Receives the `value` of the selected item. */
|
|
|
|
|
onSelect: (value: T) => void;
|
2025-04-24 11:36:34 -07:00
|
|
|
/** Function called when an item is highlighted. Receives the `value` of the selected item. */
|
|
|
|
|
onHighlight?: (value: T) => void;
|
2025-05-01 10:34:07 -07:00
|
|
|
/** Whether this select input is currently focused and should respond to input. */
|
|
|
|
|
isFocused?: boolean;
|
2025-07-11 18:05:21 -07:00
|
|
|
/** Whether to show the scroll arrows. */
|
|
|
|
|
showScrollArrows?: boolean;
|
|
|
|
|
/** The maximum number of items to show at once. */
|
|
|
|
|
maxItemsToShow?: number;
|
2025-07-17 15:51:42 -07:00
|
|
|
/** Whether to show numbers next to items. */
|
|
|
|
|
showNumbers?: boolean;
|
2025-04-22 18:25:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2025-07-11 18:05:21 -07:00
|
|
|
* A custom component that displays a list of items with radio buttons,
|
|
|
|
|
* supporting scrolling and keyboard navigation.
|
2025-04-22 18:25:03 -07:00
|
|
|
*
|
|
|
|
|
* @template T The type of the value associated with each radio item.
|
|
|
|
|
*/
|
|
|
|
|
export function RadioButtonSelect<T>({
|
|
|
|
|
items,
|
2025-07-11 18:05:21 -07:00
|
|
|
initialIndex = 0,
|
2025-04-22 18:25:03 -07:00
|
|
|
onSelect,
|
2025-04-24 11:36:34 -07:00
|
|
|
onHighlight,
|
2025-08-14 16:48:54 -07:00
|
|
|
isFocused = true,
|
2025-07-12 20:58:00 -07:00
|
|
|
showScrollArrows = false,
|
2025-07-11 18:05:21 -07:00
|
|
|
maxItemsToShow = 10,
|
2025-07-17 15:51:42 -07:00
|
|
|
showNumbers = true,
|
2025-04-22 18:25:03 -07:00
|
|
|
}: RadioButtonSelectProps<T>): React.JSX.Element {
|
2025-07-11 18:05:21 -07:00
|
|
|
return (
|
2025-09-22 11:14:41 -04:00
|
|
|
<BaseSelectionList<T, RadioSelectItem<T>>
|
|
|
|
|
items={items}
|
|
|
|
|
initialIndex={initialIndex}
|
|
|
|
|
onSelect={onSelect}
|
|
|
|
|
onHighlight={onHighlight}
|
|
|
|
|
isFocused={isFocused}
|
|
|
|
|
showNumbers={showNumbers}
|
|
|
|
|
showScrollArrows={showScrollArrows}
|
|
|
|
|
maxItemsToShow={maxItemsToShow}
|
|
|
|
|
renderItem={(item, { titleColor }) => {
|
|
|
|
|
// Handle special theme display case for ThemeDialog compatibility
|
|
|
|
|
if (item.themeNameDisplay && item.themeTypeDisplay) {
|
|
|
|
|
return (
|
|
|
|
|
<Text color={titleColor} wrap="truncate">
|
|
|
|
|
{item.themeNameDisplay}{' '}
|
|
|
|
|
<Text color={theme.text.secondary}>{item.themeTypeDisplay}</Text>
|
|
|
|
|
</Text>
|
|
|
|
|
);
|
2025-07-11 18:05:21 -07:00
|
|
|
}
|
2025-09-22 11:14:41 -04:00
|
|
|
// Regular label display
|
2025-07-11 18:05:21 -07:00
|
|
|
return (
|
2025-09-22 11:14:41 -04:00
|
|
|
<Text color={titleColor} wrap="truncate">
|
|
|
|
|
{item.label}
|
|
|
|
|
</Text>
|
2025-07-11 18:05:21 -07:00
|
|
|
);
|
2025-09-22 11:14:41 -04:00
|
|
|
}}
|
|
|
|
|
/>
|
2025-04-22 18:25:03 -07:00
|
|
|
);
|
|
|
|
|
}
|