syntaxify 0.1.0-alpha.8 copy "syntaxify: ^0.1.0-alpha.8" to clipboard
syntaxify: ^0.1.0-alpha.8 copied to clipboard

AST-based Flutter UI code generator with multi-style design system. Write components once, render in Material, Cupertino, or custom designs.

example/lib/main.dart

// ============================================
// SYNTAXIFY DEMO APP
// ============================================
// This demo shows what comes from Syntaxify vs native Flutter
//
// LEGEND:
// 🎨 SYNTAXIFY - Design system features (AppTheme, styles)
// 🎯 SYNTAXIFY - Button components (AppButton)
// 📝 SYNTAXIFY - Text components (AppText)
// ⌨️  SYNTAXIFY - Input components (AppInput)
// 🌟 SYNTAXIFY - Generated screens from .screen.dart files
// [No emoji] - Native Flutter widgets
// ============================================

// Native Flutter imports
import 'package:flutter/material.dart';

// Syntaxify imports - generated components and design system
import 'package:example/syntaxify/index.dart';

// Generated screen from meta/login.screen.dart
import 'package:example/screens/login_screen.dart';

// Tabs
import 'package:example/overview_tab.dart';

void main() {
  runApp(const MyApp()); // Native Flutter
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  DesignStyle _currentStyle = MaterialStyle();
  String _currentStyleName = 'Material';

  void _switchStyle(DesignStyle style, String name) {
    setState(() {
      _currentStyle = style;
      _currentStyleName = name;
    });
  }

  @override
  Widget build(BuildContext context) {
    return AppTheme(
      // 🎨 SYNTAXIFY: Design system wrapper
      style: _currentStyle, // Switch between Material/Cupertino/Neo
      child: MaterialApp(
        // Native Flutter
        title: 'Syntaxify Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
          useMaterial3: true,
        ),
        home: SyntaxifyDemoScreen(
          currentStyleName: _currentStyleName,
          onStyleChanged: _switchStyle,
        ),
      ),
    );
  }
}

class SyntaxifyDemoScreen extends StatefulWidget {
  final String currentStyleName;
  final Function(DesignStyle, String) onStyleChanged;

  const SyntaxifyDemoScreen({
    super.key,
    required this.currentStyleName,
    required this.onStyleChanged,
  });

  @override
  State<SyntaxifyDemoScreen> createState() => _SyntaxifyDemoScreenState();
}

class _SyntaxifyDemoScreenState extends State<SyntaxifyDemoScreen>
    with SingleTickerProviderStateMixin {
  late TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 4, vsync: this);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Syntaxify Demo'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        bottom: TabBar(
          controller: _tabController,
          tabs: const [
            Tab(icon: Icon(Icons.home), text: 'Overview'),
            Tab(icon: Icon(Icons.smart_button), text: 'Buttons'),
            Tab(icon: Icon(Icons.text_fields), text: 'Inputs'),
            Tab(icon: Icon(Icons.screen_share), text: 'Screens'),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          OverviewTab(
            currentStyleName: widget.currentStyleName,
            onStyleChanged: widget.onStyleChanged,
          ),
          const ButtonsTab(),
          const InputsTab(),
          const ScreensTab(),
        ],
      ),
    );
  }
}

// BUTTONS TAB
// ============================================
class ButtonsTab extends StatefulWidget {
  const ButtonsTab({super.key});

  @override
  State<ButtonsTab> createState() => _ButtonsTabState();
}

class _ButtonsTabState extends State<ButtonsTab> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(24.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          AppText(
            text: 'Button Components',
            variant: TextVariant.headlineMedium,
          ),
          const SizedBox(height: 8),
          AppText(
            text: 'Syntaxify buttons adapt to the selected design style.',
            variant: TextVariant.bodyLarge,
          ),
          const SizedBox(height: 32),

          // Button Variants
          AppText(
            text: 'Variants',
            variant: TextVariant.titleMedium,
          ), // 📝 SYNTAXIFY
          const SizedBox(height: 16), // Native Flutter
          // 🎯 SYNTAXIFY: Primary button - renders as ElevatedButton (Material),
          // CupertinoButton.filled (Cupertino), or custom Neo style
          AppButton.primary(
            label: 'Primary Button',
            onPressed: () => _showSnackBar(context, 'Primary button pressed'),
          ),
          const SizedBox(height: 12), // Native Flutter
          // 🎯 SYNTAXIFY: Secondary button variant
          AppButton.secondary(
            label: 'Secondary Button',
            onPressed: () => _showSnackBar(context, 'Secondary button pressed'),
          ),
          const SizedBox(height: 12), // Native Flutter
          // 🎯 SYNTAXIFY: Outlined button variant
          AppButton.outlined(
            label: 'Outlined Button',
            onPressed: () => _showSnackBar(context, 'Outlined button pressed'),
          ),
          const SizedBox(height: 12), // Native Flutter
          // 🎯 SYNTAXIFY: Disabled state
          AppButton.primary(
            label: 'Disabled Button',
            onPressed: null,
            isDisabled: true,
          ),
          const SizedBox(height: 32),

          // Interactive Demo
          AppText(text: 'Interactive Demo', variant: TextVariant.titleMedium),
          const SizedBox(height: 16),
          Container(
            padding: const EdgeInsets.all(24),
            decoration: BoxDecoration(
              color: Theme.of(
                context,
              ).colorScheme.surfaceContainerHighest.withOpacity(0.5),
              borderRadius: BorderRadius.circular(12),
            ),
            child: Column(
              children: [
                AppText(
                  text: 'Counter: $_counter',
                  variant: TextVariant.headlineMedium,
                ),
                const SizedBox(height: 16),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    AppButton.outlined(
                      label: 'Reset',
                      onPressed: () => setState(() => _counter = 0),
                    ),
                    const SizedBox(width: 16),
                    AppButton.primary(
                      label: 'Increment',
                      onPressed: () => setState(() => _counter++),
                    ),
                  ],
                ),
              ],
            ),
          ),
          const SizedBox(height: 32),

          // Typography Scale - Same component, different variants!
          AppText(text: 'Typography Scale', variant: TextVariant.titleMedium),
          const SizedBox(height: 16),

          // 📝 SYNTAXIFY: All use AppText, just different variants
          // Each adapts to the current design style (Material/Cupertino/Neo)
          AppText(text: 'Display Large', variant: TextVariant.displayLarge),
          const SizedBox(height: 8),
          AppText(text: 'Headline Medium', variant: TextVariant.headlineMedium),
          const SizedBox(height: 8),
          AppText(text: 'Title Medium', variant: TextVariant.titleMedium),
          const SizedBox(height: 8),
          AppText(text: 'Body Large', variant: TextVariant.bodyLarge),
          const SizedBox(height: 8),
          AppText(text: 'Body Medium', variant: TextVariant.bodyMedium),
          const SizedBox(height: 8),
          AppText(text: 'Label Small', variant: TextVariant.labelSmall),
        ],
      ),
    );
  }

  void _showSnackBar(BuildContext context, String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message), duration: const Duration(seconds: 1)),
    );
  }
}

// ============================================
// INPUTS TAB
// ============================================
class InputsTab extends StatefulWidget {
  const InputsTab({super.key});

  @override
  State<InputsTab> createState() => _InputsTabState();
}

class _InputsTabState extends State<InputsTab> {
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  final _phoneController = TextEditingController();

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    _phoneController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(24.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          AppText(
            text: 'Input Components',
            variant: TextVariant.headlineMedium,
          ),
          const SizedBox(height: 8),
          AppText(
            text:
                'Text input fields with different keyboard types and configurations.',
            variant: TextVariant.bodyLarge,
          ),
          const SizedBox(height: 32),

          AppText(
            text: 'Standard Inputs',
            variant: TextVariant.titleMedium,
          ), // 📝 SYNTAXIFY
          const SizedBox(height: 16), // Native Flutter
          // ⌨️ SYNTAXIFY: AppInput with email keyboard type
          // Renders as TextField (Material) or CupertinoTextField (Cupertino)
          AppInput(
            label: 'Email',
            controller: _emailController, // Native Flutter controller
            keyboardType: TextInputType.emailAddress, // Native Flutter enum
            hint: 'Enter your email',
          ),
          const SizedBox(height: 16), // Native Flutter
          // ⌨️ SYNTAXIFY: Password input with obscureText
          AppInput(
            label: 'Password',
            controller: _passwordController,
            obscureText: true, // Hides text input
            hint: 'Enter your password',
          ),
          const SizedBox(height: 16), // Native Flutter
          // ⌨️ SYNTAXIFY: Phone input with phone keyboard
          AppInput(
            label: 'Phone Number',
            controller: _phoneController,
            keyboardType: TextInputType.phone,
            hint: '+1 (555) 123-4567',
          ),
          const SizedBox(height: 32),

          // Form Demo
          AppText(text: 'Form Example', variant: TextVariant.titleMedium),
          const SizedBox(height: 16),
          Container(
            padding: const EdgeInsets.all(20),
            decoration: BoxDecoration(
              color: Theme.of(
                context,
              ).colorScheme.surfaceContainerHighest.withOpacity(0.5),
              borderRadius: BorderRadius.circular(12),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                AppText(text: 'Contact Form', variant: TextVariant.titleMedium),
                const SizedBox(height: 16),
                AppInput(label: 'Name', hint: 'John Doe'),
                const SizedBox(height: 12),
                AppInput(
                  label: 'Email',
                  keyboardType: TextInputType.emailAddress,
                  hint: 'john@example.com',
                ),
                const SizedBox(height: 12),
                AppInput(label: 'Message', hint: 'Type your message here...'),
                const SizedBox(height: 20),
                Row(
                  children: [
                    Expanded(
                      child: AppButton.outlined(
                        label: 'Clear',
                        onPressed: () {
                          _emailController.clear();
                          _passwordController.clear();
                          _phoneController.clear();
                        },
                      ),
                    ),
                    const SizedBox(width: 12),
                    Expanded(
                      child: AppButton.primary(
                        label: 'Submit',
                        onPressed: () {
                          ScaffoldMessenger.of(context).showSnackBar(
                            const SnackBar(content: Text('Form submitted!')),
                          );
                        },
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

// ============================================
// SCREENS TAB
// ============================================
class ScreensTab extends StatelessWidget {
  const ScreensTab({super.key});

  Widget _buildStep(String number, String text) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 12.0),
      child: Row(
        children: [
          Container(
            width: 36,
            height: 36,
            decoration: BoxDecoration(
              color: Colors.blue,
              borderRadius: BorderRadius.circular(18),
            ),
            child: Center(
              child: Text(
                number,
                style: const TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                  fontSize: 16,
                ),
              ),
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Text(
              text,
              style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
            ),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(24.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          AppText(text: 'Screen Generation', variant: TextVariant.displayLarge),
          const SizedBox(height: 8),
          AppText(
            text: 'The Power of .screen.dart Files',
            variant: TextVariant.headlineMedium,
          ),
          const SizedBox(height: 16),
          AppText(
            text:
                'Create entire Flutter screens with just a simple definition file. No boilerplate, no repetition - just describe your UI structure.',
            variant: TextVariant.bodyLarge,
          ),
          const SizedBox(height: 32),

          // Highlighted Process
          Container(
            padding: const EdgeInsets.all(24),
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [
                  Colors.blue.withOpacity(0.15),
                  Colors.purple.withOpacity(0.15),
                ],
              ),
              borderRadius: BorderRadius.circular(16),
              border: Border.all(color: Colors.blue.withOpacity(0.3), width: 2),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    Icon(Icons.auto_awesome, color: Colors.blue, size: 32),
                    const SizedBox(width: 12),
                    AppText(
                      text: 'How It Works',
                      variant: TextVariant.headlineMedium,
                    ),
                  ],
                ),
                const SizedBox(height: 20),
                _buildStep('1', 'Create login.screen.dart in meta/ folder'),
                _buildStep('2', 'Run: dart run syntaxify build'),
                _buildStep('3', 'Get lib/screens/login_screen.dart'),
                _buildStep('4', 'Edit freely - it\'s yours now!'),
              ],
            ),
          ),
          const SizedBox(height: 32),

          AppText(text: 'Live Example', variant: TextVariant.headlineMedium),
          const SizedBox(height: 16),
          Container(
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.amber.withOpacity(0.2),
              borderRadius: BorderRadius.circular(12),
              border: Border.all(
                color: Colors.amber.withOpacity(0.5),
                width: 2,
              ),
            ),
            child: Row(
              children: [
                Icon(Icons.file_present, color: Colors.amber[800], size: 28),
                const SizedBox(width: 12),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'meta/login.screen.dart',
                        style: TextStyle(
                          fontFamily: 'monospace',
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      const SizedBox(height: 4),
                      Text(
                        'Generated → lib/screens/login_screen.dart',
                        style: TextStyle(fontSize: 12, color: Colors.grey[700]),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 24),

          Center(
            // Native Flutter
            child: AppButton.primary(
              // 🎯 SYNTAXIFY component
              label: 'View Generated Login Screen',
              onPressed: () {
                Navigator.of(context).push(
                  // Native Flutter navigation
                  MaterialPageRoute(
                    // Native Flutter
                    builder: (context) => LoginScreen(
                      // 🌟 GENERATED from login.screen.dart!
                      handleLogin: () {
                        Navigator.of(context).pop(); // Native Flutter
                        ScaffoldMessenger.of(context).showSnackBar(
                          // Native Flutter
                          const SnackBar(
                            content: Text(
                              'Login button pressed from generated screen!',
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                );
              },
            ),
          ),
          const SizedBox(height: 32),

          // Code Preview
          AppText(
            text: 'What\'s Inside login.screen.dart?',
            variant: TextVariant.headlineMedium,
          ),
          const SizedBox(height: 8),
          AppText(
            text:
                'Just a simple, declarative structure - Syntaxify handles the rest!',
            variant: TextVariant.bodyMedium,
          ),
          const SizedBox(height: 16),
          Container(
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.grey[100],
              borderRadius: BorderRadius.circular(8),
              border: Border.all(color: Colors.grey[300]!),
            ),
            child: const Text('''final loginScreen = ScreenDefinition(
  id: 'login',
  layout: AstNode.column(children: [
    AstNode.text(text: 'Welcome Back'),
    AstNode.textField(
      label: 'Email',
      keyboardType: KeyboardType.emailAddress
    ),
    AstNode.textField(
      label: 'Password',
      obscureText: true
    ),
    AstNode.button(
      label: 'Sign In',
      onPressed: 'handleLogin'
    ),
  ]),
);''', style: TextStyle(fontFamily: 'monospace', fontSize: 12)),
          ),
        ],
      ),
    );
  }
}
0
likes
140
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

AST-based Flutter UI code generator with multi-style design system. Write components once, render in Material, Cupertino, or custom designs.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, args, code_builder, dart_style, file, freezed_annotation, json_annotation, mason_logger, path

More

Packages that depend on syntaxify