dashboards_responsive 1.0.0 copy "dashboards_responsive: ^1.0.0" to clipboard
dashboards_responsive: ^1.0.0 copied to clipboard

A Flutter package for creating responsive, grid-based dashboards with draggable and resizable chart tiles.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:dashboards_responsive/dashboards.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dashboard Grid Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
      ),
      home: const DashboardDemoPage(),
    );
  }
}

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

  @override
  State<DashboardDemoPage> createState() => _DashboardDemoPageState();
}

class _DashboardDemoPageState extends State<DashboardDemoPage> {
  late final HierarchicalDashboardControllerImpl controller;
  bool _editMode = false;
  // Override parameters for testing responsive behavior
  double? _widthOverride;
  String? _breakpointOverride;
  int? _columnsOverride;
  final config = DashboardConfig(
    columns: 12,
    columnsByBreakpoint: {
      Breakpoint.xs: 4,
      Breakpoint.sm: 8,
      Breakpoint.md: 12,
      Breakpoint.lg: 12,
      Breakpoint.xl: 12,
    },
    rowHeight: 40,
    gutter: 8,
    padding: EdgeInsets.all(8),
    breakpoints: DashboardBreakpoints(
      breakpoints: {
        Breakpoint.xs: 0,
        Breakpoint.sm: 600,
        Breakpoint.md: 900,
        Breakpoint.lg: 1200,
        Breakpoint.xl: 1536,
      },
    ),
    compactionMode: CompactionMode.vertical,
  );

  @override
  void initState() {
    super.initState();
    // Create a simple layout using the new hierarchical approach
    final layout = DashboardLayout(
      breakpointLayouts: {
        Breakpoint.xs: BreakpointLayout(
          widgets: {
            'sales': WidgetPosition(x: 0, y: 0, w: 4, h: 6),
            'traffic': WidgetPosition(x: 0, y: 6, w: 4, h: 6),
            'kpi': WidgetPosition(x: 0, y: 12, w: 4, h: 3),
            'map': WidgetPosition(x: 0, y: 15, w: 4, h: 6),
            'table': WidgetPosition(x: 0, y: 21, w: 4, h: 6),
          },
        ),
        Breakpoint.sm: BreakpointLayout(
          widgets: {
            'sales': WidgetPosition(x: 0, y: 0, w: 4, h: 6),
            'traffic': WidgetPosition(x: 4, y: 0, w: 4, h: 6),
            'kpi': WidgetPosition(x: 0, y: 6, w: 8, h: 3),
            'map': WidgetPosition(x: 0, y: 9, w: 8, h: 6),
            'table': WidgetPosition(x: 0, y: 15, w: 8, h: 6),
          },
        ),
        Breakpoint.md: BreakpointLayout(
          widgets: {
            'sales': WidgetPosition(x: 0, y: 0, w: 4, h: 6),
            'traffic': WidgetPosition(x: 4, y: 0, w: 6, h: 6),
            'kpi': WidgetPosition(x: 10, y: 0, w: 6, h: 3),
            'map': WidgetPosition(x: 0, y: 6, w: 6, h: 6),
            'table': WidgetPosition(x: 6, y: 6, w: 6, h: 6),
          },
        ),
        Breakpoint.lg: BreakpointLayout(
          widgets: {
            'sales': WidgetPosition(x: 0, y: 0, w: 3, h: 6),
            'traffic': WidgetPosition(x: 3, y: 0, w: 4, h: 6),
            'kpi': WidgetPosition(x: 7, y: 0, w: 5, h: 3),
            'map': WidgetPosition(x: 0, y: 6, w: 6, h: 6),
            'table': WidgetPosition(x: 6, y: 6, w: 6, h: 6),
          },
        ),
      },
      widgetIds: {'sales', 'traffic', 'kpi', 'map', 'table'},
    );

    controller = HierarchicalDashboardControllerImpl(initial: layout);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dashboard Grid Demo'),
        actions: [
          IconButton(
            icon: Icon(_editMode ? Icons.visibility : Icons.edit),
            onPressed: () {
              setState(() {
                _editMode = !_editMode;
              });
            },
            tooltip: _editMode ? 'Switch to View Mode' : 'Switch to Edit Mode',
          ),
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () => _showOverrideDialog(),
            tooltip: 'Screen Size Override',
          ),
          IconButton(
            icon: const Icon(Icons.save_alt),
            onPressed: () {
              final json = controller.layout.value.toJson();
              showDialog(
                context: context,
                builder: (_) => AlertDialog(
                  title: const Text('Current Layout JSON'),
                  content: SingleChildScrollView(child: Text(json.toString())),
                  actions: [
                    TextButton(
                      onPressed: () => Navigator.pop(context),
                      child: const Text('Close'),
                    ),
                  ],
                ),
              );
            },
          ),
        ],
      ),
      body: SingleChildScrollView(
        child: DashboardCanvas(
          config: config,
          controller: controller,
          enableDrag: true,
          enableResizeHorizontal: true,
          enableResizeVertical: true,
          editMode: _editMode,
          availableWidthOverride: _widthOverride,
          breakpointOverride: _breakpointOverride,
          effectiveColumnsOverride: _columnsOverride,
          widgetBuilder: (context, widgetId, position) {
            return Container(
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(8),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withValues(alpha: 0.1),
                    blurRadius: 4,
                    offset: const Offset(0, 2),
                  ),
                ],
              ),
              child: Center(
                child: Text(
                  widgetId,
                  style: Theme.of(context).textTheme.titleMedium,
                ),
              ),
            );
          },
        ),
      ),
    );
  }

  void _showOverrideDialog() {
    showDialog(
      context: context,
      builder: (context) => StatefulBuilder(
        builder: (context, setDialogState) {
          return AlertDialog(
            title: const Text('Screen Size Override'),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                // Width override
                Row(
                  children: [
                    Expanded(
                      child: TextField(
                        decoration: const InputDecoration(
                          labelText: 'Width (px)',
                          hintText: 'e.g., 800',
                        ),
                        keyboardType: TextInputType.number,
                        onChanged: (value) {
                          _widthOverride = value.isEmpty
                              ? null
                              : double.tryParse(value);
                        },
                        controller: TextEditingController(
                          text: _widthOverride?.toString() ?? '',
                        ),
                      ),
                    ),
                    IconButton(
                      icon: const Icon(Icons.clear),
                      onPressed: () {
                        setDialogState(() {
                          _widthOverride = null;
                        });
                      },
                    ),
                  ],
                ),
                const SizedBox(height: 16),
                // Breakpoint override
                Row(
                  children: [
                    Expanded(
                      child: DropdownButtonFormField<String>(
                        decoration: const InputDecoration(
                          labelText: 'Breakpoint',
                        ),
                        value: _breakpointOverride,
                        items: const [
                          DropdownMenuItem(value: null, child: Text('Auto')),
                          DropdownMenuItem(value: 'xs', child: Text('XS')),
                          DropdownMenuItem(value: 'sm', child: Text('SM')),
                          DropdownMenuItem(value: 'md', child: Text('MD')),
                          DropdownMenuItem(value: 'lg', child: Text('LG')),
                          DropdownMenuItem(value: 'xl', child: Text('XL')),
                        ],
                        onChanged: (value) {
                          setDialogState(() {
                            _breakpointOverride = value;
                          });
                        },
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 16),
                // Columns override
                Row(
                  children: [
                    Expanded(
                      child: TextField(
                        decoration: const InputDecoration(
                          labelText: 'Columns',
                          hintText: 'e.g., 8',
                        ),
                        keyboardType: TextInputType.number,
                        onChanged: (value) {
                          _columnsOverride = value.isEmpty
                              ? null
                              : int.tryParse(value);
                        },
                        controller: TextEditingController(
                          text: _columnsOverride?.toString() ?? '',
                        ),
                      ),
                    ),
                    IconButton(
                      icon: const Icon(Icons.clear),
                      onPressed: () {
                        setDialogState(() {
                          _columnsOverride = null;
                        });
                      },
                    ),
                  ],
                ),
              ],
            ),
            actions: [
              TextButton(
                onPressed: () {
                  setState(() {
                    _widthOverride = null;
                    _breakpointOverride = null;
                    _columnsOverride = null;
                  });
                  Navigator.pop(context);
                },
                child: const Text('Reset'),
              ),
              TextButton(
                onPressed: () => Navigator.pop(context),
                child: const Text('Cancel'),
              ),
              TextButton(
                onPressed: () {
                  setState(() {});
                  Navigator.pop(context);
                },
                child: const Text('Apply'),
              ),
            ],
          );
        },
      ),
    );
  }
}
0
likes
0
points
96
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter package for creating responsive, grid-based dashboards with draggable and resizable chart tiles.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, json_annotation

More

Packages that depend on dashboards_responsive