ModLayoutOne

Um pacote Flutter completo para construir layouts responsivos com suporte integrado a temas, internacionalização (i18n) e componentes reutilizáveis. O pacote utiliza GetX para gerenciamento de estado e fornece uma arquitetura modular para criar aplicações Flutter de nível empresarial.

Índice

Instalação

Adicione ao seu pubspec.yaml:

dependencies:
  mod_layout_one: ^1.0.0

Configuração Inicial

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final prefs = await SharedPreferences.getInstance();

  await ModLayout.init(
    config: ModLayoutConfig(
      appTitle: 'Meu App',
      lightTheme: MyAppTheme.light,  // Tema claro personalizado
      darkTheme: MyAppTheme.dark,    // Tema escuro personalizado
      menuItems: [
        MenuItem(
          title: 'home'.tr,
          icon: Icons.home,
          route: '/home',
        ),
        MenuItem(
          title: 'settings'.tr,
          icon: Icons.settings,
          route: '/settings',
        ),
      ],
      customTranslations: AppTranslations().keys,
    ),
    prefs: prefs,
  );

  runApp(const MyApp());
}

Componentes

Layout Base

O ModBaseLayout é o componente principal que integra sidebar, header e footer com suporte responsivo.

ModBaseLayout(
  title: 'Título da Página',
  logo: Image.asset('assets/logo.png'), // Opcional
  menuItems: [
    MenuItem(
      title: 'Dashboard',
      icon: Icons.dashboard,
      route: '/dashboard',
    ),
    MenuGroup(
      title: 'Configurações',
      icon: Icons.settings,
      children: [
        MenuItem(
          title: 'Perfil',
          icon: Icons.person,
          route: '/profile',
        ),
        MenuItem(
          title: 'Segurança',
          icon: Icons.security,
          route: '/security',
        ),
      ],
    ),
  ],
  body: Container(
    child: Text('Conteúdo da página'),
  ),
  footer: Text('© 2024 Meu App'), // Opcional
  sidebarBackgroundColor: Colors.blue, // Opcional
  appBarActions: [
    ThemeToggle(), // Botão para alternar tema claro/escuro
    LanguageSelector(), // Seletor de idioma
    UserProfile(), // Widget de perfil do usuário
  ],
)

Botões

O ModButton oferece botões customizáveis com diferentes estilos, tamanhos e estados de loading.

// Botão básico
ModButton(
  title: 'Clique aqui',
  onPressed: () async {
    // Ação do botão
    await Future.delayed(Duration(seconds: 2));
  },
)

// Botão com tipo e tamanho
ModButton(
  title: 'Salvar',
  type: ModButtonType.success,
  size: ModButtonSize.lg,
  onPressed: () async {
    // Ação de salvar
  },
)

// Botão com ícones
ModButton(
  title: 'Download',
  leftIcon: Icons.download,
  type: ModButtonType.primary,
  onPressed: () async {
    // Ação de download
  },
)

// Botão com loading customizado
ModButton(
  title: 'Processar',
  loadingText: 'Processando...',
  loadingIcon: Icons.hourglass_empty,
  type: ModButtonType.warning,
  onPressed: () async {
    await processData();
  },
)

// Botão outline (sem preenchimento)
ModButton(
  title: 'Cancelar',
  type: ModButtonType.none,
  borderColor: ModButtonType.danger,
  borderType: ModBorderType.solid,
  onPressed: () async {
    Navigator.pop(context);
  },
)

// Botão desabilitado
ModButton(
  title: 'Indisponível',
  disabled: true,
  onPressed: null,
)

// Botão com cores customizadas
ModButton(
  title: 'Custom',
  type: ModButtonType.custom,
  backgroundColor: Colors.purple,
  textColor: Colors.white,
  onPressed: () async {
    // Ação
  },
)

Caixas de Texto

O ModTextBox fornece campos de entrada de texto com validação e customização.

// Campo de texto básico
ModTextBox(
  label: 'Nome',
  hint: 'Digite seu nome',
  onChange: (value) {
    print('Nome: $value');
  },
)

// Campo com validação
ModTextBox(
  label: 'Email',
  hint: 'exemplo@email.com',
  keyboardType: TextInputType.emailAddress,
  validator: (value) {
    if (value == null || !value.contains('@')) {
      return 'Email inválido';
    }
    return null;
  },
  onChange: (value) {
    // Processar email
  },
)

// Campo de senha
ModTextBox(
  label: 'Senha',
  isPassword: true,
  size: ModTextBoxSize.md,
  onChange: (value) {
    // Processar senha
  },
)

// Campo com ícones
ModTextBox(
  label: 'Pesquisar',
  prefixIcon: Icon(Icons.search),
  suffixButton: IconButton(
    icon: Icon(Icons.clear),
    onPressed: () {
      // Limpar campo
    },
  ),
  onChange: (value) {
    // Executar pesquisa
  },
)

// Campo multilinha
ModTextBox(
  label: 'Descrição',
  hint: 'Digite uma descrição detalhada',
  multiline: true,
  minLines: 3,
  maxLines: 10,
  onChange: (value) {
    // Processar descrição
  },
)

// Campo somente leitura
ModTextBox(
  label: 'ID',
  value: '12345',
  readOnly: true,
)

// Campo com formatação
ModTextBox(
  label: 'Telefone',
  hint: '(00) 00000-0000',
  inputFormatters: [
    FilteringTextInputFormatter.digitsOnly,
    TelefoneInputFormatter(), // Seu formatter customizado
  ],
  onChange: (value) {
    // Processar telefone
  },
)

// Campo com label flutuante
ModTextBox(
  label: 'Endereço',
  floatingLabel: true,
  labelPosition: ModTextBoxLabelPosition.top,
  onChange: (value) {
    // Processar endereço
  },
)

O Dropdown básico para seleção de opções.

// Dropdown simples
Dropdown<String>(
  value: selectedValue,
  items: [
    DropdownMenuItem(value: 'op1', child: Text('Opção 1')),
    DropdownMenuItem(value: 'op2', child: Text('Opção 2')),
    DropdownMenuItem(value: 'op3', child: Text('Opção 3')),
  ],
  onChanged: (value) {
    setState(() {
      selectedValue = value;
    });
  },
)

O ModDropdownSearch oferece um dropdown avançado com pesquisa e múltipla seleção.

// Dropdown com pesquisa básico
ModDropdownSearch<String>(
  label: 'País',
  hint: 'Selecione um país',
  searchHint: 'Pesquisar país...',
  items: [
    ModDropdownSearchMenuItem(
      value: 'BR',
      child: Text('Brasil'),
      icon: Icons.flag,
    ),
    ModDropdownSearchMenuItem(
      value: 'US',
      child: Text('Estados Unidos'),
      icon: Icons.flag,
    ),
    ModDropdownSearchMenuItem(
      value: 'JP',
      child: Text('Japão'),
      icon: Icons.flag,
    ),
  ],
  onChanged: (value) {
    print('País selecionado: $value');
  },
)

// Dropdown com múltipla seleção
ModDropdownSearch<String>(
  label: 'Habilidades',
  multiSelect: true,
  searchEnabled: true,
  items: [
    ModDropdownSearchMenuItem(
      value: 'flutter',
      child: Text('Flutter'),
    ),
    ModDropdownSearchMenuItem(
      value: 'dart',
      child: Text('Dart'),
    ),
    ModDropdownSearchMenuItem(
      value: 'firebase',
      child: Text('Firebase'),
    ),
  ],
  onChanged: (value) {
    print('Habilidades selecionadas: $value');
  },
)

// Dropdown customizado
ModDropdownSearch<User>(
  label: 'Usuário',
  size: ModDropdownSearchSize.lg,
  dropdownHeight: 300,
  displayStringForOption: (user) => user?.name ?? '',
  items: users.map((user) => 
    ModDropdownSearchMenuItem(
      value: user,
      child: ListTile(
        leading: CircleAvatar(
          backgroundImage: NetworkImage(user.avatar),
        ),
        title: Text(user.name),
        subtitle: Text(user.email),
      ),
    ),
  ).toList(),
  onChanged: (user) {
    print('Usuário selecionado: ${user?.name}');
  },
)

Tabela de Dados

O ModDataTable oferece tabelas com ordenação, paginação e personalização.

// Tabela básica
ModDataTable<Map<String, dynamic>>(
  headers: [
    ModDataHeader(
      child: Text('ID'),
      field: 'id',
      width: 100,
      sortable: true,
    ),
    ModDataHeader(
      child: Text('Nome'),
      field: 'name',
      width: 200,
      sortable: true,
    ),
    ModDataHeader(
      child: Text('Email'),
      field: 'email',
      width: 250,
    ),
    ModDataHeader(
      child: Text('Ações'),
      field: 'actions',
      width: 150,
    ),
  ],
  data: userData,
  source: UserDataSource(userData),
  rowsPerPage: 10,
  totalRecords: userData.length,
  currentPage: 1,
  onPageChanged: (page) {
    // Carregar nova página
  },
  onSort: (field, direction) {
    // Ordenar dados
  },
)

// Tabela com cores alternadas e bordas
ModDataTable<Product>(
  headers: headers,
  data: products,
  source: ProductDataSource(products),
  borderStyle: BorderStyle.topLeftRightBottom,
  oddRowColor: Colors.grey[100],
  evenRowColor: Colors.white,
  headerColor: Colors.blue[50],
  rowsPerPage: 20,
  totalRecords: products.length,
  currentPage: currentPage,
  availableRowsPerPage: [10, 20, 50, 100],
  onPageChanged: (page) {
    setState(() {
      currentPage = page;
    });
  },
  onRowsPerPageChanged: (rowsPerPage) {
    setState(() {
      this.rowsPerPage = rowsPerPage;
    });
  },
)

// Tabela com redimensionamento de colunas
ModDataTable<dynamic>(
  headers: headers,
  data: data,
  source: dataSource,
  enableColumnResize: true,
  fixedHeader: true,
  showHorizontalScrollbar: true,
  onColumnWidthChanged: (field, newWidth) {
    // Salvar nova largura da coluna
  },
  rowsPerPage: 15,
  totalRecords: totalRecords,
  currentPage: currentPage,
  onPageChanged: (page) {
    loadPage(page);
  },
)

Cards

O ModCard oferece cards com header, body e footer customizáveis.

// Card básico
ModCard(
  header: Text('Título do Card'),
  content: Container(
    padding: EdgeInsets.all(16),
    child: Text('Conteúdo do card'),
  ),
  footer: Row(
    mainAxisAlignment: MainAxisAlignment.end,
    children: [
      TextButton(
        onPressed: () {},
        child: Text('Cancelar'),
      ),
      ElevatedButton(
        onPressed: () {},
        child: Text('Confirmar'),
      ),
    ],
  ),
)

// Card accordion (expansível)
ModCard(
  header: Row(
    children: [
      Icon(Icons.info),
      SizedBox(width: 8),
      Text('Informações'),
    ],
  ),
  content: Column(
    children: [
      ListTile(title: Text('Item 1')),
      ListTile(title: Text('Item 2')),
      ListTile(title: Text('Item 3')),
    ],
  ),
  isAccordion: true,
  initiallyExpanded: false,
)

// Card customizado
ModCard(
  header: Container(
    color: Colors.blue,
    padding: EdgeInsets.all(16),
    child: Text(
      'Card Customizado',
      style: TextStyle(color: Colors.white),
    ),
  ),
  content: Container(
    height: 200,
    child: Center(
      child: Text('Conteúdo personalizado'),
    ),
  ),
  backgroundColor: Colors.blue[50],
  borderRadius: BorderRadius.circular(16),
  elevation: 8,
)

O ModModal cria diálogos modais responsivos e customizáveis.

// Modal básico
showDialog(
  context: context,
  builder: (context) => ModModal(
    header: Text('Título do Modal'),
    body: Container(
      padding: EdgeInsets.all(16),
      child: Text('Conteúdo do modal'),
    ),
    footer: Row(
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: Text('Fechar'),
        ),
        ElevatedButton(
          onPressed: () {
            // Ação
            Navigator.pop(context);
          },
          child: Text('Confirmar'),
        ),
      ],
    ),
  ),
);

// Modal com tamanhos e posições
showDialog(
  context: context,
  builder: (context) => ModModal(
    header: Row(
      children: [
        Icon(Icons.warning, color: Colors.orange),
        SizedBox(width: 8),
        Text('Atenção'),
      ],
    ),
    body: Container(
      padding: EdgeInsets.all(24),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.warning_amber, size: 64, color: Colors.orange),
          SizedBox(height: 16),
          Text('Tem certeza que deseja continuar?'),
        ],
      ),
    ),
    footer: Container(
      padding: EdgeInsets.all(16),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          ModButton(
            title: 'Cancelar',
            type: ModButtonType.secondary,
            onPressed: () async => Navigator.pop(context),
          ),
          ModButton(
            title: 'Confirmar',
            type: ModButtonType.danger,
            onPressed: () async {
              // Ação perigosa
              Navigator.pop(context);
            },
          ),
        ],
      ),
    ),
    size: ModModalSize.sm,
    position: ModModalPosition.center,
    height: ModModalHeight.auto,
  ),
);

// Modal fullscreen
showDialog(
  context: context,
  builder: (context) => ModModal(
    header: AppBar(
      title: Text('Editor Fullscreen'),
      automaticallyImplyLeading: false,
      actions: [
        IconButton(
          icon: Icon(Icons.close),
          onPressed: () => Navigator.pop(context),
        ),
      ],
    ),
    body: Container(
      child: TextField(
        maxLines: null,
        decoration: InputDecoration(
          hintText: 'Digite seu texto aqui...',
          border: InputBorder.none,
        ),
      ),
    ),
    footer: Container(
      padding: EdgeInsets.all(16),
      child: ModButton(
        title: 'Salvar',
        type: ModButtonType.success,
        onPressed: () async {
          // Salvar conteúdo
          Navigator.pop(context);
        },
      ),
    ),
    fullScreen: true,
  ),
);

Toast

O ModToast exibe notificações temporárias não intrusivas.

// Toast de sucesso
ToastManager.show(
  context: context,
  toast: ModToast(
    type: ToastType.success,
    title: 'Sucesso!',
    message: 'Operação realizada com sucesso.',
    icon: Icons.check_circle,
    position: ToastPosition.topRight,
    duration: Duration(seconds: 3),
  ),
);

// Toast de erro
ToastManager.show(
  context: context,
  toast: ModToast(
    type: ToastType.error,
    title: 'Erro',
    message: 'Ocorreu um erro ao processar a solicitação.',
    icon: Icons.error,
    position: ToastPosition.topCenter,
    showCloseButton: true,
  ),
);

// Toast de aviso
ToastManager.show(
  context: context,
  toast: ModToast(
    type: ToastType.warning,
    title: 'Atenção',
    message: 'Esta ação não pode ser desfeita.',
    position: ToastPosition.bottomRight,
  ),
);

// Toast informativo
ToastManager.show(
  context: context,
  toast: ModToast(
    type: ToastType.info,
    message: 'Nova mensagem recebida',
    position: ToastPosition.bottomCenter,
    duration: Duration(seconds: 5),
  ),
);

// Toast customizado
ToastManager.show(
  context: context,
  toast: ModToast(
    type: ToastType.custom,
    title: 'Download',
    message: 'Arquivo baixado com sucesso',
    icon: Icons.download_done,
    backgroundColor: Colors.purple,
    textColor: Colors.white,
    iconColor: Colors.white,
    position: ToastPosition.topLeft,
    borderRadius: 16,
    maxWidth: 400,
    shadow: BoxShadow(
      color: Colors.purple.withOpacity(0.3),
      blurRadius: 10,
      offset: Offset(0, 5),
    ),
  ),
);

Tabs

O componente Tabs permite criar navegação em abas.

// Tabs básicas
DefaultTabController(
  length: 3,
  child: Column(
    children: [
      TabBar(
        tabs: [
          Tab(text: 'Aba 1', icon: Icon(Icons.home)),
          Tab(text: 'Aba 2', icon: Icon(Icons.star)),
          Tab(text: 'Aba 3', icon: Icon(Icons.settings)),
        ],
      ),
      Expanded(
        child: TabBarView(
          children: [
            Center(child: Text('Conteúdo da Aba 1')),
            Center(child: Text('Conteúdo da Aba 2')),
            Center(child: Text('Conteúdo da Aba 3')),
          ],
        ),
      ),
    ],
  ),
)

Grid System

Sistema de grid responsivo inspirado no Bootstrap.

// Grid responsivo básico
ModContainer(
  child: ModRow(
    columns: [
      ModColumn(
        columnSizes: {
          ScreenSize.xs: ColumnSize.col12, // 100% em telas pequenas
          ScreenSize.sm: ColumnSize.col6,  // 50% em telas pequenas
          ScreenSize.md: ColumnSize.col4,  // 33% em telas médias
          ScreenSize.lg: ColumnSize.col3,  // 25% em telas grandes
        },
        child: Card(
          child: Padding(
            padding: EdgeInsets.all(16),
            child: Text('Coluna 1'),
          ),
        ),
      ),
      ModColumn(
        columnSizes: {
          ScreenSize.xs: ColumnSize.col12,
          ScreenSize.sm: ColumnSize.col6,
          ScreenSize.md: ColumnSize.col4,
          ScreenSize.lg: ColumnSize.col3,
        },
        child: Card(
          child: Padding(
            padding: EdgeInsets.all(16),
            child: Text('Coluna 2'),
          ),
        ),
      ),
      ModColumn(
        columnSizes: {
          ScreenSize.xs: ColumnSize.col12,
          ScreenSize.sm: ColumnSize.col12,
          ScreenSize.md: ColumnSize.col4,
          ScreenSize.lg: ColumnSize.col6,
        },
        child: Card(
          child: Padding(
            padding: EdgeInsets.all(16),
            child: Text('Coluna 3'),
          ),
        ),
      ),
    ],
  ),
)

// Grid com offset e ordem
ModContainer(
  fluid: true, // Container fluido (largura total)
  child: ModRow(
    columns: [
      ModColumn(
        columnSizes: {
          ScreenSize.xs: ColumnSize.col12,
          ScreenSize.md: ColumnSize.col6,
        },
        offset: {
          ScreenSize.md: 3, // Offset de 3 colunas em telas médias
        },
        order: {
          ScreenSize.xs: 2, // Ordem 2 em telas pequenas
          ScreenSize.md: 1, // Ordem 1 em telas médias
        },
        child: Container(
          height: 100,
          color: Colors.blue,
          child: Center(child: Text('Coluna com Offset')),
        ),
      ),
    ],
  ),
)

Charts

Componente para gráficos de barras com interatividade.

// Gráfico de barras básico
ModBarChart(
  data: [
    ChartData(label: 'Jan', value: 100),
    ChartData(label: 'Fev', value: 150),
    ChartData(label: 'Mar', value: 120),
    ChartData(label: 'Abr', value: 200),
    ChartData(label: 'Mai', value: 180),
  ],
  height: 300,
  barColor: Colors.blue,
)

// Gráfico com ações customizadas
ModBarChart(
  data: chartData,
  height: 400,
  barColor: Colors.green,
  backgroundColor: Colors.grey[100],
  showGrid: true,
  showLabels: true,
  animationDuration: Duration(milliseconds: 800),
  onBarTap: (data) {
    print('Barra clicada: ${data.label} - ${data.value}');
  },
  actionButtons: [
    ChartActionButton(
      icon: Icons.download,
      onPressed: () {
        // Exportar gráfico
      },
    ),
    ChartActionButton(
      icon: Icons.refresh,
      onPressed: () {
        // Atualizar dados
      },
    ),
  ],
)

TreeView

Componente para exibir dados hierárquicos em árvore.

// TreeView básico
ModTreeView(
  nodes: [
    TreeNode(
      title: 'Documentos',
      icon: Icons.folder,
      children: [
        TreeNode(
          title: 'Trabalho',
          icon: Icons.folder,
          children: [
            TreeNode(
              title: 'Projeto.pdf',
              icon: Icons.picture_as_pdf,
            ),
            TreeNode(
              title: 'Relatório.docx',
              icon: Icons.description,
            ),
          ],
        ),
        TreeNode(
          title: 'Pessoal',
          icon: Icons.folder,
          children: [
            TreeNode(
              title: 'Fotos',
              icon: Icons.photo_library,
            ),
          ],
        ),
      ],
    ),
    TreeNode(
      title: 'Downloads',
      icon: Icons.download,
      children: [],
    ),
  ],
  onNodeTap: (node) {
    print('Nó selecionado: ${node.title}');
  },
  onNodeExpanded: (node, isExpanded) {
    print('Nó ${node.title} ${isExpanded ? "expandido" : "colapsado"}');
  },
)

Avatars

Componente para exibir avatares de usuários.

// Avatar básico
Avatar(
  imageUrl: 'https://example.com/user.jpg',
  size: 60,
)

// Avatar com iniciais
Avatar(
  name: 'João Silva',
  size: 40,
  backgroundColor: Colors.blue,
  textColor: Colors.white,
)

// Avatar com status online
Avatar(
  imageUrl: userImageUrl,
  size: 50,
  showStatusIndicator: true,
  isOnline: true,
  statusIndicatorColor: Colors.green,
)

// Avatar com borda
Avatar(
  imageUrl: userImageUrl,
  size: 80,
  borderWidth: 3,
  borderColor: Colors.blue,
)

Loading

Indicadores de carregamento customizáveis.

// Loading básico
Loading()

// Loading com mensagem
Loading(
  message: 'Carregando dados...',
)

// Loading customizado
Loading(
  size: 100,
  color: Colors.blue,
  strokeWidth: 4,
  message: 'Por favor, aguarde',
  messageStyle: TextStyle(
    fontSize: 16,
    fontWeight: FontWeight.bold,
  ),
)

// Loading overlay
LoadingOverlay(
  isLoading: isProcessing,
  child: YourContent(),
  opacity: 0.8,
  progressIndicator: CircularProgressIndicator(
    valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
  ),
)

Labels

Labels e badges para destacar informações.

// Label básico
Label(
  text: 'Novo',
  backgroundColor: Colors.green,
  textColor: Colors.white,
)

// Label com ícone
Label(
  text: 'Premium',
  icon: Icons.star,
  backgroundColor: Colors.amber,
  textColor: Colors.black,
)

// Badge numérico
Badge(
  value: 5,
  backgroundColor: Colors.red,
  textColor: Colors.white,
  child: Icon(Icons.notifications),
)

// Label outline
Label(
  text: 'Em Progresso',
  backgroundColor: Colors.transparent,
  borderColor: Colors.orange,
  borderWidth: 2,
  textColor: Colors.orange,
)

Dialogs

Diálogos de confirmação e alerta.

// Dialog de confirmação
showDialog(
  context: context,
  builder: (context) => ConfirmDialog(
    title: 'Confirmar Exclusão',
    message: 'Tem certeza que deseja excluir este item?',
    confirmText: 'Excluir',
    cancelText: 'Cancelar',
    onConfirm: () {
      // Executar exclusão
    },
  ),
);

// Dialog de alerta
showDialog(
  context: context,
  builder: (context) => AlertDialog(
    title: Text('Aviso'),
    content: Text('Esta ação requer permissões administrativas.'),
    actions: [
      TextButton(
        onPressed: () => Navigator.pop(context),
        child: Text('OK'),
      ),
    ],
  ),
);

// Dialog de input
showDialog(
  context: context,
  builder: (context) => InputDialog(
    title: 'Renomear Arquivo',
    label: 'Novo nome:',
    initialValue: 'documento.pdf',
    onConfirm: (value) {
      // Renomear arquivo
    },
  ),
);

Text Utilities

Utilitários para trabalhar com texto.

// Texto com cópia
TextCopy(
  text: 'Texto que pode ser copiado',
  showCopyButton: true,
  onCopy: () {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Copiado!')),
    );
  },
)

// Divisor de texto
TextDivider(
  text: 'OU',
  lineColor: Colors.grey,
  textStyle: TextStyle(
    color: Colors.grey[600],
    fontWeight: FontWeight.bold,
  ),
)

// Texto com highlight
HighlightText(
  text: 'Este é um texto com palavra destacada',
  highlight: 'destacada',
  highlightColor: Colors.yellow,
)

// Texto truncado com tooltip
TruncatedText(
  text: 'Este é um texto muito longo que será truncado',
  maxLength: 20,
  showTooltip: true,
)

Controllers

ThemeController

Gerencia temas claro/escuro com persistência.

// Obter o controller
final themeController = Get.find<ThemeController>();

// Alternar tema
themeController.toggleTheme();

// Definir tema específico
themeController.setTheme(ThemeMode.dark);

// Verificar tema atual
bool isDarkMode = themeController.isDarkMode;

// Ouvir mudanças de tema
ever(themeController.theme, (theme) {
  print('Tema alterado para: $theme');
});

LanguageController

Gerencia idiomas e internacionalização.

// Obter o controller
final languageController = Get.find<LanguageController>();

// Alterar idioma
languageController.changeLanguage('pt_BR');

// Obter idioma atual
String currentLanguage = languageController.currentLanguage;

// Idiomas disponíveis
List<String> languages = languageController.availableLanguages;

// Traduzir texto
String translated = 'home'.tr;

LayoutController

Controla o estado do layout (sidebar, responsividade).

// Obter o controller
final layoutController = Get.find<LayoutController>();

// Alternar sidebar
layoutController.toggleSidebar();

// Verificar se é mobile
bool isMobile = layoutController.isMobile;

// Definir item de menu selecionado
layoutController.setSelectedMenuItem('/dashboard');

// Ouvir mudanças no layout
ever(layoutController.sidebarOpen, (isOpen) {
  print('Sidebar ${isOpen ? "aberta" : "fechada"}');
});

Temas

Configuração de Tema Customizado

class MyAppTheme {
  static final light = ThemeData(
    brightness: Brightness.light,
    primarySwatch: Colors.blue,
    scaffoldBackgroundColor: Colors.grey[50],
    appBarTheme: AppBarTheme(
      backgroundColor: Colors.white,
      foregroundColor: Colors.black,
      elevation: 1,
    ),
    cardTheme: CardTheme(
      elevation: 2,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(8),
      ),
    ),
  );

  static final dark = ThemeData(
    brightness: Brightness.dark,
    primarySwatch: Colors.blue,
    scaffoldBackgroundColor: Colors.grey[900],
    appBarTheme: AppBarTheme(
      backgroundColor: Colors.grey[850],
      foregroundColor: Colors.white,
      elevation: 0,
    ),
    cardTheme: CardTheme(
      elevation: 4,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(8),
      ),
    ),
  );
}

Internacionalização

Adicionar Traduções Customizadas

class AppTranslations extends BaseTranslations {
  @override
  Map<String, Map<String, String>> get keys {
    final baseKeys = super.keys;
    
    final customKeys = {
      'en_US': {
        'welcome_message': 'Welcome to our app!',
        'logout_confirm': 'Are you sure you want to logout?',
      },
      'pt_BR': {
        'welcome_message': 'Bem-vindo ao nosso app!',
        'logout_confirm': 'Tem certeza que deseja sair?',
      },
      'es_ES': {
        'welcome_message': '¡Bienvenido a nuestra aplicación!',
        'logout_confirm': '¿Estás seguro de que quieres cerrar sesión?',
      },
    };
    
    // Mesclar traduções
    for (final locale in baseKeys.keys) {
      baseKeys[locale]!.addAll(customKeys[locale] ?? {});
    }
    
    return baseKeys;
  }
}

Usar Traduções

// No código
Text('welcome_message'.tr)

// Com parâmetros
Text('hello_user'.trParams({'name': userName}))

// Plural
Text('items_count'.trPlural('items_count', itemCount))

Breakpoints do Sistema de Grid

  • xs: < 576px (Mobile portrait)
  • sm: ≥ 576px (Mobile landscape)
  • md: ≥ 768px (Tablet)
  • lg: ≥ 992px (Desktop)
  • xl: ≥ 1200px (Large desktop)

Exemplo Completo

Para um exemplo completo de implementação, consulte o projeto de exemplo que demonstra o uso de todos os componentes em uma aplicação real.

Requisitos

  • Flutter 3.0.0 ou superior
  • Dart 2.17.0 ou superior

Dependências

  • get: ^4.6.5 (Gerenciamento de estado)
  • shared_preferences: ^2.0.0 (Persistência)
  • fl_chart: ^0.40.0 (Gráficos)

Contribuindo

Contribuições são bem-vindas! Por favor, sinta-se à vontade para enviar um Pull Request.

Licença

MIT License

Suporte

Para reportar bugs ou solicitar features, abra uma issue no GitHub.

Libraries

assets/app_images
controllers/language_controller
controllers/layout_controller
controllers/theme_controller
layout/base_layout
layout/components/mobile_drawer
layout/components/no_access_screen
layout/models/module_model
layout/widgets/language_selector
layout/widgets/module_selector_widget
layout/widgets/theme_toggle
layout/widgets/user_profile
mod_layout_one
themes/app_theme
themes/dark_theme
themes/light_theme
translations/base_translations
translations/en_us
translations/es_es
translations/pt_br
widgets/avatars/avatars
widgets/buttons/buttons
widgets/buttons/icon_buttom
widgets/cards/card_default
widgets/charts/charts
widgets/charts/controllers/bar_chart_controller
widgets/charts/mod_bar_chart
widgets/charts/models/chart_action_button_theme
widgets/charts/models/chart_data
widgets/datatable/datatable
widgets/dialogs/dialog
widgets/grid/mod_grid
widgets/grid_system/enuns/column_size
widgets/grid_system/enuns/screen_size
widgets/grid_system/grid_system
widgets/grid_system/grid_system_colums
widgets/grid_system/grid_system_container
widgets/grid_system/grid_system_rows
widgets/labels/label
widgets/loading/loading
widgets/tabs/tabs
widgets/text/text_copy
widgets/text/text_divider
widgets/textbox/textbox
widgets/toast/mod_toast
widgets/toast/toast_manager
widgets/treeview/mod_treeview