1mod components;
26mod groups;
27mod prompt;
28
29pub use components::{ComponentDef, Library, PropDef};
30pub use groups::ComponentGroup;
31pub use prompt::{PromptOptions, generate_prompt};
32
33use std::sync::LazyLock;
34
35pub fn default_library() -> &'static Library {
38 &DEFAULT_LIBRARY
39}
40
41static DEFAULT_LIBRARY: LazyLock<Library> = LazyLock::new(|| Library {
42 root: "Card",
43 components: components::all_components(),
44 groups: groups::default_groups(),
45});
46
47pub fn default_prompt() -> &'static str {
51 &DEFAULT_PROMPT
52}
53
54static DEFAULT_PROMPT: LazyLock<String> =
55 LazyLock::new(|| generate_prompt(default_library(), &PromptOptions::default()));
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn test_default_library_has_components() {
63 let lib = default_library();
64 assert!(!lib.components.is_empty());
65 assert_eq!(lib.root, "Card");
66 }
67
68 #[test]
69 fn test_default_library_has_all_expected_components() {
70 let lib = default_library();
71 let names: Vec<&str> = lib.components.iter().map(|c| c.name).collect();
72
73 assert!(names.contains(&"Stack"));
75 assert!(names.contains(&"Tabs"));
76 assert!(names.contains(&"Accordion"));
77
78 assert!(names.contains(&"Card"));
80 assert!(names.contains(&"TextContent"));
81 assert!(names.contains(&"CodeBlock"));
82
83 assert!(names.contains(&"BarChart"));
85 assert!(names.contains(&"PieChart"));
86 assert!(names.contains(&"LineChart"));
87
88 assert!(names.contains(&"Table"));
90
91 assert!(names.contains(&"Form"));
93 assert!(names.contains(&"Input"));
94 assert!(names.contains(&"Select"));
95
96 assert!(names.contains(&"Button"));
98
99 assert!(names.contains(&"ListBlock"));
101 assert!(names.contains(&"FollowUpBlock"));
102 assert!(names.contains(&"SectionBlock"));
103 }
104
105 #[test]
106 fn test_default_prompt_not_empty() {
107 let prompt = default_prompt();
108 assert!(!prompt.is_empty());
109 assert!(prompt.len() > 500);
110 }
111
112 #[test]
113 fn test_default_prompt_contains_key_sections() {
114 let prompt = default_prompt();
115 assert!(prompt.contains("## Syntax Rules"));
116 assert!(prompt.contains("## Component Signatures"));
117 assert!(prompt.contains("## Hoisting & Streaming"));
118 assert!(prompt.contains("## Important Rules"));
119 }
120
121 #[test]
122 fn test_default_prompt_instructs_openui_code_blocks() {
123 let prompt = default_prompt();
124 assert!(prompt.contains("```openui"));
125 }
126
127 #[test]
128 fn test_component_count() {
129 let lib = default_library();
130 assert!(
132 lib.components.len() >= 50,
133 "Expected at least 50 components, got {}",
134 lib.components.len()
135 );
136 }
137
138 #[test]
139 fn test_groups_cover_all_components() {
140 let lib = default_library();
141 let grouped: Vec<&str> = lib
142 .groups
143 .iter()
144 .flat_map(|g| g.components.iter().copied())
145 .collect();
146
147 for comp in &lib.components {
148 assert!(
149 grouped.contains(&comp.name),
150 "Component '{}' is not in any group",
151 comp.name
152 );
153 }
154 }
155
156 #[test]
157 fn test_prompt_contains_all_component_signatures() {
158 let lib = default_library();
159 let prompt = default_prompt();
160
161 for comp in &lib.components {
162 assert!(
163 prompt.contains(&format!("{}(", comp.name)),
164 "Prompt missing signature for component '{}'",
165 comp.name
166 );
167 }
168 }
169}