Skip to content

Tracktor/treege

Repository files navigation

Treege

Treege

Build powerful decision trees with a visual node-based editor

npm version License: ISC

🌐 Website🎮 PlaygroundFeaturesInstallationQuick StartExamples


Overview

Treege is a modern React library for creating and rendering interactive decision trees. Built on top of ReactFlow, it provides a complete solution for building complex form flows, decision logic, and conditional workflows with an intuitive visual editor.

Features

Visual Editor (treege/editor)

  • Node-based Interface: Drag-and-drop editor powered by ReactFlow
  • 4 Node Types: Flow, Group, Input, and UI nodes
  • Conditional Edges: Advanced logic with AND/OR operators (===, !==, >, <, >=, <=)
  • Multi-language Support: Built-in translation system for all labels
  • Type-safe: Full TypeScript support
  • Mini-map & Controls: Navigation tools for complex trees
  • Theme Support: Dark/light mode with customizable backgrounds

Runtime Renderer (treege/renderer)

  • Production Ready: Full-featured form generation and validation system
  • 16 Input Types: text, number, select, checkbox, radio, date, daterange, time, timerange, file, address, http, textarea, password, switch, autocomplete, and hidden
  • HTTP Integration: Built-in API integration with response mapping and search functionality
  • Advanced Validation: Required fields, pattern matching, custom validation functions
  • Conditional Logic: Dynamic field visibility based on user input and conditional edges
  • Web & Native: Both web (React) and React Native renderer implementations
  • Fully Customizable: Override any component (FormWrapper, Group, Inputs, SubmitButton, UI elements)
  • Theme Support: Dark/light mode out of the box
  • Google API Integration: Address autocomplete support

Developer Experience

  • Modular: Import only what you need (editor, renderer, or both)
  • Modern Stack: React 18/19, TailwindCSS 4, TypeScript 5
  • Well-typed: Comprehensive TypeScript definitions
  • Production Ready: Battle-tested and actively maintained

Installation

# npm
npm install treege

# pnpm
pnpm add treege

# yarn
yarn add treege

# bun
bun add treege

Quick Start

Using the Editor

Create and edit decision trees visually:

import { TreegeEditor } from "treege/editor";
import type { Flow } from "treege";

function App() {
  const [flow, setFlow] = useState<Flow | null>(null);

  const handleSave = (updatedFlow: Flow) => {
    setFlow(updatedFlow);
    console.log("Decision tree saved:", updatedFlow);
  };

  return (
    <TreegeEditor
      flow={flow}
      onSave={handleSave}
    />
  );
}

Using the Renderer

Render interactive forms from decision trees:

import { TreegeRenderer } from "treege/renderer";
import type { Flow, FormValues } from "treege";

function App() {
  const flow: Flow = {
    id: "flow-1",
    nodes: [
      {
        id: "start",
        type: "input",
        data: {
          name: "username",
          label: "Enter your username",
          required: true
        }
      }
    ],
    edges: []
  };

  const handleSubmit = (values: FormValues) => {
    console.log("Form submitted:", values);
  };

  return (
    <TreegeRenderer
      flows={flow}
      onSubmit={handleSubmit}
    />
  );
}

Using Both Together

import { TreegeEditor } from "treege/editor";
import { TreegeRenderer } from "treege/renderer";
import { useState } from "react";

function App() {
  const [flow, setFlow] = useState(null);
  const [mode, setMode] = useState<"edit" | "preview">("edit");

  return (
    <div>
      <button onClick={() => setMode(mode === "edit" ? "preview" : "edit")}>
        {mode === "edit" ? "Preview" : "Edit"}
      </button>

      {mode === "edit" ? (
        <TreegeEditor flow={flow} onSave={setFlow} />
      ) : (
        <TreegeRenderer flows={flow} onSubmit={console.log} />
      )}
    </div>
  );
}

Module Structure

Treege provides three import paths for optimal bundle size:

// Import everything (editor + renderer + types)
import { TreegeEditor, TreegeRenderer } from "treege";

// Import only the editor
import { TreegeEditor } from "treege/editor";

// Import only the renderer
import { TreegeRenderer } from "treege/renderer";

Node Types

Flow Node

Navigation node that controls the flow between different parts of the tree.

{
  type: "flow",
  data: {
    targetId: "next-node-id",
    label: "Continue"
  }
}

Input Node

Form input with validation, patterns, and conditional logic.

{
  type: "input",
  data: {
    type: "text",
    name: "email",
    label: "Email Address",
    required: true,
    pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$",
    errorMessage: "Please enter a valid email"
  }
}

Supported input types: text, number, textarea, password, select, radio, checkbox, switch, autocomplete, date, daterange, time, timerange, file, address, http, hidden

Group Node

Container for organizing multiple nodes together.

{
  type: "group",
  data: {
    label: "Personal Information"
  }
}

UI Node

Display-only elements for visual organization and content display.

{
  type: "ui",
  data: {
    type: "title", // or "divider"
    label: "Welcome to the form"
  }
}

Supported UI types:

  • title - Display headings and titles
  • divider - Visual separator between sections

Conditional Edges

Create dynamic flows with conditional logic:

{
  type: "conditional",
  data: {
    conditions: [
      {
        field: "age",
        operator: ">=",
        value: "18"
      },
      {
        field: "country",
        operator: "===",
        value: "US"
      }
    ],
    logicalOperator: "AND"
  }
}

Supported operators: ===, !==, >, <, >=, <=

Translation Support

Treege supports multiple languages out of the box:

{
  type: "input",
  data: {
    label: {
      en: "First Name",
      fr: "Prénom",
      es: "Nombre"
    }
  }
}

Customization

Custom Input Components

Override default input renderers with your own:

import { TreegeRenderer } from "treege/renderer";

const CustomTextInput = ({ node }) => {
  return <input className="my-custom-input" />;
};

<TreegeRenderer
  flows={flow}
  components={{
    inputs: {
      text: CustomTextInput
    }
  }}
/>

Custom Validation

Add custom validation logic:

<TreegeRenderer
  flows={flow}
  validate={(values, visibleNodes) => {
    const errors = {};

    if (values.password !== values.confirmPassword) {
      errors.confirmPassword = "Passwords must match";
    }

    return errors;
  }}
/>

Validation Modes

Control when validation occurs:

// Validate only on submit (default)
<TreegeRenderer validationMode="onSubmit" />

// Validate on every change
<TreegeRenderer validationMode="onChange" />

HTTP Input Integration

Use the HTTP input type to fetch and map data from APIs:

{
  type: "input",
  data: {
    type: "http",
    name: "country",
    label: "Select your country",
    httpConfig: {
      method: "GET",
      url: "https://api.example.com/countries",
      responsePath: "$.data.countries", // JSONPath to extract data
      mapping: {
        label: "name",
        value: "code"
      },
      searchParam: "query", // Enable search functionality
      fetchOnMount: true
    }
  }
}

Global Configuration

Configure the renderer globally using the TreegeConfigProvider:

import { TreegeConfigProvider } from "treege/renderer";

function App() {
  return (
    <TreegeConfigProvider
      config={{
        language: "fr",
        googleApiKey: "your-google-api-key",
        components: {
          // Your custom components
        }
      }}
    >
      <TreegeRenderer flows={flow} />
    </TreegeConfigProvider>
  );
}

Programmatic Control

Use the useTreegeRenderer hook for programmatic control:

import { useTreegeRenderer } from "treege/renderer";

function CustomForm() {
  const { values, setFieldValue, submit, reset } = useTreegeRenderer();

  return (
    <div>
      <button onClick={() => setFieldValue("email", "[email protected]")}>
        Prefill Email
      </button>
      <button onClick={submit}>Submit</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

Examples

Check out the /example directory for complete examples:

  # Run the example app
  bun example

API Reference

TreegeEditor Props

Prop Type Default Description
flow Flow | null null Initial decision tree
onSave (flow: Flow) => void - Callback when tree is saved
language string "en" UI language
theme "light" | "dark" "dark" Editor theme

TreegeRenderer Props

Prop Type Default Description
flows Flow | null - Decision tree to render
onSubmit (values: FormValues) => void - Form submission handler
onChange (values: FormValues) => void - Form change handler
validate (values, nodes) => Record<string, string> - Custom validation function
initialValues FormValues {} Initial form values
components RendererComponents - Custom component overrides
language string "en" UI language
validationMode "onSubmit" | "onChange" "onSubmit" When to validate
theme "light" | "dark" "dark" Renderer theme
googleApiKey string - API key for address input

Development

# Install dependencies
yarn install

# Start dev server
yarn dev

# Build library
yarn build

# Run linter and type check
yarn lint

# Preview build
yarn preview

Tech Stack

  • React 18/19 - UI library
  • TypeScript - Type safety
  • TailwindCSS 4 - Styling
  • ReactFlow - Node-based UI
  • Radix UI - Accessible components
  • Zustand - State management
  • Vite - Build tool

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

ISC

Credits

Created and maintained by Mickaël Austoni

Support

About

Form decision tree generator

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages