voo_json_tree 0.1.0 copy "voo_json_tree: ^0.1.0" to clipboard
voo_json_tree: ^0.1.0 copied to clipboard

A feature-rich JSON tree viewer/editor widget for Flutter with collapsible nodes, syntax highlighting, search, and editing capabilities.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VooJsonTree Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(useMaterial3: true),
      home: const ExampleHomePage(),
    );
  }
}

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

  @override
  State<ExampleHomePage> createState() => _ExampleHomePageState();
}

class _ExampleHomePageState extends State<ExampleHomePage>
    with SingleTickerProviderStateMixin {
  late TabController _tabController;
  late JsonTreeController _controller;
  VooJsonTreeTheme? _currentTheme;
  String _themeName = 'System';
  bool _useBuilders = false;

  // Sample JSON data
  final Map<String, dynamic> _sampleData = {
    'user': {
      'id': 12345,
      'name': 'John Doe',
      'email': 'john.doe@example.com',
      'website': 'https://johndoe.dev',
      'isActive': true,
      'roles': ['admin', 'developer', 'reviewer'],
      'profile': {
        'avatar': 'https://example.com/avatar.png',
        'bio': 'Software developer with 10+ years of experience',
        '_internal': 'hidden field',
        'location': {
          'city': 'San Francisco',
          'state': 'CA',
          'country': 'USA',
          'coordinates': {
            'lat': 37.7749,
            'lng': -122.4194,
          },
        },
        'socialLinks': {
          'github': 'https://github.com/johndoe',
          'twitter': '@johndoe',
          'linkedin': null,
        },
      },
    },
    'settings': {
      'theme': 'dark',
      'notifications': {
        'email': true,
        'push': false,
        'sms': false,
      },
      'privacy': {
        'profileVisible': true,
        'showEmail': false,
      },
    },
    'stats': {
      'posts': 142,
      'followers': 1583,
      'following': 234,
      'lastLogin': '2024-01-15T10:30:00Z',
    },
    'important': 'This field is highlighted!',
    'tags': ['flutter', 'dart', 'mobile', 'web'],
  };

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 5, vsync: this);
    _controller = JsonTreeController(
      config: const JsonTreeConfig(
        expandDepth: 2,
        enableSearch: true,
        enableCopy: true,
        showNodeCount: true,
      ),
    );
    _controller.setData(_sampleData);
  }

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

  void _cycleTheme(BuildContext context) {
    setState(() {
      if (_themeName == 'System') {
        _currentTheme = VooJsonTreeTheme.dark();
        _themeName = 'Dark';
      } else if (_themeName == 'Dark') {
        _currentTheme = VooJsonTreeTheme.light();
        _themeName = 'Light';
      } else if (_themeName == 'Light') {
        _currentTheme = VooJsonTreeTheme.vscode();
        _themeName = 'VS Code';
      } else if (_themeName == 'VS Code') {
        _currentTheme = VooJsonTreeTheme.monokai();
        _themeName = 'Monokai';
      } else if (_themeName == 'Monokai') {
        _currentTheme = VooJsonTreeTheme.fromTokens();
        _themeName = 'Tokens';
      } else if (_themeName == 'Tokens') {
        _currentTheme = VooJsonTreeTheme.transparent();
        _themeName = 'Transparent';
      } else {
        _currentTheme = null; // System theme
        _themeName = 'System';
      }
    });
  }

  VooJsonTreeTheme _getTheme(BuildContext context) {
    return _currentTheme ?? VooJsonTreeTheme.system(context);
  }

  JsonTreeBuilders? _getBuilders() {
    if (!_useBuilders) return null;

    return JsonTreeBuilders(
      // Make URLs clickable (styled differently)
      valueBuilder: (context, node, defaultWidget) {
        final value = node.value;
        if (value is String && value.startsWith('http')) {
          return Container(
            padding: const EdgeInsets.symmetric(horizontal: 4),
            decoration: BoxDecoration(
              color: Colors.blue.withValues(alpha: 0.2),
              borderRadius: BorderRadius.circular(4),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                const Icon(Icons.link, size: 12, color: Colors.blue),
                const SizedBox(width: 4),
                defaultWidget,
              ],
            ),
          );
        }
        return defaultWidget;
      },
      // Style internal/private keys differently
      keyBuilder: (context, node, defaultWidget) {
        if (node.key.startsWith('_')) {
          return Text(
            node.key,
            style: TextStyle(
              color: Colors.grey.shade600,
              fontStyle: FontStyle.italic,
              fontFamily: 'monospace',
              fontSize: 13,
            ),
          );
        }
        return defaultWidget;
      },
      // Highlight important nodes
      nodeBuilder: (context, node, defaultWidget) {
        if (node.key == 'important') {
          return Container(
            decoration: BoxDecoration(
              border: Border.all(color: Colors.amber, width: 2),
              borderRadius: BorderRadius.circular(4),
            ),
            child: defaultWidget,
          );
        }
        return defaultWidget;
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('VooJsonTree Example'),
        actions: [
          // Custom builders toggle
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Text('Builders', style: TextStyle(fontSize: 12)),
              Switch(
                value: _useBuilders,
                onChanged: (value) => setState(() => _useBuilders = value),
              ),
            ],
          ),
          const SizedBox(width: 8),
          // Theme selector
          TextButton.icon(
            onPressed: () => _cycleTheme(context),
            icon: const Icon(Icons.palette),
            label: Text(_themeName),
          ),
          const SizedBox(width: 8),
          // Expand all
          IconButton(
            onPressed: _controller.expandAll,
            icon: const Icon(Icons.unfold_more),
            tooltip: 'Expand all',
          ),
          // Collapse all
          IconButton(
            onPressed: _controller.collapseAll,
            icon: const Icon(Icons.unfold_less),
            tooltip: 'Collapse all',
          ),
          const SizedBox(width: 8),
        ],
        bottom: TabBar(
          controller: _tabController,
          tabs: const [
            Tab(text: 'Standard'),
            Tab(text: 'Minimal'),
            Tab(text: 'Developer'),
            Tab(text: 'Raw'),
            Tab(text: 'Responsive'),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          // Standard tab
          _buildStandardTab(),
          // Minimal tab
          _buildMinimalTab(),
          // Developer tab
          _buildDeveloperTab(),
          // Raw tab
          _buildRawTab(),
          // Responsive tab
          _buildResponsiveTab(),
        ],
      ),
    );
  }

  Widget _buildStandardTab() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          _buildInfoBar(
            'Standard View: Full features with controller, search, copy, keyboard navigation',
          ),
          const SizedBox(height: 16),
          Expanded(
            child: VooJsonTree(
              controller: _controller,
              theme: _getTheme(context),
              builders: _getBuilders(),
              showToolbar: true,
              showPathBreadcrumb: true,
              config: const JsonTreeConfig(
                expandDepth: 2,
                enableSearch: true,
                enableCopy: true,
                enableContextMenu: true,
                enableKeyboardNavigation: true,
                showNodeCount: true,
                animateExpansion: true,
              ),
              onNodeTap: (node) {
                debugPrint('Tapped: ${node.path}');
              },
            ),
          ),
          const SizedBox(height: 16),
          _buildSelectedInfo(),
        ],
      ),
    );
  }

  Widget _buildMinimalTab() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          _buildInfoBar(
            'Minimal View: Bare-bones tree with no extras - just collapsible nodes',
          ),
          const SizedBox(height: 16),
          Expanded(
            child: VooJsonTree.minimal(
              data: _sampleData,
              theme: _getTheme(context),
              onNodeTap: (node) {
                debugPrint('Minimal tapped: ${node.path}');
              },
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildDeveloperTab() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          _buildInfoBar(
            'Developer View: All expanded, full metadata, ideal for debugging',
          ),
          const SizedBox(height: 16),
          Expanded(
            child: VooJsonTree.developer(
              data: _sampleData,
              theme: _getTheme(context),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildRawTab() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          _buildInfoBar(
            'Raw View: Transparent background - tree in custom container',
          ),
          const SizedBox(height: 16),
          Expanded(
            child: Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                  colors: [
                    Colors.purple.shade900,
                    Colors.blue.shade900,
                  ],
                ),
                borderRadius: BorderRadius.circular(16),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withValues(alpha: 0.3),
                    blurRadius: 10,
                    offset: const Offset(0, 5),
                  ),
                ],
              ),
              padding: const EdgeInsets.all(20),
              child: VooJsonTree.raw(
                data: _sampleData,
                config: const JsonTreeConfig(
                  expandDepth: 1,
                  showNodeCount: true,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildResponsiveTab() {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          _buildInfoBar(
            'Responsive View: Auto-adapts to screen size (resize window to see)',
          ),
          const SizedBox(height: 16),
          Expanded(
            child: VooJsonTreeResponsive(
              data: _sampleData,
              theme: _getTheme(context),
              mobileConfig: JsonTreeConfig.minimal(),
              tabletConfig: JsonTreeConfig.compact(),
              desktopConfig: JsonTreeConfig.full(),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildInfoBar(String text) {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.surfaceContainerHighest,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Row(
        children: [
          const Icon(Icons.info_outline, size: 18),
          const SizedBox(width: 8),
          Expanded(
            child: Text(
              text,
              style: Theme.of(context).textTheme.bodySmall,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildSelectedInfo() {
    return ListenableBuilder(
      listenable: _controller,
      builder: (context, _) {
        final selected = _controller.selectedNode;
        if (selected == null) {
          return const SizedBox.shrink();
        }

        return Container(
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.surfaceContainerHighest,
            borderRadius: BorderRadius.circular(8),
          ),
          child: Row(
            children: [
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Selected: ${selected.path}',
                      style: Theme.of(context).textTheme.bodySmall?.copyWith(
                            fontFamily: 'monospace',
                          ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      'Type: ${selected.type.displayName} | '
                      'Depth: ${selected.depth}',
                      style: Theme.of(context).textTheme.bodySmall,
                    ),
                  ],
                ),
              ),
              TextButton(
                onPressed: _controller.clearSelection,
                child: const Text('Clear'),
              ),
            ],
          ),
        );
      },
    );
  }
}
1
likes
130
points
4
downloads

Publisher

verified publishervoostack.com

Weekly Downloads

A feature-rich JSON tree viewer/editor widget for Flutter with collapsible nodes, syntax highlighting, search, and editing capabilities.

Documentation

API reference

License

MIT (license)

Dependencies

equatable, flutter, voo_responsive, voo_tokens

More

Packages that depend on voo_json_tree