React

by Michael Vashevko

HTML

<div id="app"></div>

CSS

body {
  background: #20262e;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}

React

import React, { useState, useEffect } from "react";

// Sample Node class
class Node {
    constructor(name, value, children = []) {
        this.name = name;
        this.value = value;
        this.children = children;
        this.isVisible = true;
        this.isExpanded = false;
        this.isEnabled = true;
        this.parent = null;
    }
}

// TreeVisitor Utility
class TreeVisitor {
    static prepareData(root) {
        root.parent = null;  // Root has no parent
        const queue = [root];

        while (queue.length > 0) {
            const node = queue.shift();
            node.isVisible = true;
            node.isExpanded = false;
            node.isEnabled = true;

            for (const child of node.children) {
                child.parent = node;  // Set parent reference
                queue.push(child);
            }
        }
    }
}

// TreeNode Component
const TreeNode = ({ node, onToggleExpand, onToggleEnable }) => {
    return (
        <div style={{ marginLeft: "20px" }}>
            <span
                style={{ cursor: "pointer", fontWeight: "bold" }}
                onClick={() => onToggleExpand(node)}
            >
                {node.children.length > 0 ? (node.isExpanded ? "▼ " : "▶ ") : "• "}
                {node.name}
            </span>
            <button
                onClick={() => onToggleEnable(node)}
                style={{
                    marginLeft: "10px",
                    cursor: "pointer",
                    background: "none",
                    border: "none",
                    color: node.isEnabled ? "green" : "red"
                }}
            >
                {node.isEnabled ? "🟢 Disable" : "🔴 Enable"}
            </button>
            {node.isExpanded &&
                node.children.map((child) => (
                    <TreeNode
                        key={child.name}
                        node={child}
                        onToggleExpand={onToggleExpand}
                       ...