Skip to main content

everruns_openui/
groups.rs

1//! Component groups for organized prompt output.
2//!
3//! Groups organize components into logical categories in the generated prompt.
4//! This mirrors the `componentGroups` array in the TypeScript library.
5//!
6//! Ref: packages/react-ui/src/genui-lib/openuiChatLibrary.tsx
7
8/// A logical group of components for prompt organization.
9///
10/// Ref: packages/react-lang/src/library.ts `ComponentGroup` interface
11pub struct ComponentGroup {
12    /// Group display name (e.g., "Content", "Layout")
13    pub name: &'static str,
14    /// Component names belonging to this group
15    pub components: Vec<&'static str>,
16    /// Optional notes appended after the group's component signatures
17    pub notes: Vec<&'static str>,
18}
19
20/// Returns the default component groups for the chat library.
21///
22/// Ref: packages/react-ui/src/genui-lib/openuiChatLibrary.tsx `openuiChatComponentGroups`
23pub fn default_groups() -> Vec<ComponentGroup> {
24    vec![
25        // Ref: openuiChatLibrary.tsx — Content group
26        ComponentGroup {
27            name: "Content",
28            components: vec![
29                "CardHeader",
30                "TextContent",
31                "MarkDownRenderer",
32                "Callout",
33                "TextCallout",
34                "Image",
35                "ImageBlock",
36                "ImageGallery",
37                "CodeBlock",
38                "Separator",
39            ],
40            notes: vec![],
41        },
42        // Ref: openuiChatLibrary.tsx — Tables group
43        ComponentGroup {
44            name: "Tables",
45            components: vec!["Table", "Col"],
46            notes: vec![],
47        },
48        // Ref: openuiChatLibrary.tsx — Charts (2D) group
49        ComponentGroup {
50            name: "Charts (2D)",
51            components: vec![
52                "BarChart",
53                "LineChart",
54                "AreaChart",
55                "RadarChart",
56                "HorizontalBarChart",
57                "Series",
58            ],
59            notes: vec![],
60        },
61        // Ref: openuiChatLibrary.tsx — Charts (1D) group
62        ComponentGroup {
63            name: "Charts (1D)",
64            components: vec!["PieChart", "RadialChart", "SingleStackedBarChart", "Slice"],
65            notes: vec![],
66        },
67        // Ref: openuiChatLibrary.tsx — Charts (Scatter) group
68        ComponentGroup {
69            name: "Charts (Scatter)",
70            components: vec!["ScatterChart", "ScatterSeries", "Point"],
71            notes: vec![],
72        },
73        // Ref: openuiChatLibrary.tsx — Forms group
74        ComponentGroup {
75            name: "Forms",
76            components: vec![
77                "Form",
78                "FormControl",
79                "Label",
80                "Input",
81                "TextArea",
82                "Select",
83                "SelectItem",
84                "DatePicker",
85                "Slider",
86                "CheckBoxGroup",
87                "CheckBoxItem",
88                "RadioGroup",
89                "RadioItem",
90                "SwitchGroup",
91                "SwitchItem",
92            ],
93            notes: vec![],
94        },
95        // Ref: openuiChatLibrary.tsx — Buttons group
96        ComponentGroup {
97            name: "Buttons",
98            components: vec!["Button", "Buttons"],
99            notes: vec![
100                "The `action` prop type accepts: ContinueConversation (sends message to LLM), OpenUrl (navigates to URL), or Custom (app-defined).",
101            ],
102        },
103        // Ref: openuiChatLibrary.tsx — Lists & Follow-ups group
104        ComponentGroup {
105            name: "Lists & Follow-ups",
106            components: vec!["ListBlock", "ListItem", "FollowUpBlock", "FollowUpItem"],
107            notes: vec![],
108        },
109        // Ref: openuiChatLibrary.tsx — Sections group
110        ComponentGroup {
111            name: "Sections",
112            components: vec!["SectionBlock", "SectionItem"],
113            notes: vec![],
114        },
115        // Ref: openuiChatLibrary.tsx — Layout group
116        ComponentGroup {
117            name: "Layout",
118            components: vec![
119                "Stack",
120                "Card",
121                "Tabs",
122                "TabItem",
123                "Accordion",
124                "AccordionItem",
125                "Steps",
126                "StepsItem",
127                "Carousel",
128            ],
129            notes: vec![],
130        },
131        // Ref: openuiChatLibrary.tsx — Data Display group
132        ComponentGroup {
133            name: "Data Display",
134            components: vec!["TagBlock", "Tag"],
135            notes: vec![],
136        },
137    ]
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn test_groups_not_empty() {
146        let groups = default_groups();
147        assert!(!groups.is_empty());
148    }
149
150    #[test]
151    fn test_no_empty_groups() {
152        let groups = default_groups();
153        for group in &groups {
154            assert!(
155                !group.components.is_empty(),
156                "Group '{}' has no components",
157                group.name
158            );
159        }
160    }
161
162    #[test]
163    fn test_no_duplicate_components_across_groups() {
164        let groups = default_groups();
165        let mut seen = std::collections::HashSet::new();
166        for group in &groups {
167            for comp in &group.components {
168                assert!(
169                    seen.insert(*comp),
170                    "Component '{}' appears in multiple groups",
171                    comp
172                );
173            }
174        }
175    }
176}