Build powerful decision trees with a visual node-based editor
🌐 Website • 🎮 Playground • Features • Installation • Quick Start • Examples
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.
- 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
- 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
- Security: Built-in input sanitization to prevent XSS attacks
- Enhanced Error Messages: Clear, user-friendly error messages for HTTP inputs and validation
- 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
- 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
# npm npm install treege # pnpm pnpm add treege # yarn yarn add treege # bun bun add treegeCreate 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} /> ); }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} /> ); }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> ); }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";Navigation node that controls the flow between different parts of the tree.
{ type: "flow", data: { targetId: "next-node-id", label: "Continue" } }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
Container for organizing multiple nodes together.
{ type: "group", data: { label: "Personal Information" } }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 titlesdivider- Visual separator between sections
Create dynamic flows with conditional logic:
{ type: "conditional", data: { conditions: [ { field: "age", operator: ">=", value: "18" }, { field: "country", operator: "===", value: "US" } ], logicalOperator: "AND" } }Supported operators: ===, !==, >, <, >=, <=
Treege supports multiple languages out of the box:
{ type: "input", data: { label: { en: "First Name", fr: "Prénom", es: "Nombre" } } }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 } }} />Add custom validation logic:
<TreegeRenderer flows={flow} validate={(values, visibleNodes) => { const errors = {}; if (values.password !== values.confirmPassword) { errors.confirmPassword = "Passwords must match"; } return errors; }} />Control when validation occurs:
// Validate only on submit (default) <TreegeRenderer validationMode="onSubmit" /> // Validate on every change <TreegeRenderer validationMode="onChange" />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 } } }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> ); }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", "test@example.com")}> Prefill Email </button> <button onClick={submit}>Submit</button> <button onClick={reset}>Reset</button> </div> ); }Check out the /example directory for complete examples:
# Run the example app bun exampleOnce the development server is running, you can access these examples:
-
Default Example: http://localhost:5173/
- Basic demonstration of Treege functionality
-
Demo Example: http://localhost:5173/example
- Full featured demo showcasing the library capabilities
-
All Inputs Example: http://localhost:5173/example-all-inputs
- Comprehensive showcase of all 16 input types
-
Custom Input Example: http://localhost:5173/example-custom-input
- Demonstrates how to create and integrate custom input components
-
TreegeConfigProvider Example: http://localhost:5173/example-treege-config-provider
- Shows global configuration with TreegeConfigProvider
| 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 |
| 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 |
# Install dependencies yarn install # Start dev server yarn dev # Build library yarn build # Run linter and type check yarn lint # Preview build yarn preview- 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
Contributions are welcome! Please feel free to submit a Pull Request.
ISC
Created and maintained by Mickaël Austoni