UNPKG

prprompts-flutter-generator

Version:

AI-powered Flutter development with full automation + official extension support - Generate 32 security-audited guides & auto-implement in 2-3 hours. NEW v5.1: Official Claude Code plugin with hooks, Gemini TOML commands, Qwen MCP settings. Features: Comp

382 lines (338 loc) 9.89 kB
# React to Flutter Widget Tree Conversion - Live Examples ## Example 1: Simple Login Form ### Before (React Native) ```jsx function LoginForm({ onSubmit }) { return ( <View> <Text>Login</Text> <TextInput placeholder="Email" keyboardType="email-address" autoFocus={true} /> <TextInput placeholder="Password" secureTextEntry={true} /> <TouchableOpacity onPress={onSubmit}> <Text>Login</Text> </TouchableOpacity> </View> ); } ``` ### After (Flutter - Widget Tree) ```dart WidgetChild { name: 'Container', type: 'Container', properties: {}, children: [ WidgetChild { name: 'Text', properties: { data: "'Login'" } }, WidgetChild { name: 'TextField', properties: { hintText: "'Email'", keyboardType: 'email-address', autofocus: 'true' } }, WidgetChild { name: 'TextField', properties: { hintText: "'Password'", obscureText: 'true' } }, WidgetChild { name: 'InkWell', properties: { onTap: 'onSubmit' }, children: [ WidgetChild { name: 'Text', properties: { data: "'Login'" } } ] } ] } ``` ## Example 2: User List with Conditional Rendering ### Before (React) ```jsx function UserList({ users, loading, onUserClick }) { return ( <ScrollView> <Text>Users</Text> {loading ? ( <ActivityIndicator /> ) : ( users.map(user => ( <TouchableOpacity key={user.id} onPress={() => onUserClick(user)} > <View> <Text>{user.name}</Text> <Text>{user.email}</Text> </View> </TouchableOpacity> )) )} </ScrollView> ); } ``` ### After (Flutter - Widget Tree) ```dart WidgetChild { name: 'SingleChildScrollView', type: 'SingleChildScrollView', children: [ WidgetChild { name: 'Text', properties: { data: "'Users'" } }, WidgetChild { name: 'Builder', type: 'Builder', properties: { builder: '(context) => loading ? CircularProgressIndicator() : ListView.builder(...)' } } ] } // The ListView.builder is generated as: WidgetChild { name: 'ListView.builder', properties: { itemCount: 'users.length', itemBuilder: '(context, index) { final user = users[index]; return InkWell(onTap: () => onUserClick(user), child: Container(children: [Text(user.name), Text(user.email)])); }' } } ``` ## Example 3: Product Card with Image ### Before (React Native) ```jsx function ProductCard({ product, onAddToCart }) { return ( <View> <Image source={{ uri: product.imageUrl }} /> <Text>{product.name}</Text> <Text>${product.price}</Text> {product.inStock ? ( <Button title="Add to Cart" onPress={() => onAddToCart(product)} /> ) : ( <Text>Out of Stock</Text> )} </View> ); } ``` ### After (Flutter - Widget Tree) ```dart WidgetChild { name: 'Container', type: 'Container', children: [ WidgetChild { name: 'Image', properties: { image: 'NetworkImage(product.imageUrl)' } }, WidgetChild { name: 'Text', properties: { data: 'product.name' } }, WidgetChild { name: 'Text', properties: { data: '"\$${product.price}"' } }, WidgetChild { name: 'Builder', properties: { builder: '(context) => product.inStock ? ElevatedButton(onTap: () => onAddToCart(product), child: Text(\'Add to Cart\')) : Text(\'Out of Stock\')' } } ] } ``` ## Example 4: Search Input with Filter ### Before (React) ```jsx function SearchableList({ items, placeholder }) { const [query, setQuery] = useState(''); const filtered = items.filter(item => item.name.toLowerCase().includes(query.toLowerCase()) ); return ( <> <TextInput placeholder={placeholder} onChangeText={setQuery} value={query} /> {filtered.length > 0 && ( filtered.map(item => ( <View key={item.id}> <Text>{item.name}</Text> </View> )) )} </> ); } ``` ### After (Flutter - Widget Tree) ```dart // Fragment returns array of widgets: [ WidgetChild { name: 'TextField', properties: { hintText: 'placeholder', onChanged: 'setQuery', controller: 'TextEditingController(text: query)' } }, WidgetChild { name: 'Builder', properties: { builder: '(context) => filtered.length > 0 ? ListView.builder(itemCount: filtered.length, itemBuilder: (context, index) { final item = filtered[index]; return Container(child: Text(item.name)); }) : const SizedBox.shrink()' } } ] ``` ## Example 5: Settings Toggle List ### Before (React Native) ```jsx function SettingsList({ settings, onToggle }) { return ( <ScrollView> <Text>Settings</Text> {settings.map(setting => ( <View key={setting.id}> <Text>{setting.label}</Text> <Switch value={setting.enabled} onValueChange={() => onToggle(setting.id)} /> </View> ))} </ScrollView> ); } ``` ### After (Flutter - Widget Tree) ```dart WidgetChild { name: 'SingleChildScrollView', children: [ WidgetChild { name: 'Text', properties: { data: "'Settings'" } }, WidgetChild { name: 'ListView.builder', properties: { itemCount: 'settings.length', itemBuilder: '(context, index) { final setting = settings[index]; return Container(children: [Text(setting.label), Switch(value: setting.enabled, onValueChange: () => onToggle(setting.id))]); }' } } ] } ``` ## Conversion Statistics ### Files Modified 1. **lib/refactoring/generators/WidgetGenerator.js** - 925 lines (+606 lines) - Complete JSX traversal implementation - 15+ new methods for conversion - Full support for all JSX node types 2. **lib/refactoring/generators/utils/widgetMapper.js** - 323 lines (+60 lines) - 60+ widget mappings (React/HTML → Flutter) - 30+ property mappings - Enhanced event handler mappings 3. **tests/refactoring/generators/WidgetGenerator.test.js** - 472 lines (+247 lines) - 43 total tests (27 new tests for JSX conversion) - 100% coverage of conversion features ### Features Implemented ✅ **Basic Elements** - View, Text, Image, etc. ✅ **Interactive Elements** - TouchableOpacity, Button, TextInput ✅ **Lists** - Array.map(), FlatList → ListView.builder ✅ **Conditionals** - Ternary operators, logical AND ✅ **Fragments** - <> and <Fragment> ✅ **Event Handlers** - onClick → onTap, onChange → onChanged ✅ **Props Conversion** - placeholder → hintText, etc. ✅ **Images** - Network and asset images ✅ **Layout** - ScrollView, SafeAreaView, etc. ✅ **Children Handling** - Single child vs multiple children ✅ **Text Nodes** - Automatic Text widget wrapping ✅ **Whitespace** - Proper whitespace handling ✅ **Nested Components** - Recursive tree building ### Test Results ``` Test Suites: 2 passed, 2 total Tests: 59 passed, 59 total Snapshots: 0 total Time: 0.453s ``` ## Key Conversion Patterns ### 1. Element Mapping - React Native components → Flutter widgets - HTML elements → Flutter widgets - Custom components → Pass-through ### 2. Property Conversion - Event handlers: `onPress` → `onTap` - Text input: `placeholder` → `hintText` - Security: `secureTextEntry` → `obscureText` - Layout: `numberOfLines` → `maxLines` ### 3. Children Handling - Single child: `child: Widget()` - Multiple children: `children: [Widget1(), Widget2()]` - Auto-detection based on widget type ### 4. Special Cases - Fragments: Return array of children - Conditionals: Wrap in Builder widget - Lists: Convert to ListView.builder - Text nodes: Auto-wrap in Text widget ## Remaining Enhancements While the core JSX conversion is complete, these areas can be enhanced: 1. **Style Integration** - Full CSS/inline style conversion (placeholder exists) 2. **Animation Conversion** - React animations → Flutter animations 3. **Navigation** - React Router → Flutter Navigator 4. **State Management** - Redux/MobX → BLoC/Provider mapping 5. **Custom Components** - User-defined component mappings 6. **Advanced Expressions** - Complex JavaScript expressions These are documented in the TODO comments and can be implemented as follow-up work. ## API Usage ```javascript const { WidgetGenerator } = require('./WidgetGenerator'); const parser = require('@babel/parser'); // Create generator const generator = new WidgetGenerator(); // Parse JSX const jsx = parser.parse('<View><Text>Hello</Text></View>', { plugins: ['jsx'] }); // Generate widget tree const widget = generator.generateWidgetTree(jsx.program.body[0].expression); // Result: // WidgetChild { // name: 'Container', // properties: {}, // children: [WidgetChild { name: 'Text', ... }] // } ``` ## Integration Points The `generateWidgetTree()` method integrates with: 1. **ReactParser** - Extracts JSX from React components 2. **ComponentModel** - Stores component metadata 3. **WidgetModel** - Stores Flutter widget structure 4. **CodeGenerator** - Generates Dart code from widget tree 5. **Validation** - Validates generated code This creates a complete React → Flutter conversion pipeline.