| import React, { useState, useMemo, useEffect, useRef } from 'react'; |
| import { |
| BookOpen, Clock, User, Info, Link as LinkIcon, Search, X, Feather, |
| Library, ScrollText, Sparkles, LayoutGrid, Network, Move |
| } from 'lucide-react'; |
|
|
| |
| |
| const SCRIPTURES = [ |
| |
| { id: 'root', name: 'Hindu Scriptures', category: 'Root', timePeriod: 'Various', writer: 'Various Sages', description: 'The vast body of sacred texts in Hinduism, traditionally divided into Shruti (what is heard) and Smriti (what is remembered).', x: 0, y: 0, parentId: null, relatedTo: ['shruti', 'smriti'] }, |
| |
| |
| { id: 'shruti', name: 'Shruti (श्रुति)', category: 'Classification', timePeriod: 'Pre-1500 BCE', writer: 'Revealed to Rishis', description: '"That which was heard" - the most authoritative, ancient religious texts comprising the central canon of Hinduism.', x: -800, y: 150, parentId: 'root', relatedTo: ['rigveda', 'samaveda', 'yajurveda', 'atharvaveda'] }, |
| { id: 'smriti', name: 'Smriti (स्मृति)', category: 'Classification', timePeriod: 'Post-500 BCE', writer: 'Various Human Authors', description: '"That which is remembered" - a body of Hindu texts usually attributed to an author, traditionally written down and constantly revised.', x: 800, y: 150, parentId: 'root', relatedTo: ['dharmashastras', 'puranas', 'vedangas', 'darshana', 'upaveda', 'itihaas', 'agamas'] }, |
|
|
| |
| { id: 'rigveda', name: 'Rigveda', category: 'Veda', timePeriod: 'c. 1500 – 1000 BCE', writer: 'Various Rishis', description: 'The oldest sacred book of Hinduism, consisting of 1,028 hymns dedicated to various deities.', x: -1400, y: 350, parentId: 'shruti', relatedTo: ['karmakanda', 'gyanakanda'] }, |
| { id: 'samaveda', name: 'Samaveda', category: 'Veda', timePeriod: 'c. 1200 – 1000 BCE', writer: 'Various Rishis', description: 'The Veda of melodies and chants, mostly drawn from the Rigveda, set to musical notation.', x: -1000, y: 350, parentId: 'shruti', relatedTo: ['karmakanda', 'gyanakanda'] }, |
| { id: 'yajurveda', name: 'Yajurveda', category: 'Veda', timePeriod: 'c. 1200 – 1000 BCE', writer: 'Various Rishis', description: 'The Veda of prose mantras containing ritual offering formulas.', x: -600, y: 350, parentId: 'shruti', relatedTo: ['karmakanda', 'gyanakanda'] }, |
| { id: 'atharvaveda', name: 'Atharvaveda', category: 'Veda', timePeriod: 'c. 1000 – 900 BCE', writer: 'Atharvan and Angiras rishis', description: 'The "knowledge storehouse of the procedures for everyday life", dealing with spells and charms.', x: -200, y: 350, parentId: 'shruti', relatedTo: ['karmakanda', 'gyanakanda'] }, |
|
|
| |
| { id: 'karmakanda', name: 'Karma kanda (कर्मकाण्ड)', category: 'Kanda', timePeriod: 'Ancient', writer: 'Various', description: 'The section of the Vedas dealing with rituals, sacrifices, and duties. Includes Samhitas and Brahmanas.', x: -1200, y: 500, parentId: 'shruti', relatedTo: ['rigveda', 'yajurveda'] }, |
| { id: 'gyanakanda', name: 'Gyana kanda (ज्ञानकाण्ड)', category: 'Kanda', timePeriod: 'Ancient', writer: 'Various', description: 'The section of the Vedas dealing with knowledge and spirituality. Includes Aranyakas and Upanishads.', x: -400, y: 500, parentId: 'shruti', relatedTo: ['upanishads'] }, |
|
|
| |
| { id: 'aiteriya', name: 'Aitareya', category: 'Upanishad', timePeriod: 'c. 800 - 500 BCE', writer: 'Mahidasa Aitareya', description: 'Discusses three philosophical themes: the world, the soul (Atman), and the concept of ultimate reality (Brahman).', x: -600, y: 650, parentId: 'gyanakanda', relatedTo: ['rigveda'] }, |
| { id: 'chandogya', name: 'Chaandogya', category: 'Upanishad', timePeriod: 'c. 800 - 600 BCE', writer: 'Various Sages', description: 'One of the oldest and largest Upanishads, focusing on the chanting of Om and the realization of Brahman.', x: -600, y: 730, parentId: 'gyanakanda', relatedTo: ['samaveda'] }, |
| { id: 'kena', name: 'Kena', category: 'Upanishad', timePeriod: 'c. 1st millennium BCE', writer: 'Unknown', description: 'Investigates the nature of knowledge, inquiring "by whom" (Kena) the mind and senses are directed.', x: -600, y: 810, parentId: 'gyanakanda', relatedTo: ['samaveda'] }, |
| { id: 'katha', name: 'Kathaka (Katha)', category: 'Upanishad', timePeriod: 'c. 5th century BCE', writer: 'Unknown', description: 'Features the famous dialogue between the young boy Nachiketa and Yama (the deity of death).', x: -600, y: 890, parentId: 'gyanakanda', relatedTo: ['yajurveda'] }, |
| { id: 'taittiriya', name: 'Taittariya', category: 'Upanishad', timePeriod: 'c. 6th century BCE', writer: 'Taittiri Sages', description: 'Explores the five layers (Koshas) of human existence and the nature of bliss.', x: -600, y: 970, parentId: 'gyanakanda', relatedTo: ['yajurveda'] }, |
| { id: 'isha', name: 'Ishavasya', category: 'Upanishad', timePeriod: 'c. 1st millennium BCE', writer: 'Unknown', description: 'A short but profound text discussing the immanence of the Lord (Isha) in everything.', x: -600, y: 1050, parentId: 'gyanakanda', relatedTo: ['yajurveda'] }, |
| { id: 'brihadaaranyaka', name: 'Brihadaranyaka', category: 'Upanishad', timePeriod: 'c. 900 - 600 BCE', writer: 'Yajnavalkya', description: 'The "Great Forest" Upanishad. A massive text dealing with the Atman, karma, and rebirth.', x: -600, y: 1130, parentId: 'gyanakanda', relatedTo: ['yajurveda'] }, |
| { id: 'prashna', name: 'Prashna', category: 'Upanishad', timePeriod: 'c. 1st millennium BCE', writer: 'Pippalada', description: 'Structured around six questions (Prashna) asked by students regarding life, breath, and the ultimate reality.', x: -200, y: 650, parentId: 'gyanakanda', relatedTo: ['atharvaveda'] }, |
| { id: 'mundaka', name: 'Mundaka', category: 'Upanishad', timePeriod: 'c. 1st millennium BCE', writer: 'Angiras', description: 'Distinguishes between higher knowledge (of Brahman) and lower knowledge (rituals), famous for "Satyameva Jayate".', x: -200, y: 730, parentId: 'gyanakanda', relatedTo: ['atharvaveda'] }, |
| { id: 'mandukya', name: 'Maandukya', category: 'Upanishad', timePeriod: 'c. 1st millennium BCE', writer: 'Unknown', description: 'The shortest Upanishad, analyzing the four states of consciousness mapping to the syllable OM.', x: -200, y: 810, parentId: 'gyanakanda', relatedTo: ['atharvaveda'] }, |
| { id: 'kaushitaki', name: 'Kaushitaki', category: 'Upanishad', timePeriod: 'c. 800 - 500 BCE', writer: 'Unknown', description: 'Explores the nature of the self (Atman) and the ultimate reality (Brahman), emphasizing Prana (breath/life force).', x: -200, y: 890, parentId: 'gyanakanda', relatedTo: ['rigveda'] }, |
| { id: 'shvetashvatara', name: 'Shvetashvatara', category: 'Upanishad', timePeriod: 'c. 6th - 4th century BCE', writer: 'Shvetashvatara', description: 'Discusses Shiva as the supreme Lord, introducing elements of Yoga, Samkhya, and Bhakti within a Vedantic framework.', x: -200, y: 970, parentId: 'gyanakanda', relatedTo: ['yajurveda'] }, |
| { id: 'maitrayani', name: 'Maitrayani', category: 'Upanishad', timePeriod: 'c. 1st millennium BCE', writer: 'Maitri', description: 'Focuses on the concept of Atman and introduces the idea of the Trimurti (Brahma, Vishnu, Shiva) as manifestations of the Supreme.', x: -200, y: 1050, parentId: 'gyanakanda', relatedTo: ['yajurveda'] }, |
|
|
| |
| { id: 'dharmashastras', name: 'Dharmashastra', category: 'Category', timePeriod: 'Various', writer: 'Various', description: 'Treatises on Dharma (law, duty, and correct behavior).', x: 200, y: 350, parentId: 'smriti', relatedTo: ['manusmriti'] }, |
| { id: 'itihaas', name: 'Ithihaasa', category: 'Category', timePeriod: 'Various', writer: 'Various', description: '"History" - narrative epics containing profound philosophical teachings embedded in stories.', x: 500, y: 350, parentId: 'smriti', relatedTo: ['ramayana', 'mahabharat'] }, |
| { id: 'puranas', name: 'Purana', category: 'Category', timePeriod: 'Various', writer: 'Vyasa (traditionally)', description: 'Ancient lore containing narratives of the history of the universe, genealogies of kings, and myths of deities.', x: 900, y: 350, parentId: 'smriti', relatedTo: [] }, |
| { id: 'vedangas', name: 'Vedanga', category: 'Category', timePeriod: 'Ancient', writer: 'Various', description: 'Six auxiliary disciplines for understanding and preserving the Vedas.', x: 1300, y: 350, parentId: 'smriti', relatedTo: [] }, |
| { id: 'agamas', name: 'Agama', category: 'Category', timePeriod: 'Various', writer: 'Various', description: 'Theological treatises and practical manuals of divine worship (temple construction, rituals).', x: 1600, y: 350, parentId: 'smriti', relatedTo: [] }, |
| { id: 'darshana', name: 'Darshana', category: 'Category', timePeriod: 'Various', writer: 'Various', description: 'The six orthodox schools of Hindu philosophy.', x: 1900, y: 350, parentId: 'smriti', relatedTo: [] }, |
| { id: 'upaveda', name: 'Upavedas', category: 'Category', timePeriod: 'Various', writer: 'Various', description: 'Applied knowledge disciplines associated with the specific Vedas.', x: 2200, y: 350, parentId: 'smriti', relatedTo: [] }, |
|
|
| |
| |
| { id: 'manusmriti', name: 'Manu', category: 'Dharmashastra', timePeriod: 'c. 200 BCE – 300 CE', writer: 'Attributed to Manu', description: 'An ancient legal text outlining codes of conduct, laws, and social duties.', x: 200, y: 500, parentId: 'dharmashastras', relatedTo: [] }, |
| { id: 'yagyavalkyasmriti', name: 'Yajnavalkya', category: 'Dharmashastra', timePeriod: 'c. 3rd-5th century CE', writer: 'Yajnavalkya', description: 'One of the most systematically structured texts on Dharma, influential in Hindu law.', x: 200, y: 580, parentId: 'dharmashastras', relatedTo: [] }, |
| { id: 'apastamba', name: 'Apastamba etc.', category: 'Dharmashastra', timePeriod: 'c. 600 - 300 BCE', writer: 'Apastamba', description: 'One of the best-preserved Dharmasutras, offering detailed aphorisms on law, duty, and Vedic rituals.', x: 200, y: 660, parentId: 'dharmashastras', relatedTo: [] }, |
|
|
| |
| { id: 'ramayana', name: 'Ramayana', category: 'Itihasa', timePeriod: 'c. 500 BCE – 100 BCE', writer: 'Valmiki', description: 'The epic narrating the life of Rama, exploring human values and the concept of dharma.', x: 500, y: 500, parentId: 'itihaas', relatedTo: ['mahabharat'] }, |
| { id: 'mahabharat', name: 'Mahabharata', category: 'Itihasa', timePeriod: 'c. 400 BCE – 400 CE', writer: 'Vyasa', description: 'The massive epic narrating the Kurukshetra War. It contains profound philosophical teachings.', x: 500, y: 580, parentId: 'itihaas', relatedTo: ['ramayana', 'gita'] }, |
| { id: 'gita', name: 'Gita', category: 'Itihasa', timePeriod: 'c. 400 BCE – 200 CE', writer: 'Vyasa', description: 'A 700-verse philosophical dialogue embedded in the Mahabharata between Prince Arjuna and Krishna regarding duty (Dharma) and righteous action.', x: 500, y: 660, parentId: 'mahabharat', relatedTo: ['upanishads'] }, |
|
|
| |
| |
| { id: 'brahmapurana', name: 'Brahma', category: 'Purana', timePeriod: 'c. 1st millennium CE', writer: 'Vyasa', description: 'One of the Mahapuranas, dealing with cosmology and geography, specifically regions around Godavari river.', x: 800, y: 500, parentId: 'puranas', relatedTo: [] }, |
| { id: 'padmapurana', name: 'Padma', category: 'Purana', timePeriod: 'c. 4th-15th century CE', writer: 'Vyasa', description: 'A massive text detailing cosmology, geography, and legends, often with a strong Vaishnava focus.', x: 800, y: 580, parentId: 'puranas', relatedTo: [] }, |
| { id: 'vishnupurana', name: 'Vishnu', category: 'Purana', timePeriod: 'c. 400 BCE - 900 CE', writer: 'Parashara', description: 'An important Pancharatra text detailing myths, cosmology, and genealogies centered on Vishnu.', x: 800, y: 660, parentId: 'puranas', relatedTo: [] }, |
| { id: 'vayupurana', name: 'Vayu', category: 'Purana', timePeriod: 'c. 300-500 CE', writer: 'Vyasa', description: 'One of the oldest Puranas, dedicated to Vayu (the wind god), containing extensive kingly genealogies.', x: 800, y: 740, parentId: 'puranas', relatedTo: [] }, |
| { id: 'bhagavatam', name: 'Bhagavata', category: 'Purana', timePeriod: 'c. 800 – 1000 CE', writer: 'Vyasa', description: 'Revered Purana promoting bhakti (devotion) to Krishna.', x: 800, y: 820, parentId: 'puranas', relatedTo: ['mahabharat'] }, |
| { id: 'naradapurana', name: 'Narada', category: 'Purana', timePeriod: 'c. 10th-12th century CE', writer: 'Vyasa', description: 'A text presented as teachings from the sage Narada, emphasizing devotion (Bhakti) to Vishnu.', x: 800, y: 900, parentId: 'puranas', relatedTo: [] }, |
| { id: 'markandeya', name: 'Markandeya', category: 'Purana', timePeriod: 'c. 3rd-4th century CE', writer: 'Vyasa', description: 'Features conversations between sages and includes the famous Devi Mahatmya (glory of the Goddess).', x: 800, y: 980, parentId: 'puranas', relatedTo: [] }, |
| { id: 'agnipurana', name: 'Agni', category: 'Purana', timePeriod: 'c. 8th-11th century CE', writer: 'Vyasa', description: 'An encyclopedic Purana covering diverse topics like ritual worship, cosmology, astrology, and martial arts.', x: 800, y: 1060, parentId: 'puranas', relatedTo: [] }, |
| { id: 'bhavishya', name: 'Bhavishya', category: 'Purana', timePeriod: 'c. 11th century CE', writer: 'Vyasa', description: 'A Purana notable for containing prophecies regarding future events and dynasties.', x: 800, y: 1140, parentId: 'puranas', relatedTo: [] }, |
| |
| { id: 'brahmavaivarta', name: 'Brahmavaivarta', category: 'Purana', timePeriod: 'c. 8th-16th century CE', writer: 'Vyasa', description: 'Focuses heavily on the life and deeds of Krishna and his consort Radha.', x: 1000, y: 500, parentId: 'puranas', relatedTo: [] }, |
| { id: 'lingapurana', name: 'Linga', category: 'Purana', timePeriod: 'c. 5th-10th century CE', writer: 'Vyasa', description: 'Dedicated to Shiva, emphasizing his worship through the Lingam and detailing Shaiva philosophy.', x: 1000, y: 580, parentId: 'puranas', relatedTo: [] }, |
| { id: 'varaha', name: 'Varaha', category: 'Purana', timePeriod: 'c. 10th-12th century CE', writer: 'Vyasa', description: 'Narrated by Vishnu in his boar avatar (Varaha), focusing on devotion and pilgrimage sites.', x: 1000, y: 660, parentId: 'puranas', relatedTo: [] }, |
| { id: 'skanda', name: 'Skanda', category: 'Purana', timePeriod: 'c. 8th century CE onwards', writer: 'Vyasa', description: 'The largest Mahapurana, containing numerous geographical and pilgrimage guides (Tirtha Mahatmyas).', x: 1000, y: 740, parentId: 'puranas', relatedTo: [] }, |
| { id: 'vamana', name: 'Vamana', category: 'Purana', timePeriod: 'c. 9th-11th century CE', writer: 'Vyasa', description: 'Centered around the dwarf avatar (Vamana) of Vishnu, but contains substantial Shaiva material.', x: 1000, y: 820, parentId: 'puranas', relatedTo: [] }, |
| { id: 'kurma', name: 'Kurma', category: 'Purana', timePeriod: 'c. 8th century CE', writer: 'Vyasa', description: 'Narrated by Vishnu in his tortoise avatar (Kurma), covering mythology and the Kurma Gita.', x: 1000, y: 900, parentId: 'puranas', relatedTo: [] }, |
| { id: 'matsyapurana', name: 'Matsya', category: 'Purana', timePeriod: 'c. 3rd century CE', writer: 'Vyasa', description: 'Named after the fish avatar of Vishnu, containing diverse encyclopedic topics.', x: 1000, y: 980, parentId: 'puranas', relatedTo: [] }, |
| { id: 'garuda', name: 'Garuda', category: 'Purana', timePeriod: 'c. 1st millennium CE', writer: 'Vyasa', description: 'A Vaishnava text famous for its detailed descriptions of death, the afterlife, and funeral rites.', x: 1000, y: 1060, parentId: 'puranas', relatedTo: [] }, |
| { id: 'brahmanda', name: 'Brahmanda', category: 'Purana', timePeriod: 'c. 4th-6th century CE', writer: 'Vyasa', description: 'Details the \'cosmic egg\' (Brahmanda) cosmology, genealogies, and the famous Lalita Sahasranama.', x: 1000, y: 1140, parentId: 'puranas', relatedTo: [] }, |
| { id: 'shivapurana', name: 'Shiva', category: 'Purana', timePeriod: 'c. 10th-11th century CE', writer: 'Romaharshana/Vyasa', description: 'A major text centered on the Hindu god Shiva and his consort Parvati.', x: 900, y: 1220, parentId: 'puranas', relatedTo: [] }, |
|
|
| |
| { id: 'shiksha', name: 'Shiksha (phonetics)', category: 'Vedanga', timePeriod: 'Ancient', writer: 'Various', description: 'Phonetics, phonology, and pronunciation of Vedic mantras.', x: 1300, y: 500, parentId: 'vedangas', relatedTo: [] }, |
| { id: 'vyakarana', name: 'Vyakarana (grammar)', category: 'Vedanga', timePeriod: 'Ancient', writer: 'Panini (notable)', description: 'Grammar and linguistic analysis.', x: 1300, y: 580, parentId: 'vedangas', relatedTo: [] }, |
| { id: 'kalpa', name: 'Kalpasutra (Rites)', category: 'Vedanga', timePeriod: 'Ancient', writer: 'Various', description: 'Ritual instructions, rules, and geometry.', x: 1300, y: 660, parentId: 'vedangas', relatedTo: [] }, |
| { id: 'jyotisha', name: 'Jyotisha (Astronomy)', category: 'Vedanga', timePeriod: 'Ancient', writer: 'Lagadha (notable)', description: 'Auspicious timekeeping and astronomy for rituals.', x: 1300, y: 740, parentId: 'vedangas', relatedTo: [] }, |
| { id: 'nirukta', name: 'Nirukta (Etymology)', category: 'Vedanga', timePeriod: 'Ancient', writer: 'Yaska (notable)', description: 'Etymology and explanation of complex Vedic words.', x: 1300, y: 820, parentId: 'vedangas', relatedTo: [] }, |
| { id: 'chhanda', name: 'Chhanda (metre)', category: 'Vedanga', timePeriod: 'Ancient', writer: 'Pingala (notable)', description: 'Study of poetic meters in Vedic texts.', x: 1300, y: 900, parentId: 'vedangas', relatedTo: [] }, |
|
|
| |
| { id: 'pancharatra', name: 'Pancharatra', category: 'Agama', timePeriod: 'Various', writer: 'Various', description: 'Agamas centered on the worship of Lord Vishnu/Narayana.', x: 1600, y: 500, parentId: 'agamas', relatedTo: [] }, |
| { id: 'shaiva', name: 'Shaiva', category: 'Agama', timePeriod: 'Various', writer: 'Various', description: 'Agamas detailing the rituals and philosophy of Shaivism.', x: 1600, y: 580, parentId: 'agamas', relatedTo: [] }, |
| { id: 'shakta', name: 'Shaakta', category: 'Agama', timePeriod: 'Various', writer: 'Various', description: 'Tantric texts focusing on the worship of the Goddess (Devi / Shakti).', x: 1600, y: 660, parentId: 'agamas', relatedTo: [] }, |
|
|
| |
| { id: 'nyaya', name: 'Nyaaya', category: 'Darshana', timePeriod: 'Ancient', writer: 'Gautama', description: 'School focused on logic and epistemology.', x: 1900, y: 500, parentId: 'darshana', relatedTo: ['vaisheshika'] }, |
| { id: 'vaisheshika', name: 'Vaisheshika', category: 'Darshana', timePeriod: 'Ancient', writer: 'Kanada', description: 'School of atomism, postulating that all objects in the physical universe are reducible to atoms.', x: 1900, y: 580, parentId: 'darshana', relatedTo: ['nyaya'] }, |
| { id: 'samkhya', name: 'Sankhya', category: 'Darshana', timePeriod: 'Ancient', writer: 'Kapila', description: 'Strongly dualistic school identifying reality as consciousness (Purusha) and matter (Prakriti).', x: 1900, y: 660, parentId: 'darshana', relatedTo: ['yoga'] }, |
| { id: 'yoga', name: 'Yoga', category: 'Darshana', timePeriod: 'Ancient', writer: 'Patanjali', description: 'School focusing on meditation, contemplation and liberation (closely linked to Samkhya).', x: 1900, y: 740, parentId: 'darshana', relatedTo: ['samkhya'] }, |
| { id: 'purva_mimamsa', name: 'Purva Mimamsa', category: 'Darshana', timePeriod: 'Ancient', writer: 'Sage Jaimini', description: 'Also known as "Karma Mimamsa". Focuses on the Karma-kanda (ritualistic portion of the Vedas). It emphasizes the correct performance of Vedic rituals and achieving salvation through Dharma. Key Text: Mimamsa Sutra.', x: 1900, y: 820, parentId: 'darshana', relatedTo: ['uttara_mimamsa', 'karmakanda'] }, |
| { id: 'uttara_mimamsa', name: 'Uttara Mimamsa (Vedanta)', category: 'Darshana', timePeriod: 'Ancient', writer: 'Sage Badarayana (Vyasa)', description: 'Also known as "Jnana Mimamsa" or Vedanta. Focuses on the Jnana-kanda (knowledge portion of the Vedas). Explores the nature of Brahman (Universal Soul), Atman, and Moksha. Key Text: Brahma Sutra.', x: 1900, y: 900, parentId: 'darshana', relatedTo: ['purva_mimamsa', 'gyanakanda', 'upanishads'] }, |
|
|
| |
| { id: 'arthashastra', name: 'Arthashastra', category: 'Upaveda', timePeriod: 'Ancient', writer: 'Chanakya (Kautilya)', description: 'The science of statecraft, economic policy, and military strategy.', x: 2200, y: 500, parentId: 'upaveda', relatedTo: [] }, |
| { id: 'ayurveda', name: 'Ayurveda', category: 'Upaveda', timePeriod: 'Ancient', writer: 'Various', description: 'The ancient Indian system of medicine and life science (associated with Rigveda/Atharvaveda).', x: 2200, y: 580, parentId: 'upaveda', relatedTo: ['rigveda', 'atharvaveda'] }, |
| { id: 'gandharvaveda', name: 'Gandharvaveda', category: 'Upaveda', timePeriod: 'Ancient', writer: 'Various', description: 'The science of music, dance, and arts (associated with Samaveda).', x: 2200, y: 660, parentId: 'upaveda', relatedTo: ['samaveda'] }, |
| { id: 'dhanurveda', name: 'Dhanurveda', category: 'Upaveda', timePeriod: 'Ancient', writer: 'Various', description: 'The science of archery and warfare (associated with Yajurveda).', x: 2200, y: 740, parentId: 'upaveda', relatedTo: ['yajurveda'] }, |
| { id: 'shilpasthapatya', name: 'Shilpa-Sthapatya', category: 'Upaveda', timePeriod: 'Ancient', writer: 'Various', description: 'The science of architecture, engineering, and fine arts.', x: 2200, y: 820, parentId: 'upaveda', relatedTo: [] } |
| ]; |
|
|
| |
| const CATEGORY_COLORS = { |
| 'Root': { bg: 'bg-indigo-600', border: 'border-indigo-800', text: 'text-indigo-50', light: 'bg-indigo-600', icon: 'text-indigo-200', badge: 'bg-indigo-800 text-indigo-100', node: 'bg-indigo-600 text-white border-indigo-800 shadow-indigo-500/50' }, |
| 'Classification': { bg: 'bg-violet-500', border: 'border-violet-700', text: 'text-violet-50', light: 'bg-violet-500', icon: 'text-violet-200', badge: 'bg-violet-700 text-violet-100', node: 'bg-violet-500 text-white border-violet-700 shadow-violet-500/40' }, |
| 'Category': { bg: 'bg-blue-500', border: 'border-blue-700', text: 'text-blue-50', light: 'bg-blue-500', icon: 'text-blue-200', badge: 'bg-blue-700 text-blue-100', node: 'bg-blue-500 text-white border-blue-700 shadow-blue-500/30' }, |
| 'Veda': { bg: 'bg-amber-100', border: 'border-amber-400', text: 'text-amber-900', light: 'bg-amber-50', icon: 'text-amber-600', badge: 'bg-amber-200 text-amber-800', node: 'bg-amber-100 text-amber-900 border-amber-400 shadow-amber-900/10' }, |
| 'Kanda': { bg: 'bg-orange-100', border: 'border-orange-400', text: 'text-orange-900', light: 'bg-orange-50', icon: 'text-orange-600', badge: 'bg-orange-200 text-orange-800', node: 'bg-orange-100 text-orange-900 border-orange-400 shadow-orange-900/10' }, |
| 'Upanishad': { bg: 'bg-cyan-100', border: 'border-cyan-400', text: 'text-cyan-900', light: 'bg-cyan-50', icon: 'text-cyan-600', badge: 'bg-cyan-200 text-cyan-800', node: 'bg-cyan-100 text-cyan-900 border-cyan-400 shadow-cyan-900/10' }, |
| 'Itihasa': { bg: 'bg-rose-100', border: 'border-rose-400', text: 'text-rose-900', light: 'bg-rose-50', icon: 'text-rose-600', badge: 'bg-rose-200 text-rose-800', node: 'bg-rose-100 text-rose-900 border-rose-400 shadow-rose-900/10' }, |
| 'Purana': { bg: 'bg-purple-100', border: 'border-purple-400', text: 'text-purple-900', light: 'bg-purple-50', icon: 'text-purple-600', badge: 'bg-purple-200 text-purple-800', node: 'bg-purple-100 text-purple-900 border-purple-400 shadow-purple-900/10' }, |
| 'Darshana': { bg: 'bg-emerald-100', border: 'border-emerald-400', text: 'text-emerald-900', light: 'bg-emerald-50', icon: 'text-emerald-600', badge: 'bg-emerald-200 text-emerald-800', node: 'bg-emerald-100 text-emerald-900 border-emerald-400 shadow-emerald-900/10' }, |
| 'Dharmashastra': { bg: 'bg-slate-100', border: 'border-slate-400', text: 'text-slate-900', light: 'bg-slate-50', icon: 'text-slate-600', badge: 'bg-slate-200 text-slate-800', node: 'bg-slate-100 text-slate-900 border-slate-400 shadow-slate-900/10' }, |
| 'Vedanga': { bg: 'bg-lime-100', border: 'border-lime-400', text: 'text-lime-900', light: 'bg-lime-50', icon: 'text-lime-600', badge: 'bg-lime-200 text-lime-800', node: 'bg-lime-100 text-lime-900 border-lime-400 shadow-lime-900/10' }, |
| 'Agama': { bg: 'bg-fuchsia-100', border: 'border-fuchsia-400', text: 'text-fuchsia-900', light: 'bg-fuchsia-50', icon: 'text-fuchsia-600', badge: 'bg-fuchsia-200 text-fuchsia-800', node: 'bg-fuchsia-100 text-fuchsia-900 border-fuchsia-400 shadow-fuchsia-900/10' }, |
| 'Upaveda': { bg: 'bg-sky-100', border: 'border-sky-400', text: 'text-sky-900', light: 'bg-sky-50', icon: 'text-sky-600', badge: 'bg-sky-200 text-sky-800', node: 'bg-sky-100 text-sky-900 border-sky-400 shadow-sky-900/10' }, |
| }; |
|
|
| |
| const WIRE_COLORS = { |
| 'Classification': '#8b5cf6', 'Veda': '#f59e0b', 'Kanda': '#f97316', |
| 'Upanishad': '#06b6d4', 'Category': '#3b82f6', 'Dharmashastra': '#64748b', |
| 'Itihasa': '#f43f5e', 'Purana': '#a855f7', 'Vedanga': '#84cc16', |
| 'Agama': '#d946ef', 'Darshana': '#10b981', 'Upaveda': '#0ea5e9', |
| }; |
|
|
| const DEFAULT_COLOR = { bg: 'bg-gray-100', border: 'border-gray-400', text: 'text-gray-900', light: 'bg-gray-50', icon: 'text-gray-600', badge: 'bg-gray-200 text-gray-800', node: 'bg-gray-100 text-gray-900 border-gray-400' }; |
|
|
| export default function App() { |
| const [viewMode, setViewMode] = useState('grid'); |
| const [searchQuery, setSearchQuery] = useState(''); |
| const [selectedCategory, setSelectedCategory] = useState('All'); |
| const [activeScriptureId, setActiveScriptureId] = useState(null); |
|
|
| |
| const displayableScriptures = SCRIPTURES.filter(s => !['Root', 'Classification', 'Category'].includes(s.category)); |
|
|
| |
| const filterCategories = ['All', ...Array.from(new Set(displayableScriptures.map(s => s.category)))]; |
|
|
| |
| const filteredScriptures = useMemo(() => { |
| return displayableScriptures.filter(scripture => { |
| const matchesSearch = scripture.name.toLowerCase().includes(searchQuery.toLowerCase()) || |
| scripture.writer.toLowerCase().includes(searchQuery.toLowerCase()); |
| const matchesCategory = selectedCategory === 'All' || scripture.category === selectedCategory; |
| return matchesSearch && matchesCategory; |
| }); |
| }, [searchQuery, selectedCategory]); |
|
|
| const activeScripture = SCRIPTURES.find(s => s.id === activeScriptureId); |
| const getScriptureById = (id) => SCRIPTURES.find(s => s.id === id); |
|
|
| |
| useEffect(() => { |
| const handleKeyDown = (e) => { |
| |
| if (e.target.tagName.toLowerCase() === 'input') return; |
| |
| if (e.key === 'z' || e.key === 'Z') { |
| setViewMode(prev => prev === 'grid' ? 'mindmap' : 'grid'); |
| } |
| }; |
| window.addEventListener('keydown', handleKeyDown); |
| return () => window.removeEventListener('keydown', handleKeyDown); |
| }, []); |
|
|
| return ( |
| <div className={`min-h-screen bg-stone-50 font-sans text-stone-900 selection:bg-orange-200 flex flex-col ${viewMode === 'mindmap' ? 'overflow-hidden' : ''}`}> |
| |
| {} |
| <header className="bg-gradient-to-r from-orange-600 via-red-500 to-amber-500 text-white shadow-md z-20 flex-shrink-0 relative"> |
| <div className="max-w-[1400px] mx-auto px-4 py-4 md:py-6"> |
| <div className="flex flex-col md:flex-row md:items-center justify-between gap-4"> |
| <div className="flex items-center gap-3"> |
| <div className="p-2 bg-white/20 rounded-full backdrop-blur-sm"> |
| <Library size={28} className="text-white" /> |
| </div> |
| <div> |
| <h1 className="text-xl md:text-2xl font-bold tracking-tight leading-tight">Ancient Indian Scriptures</h1> |
| <p className="text-white/80 text-xs md:text-sm font-medium">Explore the interconnected wisdom of millennia</p> |
| </div> |
| </div> |
| |
| <div className="flex items-center gap-3 w-full md:w-auto"> |
| {viewMode === 'grid' && ( |
| <div className="relative flex-grow md:w-64 lg:w-72"> |
| <Search className="absolute left-3 top-1/2 -translate-y-1/2 text-white/60" size={16} /> |
| <input |
| type="text" |
| placeholder="Search text or author..." |
| value={searchQuery} |
| onChange={(e) => setSearchQuery(e.target.value)} |
| className="w-full pl-9 pr-4 py-2 text-sm rounded-full bg-white/10 border border-white/20 text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/50 backdrop-blur-sm transition-all" |
| /> |
| </div> |
| )} |
| |
| <button |
| onClick={() => setViewMode(v => v === 'grid' ? 'mindmap' : 'grid')} |
| className="flex items-center gap-2 px-4 py-2 bg-white/10 hover:bg-white/20 border border-white/30 rounded-full transition-all text-sm font-semibold whitespace-nowrap" |
| title="Shortcut: Press 'Z'" |
| > |
| {viewMode === 'grid' ? <Network size={16} /> : <LayoutGrid size={16} />} |
| <span className="hidden sm:inline">{viewMode === 'grid' ? 'Flowchart View' : 'Grid View'}</span> |
| <kbd className="hidden sm:inline ml-1 bg-white/20 px-1.5 py-0.5 rounded text-[10px]">Z</kbd> |
| </button> |
| </div> |
| </div> |
| </div> |
| </header> |
|
|
| {} |
| <div className="flex-grow relative flex flex-col"> |
| {viewMode === 'grid' ? ( |
| <main className="max-w-[1400px] mx-auto px-4 py-8 w-full"> |
| {} |
| <div className="flex flex-wrap gap-2 mb-8 justify-center"> |
| {filterCategories.map(cat => { |
| const isSelected = selectedCategory === cat; |
| const colors = cat === 'All' ? { badge: 'bg-stone-200 text-stone-800 border-stone-300' } : (CATEGORY_COLORS[cat] || DEFAULT_COLOR); |
| |
| return ( |
| <button |
| key={cat} |
| onClick={() => setSelectedCategory(cat)} |
| className={`px-3 py-1.5 rounded-full text-xs sm:text-sm font-semibold transition-all border ${ |
| isSelected |
| ? `ring-2 ring-offset-2 ring-orange-400 shadow-sm ${colors.badge}` |
| : 'bg-white border-stone-200 text-stone-600 hover:bg-stone-100' |
| }`} |
| > |
| {cat} |
| </button> |
| ) |
| })} |
| </div> |
|
|
| {} |
| {filteredScriptures.length > 0 ? ( |
| <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"> |
| {filteredScriptures.map((scripture) => { |
| const theme = CATEGORY_COLORS[scripture.category] || DEFAULT_COLOR; |
| |
| return ( |
| <div |
| key={scripture.id} |
| onClick={() => setActiveScriptureId(scripture.id)} |
| className={`relative group cursor-pointer overflow-hidden rounded-2xl border-2 ${theme.border} ${theme.light} hover:shadow-xl hover:-translate-y-1 transition-all duration-300 flex flex-col h-full`} |
| > |
| <div className={`p-5 flex-grow flex flex-col`}> |
| <div className="flex justify-between items-start mb-3"> |
| <span className={`text-[10px] font-bold px-2 py-0.5 rounded-full uppercase tracking-wider ${theme.badge}`}> |
| {scripture.category} |
| </span> |
| <BookOpen size={16} className={`${theme.icon} opacity-50 group-hover:opacity-100 transition-opacity`} /> |
| </div> |
| |
| <h2 className={`text-xl font-extrabold mb-2 ${theme.text}`}> |
| {scripture.name} |
| </h2> |
| |
| <div className="space-y-1.5 mb-3 flex-grow"> |
| <div className="flex items-center gap-2 text-xs text-stone-600"> |
| <Clock size={12} className={theme.icon} /> |
| <span>{scripture.timePeriod}</span> |
| </div> |
| <div className="flex items-center gap-2 text-xs text-stone-600"> |
| <Feather size={12} className={theme.icon} /> |
| <span className="truncate">{scripture.writer}</span> |
| </div> |
| </div> |
| |
| <p className="text-xs sm:text-sm text-stone-700 line-clamp-3 leading-relaxed mb-4"> |
| {scripture.description} |
| </p> |
|
|
| <div className="mt-auto pt-3 border-t border-black/5 flex items-center justify-between"> |
| <div className="flex items-center gap-1 text-[10px] sm:text-xs font-semibold text-stone-500"> |
| <LinkIcon size={10} /> |
| <span>{scripture.relatedTo ? scripture.relatedTo.length : 0} Links</span> |
| </div> |
| <span className={`text-xs font-bold flex items-center gap-1 ${theme.icon} group-hover:translate-x-1 transition-transform`}> |
| View <Sparkles size={12} /> |
| </span> |
| </div> |
| </div> |
| </div> |
| ); |
| })} |
| </div> |
| ) : ( |
| <div className="text-center py-20"> |
| <ScrollText size={48} className="mx-auto text-stone-300 mb-4" /> |
| <h3 className="text-xl font-bold text-stone-500">No scriptures found matching your search.</h3> |
| <button |
| onClick={() => {setSearchQuery(''); setSelectedCategory('All');}} |
| className="mt-4 px-6 py-2 bg-orange-100 text-orange-700 rounded-full font-medium hover:bg-orange-200 transition-colors" |
| > |
| Clear Filters |
| </button> |
| </div> |
| )} |
| </main> |
| ) : ( |
| <MindMapView onNodeClick={setActiveScriptureId} /> |
| )} |
| </div> |
|
|
| {} |
| {activeScripture && ( |
| <div className="fixed inset-0 z-50 flex items-center justify-center p-4"> |
| <div |
| className="absolute inset-0 bg-stone-900/60 backdrop-blur-sm transition-opacity" |
| onClick={() => setActiveScriptureId(null)} |
| ></div> |
| |
| <div className="relative w-full max-w-2xl bg-white rounded-3xl shadow-2xl overflow-hidden flex flex-col max-h-[90vh] animate-in fade-in zoom-in-95 duration-200"> |
| {(() => { |
| const theme = CATEGORY_COLORS[activeScripture.category] || DEFAULT_COLOR; |
| const isStructural = ['Root', 'Classification', 'Category'].includes(activeScripture.category); |
| return ( |
| <> |
| <div className={`p-6 sm:p-8 ${theme.bg} border-b ${theme.border} relative`}> |
| <button |
| onClick={() => setActiveScriptureId(null)} |
| className="absolute top-4 right-4 p-2 bg-white/50 hover:bg-white rounded-full transition-colors z-10" |
| > |
| <X size={20} className={theme.text} /> |
| </button> |
| |
| <span className={`inline-block text-[10px] sm:text-xs font-bold px-3 py-1 rounded-full uppercase tracking-wider mb-3 bg-white/60 ${theme.text}`}> |
| {activeScripture.category} |
| </span> |
| |
| <h2 className={`text-2xl sm:text-4xl font-extrabold mb-4 ${theme.text}`}> |
| {activeScripture.name} |
| </h2> |
| |
| {!isStructural && ( |
| <div className="grid grid-cols-1 sm:grid-cols-2 gap-3"> |
| <div className="flex items-center gap-3 bg-white/40 px-4 py-2 rounded-xl backdrop-blur-sm"> |
| <Clock size={16} className={theme.icon} /> |
| <div> |
| <p className="text-[10px] text-black/50 font-bold uppercase">Time Period</p> |
| <p className={`text-sm font-semibold ${theme.text}`}>{activeScripture.timePeriod}</p> |
| </div> |
| </div> |
| <div className="flex items-center gap-3 bg-white/40 px-4 py-2 rounded-xl backdrop-blur-sm"> |
| <User size={16} className={theme.icon} /> |
| <div> |
| <p className="text-[10px] text-black/50 font-bold uppercase">Authorship</p> |
| <p className={`text-sm font-semibold ${theme.text}`}>{activeScripture.writer}</p> |
| </div> |
| </div> |
| </div> |
| )} |
| </div> |
|
|
| <div className="p-6 sm:p-8 overflow-y-auto"> |
| <div className="mb-6"> |
| <h3 className="text-base sm:text-lg font-bold text-stone-800 flex items-center gap-2 mb-2"> |
| <Info size={18} className="text-orange-500" /> |
| Overview |
| </h3> |
| <p className="text-sm sm:text-base text-stone-600 leading-relaxed"> |
| {activeScripture.description} |
| </p> |
| </div> |
|
|
| {} |
| <div className="mb-6"> |
| {activeScripture.parentId && ( |
| <div className="mb-4"> |
| <h4 className="text-xs font-bold text-stone-400 uppercase mb-2">Belongs To</h4> |
| <RelatedButton id={activeScripture.parentId} onClick={setActiveScriptureId} /> |
| </div> |
| )} |
| |
| {SCRIPTURES.filter(s => s.parentId === activeScripture.id).length > 0 && ( |
| <div> |
| <h4 className="text-xs font-bold text-stone-400 uppercase mb-2">Contains</h4> |
| <div className="flex flex-wrap gap-2"> |
| {SCRIPTURES.filter(s => s.parentId === activeScripture.id).map(child => ( |
| <RelatedButton key={child.id} id={child.id} onClick={setActiveScriptureId} /> |
| ))} |
| </div> |
| </div> |
| )} |
| </div> |
|
|
| {} |
| {activeScripture.relatedTo && activeScripture.relatedTo.length > 0 && ( |
| <div className="border-t border-stone-100 pt-6"> |
| <h3 className="text-base sm:text-lg font-bold text-stone-800 flex items-center gap-2 mb-4"> |
| <LinkIcon size={18} className="text-orange-500" /> |
| Thematically Related |
| </h3> |
| <div className="flex flex-wrap gap-2"> |
| {activeScripture.relatedTo.map(relatedId => ( |
| <RelatedButton key={relatedId} id={relatedId} onClick={setActiveScriptureId} /> |
| ))} |
| </div> |
| </div> |
| )} |
| </div> |
| </> |
| ); |
| })()} |
| </div> |
| </div> |
| )} |
| </div> |
| ); |
| } |
|
|
| |
| function RelatedButton({ id, onClick }) { |
| const item = SCRIPTURES.find(s => s.id === id); |
| if (!item) return null; |
| const theme = CATEGORY_COLORS[item.category] || DEFAULT_COLOR; |
| |
| return ( |
| <button |
| onClick={() => onClick(item.id)} |
| className={`flex items-center gap-2 px-3 py-1.5 rounded-lg border ${theme.border} ${theme.light} hover:shadow-md hover:-translate-y-0.5 transition-all group text-left`} |
| > |
| <BookOpen size={12} className={theme.icon} /> |
| <div> |
| <p className={`font-bold text-xs ${theme.text} group-hover:underline decoration-2 underline-offset-2`}> |
| {item.name} |
| </p> |
| </div> |
| </button> |
| ); |
| } |
|
|
| |
| function MindMapView({ onNodeClick }) { |
| const containerRef = useRef(null); |
| const [pan, setPan] = useState({ x: 0, y: 0 }); |
| const [zoom, setZoom] = useState(0.5); |
| const [isDragging, setIsDragging] = useState(false); |
| const [startPan, setStartPan] = useState({ x: 0, y: 0 }); |
|
|
| |
| useEffect(() => { |
| if (containerRef.current) { |
| const rect = containerRef.current.getBoundingClientRect(); |
| setPan({ x: rect.width / 2, y: rect.height / 4 }); |
| } |
| }, []); |
|
|
| const handlePointerDown = (e) => { |
| |
| if (e.target.closest('.mindmap-node')) return; |
| setIsDragging(true); |
| setStartPan({ x: e.clientX - pan.x, y: e.clientY - pan.y }); |
| e.target.setPointerCapture(e.pointerId); |
| }; |
|
|
| const handlePointerMove = (e) => { |
| if (!isDragging) return; |
| setPan({ |
| x: e.clientX - startPan.x, |
| y: e.clientY - startPan.y, |
| }); |
| }; |
|
|
| const handlePointerUp = (e) => { |
| setIsDragging(false); |
| e.target.releasePointerCapture(e.pointerId); |
| }; |
|
|
| const handleWheel = (e) => { |
| |
| const zoomFactor = -e.deltaY * 0.001; |
| setZoom(z => Math.min(Math.max(0.1, z + zoomFactor), 2.5)); |
| }; |
|
|
| return ( |
| <div |
| ref={containerRef} |
| className="absolute inset-0 bg-[#f4f0ec] overflow-hidden cursor-grab active:cursor-grabbing touch-none" |
| style={{ backgroundImage: 'radial-gradient(#cbd5e1 1px, transparent 1px)', backgroundSize: '40px 40px', backgroundPosition: `${pan.x}px ${pan.y}px` }} |
| onPointerDown={handlePointerDown} |
| onPointerMove={handlePointerMove} |
| onPointerUp={handlePointerUp} |
| onPointerCancel={handlePointerUp} |
| onWheel={handleWheel} |
| > |
| <div className="absolute top-4 left-4 z-10 flex flex-col gap-2 bg-white/80 p-3 rounded-xl shadow-sm backdrop-blur-sm border border-stone-200"> |
| <div className="flex items-center gap-2 text-xs font-semibold text-stone-600"> |
| <Move size={14} /> Drag canvas to pan |
| </div> |
| <div className="flex items-center gap-2 text-xs font-semibold text-stone-600"> |
| <Search size={14} /> Scroll to zoom ({Math.round(zoom * 100)}%) |
| </div> |
| </div> |
|
|
| {} |
| <div |
| className="absolute origin-top-left will-change-transform" |
| style={{ transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})` }} |
| > |
| {} |
| <svg className="absolute inset-0 overflow-visible pointer-events-none" style={{ width: 1, height: 1 }}> |
| {SCRIPTURES.map(node => { |
| if (!node.parentId) return null; |
| const parent = SCRIPTURES.find(p => p.id === node.parentId); |
| if (!parent) return null; |
| |
| |
| const startX = parent.x; |
| const startY = parent.y + 20; |
| const endX = node.x; |
| const endY = node.y - 20; |
| |
| |
| const pathData = `M ${startX} ${startY} C ${startX} ${startY + Math.abs(endY - startY)/2}, ${endX} ${startY + Math.abs(endY - startY)/2}, ${endX} ${endY}`; |
| |
| |
| const strokeColor = WIRE_COLORS[node.category] || '#94a3b8'; |
| const isMainBranch = parent.id === 'root' || parent.id === 'shruti' || parent.id === 'smriti'; |
|
|
| return ( |
| <path |
| key={`edge-${node.id}`} |
| d={pathData} |
| fill="none" |
| stroke={strokeColor} |
| strokeWidth={isMainBranch ? "6" : "3"} |
| strokeOpacity={0.7} |
| strokeLinecap="round" |
| className="transition-all duration-500 drop-shadow-sm" |
| /> |
| ); |
| })} |
| </svg> |
|
|
| {} |
| {SCRIPTURES.map(node => { |
| const theme = CATEGORY_COLORS[node.category] || DEFAULT_COLOR; |
| const isStructural = ['Root', 'Classification', 'Category'].includes(node.category); |
| |
| return ( |
| <div |
| key={node.id} |
| className={`mindmap-node absolute transform -translate-x-1/2 -translate-y-1/2 cursor-pointer transition-transform hover:scale-110 active:scale-95 ${ |
| isStructural ? 'z-20' : 'z-10' |
| }`} |
| style={{ left: node.x, top: node.y }} |
| onClick={(e) => { e.stopPropagation(); onNodeClick(node.id); }} |
| > |
| <div className={` |
| ${isStructural ? 'px-6 py-3 font-bold text-lg rounded-xl border-2' : 'px-4 py-2 font-semibold text-sm rounded-lg border'} |
| shadow-sm backdrop-blur-sm whitespace-nowrap text-center |
| ${theme.node || `${theme.bg} ${theme.text} ${theme.border}`} |
| `}> |
| {node.name} |
| {!isStructural && ( |
| <div className={`text-[10px] mt-1 opacity-70`}>{node.category}</div> |
| )} |
| </div> |
| </div> |
| ); |
| })} |
| </div> |
| </div> |
| ); |
| } |