import React, { useState, useEffect, useRef, useMemo } from 'react'; import { TreeDeciduous, Tent, Palette, PawPrint, Crosshair, Globe, Leaf, ZoomIn, ZoomOut, RefreshCw, Sprout } from 'lucide-react'; const generateForestData = () => { return { id: 'root', label: 'FOREST', icon: 'TreeDeciduous', color: '#22c55e', children: [ { id: 'fauna', label: 'Fauna', icon: 'PawPrint', color: '#ef4444', children: [ { id: 'mammals', label: 'Mammals', children: [ { id: 'predators', label: 'Predators', children: [{id: 'wolves', label: 'Wolves'}, {id: 'bears', label: 'Bears'}, {id: 'bigcats', label: 'Lynx/Cougar'}, {id: 'foxes', label: 'Foxes'}] }, { id: 'herbivores', label: 'Herbivores', children: [{id: 'deer', label: 'Deer/Elk'}, {id: 'moose', label: 'Moose'}, {id: 'rabbits', label: 'Rabbits'}, {id: 'rodents', label: 'Squirrels/Beavers'}] }, { id: 'primates', label: 'Primates', children: [{id: 'monkeys', label: 'Howler Monkeys'}, {id: 'lemurs', label: 'Lemurs'}, {id: 'apes', label: 'Gorillas'}] } ] }, { id: 'birds', label: 'Birds', children: [ { id: 'raptors', label: 'Raptors', children: [{id: 'eagles', label: 'Eagles'}, {id: 'owls', label: 'Owls (Nocturnal)'}, {id: 'hawks', label: 'Hawks'}] }, { id: 'songbirds', label: 'Songbirds', children: [{id: 'cardinals', label: 'Cardinals'}, {id: 'warblers', label: 'Warblers'}, {id: 'robins', label: 'Thrushes'}] }, { id: 'ground', label: 'Ground Birds', children: [{id: 'turkey', label: 'Wild Turkey'}, {id: 'grouse', label: 'Grouse'}] } ] }, { id: 'insects', label: 'Insects & Micro', children: [ { id: 'pollinators', label: 'Pollinators', children: [{id: 'bees', label: 'Wild Bees'}, {id: 'butterflies', label: 'Butterflies'}] }, { id: 'decomposers', label: 'Decomposers', children: [{id: 'beetles', label: 'Beetles'}, {id: 'ants', label: 'Ant Colonies'}, {id: 'termites', label: 'Termites'}] }, { id: 'pests', label: 'Pests', children: [{id: 'mosquitoes', label: 'Mosquitoes'}, {id: 'ticks', label: 'Ticks'}] } ] } ] }, { id: 'flora', label: 'Flora', icon: 'Leaf', color: '#84cc16', children: [ { id: 'trees', label: 'Trees', children: [ { id: 'deciduous', label: 'Deciduous', children: [{id: 'oak', label: 'Oak'}, {id: 'maple', label: 'Maple'}, {id: 'birch', label: 'Birch'}, {id: 'beech', label: 'Beech'}] }, { id: 'coniferous', label: 'Coniferous', children: [{id: 'pine', label: 'Pine'}, {id: 'spruce', label: 'Spruce'}, {id: 'fir', label: 'Fir'}, {id: 'redwood', label: 'Sequoia'}] } ] }, { id: 'understory', label: 'Understory', children: [ { id: 'shrubs', label: 'Shrubs', children: [{id: 'ferns', label: 'Ferns'}, {id: 'berries', label: 'Berry Bushes'}] }, { id: 'flowers', label: 'Wildflowers', children: [{id: 'orchids', label: 'Orchids'}, {id: 'trillium', label: 'Trillium'}] } ] }, { id: 'fungi', label: 'Fungi & Moss', children: [ { id: 'mushrooms', label: 'Mushrooms', children: [{id: 'edible', label: 'Chanterelles'}, {id: 'poison', label: 'Amanita'}] }, { id: 'lichen', label: 'Lichen', children: [{id: 'symbiosis', label: 'Algae+Fungus'}] }, { id: 'moss', label: 'Mosses', children: [{id: 'peat', label: 'Peat Moss'}, {id: 'sphagnum', label: 'Sphagnum'}] } ] } ] }, { id: 'climate', label: 'Climate Zones', icon: 'Globe', color: '#3b82f6', children: [ { id: 'tropical', label: 'Tropical', children: [ { id: 'rainforest', label: 'Rainforest', children: [{id: 'amazon', label: 'Amazonian'}, {id: 'congo', label: 'Congo'}] }, { id: 'monsoon', label: 'Seasonal Monsoon'} ] }, { id: 'temperate', label: 'Temperate', children: [ { id: 'deciduous_forest', label: 'Deciduous Forest' }, { id: 'mediterranean', label: 'Mediterranean / Chaparral' } ] }, { id: 'boreal', label: 'Boreal (Taiga)', children: [ { id: 'subarctic', label: 'Subarctic' }, { id: 'tundra_edge', label: 'Tundra Edge' } ] }, { id: 'weather', label: 'Weather Events', children: [ { id: 'rain', label: 'Precipitation' }, { id: 'fog', label: 'Mist/Fog' }, { id: 'snow', label: 'Snowpack' } ] } ] }, { id: 'hunting', label: 'Hunting & Survival', icon: 'Crosshair', color: '#d97706', children: [ { id: 'methods', label: 'Methods', children: [ { id: 'bow', label: 'Bow Hunting' }, { id: 'rifle', label: 'Rifle/Firearm' }, { id: 'trapping', label: 'Trapping' }, { id: 'tracking', label: 'Tracking Skills' } ] }, { id: 'game', label: 'Game Types', children: [ { id: 'big_game', label: 'Big Game' }, { id: 'small_game', label: 'Small Game' }, { id: 'waterfowl', label: 'Waterfowl' } ] }, { id: 'survival', label: 'Bushcraft', children: [ { id: 'shelter', label: 'Shelter Building' }, { id: 'fire', label: 'Fire Starting' }, { id: 'foraging', label: 'Foraging' }, { id: 'water', label: 'Water Purification' } ] }, { id: 'ethics', label: 'Ethics', children: [ { id: 'conservation', label: 'Population Control' }, { id: 'tags', label: 'Tags & Seasons' }, { id: 'waste', label: 'No Waste' } ] } ] }, { id: 'recreation', label: 'Recreation & Travel', icon: 'Tent', color: '#a855f7', children: [ { id: 'active', label: 'Active', children: [ { id: 'hiking', label: 'Hiking/Trekking' }, { id: 'climbing', label: 'Rock Climbing' }, { id: 'biking', label: 'Mountain Biking' }, { id: 'running', label: 'Trail Running' } ] }, { id: 'leisure', label: 'Leisure', children: [ { id: 'camping', label: 'Camping' }, { id: 'birding', label: 'Bird Watching' }, { id: 'photography', label: 'Photography' }, { id: 'shinrin', label: 'Forest Bathing' } ] }, { id: 'infrastructure', label: 'Infrastructure', children: [ { id: 'national_parks', label: 'National Parks' }, { id: 'trails', label: 'Trail Markers' }, { id: 'lodges', label: 'Lodges & Cabins' } ] } ] }, { id: 'colors', label: 'Colors & Aesthetics', icon: 'Palette', color: '#ec4899', children: [ { id: 'seasonal', label: 'Seasonal', children: [ { id: 'autumn', label: 'Autumn', children: [{id: 'rust', label: 'Russet'}, {id: 'gold', label: 'Gold'}, {id: 'orange', label: 'Burnt Orange'}] }, { id: 'spring', label: 'Spring', children: [{id: 'fresh_green', label: 'Fresh Green'}, {id: 'buds', label: 'Pink/White Buds'}] }, { id: 'winter', label: 'Winter', children: [{id: 'white', label: 'Snow White'}, {id: 'grey', label: 'Slate Grey'}, {id: 'evergreen', label: 'Deep Green'}] } ] }, { id: 'textures', label: 'Textures', children: [ { id: 'bark', label: 'Rough Bark' }, { id: 'moss_tex', label: 'Velvet Moss' }, { id: 'canopy', label: 'Dappled Light' } ] } ] }, { id: 'ecology', label: 'Ecology & Science', icon: 'Sprout', color: '#06b6d4', children: [ { id: 'cycles', label: 'Cycles', children: [ { id: 'carbon', label: 'Carbon Sink' }, { id: 'water_cycle', label: 'Water Retention' }, { id: 'nutrient', label: 'Nutrient Cycling' } ] }, { id: 'layers', label: 'Forest Layers', children: [ { id: 'floor', label: 'Forest Floor' }, { id: 'understory_layer', label: 'Understory' }, { id: 'canopy_layer', label: 'Canopy' }, { id: 'emergent', label: 'Emergent Layer' } ] }, { id: 'soil', label: 'Soil Health', children: [ { id: 'mycelium', label: 'Mycelium Network' }, { id: 'humus', label: 'Humus' } ] } ] } ] }; }; const fullData = generateForestData(); const countLeaves = (node, collapsedIds) => { if (collapsedIds.has(node.id) || !node.children || node.children.length === 0) { return 1; } return node.children.reduce((acc, child) => acc + countLeaves(child, collapsedIds), 0); }; const calculateLayout = (node, startAngle, endAngle, depth, collapsedIds, coords = {}) => { const radius = depth * 180; const midAngle = startAngle + (endAngle - startAngle) / 2; const rad = (midAngle - 90) * (Math.PI / 180); const x = Math.cos(rad) * radius; const y = Math.sin(rad) * radius; coords[node.id] = { x, y, angle: midAngle }; if (collapsedIds.has(node.id) || !node.children) return coords; const totalLeaves = countLeaves(node, collapsedIds); let currentStartAngle = startAngle; node.children.forEach(child => { const childLeaves = countLeaves(child, collapsedIds); const childWedge = (childLeaves / totalLeaves) * (endAngle - startAngle); calculateLayout(child, currentStartAngle, currentStartAngle + childWedge, depth + 1, collapsedIds, coords); currentStartAngle += childWedge; }); return coords; }; const Node = ({ data, x, y, color, isCollapsed, onToggle, isRoot }) => { const Icon = data.icon ? ({ TreeDeciduous, Tent, Palette, PawPrint, Crosshair, Globe, Leaf, Sprout }[data.icon] || Leaf) : null; return (
Explore the digital ecosystem. Drag to pan, scroll to zoom. Click nodes to expand branches.