chartify 1.0.2 copy "chartify: ^1.0.2" to clipboard
chartify: ^1.0.2 copied to clipboard

A high-performance Flutter chart library with 32+ chart types including line, bar, pie, radar, gauge, sankey, treemap, and more. Modern theming, animations, and accessibility.

example/lib/main.dart

import 'dart:math' as math;

import 'package:chartify/chartify.dart';
import 'package:flutter/material.dart';

import 'url_helper.dart' if (dart.library.js_interop) 'url_helper_web.dart';

void main() {
  runApp(const ChartifyExampleApp());
}

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

  @override
  State<ChartifyExampleApp> createState() => _ChartifyExampleAppState();
}

class _ChartifyExampleAppState extends State<ChartifyExampleApp> {
  bool _isDarkMode = true;
  String? _chartId;

  @override
  void initState() {
    super.initState();
    _chartId = getChartIdFromUrl();
  }

  void _toggleTheme() {
    setState(() {
      _isDarkMode = !_isDarkMode;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Chartify',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6366F1),
          brightness: Brightness.light,
        ),
        useMaterial3: true,
        fontFamily: 'SF Pro Display',
        extensions: [ChartThemeData.modern()],
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6366F1),
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
        fontFamily: 'SF Pro Display',
        scaffoldBackgroundColor: const Color(0xFF0F0F1A),
        extensions: [
          ChartThemeData.modernDark(),
        ],
      ),
      themeMode: _isDarkMode ? ThemeMode.dark : ThemeMode.light,
      home: _chartId != null
          ? StandaloneChartView(
              chartId: _chartId!,
              isDarkMode: _isDarkMode,
              onThemeToggle: _toggleTheme,
            )
          : ChartGallery(
              isDarkMode: _isDarkMode,
              onThemeToggle: _toggleTheme,
            ),
    );
  }
}

/// Standalone view for a single chart, used for documentation embeds
class StandaloneChartView extends StatelessWidget {
  const StandaloneChartView({
    super.key,
    required this.chartId,
    required this.isDarkMode,
    required this.onThemeToggle,
  });

  final String chartId;
  final bool isDarkMode;
  final VoidCallback onThemeToggle;

  /// Map URL chart IDs to chart builders
  static final Map<String, Widget Function(BuildContext)> chartBuilders = {
    'line': (context) => const SimpleLineChartExample(),
    'multi-series': (context) => const MultiSeriesLineChartExample(),
    'area': (context) => const AreaChartExample(),
    'bar': (context) => const BarChartExample(),
    'pie': (context) => const PieChartExample(),
    'scatter': (context) => const ScatterChartExample(),
    'radar': (context) => const RadarChartExample(),
    'gauge': (context) => const GaugeChartExample(),
    'sparkline': (context) => const SparklineChartExample(),
    'bubble': (context) => const BubbleChartExample(),
    'radial-bar': (context) => const RadialBarChartExample(),
    'candlestick': (context) => const CandlestickChartExample(),
    'histogram': (context) => const HistogramChartExample(),
    'waterfall': (context) => const WaterfallChartExample(),
    'box-plot': (context) => const BoxPlotChartExample(),
    'funnel': (context) => const FunnelChartExample(),
    'pyramid': (context) => const PyramidChartExample(),
    'heatmap': (context) => const HeatmapChartExample(),
    'treemap': (context) => const TreemapChartExample(),
    'sunburst': (context) => const SunburstChartExample(),
    'bullet': (context) => const BulletChartExample(),
    'step': (context) => const StepChartExample(),
    'range': (context) => const RangeChartExample(),
    'lollipop': (context) => const LollipopChartExample(),
    'dumbbell': (context) => const DumbbellChartExample(),
    'slope': (context) => const SlopeChartExample(),
    'rose': (context) => const RoseChartExample(),
    'bump': (context) => const BumpChartExample(),
    'calendar': (context) => const CalendarHeatmapExample(),
    'gantt': (context) => const GanttChartExample(),
    'sankey': (context) => const SankeyChartExample(),
    'interactive': (context) => const InteractiveChartExample(),
    'animated': (context) => const AnimatedLineChartExample(),
  };

  @override
  Widget build(BuildContext context) {
    final builder = chartBuilders[chartId];
    final theme = Theme.of(context);
    final isDark = theme.brightness == Brightness.dark;

    if (builder == null) {
      return Scaffold(
        backgroundColor: isDark ? const Color(0xFF0F0F1A) : theme.colorScheme.surface,
        body: Center(
          child: Text(
            'Chart "$chartId" not found',
            style: TextStyle(color: theme.colorScheme.error),
          ),
        ),
      );
    }

    return Scaffold(
      backgroundColor: isDark ? const Color(0xFF0F0F1A) : theme.colorScheme.surface,
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: builder(context),
        ),
      ),
    );
  }
}

// Chart categories for filtering
enum ChartCategory { all, basic, advanced, statistical, hierarchical, specialty }

class ChartGallery extends StatefulWidget {
  const ChartGallery({
    super.key,
    required this.isDarkMode,
    required this.onThemeToggle,
  });

  final bool isDarkMode;
  final VoidCallback onThemeToggle;

  @override
  State<ChartGallery> createState() => _ChartGalleryState();
}

class _ChartGalleryState extends State<ChartGallery> with TickerProviderStateMixin {
  int _selectedIndex = 0;
  ChartCategory _selectedCategory = ChartCategory.all;
  late PageController _pageController;
  late AnimationController _fabAnimationController;

  final List<ChartExample> _examples = [
    // Basic Charts
    ChartExample(
      name: 'Interactive',
      description: 'Touch to explore data points',
      icon: Icons.touch_app_rounded,
      color: const Color(0xFF6366F1),
      category: ChartCategory.basic,
      builder: (context) => const InteractiveChartExample(),
    ),
    ChartExample(
      name: 'Line Chart',
      description: 'Track trends over time',
      icon: Icons.show_chart_rounded,
      color: const Color(0xFF10B981),
      category: ChartCategory.basic,
      builder: (context) => const SimpleLineChartExample(),
    ),
    ChartExample(
      name: 'Multi-Series',
      description: 'Compare multiple datasets',
      icon: Icons.stacked_line_chart_rounded,
      color: const Color(0xFF3B82F6),
      category: ChartCategory.basic,
      builder: (context) => const MultiSeriesLineChartExample(),
    ),
    ChartExample(
      name: 'Area Chart',
      description: 'Visualize volume over time',
      icon: Icons.area_chart_rounded,
      color: const Color(0xFF8B5CF6),
      category: ChartCategory.basic,
      builder: (context) => const AreaChartExample(),
    ),
    ChartExample(
      name: 'Animated',
      description: 'Dynamic live data',
      icon: Icons.animation_rounded,
      color: const Color(0xFFF59E0B),
      category: ChartCategory.basic,
      builder: (context) => const AnimatedLineChartExample(),
    ),
    ChartExample(
      name: 'Bar Chart',
      description: 'Compare categories',
      icon: Icons.bar_chart_rounded,
      color: const Color(0xFFEF4444),
      category: ChartCategory.basic,
      builder: (context) => const BarChartExample(),
    ),
    ChartExample(
      name: 'Pie Chart',
      description: 'Show proportions',
      icon: Icons.pie_chart_rounded,
      color: const Color(0xFFEC4899),
      category: ChartCategory.basic,
      builder: (context) => const PieChartExample(),
    ),
    // Advanced Charts
    ChartExample(
      name: 'Scatter',
      description: 'Plot data distribution',
      icon: Icons.scatter_plot_rounded,
      color: const Color(0xFF14B8A6),
      category: ChartCategory.advanced,
      builder: (context) => const ScatterChartExample(),
    ),
    ChartExample(
      name: 'Radar',
      description: 'Multi-dimensional comparison',
      icon: Icons.radar_rounded,
      color: const Color(0xFF8B5CF6),
      category: ChartCategory.advanced,
      builder: (context) => const RadarChartExample(),
    ),
    ChartExample(
      name: 'Gauge',
      description: 'Display single metrics',
      icon: Icons.speed_rounded,
      color: const Color(0xFF22C55E),
      category: ChartCategory.advanced,
      builder: (context) => const GaugeChartExample(),
    ),
    ChartExample(
      name: 'Sparkline',
      description: 'Compact inline charts',
      icon: Icons.insights_rounded,
      color: const Color(0xFF06B6D4),
      category: ChartCategory.advanced,
      builder: (context) => const SparklineChartExample(),
    ),
    ChartExample(
      name: 'Bubble',
      description: '3D data visualization',
      icon: Icons.bubble_chart_rounded,
      color: const Color(0xFFA855F7),
      category: ChartCategory.advanced,
      builder: (context) => const BubbleChartExample(),
    ),
    ChartExample(
      name: 'Radial Bar',
      description: 'Circular progress display',
      icon: Icons.donut_large_rounded,
      color: const Color(0xFFD946EF),
      category: ChartCategory.advanced,
      builder: (context) => const RadialBarChartExample(),
    ),
    // Statistical Charts
    ChartExample(
      name: 'Candlestick',
      description: 'Financial OHLC data',
      icon: Icons.candlestick_chart_rounded,
      color: const Color(0xFF22C55E),
      category: ChartCategory.statistical,
      builder: (context) => const CandlestickChartExample(),
    ),
    ChartExample(
      name: 'Histogram',
      description: 'Data distribution',
      icon: Icons.equalizer_rounded,
      color: const Color(0xFF6366F1),
      category: ChartCategory.statistical,
      builder: (context) => const HistogramChartExample(),
    ),
    ChartExample(
      name: 'Waterfall',
      description: 'Cumulative effect',
      icon: Icons.waterfall_chart_rounded,
      color: const Color(0xFF0EA5E9),
      category: ChartCategory.statistical,
      builder: (context) => const WaterfallChartExample(),
    ),
    ChartExample(
      name: 'Box Plot',
      description: 'Statistical summary',
      icon: Icons.candlestick_chart_rounded,
      color: const Color(0xFFF97316),
      category: ChartCategory.statistical,
      builder: (context) => const BoxPlotChartExample(),
    ),
    // Hierarchical Charts
    ChartExample(
      name: 'Funnel',
      description: 'Conversion pipeline',
      icon: Icons.filter_alt_rounded,
      color: const Color(0xFF8B5CF6),
      category: ChartCategory.hierarchical,
      builder: (context) => const FunnelChartExample(),
    ),
    ChartExample(
      name: 'Pyramid',
      description: 'Hierarchical layers',
      icon: Icons.change_history_rounded,
      color: const Color(0xFFF59E0B),
      category: ChartCategory.hierarchical,
      builder: (context) => const PyramidChartExample(),
    ),
    ChartExample(
      name: 'Heatmap',
      description: 'Intensity matrix',
      icon: Icons.grid_on_rounded,
      color: const Color(0xFFEF4444),
      category: ChartCategory.hierarchical,
      builder: (context) => const HeatmapChartExample(),
    ),
    ChartExample(
      name: 'Treemap',
      description: 'Nested rectangles',
      icon: Icons.dashboard_rounded,
      color: const Color(0xFF22C55E),
      category: ChartCategory.hierarchical,
      builder: (context) => const TreemapChartExample(),
    ),
    ChartExample(
      name: 'Sunburst',
      description: 'Radial hierarchy',
      icon: Icons.wb_sunny_rounded,
      color: const Color(0xFFFBBF24),
      category: ChartCategory.hierarchical,
      builder: (context) => const SunburstChartExample(),
    ),
    // Specialty Charts
    ChartExample(
      name: 'Bullet',
      description: 'KPI indicators',
      icon: Icons.linear_scale_rounded,
      color: const Color(0xFF64748B),
      category: ChartCategory.specialty,
      builder: (context) => const BulletChartExample(),
    ),
    ChartExample(
      name: 'Step',
      description: 'Discrete changes',
      icon: Icons.stairs_rounded,
      color: const Color(0xFF0891B2),
      category: ChartCategory.specialty,
      builder: (context) => const StepChartExample(),
    ),
    ChartExample(
      name: 'Range',
      description: 'Min/max values',
      icon: Icons.swap_vert_rounded,
      color: const Color(0xFF7C3AED),
      category: ChartCategory.specialty,
      builder: (context) => const RangeChartExample(),
    ),
    ChartExample(
      name: 'Lollipop',
      description: 'Values with markers',
      icon: Icons.radio_button_checked_rounded,
      color: const Color(0xFFDB2777),
      category: ChartCategory.specialty,
      builder: (context) => const LollipopChartExample(),
    ),
    ChartExample(
      name: 'Dumbbell',
      description: 'Before & after',
      icon: Icons.compare_arrows_rounded,
      color: const Color(0xFF059669),
      category: ChartCategory.specialty,
      builder: (context) => const DumbbellChartExample(),
    ),
    ChartExample(
      name: 'Slope',
      description: 'Trend changes',
      icon: Icons.trending_up_rounded,
      color: const Color(0xFF2563EB),
      category: ChartCategory.specialty,
      builder: (context) => const SlopeChartExample(),
    ),
    ChartExample(
      name: 'Rose',
      description: 'Polar bar chart',
      icon: Icons.donut_small_rounded,
      color: const Color(0xFFE11D48),
      category: ChartCategory.specialty,
      builder: (context) => const RoseChartExample(),
    ),
    ChartExample(
      name: 'Bump',
      description: 'Ranking over time',
      icon: Icons.leaderboard_rounded,
      color: const Color(0xFF9333EA),
      category: ChartCategory.specialty,
      builder: (context) => const BumpChartExample(),
    ),
    ChartExample(
      name: 'Calendar',
      description: 'GitHub-style heatmap',
      icon: Icons.calendar_month_rounded,
      color: const Color(0xFF16A34A),
      category: ChartCategory.specialty,
      builder: (context) => const CalendarHeatmapExample(),
    ),
    ChartExample(
      name: 'Gantt',
      description: 'Project timeline',
      icon: Icons.view_timeline_rounded,
      color: const Color(0xFF0284C7),
      category: ChartCategory.specialty,
      builder: (context) => const GanttChartExample(),
    ),
    ChartExample(
      name: 'Sankey',
      description: 'Flow visualization',
      icon: Icons.account_tree_rounded,
      color: const Color(0xFFC026D3),
      category: ChartCategory.specialty,
      builder: (context) => const SankeyChartExample(),
    ),
  ];

  List<ChartExample> get _filteredExamples {
    if (_selectedCategory == ChartCategory.all) return _examples;
    return _examples.where((e) => e.category == _selectedCategory).toList();
  }

  @override
  void initState() {
    super.initState();
    _pageController = PageController(viewportFraction: 1.0);
    _fabAnimationController = AnimationController(
      duration: const Duration(milliseconds: 300),
      vsync: this,
    );
  }

  @override
  void dispose() {
    _pageController.dispose();
    _fabAnimationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    final isWideScreen = screenWidth > 900;
    final theme = Theme.of(context);
    final isDark = theme.brightness == Brightness.dark;

    if (isWideScreen) {
      return _buildDesktopLayout(theme, isDark);
    }
    return _buildMobileLayout(theme, isDark);
  }

  Widget _buildMobileLayout(ThemeData theme, bool isDark) {
    final filteredExamples = _filteredExamples;
    final safeSelectedIndex = _selectedIndex.clamp(0, filteredExamples.length - 1);
    final currentExample = filteredExamples[safeSelectedIndex];

    return Scaffold(
      backgroundColor: isDark ? const Color(0xFF0F0F1A) : theme.colorScheme.surface,
      body: SafeArea(
        child: Column(
          children: [
            // Header with gradient
            _buildMobileHeader(theme, isDark, currentExample),
            // Category chips
            _buildCategoryChips(theme, isDark),
            // Chart area
            Expanded(
              child: _buildMobileChartArea(theme, isDark, filteredExamples, safeSelectedIndex),
            ),
            // Bottom navigation dots
            _buildPageIndicator(theme, isDark, filteredExamples, safeSelectedIndex),
          ],
        ),
      ),
    );
  }

  Widget _buildMobileHeader(ThemeData theme, bool isDark, ChartExample currentExample) {
    return Container(
      padding: const EdgeInsets.fromLTRB(20, 16, 20, 12),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: isDark
              ? [const Color(0xFF1A1A2E), const Color(0xFF16213E)]
              : [theme.colorScheme.primaryContainer, theme.colorScheme.secondaryContainer],
        ),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Container(
                padding: const EdgeInsets.all(10),
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    colors: [currentExample.color, currentExample.color.withValues(alpha: 0.7)],
                  ),
                  borderRadius: BorderRadius.circular(14),
                  boxShadow: [
                    BoxShadow(
                      color: currentExample.color.withValues(alpha: 0.4),
                      blurRadius: 12,
                      offset: const Offset(0, 4),
                    ),
                  ],
                ),
                child: Icon(
                  currentExample.icon,
                  color: Colors.white,
                  size: 24,
                ),
              ),
              const SizedBox(width: 14),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Chartify',
                      style: TextStyle(
                        fontSize: 24,
                        fontWeight: FontWeight.w700,
                        color: isDark ? Colors.white : theme.colorScheme.onSurface,
                        letterSpacing: -0.5,
                      ),
                    ),
                    Text(
                      '${_examples.length} Chart Types',
                      style: TextStyle(
                        fontSize: 13,
                        color: isDark ? Colors.white60 : theme.colorScheme.onSurfaceVariant,
                      ),
                    ),
                  ],
                ),
              ),
              IconButton(
                onPressed: widget.onThemeToggle,
                style: IconButton.styleFrom(
                  backgroundColor: isDark ? Colors.white10 : Colors.black.withValues(alpha: 0.05),
                ),
                icon: AnimatedSwitcher(
                  duration: const Duration(milliseconds: 300),
                  transitionBuilder: (child, animation) {
                    return RotationTransition(
                      turns: Tween(begin: 0.75, end: 1.0).animate(animation),
                      child: FadeTransition(opacity: animation, child: child),
                    );
                  },
                  child: Icon(
                    isDark ? Icons.light_mode_rounded : Icons.dark_mode_rounded,
                    key: ValueKey(isDark),
                    color: isDark ? Colors.amber : theme.colorScheme.onSurfaceVariant,
                  ),
                ),
              ),
              const SizedBox(width: 4),
              IconButton(
                onPressed: () => _showChartPicker(context),
                style: IconButton.styleFrom(
                  backgroundColor: isDark ? Colors.white10 : Colors.black.withValues(alpha: 0.05),
                ),
                icon: Icon(
                  Icons.apps_rounded,
                  color: isDark ? Colors.white70 : theme.colorScheme.onSurfaceVariant,
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildCategoryChips(ThemeData theme, bool isDark) {
    final categories = [
      (ChartCategory.all, 'All', Icons.grid_view_rounded),
      (ChartCategory.basic, 'Basic', Icons.show_chart_rounded),
      (ChartCategory.advanced, 'Advanced', Icons.auto_graph_rounded),
      (ChartCategory.statistical, 'Stats', Icons.analytics_rounded),
      (ChartCategory.hierarchical, 'Hierarchy', Icons.account_tree_rounded),
      (ChartCategory.specialty, 'Specialty', Icons.star_rounded),
    ];

    return Container(
      height: 50,
      margin: const EdgeInsets.only(top: 8),
      child: ListView.builder(
        scrollDirection: Axis.horizontal,
        padding: const EdgeInsets.symmetric(horizontal: 16),
        itemCount: categories.length,
        itemBuilder: (context, index) {
          final (category, label, icon) = categories[index];
          final isSelected = _selectedCategory == category;
          return Padding(
            padding: const EdgeInsets.only(right: 8),
            child: FilterChip(
              selected: isSelected,
              showCheckmark: false,
              avatar: Icon(
                icon,
                size: 16,
                color: isSelected
                    ? Colors.white
                    : (isDark ? Colors.white60 : theme.colorScheme.onSurfaceVariant),
              ),
              label: Text(
                label,
                style: TextStyle(
                  fontSize: 12,
                  fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
                  color: isSelected
                      ? Colors.white
                      : (isDark ? Colors.white70 : theme.colorScheme.onSurface),
                ),
              ),
              backgroundColor: isDark ? const Color(0xFF1E1E2D) : theme.colorScheme.surfaceContainerHighest,
              selectedColor: theme.colorScheme.primary,
              side: BorderSide.none,
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
              padding: const EdgeInsets.symmetric(horizontal: 8),
              onSelected: (_) {
                setState(() {
                  _selectedCategory = category;
                  _selectedIndex = 0;
                  _pageController.jumpToPage(0);
                });
              },
            ),
          );
        },
      ),
    );
  }

  Widget _buildMobileChartArea(ThemeData theme, bool isDark, List<ChartExample> examples, int selectedIndex) {
    return PageView.builder(
      controller: _pageController,
      itemCount: examples.length,
      onPageChanged: (index) {
        setState(() => _selectedIndex = index);
      },
      itemBuilder: (context, index) {
        final example = examples[index];
        return Padding(
          padding: const EdgeInsets.fromLTRB(16, 12, 16, 8),
          child: Column(
            children: [
              // Chart title card
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                decoration: BoxDecoration(
                  color: isDark ? const Color(0xFF1E1E2D) : Colors.white,
                  borderRadius: BorderRadius.circular(16),
                  border: Border.all(
                    color: isDark ? Colors.white10 : Colors.black.withValues(alpha: 0.05),
                  ),
                ),
                child: Row(
                  children: [
                    Container(
                      padding: const EdgeInsets.all(8),
                      decoration: BoxDecoration(
                        color: example.color.withValues(alpha: 0.15),
                        borderRadius: BorderRadius.circular(10),
                      ),
                      child: Icon(example.icon, color: example.color, size: 20),
                    ),
                    const SizedBox(width: 12),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            example.name,
                            style: TextStyle(
                              fontSize: 16,
                              fontWeight: FontWeight.w600,
                              color: isDark ? Colors.white : theme.colorScheme.onSurface,
                            ),
                          ),
                          Text(
                            example.description,
                            style: TextStyle(
                              fontSize: 12,
                              color: isDark ? Colors.white54 : theme.colorScheme.onSurfaceVariant,
                            ),
                          ),
                        ],
                      ),
                    ),
                    Container(
                      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
                      decoration: BoxDecoration(
                        color: example.color.withValues(alpha: 0.15),
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: Text(
                        '${index + 1}/${examples.length}',
                        style: TextStyle(
                          fontSize: 11,
                          fontWeight: FontWeight.w600,
                          color: example.color,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              const SizedBox(height: 12),
              // Chart container
              Expanded(
                child: Container(
                  decoration: BoxDecoration(
                    color: isDark ? const Color(0xFF1E1E2D) : Colors.white,
                    borderRadius: BorderRadius.circular(20),
                    border: Border.all(
                      color: isDark ? Colors.white10 : Colors.black.withValues(alpha: 0.05),
                    ),
                    boxShadow: [
                      BoxShadow(
                        color: example.color.withValues(alpha: isDark ? 0.1 : 0.05),
                        blurRadius: 20,
                        offset: const Offset(0, 8),
                      ),
                    ],
                  ),
                  padding: const EdgeInsets.all(16),
                  child: example.builder(context),
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildPageIndicator(ThemeData theme, bool isDark, List<ChartExample> examples, int selectedIndex) {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 16),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // Previous button
          IconButton(
            onPressed: selectedIndex > 0
                ? () => _pageController.previousPage(
                      duration: const Duration(milliseconds: 300),
                      curve: Curves.easeOutCubic,
                    )
                : null,
            icon: Icon(
              Icons.chevron_left_rounded,
              color: selectedIndex > 0
                  ? (isDark ? Colors.white70 : theme.colorScheme.primary)
                  : (isDark ? Colors.white24 : theme.colorScheme.onSurface.withValues(alpha: 0.3)),
            ),
          ),
          // Dots
          SizedBox(
            height: 8,
            child: ListView.builder(
              shrinkWrap: true,
              scrollDirection: Axis.horizontal,
              itemCount: math.min(examples.length, 7),
              itemBuilder: (context, index) {
                final dotIndex = _getDotIndex(index, selectedIndex, examples.length);
                final isSelected = dotIndex == selectedIndex;
                final distance = (dotIndex - selectedIndex).abs();
                final scale = distance == 0 ? 1.0 : (distance == 1 ? 0.7 : 0.5);

                return AnimatedContainer(
                  duration: const Duration(milliseconds: 200),
                  margin: const EdgeInsets.symmetric(horizontal: 3),
                  width: isSelected ? 24 : 8 * scale,
                  height: 8 * scale,
                  decoration: BoxDecoration(
                    color: isSelected
                        ? examples[selectedIndex].color
                        : (isDark ? Colors.white24 : theme.colorScheme.outline.withValues(alpha: 0.3)),
                    borderRadius: BorderRadius.circular(4),
                  ),
                );
              },
            ),
          ),
          // Next button
          IconButton(
            onPressed: selectedIndex < examples.length - 1
                ? () => _pageController.nextPage(
                      duration: const Duration(milliseconds: 300),
                      curve: Curves.easeOutCubic,
                    )
                : null,
            icon: Icon(
              Icons.chevron_right_rounded,
              color: selectedIndex < examples.length - 1
                  ? (isDark ? Colors.white70 : theme.colorScheme.primary)
                  : (isDark ? Colors.white24 : theme.colorScheme.onSurface.withValues(alpha: 0.3)),
            ),
          ),
        ],
      ),
    );
  }

  int _getDotIndex(int displayIndex, int selectedIndex, int total) {
    if (total <= 7) return displayIndex;
    final start = (selectedIndex - 3).clamp(0, total - 7);
    return start + displayIndex;
  }

  void _showChartPicker(BuildContext context) {
    final theme = Theme.of(context);
    final isDark = theme.brightness == Brightness.dark;

    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      builder: (context) => DraggableScrollableSheet(
        initialChildSize: 0.7,
        minChildSize: 0.5,
        maxChildSize: 0.9,
        builder: (context, scrollController) => Container(
          decoration: BoxDecoration(
            color: isDark ? const Color(0xFF1E1E2D) : Colors.white,
            borderRadius: const BorderRadius.vertical(top: Radius.circular(24)),
          ),
          child: Column(
            children: [
              // Handle
              Container(
                margin: const EdgeInsets.only(top: 12),
                width: 40,
                height: 4,
                decoration: BoxDecoration(
                  color: isDark ? Colors.white24 : Colors.black12,
                  borderRadius: BorderRadius.circular(2),
                ),
              ),
              // Title
              Padding(
                padding: const EdgeInsets.all(20),
                child: Text(
                  'All Charts',
                  style: TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.w700,
                    color: isDark ? Colors.white : theme.colorScheme.onSurface,
                  ),
                ),
              ),
              // Grid
              Expanded(
                child: GridView.builder(
                  controller: scrollController,
                  padding: const EdgeInsets.fromLTRB(16, 0, 16, 24),
                  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3,
                    childAspectRatio: 0.9,
                    crossAxisSpacing: 12,
                    mainAxisSpacing: 12,
                  ),
                  itemCount: _examples.length,
                  itemBuilder: (context, index) {
                    final example = _examples[index];
                    final isSelected = index == _selectedIndex && _selectedCategory == ChartCategory.all;
                    return GestureDetector(
                      onTap: () {
                        setState(() {
                          _selectedCategory = ChartCategory.all;
                          _selectedIndex = index;
                          _pageController.jumpToPage(index);
                        });
                        Navigator.pop(context);
                      },
                      child: AnimatedContainer(
                        duration: const Duration(milliseconds: 200),
                        decoration: BoxDecoration(
                          color: isSelected
                              ? example.color.withValues(alpha: 0.2)
                              : (isDark ? const Color(0xFF252538) : theme.colorScheme.surfaceContainerHighest),
                          borderRadius: BorderRadius.circular(16),
                          border: Border.all(
                            color: isSelected ? example.color : Colors.transparent,
                            width: 2,
                          ),
                        ),
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Container(
                              padding: const EdgeInsets.all(12),
                              decoration: BoxDecoration(
                                color: example.color.withValues(alpha: 0.15),
                                shape: BoxShape.circle,
                              ),
                              child: Icon(example.icon, color: example.color, size: 24),
                            ),
                            const SizedBox(height: 8),
                            Text(
                              example.name,
                              style: TextStyle(
                                fontSize: 12,
                                fontWeight: FontWeight.w600,
                                color: isDark ? Colors.white : theme.colorScheme.onSurface,
                              ),
                              textAlign: TextAlign.center,
                            ),
                          ],
                        ),
                      ),
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildDesktopLayout(ThemeData theme, bool isDark) {
    return Scaffold(
      backgroundColor: isDark ? const Color(0xFF0F0F1A) : theme.colorScheme.surface,
      body: Row(
        children: [
          // Sidebar
          Container(
            width: 280,
            decoration: BoxDecoration(
              color: isDark ? const Color(0xFF1A1A2E) : theme.colorScheme.surfaceContainerLow,
              border: Border(
                right: BorderSide(
                  color: isDark ? Colors.white10 : theme.colorScheme.outlineVariant.withValues(alpha: 0.5),
                ),
              ),
            ),
            child: Column(
              children: [
                // Logo and theme toggle
                Container(
                  padding: const EdgeInsets.all(24),
                  child: Row(
                    children: [
                      Container(
                        padding: const EdgeInsets.all(10),
                        decoration: BoxDecoration(
                          gradient: LinearGradient(
                            colors: [theme.colorScheme.primary, theme.colorScheme.secondary],
                          ),
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: const Icon(Icons.bar_chart_rounded, color: Colors.white),
                      ),
                      const SizedBox(width: 12),
                      Expanded(
                        child: Text(
                          'Chartify',
                          style: TextStyle(
                            fontSize: 22,
                            fontWeight: FontWeight.w700,
                            color: isDark ? Colors.white : theme.colorScheme.onSurface,
                          ),
                        ),
                      ),
                      IconButton(
                        onPressed: widget.onThemeToggle,
                        tooltip: isDark ? 'Switch to Light Mode' : 'Switch to Dark Mode',
                        style: IconButton.styleFrom(
                          backgroundColor: isDark ? Colors.white10 : Colors.black.withValues(alpha: 0.05),
                        ),
                        icon: AnimatedSwitcher(
                          duration: const Duration(milliseconds: 300),
                          transitionBuilder: (child, animation) {
                            return RotationTransition(
                              turns: Tween(begin: 0.75, end: 1.0).animate(animation),
                              child: FadeTransition(opacity: animation, child: child),
                            );
                          },
                          child: Icon(
                            isDark ? Icons.light_mode_rounded : Icons.dark_mode_rounded,
                            key: ValueKey(isDark),
                            color: isDark ? Colors.amber : theme.colorScheme.onSurfaceVariant,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                // List
                Expanded(
                  child: ListView.builder(
                    padding: const EdgeInsets.symmetric(horizontal: 12),
                    itemCount: _examples.length,
                    itemBuilder: (context, index) {
                      final example = _examples[index];
                      final isSelected = index == _selectedIndex;
                      return Padding(
                        padding: const EdgeInsets.only(bottom: 4),
                        child: ListTile(
                          leading: Container(
                            padding: const EdgeInsets.all(8),
                            decoration: BoxDecoration(
                              color: isSelected ? example.color : example.color.withValues(alpha: 0.15),
                              borderRadius: BorderRadius.circular(8),
                            ),
                            child: Icon(
                              example.icon,
                              size: 18,
                              color: isSelected ? Colors.white : example.color,
                            ),
                          ),
                          title: Text(
                            example.name,
                            style: TextStyle(
                              fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
                              color: isSelected
                                  ? (isDark ? Colors.white : theme.colorScheme.primary)
                                  : (isDark ? Colors.white70 : null),
                            ),
                          ),
                          subtitle: Text(
                            example.description,
                            style: TextStyle(
                              fontSize: 12,
                              color: isDark ? Colors.white38 : theme.colorScheme.onSurfaceVariant,
                            ),
                          ),
                          selected: isSelected,
                          selectedTileColor: isDark
                              ? Colors.white.withValues(alpha: 0.05)
                              : theme.colorScheme.primaryContainer.withValues(alpha: 0.5),
                          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
                          onTap: () => setState(() => _selectedIndex = index),
                        ),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),
          // Main content
          Expanded(
            child: Column(
              children: [
                // Header
                Container(
                  padding: const EdgeInsets.all(20),
                  decoration: BoxDecoration(
                    color: isDark ? const Color(0xFF1A1A2E) : theme.colorScheme.surface,
                    border: Border(
                      bottom: BorderSide(
                        color: isDark ? Colors.white10 : theme.colorScheme.outlineVariant.withValues(alpha: 0.5),
                      ),
                    ),
                  ),
                  child: Row(
                    children: [
                      Container(
                        padding: const EdgeInsets.all(12),
                        decoration: BoxDecoration(
                          color: _examples[_selectedIndex].color.withValues(alpha: 0.15),
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Icon(
                          _examples[_selectedIndex].icon,
                          color: _examples[_selectedIndex].color,
                        ),
                      ),
                      const SizedBox(width: 16),
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            _examples[_selectedIndex].name,
                            style: TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.w700,
                              color: isDark ? Colors.white : theme.colorScheme.onSurface,
                            ),
                          ),
                          Text(
                            _examples[_selectedIndex].description,
                            style: TextStyle(
                              color: isDark ? Colors.white54 : theme.colorScheme.onSurfaceVariant,
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
                // Chart
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(24),
                    child: Container(
                      decoration: BoxDecoration(
                        color: isDark ? const Color(0xFF1E1E2D) : Colors.white,
                        borderRadius: BorderRadius.circular(20),
                        border: Border.all(
                          color: isDark ? Colors.white10 : theme.colorScheme.outlineVariant.withValues(alpha: 0.3),
                        ),
                        boxShadow: [
                          BoxShadow(
                            color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05),
                            blurRadius: 20,
                            offset: const Offset(0, 8),
                          ),
                        ],
                      ),
                      padding: const EdgeInsets.all(24),
                      child: _examples[_selectedIndex].builder(context),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class ChartExample {
  const ChartExample({
    required this.name,
    required this.description,
    required this.icon,
    required this.builder,
    required this.color,
    this.category = ChartCategory.basic,
  });

  final String name;
  final String description;
  final IconData icon;
  final Widget Function(BuildContext context) builder;
  final Color color;
  final ChartCategory category;
}

// ============== Chart Examples ==============

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

  @override
  State<InteractiveChartExample> createState() => _InteractiveChartExampleState();
}

class _InteractiveChartExampleState extends State<InteractiveChartExample> {
  String _lastTapped = 'Tap or hover over data points';

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.primaryContainer.withValues(alpha: 0.3),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(
                Icons.info_outline,
                size: 16,
                color: Theme.of(context).colorScheme.primary,
              ),
              const SizedBox(width: 8),
              Text(
                _lastTapped,
                style: TextStyle(
                  color: Theme.of(context).colorScheme.primary,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ],
          ),
        ),
        const SizedBox(height: 16),
        Expanded(
          child: LineChart(
            data: LineChartData(
              series: [
                LineSeries<int, double>(
                  name: 'Revenue',
                  data: const [
                    DataPoint(x: 0, y: 4200),
                    DataPoint(x: 1, y: 5800),
                    DataPoint(x: 2, y: 4900),
                    DataPoint(x: 3, y: 7200),
                    DataPoint(x: 4, y: 6100),
                    DataPoint(x: 5, y: 8500),
                    DataPoint(x: 6, y: 7800),
                  ],
                  color: const Color(0xFF6366F1),
                  strokeWidth: 3,
                  curved: true,
                  showMarkers: true,
                  markerSize: 8,
                  fillArea: true,
                  areaOpacity: 0.15,
                ),
              ],
              xAxis: AxisConfig(
                label: 'Month',
                labelFormatter: (value) {
                  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'];
                  final index = value.toInt();
                  if (index >= 0 && index < months.length) {
                    return months[index];
                  }
                  return '';
                },
              ),
              yAxis: AxisConfig(
                label: 'Revenue',
                min: 0,
                labelFormatter: (value) => '\$${(value / 1000).toStringAsFixed(1)}K',
              ),
            ),
            tooltip: const TooltipConfig(
              enabled: true,
              showIndicatorLine: true,
              showIndicatorDot: true,
            ),
            showCrosshair: true,
            animation: const ChartAnimation(
              duration: Duration(milliseconds: 800),
              curve: Curves.easeOutCubic,
            ),
            onDataPointTap: (info) {
              setState(() {
                _lastTapped = 'Tapped: \$${info.yValue} at month ${info.xValue}';
              });
            },
          ),
        ),
      ],
    );
  }
}

class SimpleLineChartExample extends StatelessWidget {
  const SimpleLineChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return LineChart(
      data: LineChartData(
        series: [
          LineSeries<int, double>(
            name: 'Sales',
            data: const [
              DataPoint(x: 0, y: 10),
              DataPoint(x: 1, y: 25),
              DataPoint(x: 2, y: 15),
              DataPoint(x: 3, y: 30),
              DataPoint(x: 4, y: 22),
              DataPoint(x: 5, y: 35),
              DataPoint(x: 6, y: 28),
            ],
            color: const Color(0xFF10B981),
            strokeWidth: 3,
            showMarkers: true,
            markerSize: 8,
          ),
        ],
        xAxis: const AxisConfig(label: 'Month'),
        yAxis: const AxisConfig(label: 'Sales (\$K)', min: 0),
      ),
      tooltip: const TooltipConfig(enabled: true),
      showCrosshair: true,
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class MultiSeriesLineChartExample extends StatelessWidget {
  const MultiSeriesLineChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return LineChart(
      data: LineChartData(
        series: [
          LineSeries<int, double>(
            name: 'Revenue',
            data: const [
              DataPoint(x: 0, y: 50),
              DataPoint(x: 1, y: 75),
              DataPoint(x: 2, y: 65),
              DataPoint(x: 3, y: 90),
              DataPoint(x: 4, y: 85),
              DataPoint(x: 5, y: 100),
            ],
            color: const Color(0xFF3B82F6),
            strokeWidth: 2.5,
            curved: true,
          ),
          LineSeries<int, double>(
            name: 'Costs',
            data: const [
              DataPoint(x: 0, y: 40),
              DataPoint(x: 1, y: 55),
              DataPoint(x: 2, y: 50),
              DataPoint(x: 3, y: 60),
              DataPoint(x: 4, y: 65),
              DataPoint(x: 5, y: 70),
            ],
            color: const Color(0xFFEF4444),
            strokeWidth: 2.5,
            curved: true,
          ),
          LineSeries<int, double>(
            name: 'Profit',
            data: const [
              DataPoint(x: 0, y: 10),
              DataPoint(x: 1, y: 20),
              DataPoint(x: 2, y: 15),
              DataPoint(x: 3, y: 30),
              DataPoint(x: 4, y: 20),
              DataPoint(x: 5, y: 30),
            ],
            color: const Color(0xFF22C55E),
            strokeWidth: 2.5,
            curved: true,
            dashPattern: const [8, 4],
          ),
        ],
        xAxis: const AxisConfig(label: 'Quarter'),
        yAxis: const AxisConfig(label: 'Amount (\$K)', min: 0),
        showLegend: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      showCrosshair: true,
      animation: const ChartAnimation.staggered(),
    );
  }
}

class AreaChartExample extends StatelessWidget {
  const AreaChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return LineChart(
      data: LineChartData(
        series: [
          LineSeries<int, double>(
            name: 'Active Users',
            data: const [
              DataPoint(x: 0, y: 1200),
              DataPoint(x: 1, y: 2800),
              DataPoint(x: 2, y: 2100),
              DataPoint(x: 3, y: 3900),
              DataPoint(x: 4, y: 3200),
              DataPoint(x: 5, y: 4800),
              DataPoint(x: 6, y: 4200),
            ],
            color: const Color(0xFF8B5CF6),
            strokeWidth: 3,
            curved: true,
            fillArea: true,
            areaOpacity: 0.25,
            showMarkers: false,
          ),
        ],
        xAxis: AxisConfig(
          label: 'Day',
          labelFormatter: (value) {
            const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
            final index = value.toInt();
            if (index >= 0 && index < days.length) {
              return days[index];
            }
            return '';
          },
        ),
        yAxis: AxisConfig(
          label: 'Users',
          min: 0,
          labelFormatter: (value) => '${(value / 1000).toStringAsFixed(1)}K',
        ),
      ),
      tooltip: const TooltipConfig(enabled: true),
      showCrosshair: true,
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        type: AnimationType.draw,
      ),
    );
  }
}

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

  @override
  State<AnimatedLineChartExample> createState() =>
      _AnimatedLineChartExampleState();
}

class _AnimatedLineChartExampleState extends State<AnimatedLineChartExample> {
  late List<DataPoint<int, double>> _data;
  final _random = math.Random();

  @override
  void initState() {
    super.initState();
    _generateData();
  }

  void _generateData() {
    _data = List.generate(
      10,
      (i) => DataPoint<int, double>(
        x: i,
        y: 20 + _random.nextDouble() * 80,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: LineChart(
            key: ValueKey(_data.hashCode),
            data: LineChartData(
              series: [
                LineSeries<int, double>(
                  name: 'Random Data',
                  data: _data,
                  color: const Color(0xFFF59E0B),
                  strokeWidth: 3,
                  curved: true,
                  showMarkers: true,
                  markerSize: 10,
                  markerShape: MarkerShape.diamond,
                  fillArea: true,
                  areaOpacity: 0.1,
                ),
              ],
              yAxis: const AxisConfig(min: 0, max: 100),
            ),
            tooltip: const TooltipConfig(enabled: true),
            showCrosshair: true,
            animation: const ChartAnimation(
              duration: Duration(milliseconds: 600),
              curve: Curves.easeOutCubic,
            ),
          ),
        ),
        const SizedBox(height: 20),
        FilledButton.icon(
          onPressed: () {
            setState(() {
              _generateData();
            });
          },
          icon: const Icon(Icons.refresh),
          label: const Text('Generate New Data'),
          style: FilledButton.styleFrom(
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
          ),
        ),
      ],
    );
  }
}

class BarChartExample extends StatelessWidget {
  const BarChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return BarChart(
      data: BarChartData(
        series: [
          BarSeries.fromValues<double>(
            name: 'Sales',
            values: const [45, 72, 53, 85, 61, 78],
            color: const Color(0xFF3B82F6),
          ),
          BarSeries.fromValues<double>(
            name: 'Expenses',
            values: const [32, 48, 41, 52, 38, 55],
            color: const Color(0xFFEF4444),
          ),
        ],
        xAxis: BarXAxisConfig(
          categories: const ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
        ),
        yAxis: const BarYAxisConfig(min: 0),
        grouping: BarGrouping.grouped,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

class PieChartExample extends StatelessWidget {
  const PieChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return PieChart(
      data: PieChartData(
        sections: [
          PieSection(
            value: 35,
            label: 'Mobile',
            gradient: const LinearGradient(
              colors: [Color(0xFF6366F1), Color(0xFF8B5CF6)],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
            ),
            shadowElevation: 6,
          ),
          const PieSection(
            value: 30,
            label: 'Desktop',
            color: Color(0xFF10B981),
            shadowElevation: 4,
          ),
          PieSection(
            value: 20,
            label: 'Tablet',
            gradient: const LinearGradient(
              colors: [Color(0xFFF59E0B), Color(0xFFEF4444)],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
            ),
            shadowElevation: 4,
          ),
          const PieSection(
            value: 15,
            label: 'Other',
            color: Color(0xFF8B5CF6),
            shadowElevation: 4,
          ),
        ],
        holeRadius: 0.5,
        showLabels: true,
        labelPosition: PieLabelPosition.outside,
        labelConnector: PieLabelConnector.elbow,
        segmentGap: 3,
        enableShadows: true,
        hoverDuration: const Duration(milliseconds: 200),
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
      centerWidget: const Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            'Total',
            style: TextStyle(
              fontSize: 14,
              color: Colors.grey,
            ),
          ),
          Text(
            '100',
            style: TextStyle(
              fontSize: 28,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );
  }
}

class ScatterChartExample extends StatelessWidget {
  const ScatterChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ScatterChart(
      data: ScatterChartData(
        series: [
          ScatterSeries<double, double>(
            name: 'Group A',
            data: const [
              ScatterDataPoint(x: 10, y: 20, size: 12),
              ScatterDataPoint(x: 25, y: 35, size: 18),
              ScatterDataPoint(x: 40, y: 28, size: 10),
              ScatterDataPoint(x: 55, y: 45, size: 15),
              ScatterDataPoint(x: 70, y: 38, size: 22),
            ],
            color: const Color(0xFF6366F1),
            pointSize: 12,
          ),
          ScatterSeries<double, double>(
            name: 'Group B',
            data: const [
              ScatterDataPoint(x: 15, y: 50, size: 14),
              ScatterDataPoint(x: 30, y: 65, size: 10),
              ScatterDataPoint(x: 45, y: 55, size: 16),
              ScatterDataPoint(x: 60, y: 72, size: 12),
              ScatterDataPoint(x: 80, y: 60, size: 20),
            ],
            color: const Color(0xFFEC4899),
            pointSize: 12,
          ),
        ],
        xAxis: const AxisConfig(label: 'X Value', min: 0, max: 100),
        yAxis: const AxisConfig(label: 'Y Value', min: 0, max: 100),
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class RadarChartExample extends StatelessWidget {
  const RadarChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return RadarChart(
      data: const RadarChartData(
        axes: ['Speed', 'Power', 'Defense', 'Range', 'Accuracy', 'Mobility'],
        series: [
          RadarSeries(
            name: 'Player A',
            values: [85, 70, 60, 90, 75, 80],
            color: Color(0xFF3B82F6),
          ),
          RadarSeries(
            name: 'Player B',
            values: [70, 85, 75, 65, 90, 70],
            color: Color(0xFFEF4444),
          ),
        ],
        tickCount: 5,
        gridType: RadarGridType.polygon,
      ),
      tooltipConfig: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

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

  @override
  State<GaugeChartExample> createState() => _GaugeChartExampleState();
}

class _GaugeChartExampleState extends State<GaugeChartExample> {
  double _value = 72;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: GaugeChart(
            data: GaugeChartData(
              value: _value,
              minValue: 0,
              maxValue: 100,
              ranges: const [
                GaugeRange(start: 0, end: 30, color: Color(0xFFEF4444)),
                GaugeRange(start: 30, end: 70, color: Color(0xFFF59E0B)),
                GaugeRange(start: 70, end: 100, color: Color(0xFF22C55E)),
              ],
              label: 'Performance',
              showTicks: true,
              majorTickCount: 5,
            ),
            animation: const ChartAnimation(
              duration: Duration(milliseconds: 800),
              curve: Curves.easeOutCubic,
            ),
          ),
        ),
        const SizedBox(height: 20),
        Slider(
          value: _value,
          min: 0,
          max: 100,
          divisions: 100,
          label: _value.toStringAsFixed(0),
          onChanged: (value) => setState(() => _value = value),
        ),
      ],
    );
  }
}

// ============== New Chart Examples ==============

class SparklineChartExample extends StatelessWidget {
  const SparklineChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Line Sparkline', style: TextStyle(fontWeight: FontWeight.bold)),
        const SizedBox(height: 8),
        SizedBox(
          height: 50,
          child: SparklineChart(
            data: const SparklineChartData(
              values: [10, 25, 15, 30, 22, 35, 28, 40, 32, 45],
              type: SparklineType.line,
              color: Color(0xFF6366F1),
              showLastMarker: true,
              showMinMarker: true,
              showMaxMarker: true,
            ),
          ),
        ),
        const SizedBox(height: 24),
        const Text('Area Sparkline', style: TextStyle(fontWeight: FontWeight.bold)),
        const SizedBox(height: 8),
        SizedBox(
          height: 50,
          child: SparklineChart(
            data: const SparklineChartData(
              values: [5, 20, 12, 28, 18, 35, 25, 42, 30, 48],
              type: SparklineType.area,
              color: Color(0xFF10B981),
              areaOpacity: 0.3,
            ),
          ),
        ),
        const SizedBox(height: 24),
        const Text('Bar Sparkline', style: TextStyle(fontWeight: FontWeight.bold)),
        const SizedBox(height: 8),
        SizedBox(
          height: 50,
          child: SparklineChart(
            data: const SparklineChartData(
              values: [15, -10, 25, -5, 30, 20, -15, 35, 10, 40],
              type: SparklineType.bar,
              color: Color(0xFF3B82F6),
              negativeColor: Color(0xFFEF4444),
            ),
          ),
        ),
        const SizedBox(height: 24),
        const Text('Win/Loss Sparkline', style: TextStyle(fontWeight: FontWeight.bold)),
        const SizedBox(height: 8),
        SizedBox(
          height: 50,
          child: SparklineChart(
            data: const SparklineChartData(
              values: [1, -1, 1, 1, -1, 1, -1, -1, 1, 1],
              type: SparklineType.winLoss,
              color: Color(0xFF22C55E),
              negativeColor: Color(0xFFEF4444),
            ),
          ),
        ),
      ],
    );
  }
}

class BubbleChartExample extends StatelessWidget {
  const BubbleChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return BubbleChart(
      data: BubbleChartData(
        series: [
          BubbleSeries<double, double>(
            name: 'Products',
            data: const [
              BubbleDataPoint(x: 10, y: 20, size: 100),
              BubbleDataPoint(x: 25, y: 45, size: 200),
              BubbleDataPoint(x: 40, y: 30, size: 150),
              BubbleDataPoint(x: 55, y: 60, size: 300),
              BubbleDataPoint(x: 70, y: 40, size: 180),
              BubbleDataPoint(x: 85, y: 70, size: 250),
            ],
            color: const Color(0xFF6366F1),
            opacity: 0.7,
          ),
          BubbleSeries<double, double>(
            name: 'Services',
            data: const [
              BubbleDataPoint(x: 15, y: 55, size: 120),
              BubbleDataPoint(x: 35, y: 25, size: 180),
              BubbleDataPoint(x: 50, y: 50, size: 220),
              BubbleDataPoint(x: 65, y: 35, size: 140),
              BubbleDataPoint(x: 80, y: 55, size: 200),
            ],
            color: const Color(0xFFEC4899),
            opacity: 0.7,
          ),
        ],
        xAxis: const AxisConfig(label: 'Revenue', min: 0, max: 100),
        yAxis: const AxisConfig(label: 'Growth', min: 0, max: 100),
        sizeConfig: const BubbleSizeConfig(
          minSize: 10,
          maxSize: 50,
          scaling: BubbleSizeScaling.sqrt,
        ),
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class RadialBarChartExample extends StatelessWidget {
  const RadialBarChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return RadialBarChart(
      data: const RadialBarChartData(
        bars: [
          RadialBarItem(
            label: 'Sales',
            value: 85,
            maxValue: 100,
            color: Color(0xFF6366F1),
          ),
          RadialBarItem(
            label: 'Marketing',
            value: 72,
            maxValue: 100,
            color: Color(0xFF10B981),
          ),
          RadialBarItem(
            label: 'Support',
            value: 60,
            maxValue: 100,
            color: Color(0xFFF59E0B),
          ),
          RadialBarItem(
            label: 'Development',
            value: 90,
            maxValue: 100,
            color: Color(0xFFEC4899),
          ),
        ],
        innerRadius: 0.3,
        trackGap: 8,
        strokeCap: StrokeCap.round,
        showLabels: true,
      ),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

class CandlestickChartExample extends StatelessWidget {
  const CandlestickChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    final now = DateTime.now();
    return CandlestickChart(
      data: CandlestickChartData(
        data: [
          CandlestickDataPoint(date: now.subtract(const Duration(days: 9)), open: 100, high: 110, low: 95, close: 105),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 8)), open: 105, high: 115, low: 100, close: 98),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 7)), open: 98, high: 108, low: 92, close: 106),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 6)), open: 106, high: 120, low: 104, close: 118),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 5)), open: 118, high: 125, low: 115, close: 112),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 4)), open: 112, high: 118, low: 105, close: 108),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 3)), open: 108, high: 122, low: 106, close: 120),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 2)), open: 120, high: 128, low: 118, close: 125),
          CandlestickDataPoint(date: now.subtract(const Duration(days: 1)), open: 125, high: 130, low: 120, close: 118),
          CandlestickDataPoint(date: now, open: 118, high: 126, low: 115, close: 124),
        ],
        bullishColor: const Color(0xFF22C55E),
        bearishColor: const Color(0xFFEF4444),
        style: CandlestickStyle.filled,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class HistogramChartExample extends StatelessWidget {
  const HistogramChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    // Generate sample data (normal distribution)
    final random = math.Random(42);
    final values = List.generate(200, (_) {
      // Box-Muller transform for normal distribution
      final u1 = random.nextDouble();
      final u2 = random.nextDouble();
      return 50 + 15 * math.sqrt(-2 * math.log(u1)) * math.cos(2 * math.pi * u2);
    });

    return HistogramChart(
      data: HistogramChartData(
        values: values,
        binCount: 15,
        color: const Color(0xFF6366F1),
        showDistributionCurve: true,
        distributionCurveColor: const Color(0xFFEC4899),
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class WaterfallChartExample extends StatelessWidget {
  const WaterfallChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return WaterfallChart(
      data: const WaterfallChartData(
        items: [
          WaterfallItem(label: 'Start', value: 100, type: WaterfallItemType.total),
          WaterfallItem(label: 'Sales', value: 50, type: WaterfallItemType.increase),
          WaterfallItem(label: 'Services', value: 30, type: WaterfallItemType.increase),
          WaterfallItem(label: 'Costs', value: -40, type: WaterfallItemType.decrease),
          WaterfallItem(label: 'Tax', value: -20, type: WaterfallItemType.decrease),
          WaterfallItem(label: 'Subtotal', value: 120, type: WaterfallItemType.subtotal),
          WaterfallItem(label: 'Investment', value: 25, type: WaterfallItemType.increase),
          WaterfallItem(label: 'Expenses', value: -15, type: WaterfallItemType.decrease),
          WaterfallItem(label: 'Final', value: 130, type: WaterfallItemType.total),
        ],
        increaseColor: Color(0xFF22C55E),
        decreaseColor: Color(0xFFEF4444),
        totalColor: Color(0xFF3B82F6),
        showConnectors: true,
        showValues: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
      ),
    );
  }
}

class BoxPlotChartExample extends StatelessWidget {
  const BoxPlotChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return BoxPlotChart(
      data: const BoxPlotChartData(
        items: [
          BoxPlotItem(
            label: 'Q1',
            min: 10,
            q1: 25,
            median: 35,
            q3: 50,
            max: 70,
            outliers: [5, 80],
            mean: 38,
          ),
          BoxPlotItem(
            label: 'Q2',
            min: 15,
            q1: 30,
            median: 45,
            q3: 60,
            max: 75,
            outliers: [8],
            mean: 44,
          ),
          BoxPlotItem(
            label: 'Q3',
            min: 20,
            q1: 35,
            median: 50,
            q3: 65,
            max: 80,
            mean: 50,
          ),
          BoxPlotItem(
            label: 'Q4',
            min: 25,
            q1: 40,
            median: 55,
            q3: 70,
            max: 85,
            outliers: [15, 95],
            mean: 54,
          ),
        ],
        showOutliers: true,
        showMean: true,
        boxWidth: 0.6,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class FunnelChartExample extends StatelessWidget {
  const FunnelChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return FunnelChart(
      data: const FunnelChartData(
        sections: [
          FunnelSection(label: 'Visitors', value: 10000, color: Color(0xFF6366F1)),
          FunnelSection(label: 'Leads', value: 6500, color: Color(0xFF8B5CF6)),
          FunnelSection(label: 'Prospects', value: 4200, color: Color(0xFFA855F7)),
          FunnelSection(label: 'Negotiations', value: 2100, color: Color(0xFFC084FC)),
          FunnelSection(label: 'Sales', value: 1200, color: Color(0xFFD8B4FE)),
        ],
        mode: FunnelMode.proportional,
        neckWidth: 0.3,
        gap: 4,
        showLabels: true,
        showValues: true,
        showConversionRate: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

class PyramidChartExample extends StatelessWidget {
  const PyramidChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return PyramidChart(
      data: const PyramidChartData(
        sections: [
          PyramidSection(label: 'Basic', value: 50, color: Color(0xFF22C55E)),
          PyramidSection(label: 'Standard', value: 35, color: Color(0xFF3B82F6)),
          PyramidSection(label: 'Premium', value: 25, color: Color(0xFF8B5CF6)),
          PyramidSection(label: 'Enterprise', value: 15, color: Color(0xFFF59E0B)),
          PyramidSection(label: 'Ultimate', value: 8, color: Color(0xFFEF4444)),
        ],
        mode: PyramidMode.proportional,
        gap: 3,
        showLabels: true,
        labelPosition: PyramidLabelPosition.right,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
      ),
    );
  }
}

class HeatmapChartExample extends StatelessWidget {
  const HeatmapChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return HeatmapChart(
      data: HeatmapChartData(
        data: const [
          [1.0, 2.5, 3.2, 4.1, 2.8],
          [2.3, 4.5, 5.1, 3.8, 4.2],
          [3.1, 3.8, 6.2, 5.5, 3.9],
          [4.2, 5.1, 4.8, 7.2, 5.8],
          [2.9, 3.5, 5.2, 6.1, 8.0],
        ],
        rowLabels: const ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
        columnLabels: const ['9AM', '11AM', '1PM', '3PM', '5PM'],
        colorScale: HeatmapColorScale.viridis,
        showValues: true,
        cellPadding: 2,
        cellBorderRadius: 4,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class TreemapChartExample extends StatelessWidget {
  const TreemapChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return TreemapChart(
      data: TreemapChartData(
        root: TreemapNode(
          label: 'Portfolio',
          children: [
            TreemapNode(
              label: 'Technology',
              children: [
                const TreemapNode(label: 'Apple', value: 35, color: Color(0xFF6366F1)),
                const TreemapNode(label: 'Google', value: 28, color: Color(0xFF8B5CF6)),
                const TreemapNode(label: 'Microsoft', value: 22, color: Color(0xFFA855F7)),
              ],
            ),
            TreemapNode(
              label: 'Finance',
              children: [
                const TreemapNode(label: 'JPMorgan', value: 18, color: Color(0xFF22C55E)),
                const TreemapNode(label: 'Goldman', value: 12, color: Color(0xFF10B981)),
              ],
            ),
            TreemapNode(
              label: 'Healthcare',
              children: [
                const TreemapNode(label: 'Johnson', value: 15, color: Color(0xFF3B82F6)),
                const TreemapNode(label: 'Pfizer', value: 10, color: Color(0xFF0EA5E9)),
              ],
            ),
            const TreemapNode(label: 'Energy', value: 20, color: Color(0xFFF59E0B)),
          ],
        ),
        algorithm: TreemapLayoutAlgorithm.squarified,
        padding: 3,
        showLabels: true,
        labelPosition: TreemapLabelPosition.topLeft,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class SunburstChartExample extends StatelessWidget {
  const SunburstChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return SunburstChart(
      data: SunburstChartData(
        root: SunburstNode(
          label: 'Total',
          children: [
            SunburstNode(
              label: 'Americas',
              color: const Color(0xFF6366F1),
              children: [
                const SunburstNode(label: 'USA', value: 40, color: Color(0xFF818CF8)),
                const SunburstNode(label: 'Canada', value: 15, color: Color(0xFFA5B4FC)),
                const SunburstNode(label: 'Brazil', value: 12, color: Color(0xFFC7D2FE)),
              ],
            ),
            SunburstNode(
              label: 'Europe',
              color: const Color(0xFF22C55E),
              children: [
                const SunburstNode(label: 'UK', value: 18, color: Color(0xFF4ADE80)),
                const SunburstNode(label: 'Germany', value: 16, color: Color(0xFF86EFAC)),
                const SunburstNode(label: 'France', value: 14, color: Color(0xFFBBF7D0)),
              ],
            ),
            SunburstNode(
              label: 'Asia',
              color: const Color(0xFFF59E0B),
              children: [
                const SunburstNode(label: 'China', value: 25, color: Color(0xFFFBBF24)),
                const SunburstNode(label: 'Japan', value: 18, color: Color(0xFFFCD34D)),
                const SunburstNode(label: 'India', value: 12, color: Color(0xFFFDE68A)),
              ],
            ),
          ],
        ),
        innerRadius: 40,
        ringWidth: 50,
        gap: 1,
        showLabels: true,
        showCenterLabel: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

// ============== Phase 6 Chart Examples ==============

class BulletChartExample extends StatelessWidget {
  const BulletChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return BulletChart(
      data: const BulletChartData(
        items: [
          BulletItem(
            label: 'Revenue',
            value: 275,
            target: 250,
            ranges: [150, 225, 300],
            max: 300,
          ),
          BulletItem(
            label: 'Profit',
            value: 22,
            target: 25,
            ranges: [10, 18, 30],
            max: 30,
          ),
          BulletItem(
            label: 'Orders',
            value: 1500,
            target: 1200,
            ranges: [800, 1100, 1600],
            max: 1600,
          ),
          BulletItem(
            label: 'Satisfaction',
            value: 4.5,
            target: 4.2,
            ranges: [3.0, 3.8, 5.0],
            max: 5.0,
          ),
        ],
        orientation: BulletOrientation.horizontal,
        rangeColors: [
          Color(0xFFE5E7EB),
          Color(0xFFD1D5DB),
          Color(0xFF9CA3AF),
        ],
        valueColor: Color(0xFF1F2937),
        targetColor: Color(0xFFEF4444),
        showLabels: true,
        showValues: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class StepChartExample extends StatelessWidget {
  const StepChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return StepChart(
      data: StepChartData(
        series: [
          StepSeries<int, double>(
            name: 'Temperature',
            data: const [
              DataPoint(x: 0, y: 20),
              DataPoint(x: 1, y: 22),
              DataPoint(x: 2, y: 22),
              DataPoint(x: 3, y: 25),
              DataPoint(x: 4, y: 23),
              DataPoint(x: 5, y: 28),
              DataPoint(x: 6, y: 26),
            ],
            color: const Color(0xFF6366F1),
            lineWidth: 2.5,
            showMarkers: true,
            fillArea: true,
            fillOpacity: 0.2,
          ),
        ],
        xAxisLabel: 'Hour',
        yAxisLabel: 'Temperature (°C)',
        minY: 15,
        maxY: 35,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class RangeChartExample extends StatelessWidget {
  const RangeChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return RangeChart(
      data: const RangeChartData(
        items: [
          RangeItem(label: 'Jan', min: 5, max: 15, mid: 10, color: Color(0xFF6366F1)),
          RangeItem(label: 'Feb', min: 8, max: 18, mid: 12, color: Color(0xFF8B5CF6)),
          RangeItem(label: 'Mar', min: 12, max: 22, mid: 16, color: Color(0xFFA855F7)),
          RangeItem(label: 'Apr', min: 15, max: 25, mid: 20, color: Color(0xFFC084FC)),
          RangeItem(label: 'May', min: 18, max: 28, mid: 23, color: Color(0xFFD8B4FE)),
          RangeItem(label: 'Jun', min: 22, max: 32, mid: 27, color: Color(0xFFE9D5FF)),
        ],
        orientation: RangeOrientation.vertical,
        barWidth: 0.6,
        showMidMarker: true,
        showValues: true,
        cornerRadius: 4,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class LollipopChartExample extends StatelessWidget {
  const LollipopChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return LollipopChart(
      data: const LollipopChartData(
        items: [
          LollipopItem(label: 'Product A', value: 85, color: Color(0xFF6366F1)),
          LollipopItem(label: 'Product B', value: 65, color: Color(0xFF8B5CF6)),
          LollipopItem(label: 'Product C', value: 92, color: Color(0xFFA855F7)),
          LollipopItem(label: 'Product D', value: 48, color: Color(0xFFC084FC)),
          LollipopItem(label: 'Product E', value: 73, color: Color(0xFFD8B4FE)),
        ],
        orientation: LollipopOrientation.horizontal,
        markerShape: LollipopMarkerShape.circle,
        markerSize: 14,
        stemWidth: 2,
        showLabels: true,
        showValues: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class DumbbellChartExample extends StatelessWidget {
  const DumbbellChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return DumbbellChart(
      data: const DumbbellChartData(
        items: [
          DumbbellItem(label: '2020', startValue: 45, endValue: 72),
          DumbbellItem(label: '2021', startValue: 52, endValue: 68),
          DumbbellItem(label: '2022', startValue: 38, endValue: 85),
          DumbbellItem(label: '2023', startValue: 60, endValue: 78),
          DumbbellItem(label: '2024', startValue: 55, endValue: 92),
        ],
        orientation: DumbbellOrientation.horizontal,
        markerSize: 12,
        connectorWidth: 3,
        showLabels: true,
        showValues: true,
        startColor: Color(0xFF6366F1),
        endColor: Color(0xFF22C55E),
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class SlopeChartExample extends StatelessWidget {
  const SlopeChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return SlopeChart(
      data: const SlopeChartData(
        items: [
          SlopeItem(label: 'Product A', startValue: 45, endValue: 72, color: Color(0xFF6366F1)),
          SlopeItem(label: 'Product B', startValue: 68, endValue: 52, color: Color(0xFFEF4444)),
          SlopeItem(label: 'Product C', startValue: 55, endValue: 85, color: Color(0xFF22C55E)),
          SlopeItem(label: 'Product D', startValue: 40, endValue: 65, color: Color(0xFFF59E0B)),
          SlopeItem(label: 'Product E', startValue: 75, endValue: 58, color: Color(0xFF8B5CF6)),
        ],
        startLabel: '2023',
        endLabel: '2024',
        lineWidth: 2.5,
        markerSize: 10,
        showLabels: true,
        showValues: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

class RoseChartExample extends StatelessWidget {
  const RoseChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return RoseChart(
      data: const RoseChartData(
        segments: [
          RoseSegment(label: 'N', value: 12, color: Color(0xFF6366F1)),
          RoseSegment(label: 'NE', value: 8, color: Color(0xFF8B5CF6)),
          RoseSegment(label: 'E', value: 15, color: Color(0xFFA855F7)),
          RoseSegment(label: 'SE', value: 22, color: Color(0xFFC084FC)),
          RoseSegment(label: 'S', value: 18, color: Color(0xFFD8B4FE)),
          RoseSegment(label: 'SW', value: 10, color: Color(0xFFE9D5FF)),
          RoseSegment(label: 'W', value: 25, color: Color(0xFFF3E8FF)),
          RoseSegment(label: 'NW', value: 14, color: Color(0xFFEDE9FE)),
        ],
        innerRadius: 0.2,
        gap: 2,
        showLabels: true,
        showValues: true,
        startAngle: -90,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

class BumpChartExample extends StatelessWidget {
  const BumpChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return BumpChart(
      data: const BumpChartData(
        series: [
          BumpSeries(label: 'Team A', rankings: [1, 2, 1, 3, 2, 1], color: Color(0xFF6366F1)),
          BumpSeries(label: 'Team B', rankings: [2, 1, 3, 1, 1, 2], color: Color(0xFF22C55E)),
          BumpSeries(label: 'Team C', rankings: [3, 3, 2, 2, 3, 3], color: Color(0xFFF59E0B)),
          BumpSeries(label: 'Team D', rankings: [4, 4, 4, 4, 4, 4], color: Color(0xFFEF4444)),
        ],
        timeLabels: ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6'],
        lineWidth: 3,
        markerSize: 10,
        showLabels: true,
        showRankings: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}

class CalendarHeatmapExample extends StatelessWidget {
  const CalendarHeatmapExample({super.key});

  @override
  Widget build(BuildContext context) {
    // Generate sample data for the past year
    final now = DateTime.now();
    final random = math.Random(42);
    final data = <CalendarDataPoint>[];

    for (var i = 0; i < 365; i++) {
      final date = now.subtract(Duration(days: i));
      // Generate random values with some patterns
      final dayOfWeek = date.weekday;
      final baseValue = dayOfWeek <= 5 ? 3 : 1; // Lower on weekends
      final value = random.nextInt(5) + baseValue;
      if (random.nextDouble() > 0.3) {
        // 70% chance of having data
        data.add(CalendarDataPoint(date: date, value: value.toDouble()));
      }
    }

    return CalendarHeatmapChart(
      data: CalendarHeatmapData(
        data: data,
        colorStops: const [
          Color(0xFFEBEDF0),
          Color(0xFF9BE9A8),
          Color(0xFF40C463),
          Color(0xFF30A14E),
          Color(0xFF216E39),
        ],
        cellSize: 12,
        cellSpacing: 3,
        cellRadius: 2,
        showDayLabels: true,
        showMonthLabels: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
      ),
    );
  }
}

class GanttChartExample extends StatelessWidget {
  const GanttChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    final now = DateTime.now();
    return GanttChart(
      data: GanttChartData(
        tasks: [
          GanttTask(
            id: '1',
            label: 'Planning',
            start: now,
            end: now.add(const Duration(days: 7)),
            progress: 1.0,
            color: const Color(0xFF6366F1),
          ),
          GanttTask(
            id: '2',
            label: 'Design',
            start: now.add(const Duration(days: 5)),
            end: now.add(const Duration(days: 15)),
            progress: 0.8,
            color: const Color(0xFF8B5CF6),
          ),
          GanttTask(
            id: '3',
            label: 'Development',
            start: now.add(const Duration(days: 12)),
            end: now.add(const Duration(days: 35)),
            progress: 0.4,
            color: const Color(0xFFA855F7),
          ),
          GanttTask(
            id: '4',
            label: 'Testing',
            start: now.add(const Duration(days: 30)),
            end: now.add(const Duration(days: 42)),
            progress: 0.1,
            color: const Color(0xFFC084FC),
          ),
          GanttTask(
            id: '5',
            label: 'Deployment',
            start: now.add(const Duration(days: 40)),
            end: now.add(const Duration(days: 45)),
            progress: 0.0,
            color: const Color(0xFFD8B4FE),
            isMilestone: false,
          ),
          GanttTask(
            id: '6',
            label: 'Launch',
            start: now.add(const Duration(days: 45)),
            end: now.add(const Duration(days: 45)),
            progress: 0.0,
            color: const Color(0xFF22C55E),
            isMilestone: true,
          ),
        ],
        showProgress: true,
        showLabels: true,
        showDates: true,
        barHeight: 24,
        barRadius: 4,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 800),
      ),
    );
  }
}

class SankeyChartExample extends StatelessWidget {
  const SankeyChartExample({super.key});

  @override
  Widget build(BuildContext context) {
    return SankeyChart(
      data: const SankeyChartData(
        nodes: [
          SankeyNode(id: 'salary', label: 'Salary', color: Color(0xFF22C55E)),
          SankeyNode(id: 'freelance', label: 'Freelance', color: Color(0xFF3B82F6)),
          SankeyNode(id: 'investments', label: 'Investments', color: Color(0xFF8B5CF6)),
          SankeyNode(id: 'housing', label: 'Housing', color: Color(0xFFEF4444)),
          SankeyNode(id: 'food', label: 'Food', color: Color(0xFFF59E0B)),
          SankeyNode(id: 'transport', label: 'Transport', color: Color(0xFF06B6D4)),
          SankeyNode(id: 'savings', label: 'Savings', color: Color(0xFF10B981)),
          SankeyNode(id: 'entertainment', label: 'Entertainment', color: Color(0xFFEC4899)),
        ],
        links: [
          SankeyLink(sourceId: 'salary', targetId: 'housing', value: 1500),
          SankeyLink(sourceId: 'salary', targetId: 'food', value: 800),
          SankeyLink(sourceId: 'salary', targetId: 'transport', value: 400),
          SankeyLink(sourceId: 'salary', targetId: 'savings', value: 1200),
          SankeyLink(sourceId: 'salary', targetId: 'entertainment', value: 300),
          SankeyLink(sourceId: 'freelance', targetId: 'savings', value: 800),
          SankeyLink(sourceId: 'freelance', targetId: 'entertainment', value: 200),
          SankeyLink(sourceId: 'investments', targetId: 'savings', value: 500),
        ],
        nodeWidth: 20,
        nodePadding: 15,
        linkOpacity: 0.5,
        showLabels: true,
        showValues: true,
      ),
      tooltip: const TooltipConfig(enabled: true),
      animation: const ChartAnimation(
        duration: Duration(milliseconds: 1000),
        curve: Curves.easeOutCubic,
      ),
    );
  }
}
2
likes
160
points
153
downloads
screenshot

Publisher

verified publishersitharaj.in

Weekly Downloads

A high-performance Flutter chart library with 32+ chart types including line, bar, pie, radar, gauge, sankey, treemap, and more. Modern theming, animations, and accessibility.

Repository (GitHub)
View/report issues

Topics

#chart #visualization #data-visualization #graph #ui

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

collection, flutter, vector_math

More

Packages that depend on chartify