mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-15 02:42:45 +08:00
feat: Enhance A2UI with RadioGroup and Markdown support
- Added support for RadioGroup component in A2UI, allowing single selection from multiple options. - Implemented Markdown parsing in A2UIPopupCard for better content rendering. - Updated A2UIPopupCard to handle different question types and improved layout for multi-select and single-select questions. - Introduced new utility functions for handling disabled items during installation. - Enhanced installation process to restore previously disabled skills and commands. - Updated notification store and related tests to accommodate new features. - Adjusted Vite configuration for better development experience.
This commit is contained in:
@@ -104,6 +104,19 @@ export const CheckboxComponentSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
/** RadioGroup component - single selection from multiple options */
|
||||
export const RadioGroupComponentSchema = z.object({
|
||||
RadioGroup: z.object({
|
||||
options: z.array(z.object({
|
||||
label: TextContentSchema,
|
||||
value: z.string(),
|
||||
description: TextContentSchema.optional(),
|
||||
})),
|
||||
selectedValue: TextContentSchema.optional(),
|
||||
onChange: ActionSchema,
|
||||
}),
|
||||
});
|
||||
|
||||
/** Code block component */
|
||||
export const CodeBlockComponentSchema = z.object({
|
||||
CodeBlock: z.object({
|
||||
@@ -160,6 +173,7 @@ export const ComponentSchema: z.ZodType<any> = z.union([
|
||||
TextFieldComponentSchema,
|
||||
TextAreaComponentSchema,
|
||||
CheckboxComponentSchema,
|
||||
RadioGroupComponentSchema,
|
||||
CodeBlockComponentSchema,
|
||||
ProgressComponentSchema,
|
||||
CardComponentSchema,
|
||||
@@ -202,6 +216,7 @@ export type DropdownComponent = z.infer<typeof DropdownComponentSchema>;
|
||||
export type TextFieldComponent = z.infer<typeof TextFieldComponentSchema>;
|
||||
export type TextAreaComponent = z.infer<typeof TextAreaComponentSchema>;
|
||||
export type CheckboxComponent = z.infer<typeof CheckboxComponentSchema>;
|
||||
export type RadioGroupComponent = z.infer<typeof RadioGroupComponentSchema>;
|
||||
export type CodeBlockComponent = z.infer<typeof CodeBlockComponentSchema>;
|
||||
export type ProgressComponent = z.infer<typeof ProgressComponentSchema>;
|
||||
export type CardComponent = z.infer<typeof CardComponentSchema>;
|
||||
@@ -223,6 +238,7 @@ export type A2UIComponentType =
|
||||
| 'TextField'
|
||||
| 'TextArea'
|
||||
| 'Checkbox'
|
||||
| 'RadioGroup'
|
||||
| 'CodeBlock'
|
||||
| 'Progress'
|
||||
| 'Card'
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// ========================================
|
||||
// A2UI RadioGroup Component Renderer
|
||||
// ========================================
|
||||
// Maps A2UI RadioGroup component to shadcn/ui RadioGroup
|
||||
// Used for single-select questions with visible options
|
||||
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/RadioGroup';
|
||||
import { Label } from '@/components/ui/Label';
|
||||
import type { ComponentRenderer } from '../../core/A2UIComponentRegistry';
|
||||
import { resolveLiteralOrBinding, resolveTextContent } from '../A2UIRenderer';
|
||||
import type { RadioGroupComponent } from '../../core/A2UITypes';
|
||||
|
||||
interface A2UIRadioGroupProps {
|
||||
component: RadioGroupComponent;
|
||||
state: Record<string, unknown>;
|
||||
onAction: (actionId: string, params: Record<string, unknown>) => void | Promise<void>;
|
||||
resolveBinding: (binding: { path: string }) => unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* A2UI RadioGroup Component Renderer
|
||||
* Single selection from visible options with onChange handler
|
||||
*/
|
||||
export const A2UIRadioGroup: ComponentRenderer = ({ component, state, onAction, resolveBinding }) => {
|
||||
const radioGroupComp = component as RadioGroupComponent;
|
||||
const { RadioGroup: radioConfig } = radioGroupComp;
|
||||
|
||||
// Resolve initial selected value from binding
|
||||
const getInitialValue = (): string | undefined => {
|
||||
if (!radioConfig.selectedValue) return undefined;
|
||||
const resolved = resolveLiteralOrBinding(radioConfig.selectedValue, resolveBinding);
|
||||
return resolved ? String(resolved) : undefined;
|
||||
};
|
||||
|
||||
// Local state for controlled radio group
|
||||
const [selectedValue, setSelectedValue] = useState<string | undefined>(getInitialValue());
|
||||
|
||||
// Handle change with action dispatch
|
||||
const handleChange = useCallback((newValue: string) => {
|
||||
setSelectedValue(newValue);
|
||||
|
||||
// Trigger action with new selected value
|
||||
onAction(radioConfig.onChange.actionId, {
|
||||
value: newValue,
|
||||
...(radioConfig.onChange.parameters || {}),
|
||||
});
|
||||
}, [radioConfig.onChange, onAction]);
|
||||
|
||||
return (
|
||||
<RadioGroup value={selectedValue} onValueChange={handleChange} className="space-y-2">
|
||||
{radioConfig.options.map((option, idx) => {
|
||||
const labelText = resolveTextContent(option.label, resolveBinding);
|
||||
const descriptionText = option.description
|
||||
? resolveTextContent(option.description, resolveBinding)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div key={option.value || idx} className="flex items-start space-x-3 py-1">
|
||||
<RadioGroupItem
|
||||
value={option.value}
|
||||
id={`radio-${option.value}`}
|
||||
className="mt-0.5"
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<Label
|
||||
htmlFor={`radio-${option.value}`}
|
||||
className="text-sm font-medium leading-none cursor-pointer"
|
||||
>
|
||||
{labelText}
|
||||
</Label>
|
||||
{descriptionText && (
|
||||
<span className="text-xs text-muted-foreground mt-1">
|
||||
{descriptionText}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</RadioGroup>
|
||||
);
|
||||
};
|
||||
@@ -14,6 +14,7 @@ import { A2UIDropdown } from './A2UIDropdown';
|
||||
import { A2UITextField } from './A2UITextField';
|
||||
import { A2UITextArea } from './A2UITextArea';
|
||||
import { A2UICheckbox } from './A2UICheckbox';
|
||||
import { A2UIRadioGroup } from './A2UIRadioGroup';
|
||||
import { A2UIProgress } from './A2UIProgress';
|
||||
import { A2UICard } from './A2UICard';
|
||||
import { A2UICLIOutput } from './A2UICLIOutput';
|
||||
@@ -27,6 +28,7 @@ a2uiRegistry.register('Dropdown' as A2UIComponentType, A2UIDropdown);
|
||||
a2uiRegistry.register('TextField' as A2UIComponentType, A2UITextField);
|
||||
a2uiRegistry.register('TextArea' as A2UIComponentType, A2UITextArea);
|
||||
a2uiRegistry.register('Checkbox' as A2UIComponentType, A2UICheckbox);
|
||||
a2uiRegistry.register('RadioGroup' as A2UIComponentType, A2UIRadioGroup);
|
||||
a2uiRegistry.register('Progress' as A2UIComponentType, A2UIProgress);
|
||||
a2uiRegistry.register('Card' as A2UIComponentType, A2UICard);
|
||||
a2uiRegistry.register('CLIOutput' as A2UIComponentType, A2UICLIOutput);
|
||||
@@ -39,6 +41,7 @@ export * from './A2UIDropdown';
|
||||
export * from './A2UITextField';
|
||||
export * from './A2UITextArea';
|
||||
export * from './A2UICheckbox';
|
||||
export * from './A2UIRadioGroup';
|
||||
export * from './A2UIProgress';
|
||||
export * from './A2UICard';
|
||||
export * from './A2UICLIOutput';
|
||||
|
||||
Reference in New Issue
Block a user