Tree Navigator

Pub Version License: MIT

A powerful Flutter library for navigating and managing complex JSON tree data structures with support for conditional logic, script engine, and multiple navigation strategies.

✨ Key Features

  • 🌳 JSON Tree Navigation: Easily traverse through nodes in JSON data trees
  • 🎯 Smart Navigation: Support for both static and dynamic navigation based on conditions
  • πŸ”§ Script Engine: Execute complex logic with built-in script engine
  • πŸ“Š State Management: Track and manage navigation state
  • πŸ“ Navigation History: Record and trace selection history
  • 🎨 Multiple Strategies: Support for JSON Rule Engine and Strategy Pattern
  • πŸ”„ Flexible: Easily extensible with custom functions and strategies

πŸš€ Installation

Add the dependency to your pubspec.yaml file:

dependencies:
  tree_navigator: ^1.0.0

Then run:

flutter pub get

πŸ“– Usage

Basic Initialization

import 'package:tree_navigator/tree_navigator.dart';

// Initialize TreeNavigator with JSON file
var navigator = TreeNavigator('/path/to/assets', 'tree_data.json');

// Get current node information
print('Current node: ${navigator.current().key}');
print('Label: ${navigator.current().label}');

JSON File Structure

{
  "key": "ROOT",
  "label": "Home",
  "options": [
    {
      "key": "STATIC-NODE",
      "label": "Static Navigation",
      "leadsTo": "TARGET-NODE"
    },
    {
      "key": "DYNAMIC-NODE", 
      "label": "Dynamic Navigation",
      "script": "age >= 18 ? ADULT : CHILD"
    }
  ],
  "children": [
    {
      "key": "TARGET-NODE",
      "label": "Target Node",
      "options": [],
      "children": []
    },
    {
      "key": "ADULT",
      "label": "Adult",
      "options": [],
      "children": []
    },
    {
      "key": "CHILD", 
      "label": "Child",
      "options": [],
      "children": []
    }
  ]
}

Basic Navigation

// Set selection for current node
navigator.set('ROOT', 'STATIC-NODE');

// Move to next node
try {
  var nextNode = navigator.next();
  print('Moved to: ${nextNode?.key}');
} catch (e) {
  print('Navigation error: $e');
}

// Go back to previous node
navigator.prev();

// Reset to root
navigator.reset();

Conditional Navigation

// Set state
navigator.set('age', 25);
navigator.set('ROOT', 'DYNAMIC-NODE');

// Script will automatically evaluate: age >= 18 ? ADULT : CHILD
var nextNode = navigator.next(); // Will go to "ADULT" node

Registering Custom Functions

// Register custom function
navigator.registerScriptFunction('checkAge', (
  Map<String, dynamic> context,
  List<String> params,
  Map<String, dynamic>? extraParams
) {
  Map<String, dynamic> state = context['state'] ?? {};
  int age = state['age'] ?? 0;
  
  return age >= 18 ? 'ADULT' : 'CHILD';
});

// Use in JSON
{
  "key": "AGE-CHECK",
  "label": "Age Check",
  "script": "checkAge()"
}

JSON Rule Engine

// Define rule
Map<String, dynamic> ageRule = {
  "type": "condition",
  "field": "age", 
  "operator": ">=",
  "value": 18,
  "true": "ADULT",
  "false": "CHILD"
};

// Execute rule
navigator.set('age', 20);
String? result = navigator.executeJsonRule(ageRule);
print('Result: $result'); // Output: ADULT

Strategy Pattern

import 'package:tree_navigator/script_engine.dart';

// Create strategy
var ageStrategy = ConditionalStrategy(
  condition: 'age >= 18',
  trueNode: 'ADULT',
  falseNode: 'CHILD',
);

// Execute strategy
navigator.set('age', 16);
String? result = navigator.executeStrategy(ageStrategy);
print('Result: $result'); // Output: CHILD

Utility Functions

// Get navigation history
List<String> history = navigator.history();
print('History: $history');

// Get journey (detailed selections)
List<TraceItem> journey = navigator.journey();
for (var trace in journey) {
  print('Selected: ${trace.key}, Params: ${trace.params}');
}

// Find all leaf nodes
List<TreeNode> leafs = navigator.getleafs(navigator.current());
for (var leaf in leafs) {
  print('Leaf: ${leaf.key} - ${leaf.label}');
}

// Get last selection
TraceItem? lastChoice = navigator.lastsel();
print('Last choice: ${lastChoice?.key}');

🎯 Real-world Examples

Example 1: Survey System

// Initialize with survey file
var survey = TreeNavigator('/assets', 'survey.json');

// Set user information
survey.set('age', 25);
survey.set('gender', 'male');
survey.set('income', 50000);

// Navigate through questions
survey.set('Q1', 'YES');
var nextQuestion = survey.next();

// Check final result
if (survey.getleafs(survey.current()).isNotEmpty) {
  print('Survey completed!');
}

Example 2: Dynamic Menu System

// Menu changes based on user permissions
var menu = TreeNavigator('/assets', 'menu.json');

menu.set('userRole', 'admin');
menu.set('permissions', ['read', 'write', 'delete']);

// Script in JSON will check permissions and display appropriate menu
var menuItems = menu.current().options;

πŸ“Š Demo Results

When running with test2.json file, the library will execute the following scenarios:

Scenario 1: Static Navigation

πŸ“ Current Node: ROOT
🎯 Options: STATIC-NODE, RULE-NODE
πŸ‘† Select: STATIC-NODE β†’ Navigate to STATIC-18

Scenario 2: Script Navigation (age β‰₯ 18)

πŸŽ‚ Set age = 25
πŸ‘† Select: RULE-NODE β†’ Script evaluates β†’ Navigate to OVER-18

Scenario 3: Script Navigation (age < 18)

πŸŽ‚ Set age = 15  
πŸ‘† Select: RULE-NODE β†’ Script evaluates β†’ Navigate to UNDER-18

πŸ”§ API Reference

TreeNavigator

Method Description
current() Get current node
next([params]) Move to next node
prev() Go back to previous node
reset() Reset to root node
set(key, value) Set state
history() Get navigation history
journey() Get detailed selections
getleafs(node) Find all leaf nodes
lastsel() Get last selection

Script Engine

Method Description
registerFunction(name, fn) Register custom function
executeScript(script, context) Execute script
executeJsonRule(rule) Execute JSON rule
executeStrategy(strategy) Execute strategy

🀝 Contributing

We welcome all contributions! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Create a Pull Request

πŸ“„ License

This project is distributed under the MIT License. See the LICENSE file for more details.

πŸ†˜ Support

  • πŸ“§ Email: ducphan1311@gmail.com
  • πŸ› Issues: GitHub Issues