From ac65a95ad757855736b6e3547042c71fe32a7aa0 Mon Sep 17 00:00:00 2001 From: ras-al Date: Wed, 7 Jan 2026 22:15:05 +0530 Subject: [PATCH 1/6] Feat: Complete Multi-Algorithm Comparison and UI Overhaul Features Implemented: - Multi-Algorithm Comparison: - Enabled support for running up to 6 sorting algorithms simultaneously. - Implemented dynamic grid layout (1x1, 1x2, 2x3) that adapts to the number of active algorithms. - Added 'Add Algorithm' and 'Remove Algorithm' controls to the sidebar. - Refactored state management to handle an array of algorithm instances. - Synchronized 'Play/Pause' functionality to wait for all algorithms to complete before stopping. UI & Visualization Enhancements: - Fixed Bar Label Visibility: Scaled max bar height to 90% to prevent numerical values from being clipped at the top. - Light Mode Visibility Fixes: - Corrected text contrast for Contributors Section, Linked List, Tree, Heap, and DP visualizers. - Updated node and edge colors for better visibility on light backgrounds. - Sorting Performance: Tweaked speed calculation logic for significantly faster execution at high settings. - Textual Feedback: Added real-time step descriptions (e.g., 'Comparing 5 and 10', 'Swapping elements') below the visualization. Bug Fixes: - Fixed 'ReferenceError: arraySize is not defined' by restoring missing core state variables. - Resolved Syntax Errors in DsaVisualization.jsx by restoring accidentally deleted Header and Sidebar components. - Fixed layout shift issues in the main visualizer container. --- src/components/dsa/ContributorsSection.jsx | 28 +- src/lib/dsaAlgorithms.js | 436 ++++++++------- src/pages/DsaVisualization.jsx | 602 ++++++++++++--------- 3 files changed, 592 insertions(+), 474 deletions(-) diff --git a/src/components/dsa/ContributorsSection.jsx b/src/components/dsa/ContributorsSection.jsx index 3237e69..2c9c304 100644 --- a/src/components/dsa/ContributorsSection.jsx +++ b/src/components/dsa/ContributorsSection.jsx @@ -12,9 +12,9 @@ const ContributorsSection = ({ darkMode }) => {
-

Contributors to this page

+

Contributors to this page

- +
{dsaContributors.map((contributor, index) => ( {
- {contributor.name}
- -

{contributor.name}

-

{contributor.role}

- - - - -
- - - + + +
@@ -377,9 +415,9 @@ const GraphVisualizer = ({ algorithmName, isPlaying, setIsPlaying, speed, onFini const end = nodes.find(n => n.id === edge.to); if (!start || !end) return null; const isActive = visualState.activeLink && ((visualState.activeLink.from === edge.from && visualState.activeLink.to === edge.to) || (!isDirected && visualState.activeLink.from === edge.to && visualState.activeLink.to === edge.from)); - return ( {isWeighted && ({edge.weight})}); + return ({isWeighted && ({edge.weight})}); })} - {editMode === 'add-edge' && edgeStartNode !== null && (() => { const start = nodes.find(n => n.id === edgeStartNode); if(start) return ; return null; })()} + {editMode === 'add-edge' && edgeStartNode !== null && (() => { const start = nodes.find(n => n.id === edgeStartNode); if (start) return ; return null; })()} {nodes.map((node) => { const isStart = node.id === startNode; const isEnd = node.id === endNode; @@ -398,48 +436,49 @@ const GraphVisualizer = ({ algorithmName, isPlaying, setIsPlaying, speed, onFini const DsaVisualization = () => { const { toast } = useToast(); + const [sortingAlgorithms, setSortingAlgorithms] = useState(['BubbleSort']); + const [finishedCount, setFinishedCount] = useState(0); + + // Keep legacy state for non-sorting tabs + const [algorithm, setAlgorithm] = useState('BFS'); + const [activeTab, setActiveTab] = useState('sorting'); - const [algorithm, setAlgorithm] = useState('BubbleSort'); - const [secondAlgorithm, setSecondAlgorithm] = useState('QuickSort'); - const [arraySize, setArraySize] = useState(20); + const [arraySize, setArraySize] = useState(20); const [speed, setSpeed] = useState(50); const [isPlaying, setIsPlaying] = useState(false); const [isComparisonMode, setIsComparisonMode] = useState(false); const [darkMode, setDarkMode] = useState(true); const [customInput, setCustomInput] = useState(''); - const [searchTarget, setSearchTarget] = useState(42); // Default target - + const [searchTarget, setSearchTarget] = useState(42); const [array, setArray] = useState([]); - useEffect(() => { - if (activeTab === 'sorting' || activeTab === 'searching') { - resetArray(); - } - }, [arraySize, activeTab]); + // Independent effect for sortingAlgorithms initialization if needed, + // but we initialized it with default ['BubbleSort']. + + // Helper for algo options (moved inside or kept outside if static, assuming it was static or defined inside) + const algoOptions = { + sorting: ['BubbleSort', 'SelectionSort', 'InsertionSort', 'MergeSort', 'QuickSort'], + searching: ['BinarySearch', 'LinearSearch'], + graphs: ['BFS', 'DFS', 'Dijkstra', 'AStar'], + linkedlist: [], + trees: [], + heaps: [], + dp: [] + }; const resetArray = () => { setIsPlaying(false); - // If binary search, we should ideally sort, but random is fine for linear. - // To keep it simple, we generate random. - // If user selects BinarySearch, we might want to auto-sort or let them visualize fail/sort. + setFinishedCount(0); const newArr = Array.from({ length: arraySize }, () => Math.floor(Math.random() * 100) + 5); - - // If searching, ensure the target is present randomly 50% of the time for fun, or just random. - // Let's just keep random. setArray(newArr); + + // Reset bar styles const bars = document.querySelectorAll('[class^="bar-"]'); bars.forEach(bar => { - bar.style.backgroundColor = 'rgba(148, 163, 184, 0.5)'; + bar.style.backgroundColor = darkMode ? 'rgba(148, 163, 184, 0.5)' : '#64748b'; bar.style.opacity = '1'; }); }; - - // Auto-sort if switching to Binary Search to avoid confusion - useEffect(() => { - if (algorithm === 'BinarySearch') { - setArray(prev => [...prev].sort((a,b) => a-b)); - } - }, [algorithm]); const handlePlay = () => { setIsPlaying(!isPlaying); }; @@ -449,16 +488,69 @@ const DsaVisualization = () => { if (arr.length > 0) { setArray(arr); setArraySize(arr.length); setIsPlaying(false); } }; - const algoOptions = { - sorting: ['BubbleSort', 'SelectionSort', 'InsertionSort', 'MergeSort', 'QuickSort'], - searching: ['BinarySearch', 'LinearSearch'], - graphs: ['BFS', 'DFS', 'Dijkstra', 'AStar'], - linkedlist: [], - trees: [], - heaps: [], - dp: [] + // Auto-sort for BinarySearch logic (if applicable for single algo viewing) + useEffect(() => { + if (activeTab === 'searching' && algorithm === 'BinarySearch') { + setArray(prev => [...prev].sort((a, b) => a - b)); + } + }, [algorithm, activeTab]); + + + useEffect(() => { + if (activeTab === 'sorting' || activeTab === 'searching') { + resetArray(); + } + }, [arraySize, activeTab]); + + // Cleanup finishedCount when playing starts or specific changes happen + useEffect(() => { + if (isPlaying) { + setFinishedCount(0); + } + }, [isPlaying]); + + // Check if all algorithms finished + useEffect(() => { + if (activeTab === 'sorting' && isPlaying && finishedCount >= sortingAlgorithms.length && sortingAlgorithms.length > 0) { + setIsPlaying(false); + } + }, [finishedCount, sortingAlgorithms.length, isPlaying, activeTab]); + + const handleAlgorithmFinished = () => { + setFinishedCount(prev => prev + 1); + } + + const addAlgorithm = () => { + if (sortingAlgorithms.length < 6) { + setSortingAlgorithms([...sortingAlgorithms, 'BubbleSort']); + } + }; + + const removeAlgorithm = (index) => { + if (sortingAlgorithms.length > 1) { + const newAlgos = [...sortingAlgorithms]; + newAlgos.splice(index, 1); + setSortingAlgorithms(newAlgos); + } }; + const updateAlgorithm = (index, value) => { + const newAlgos = [...sortingAlgorithms]; + newAlgos[index] = value; + setSortingAlgorithms(newAlgos); + }; + + // ... + + // Inside SortingVisualizer (Update style height logic) + // style={{ height: `${(val / Math.max(...array)) * 90}%`, ... }} + + // ... Selection Options Logic ... + // If activeTab === 'sorting', render list of selects + + // ... Grid Logic ... + // sortingAlgorithms.map(...) + return (
@@ -499,8 +591,8 @@ const DsaVisualization = () => {

- )} - > - {algo.replace(/([A-Z])/g, ' $1').trim()} - + ))} - - - {activeTab === 'sorting' && ( -
- - + {sortingAlgorithms.length < 6 && ( + + )}
- )} - {isComparisonMode && activeTab === 'sorting' && ( - + + + {algoOptions[activeTab]?.map(algo => ( - { ))} - )} - - )} + + ) + } {(activeTab === 'sorting' || activeTab === 'searching') && ( -
+
-
Size{arraySize}
- setArraySize(val[0])} disabled={isPlaying}/> +
Size{arraySize}
+ setArraySize(val[0])} disabled={isPlaying} />
-
Speed{speed}%
+
Speed{speed}%
setSpeed(val[0])} />
@@ -603,24 +707,23 @@ const DsaVisualization = () => { {(activeTab === 'sorting' || activeTab === 'searching') && (
)} - - {/* Fix: Added Search Target Input */} + {activeTab === 'searching' && (
- setSearchTarget(parseInt(e.target.value) || 0)} + setSearchTarget(parseInt(e.target.value) || 0)} className="h-9 text-sm" />
@@ -640,83 +743,100 @@ const DsaVisualization = () => {
- {activeTab === 'sorting' || activeTab === 'searching' ? ( -
- - -
-

{algorithm.replace(/([A-Z])/g, ' $1').trim()}

- {activeTab === 'searching' &&
Target: {searchTarget}
} -
- -
- 공급
- {isComparisonMode && ( + { + activeTab === 'sorting' ? ( +
+ {sortingAlgorithms.map((algo, index) => ( + + +
+

+ {algo.replace(/([A-Z])/g, ' $1').trim()} +

+
+ +
+
+ ))} +
+ ) : activeTab === 'searching' ? ( + // Searching View + // Use 'algorithm' state instead of 'sortingAlgorithms[0]' +
-
-

{secondAlgorithm.replace(/([A-Z])/g, ' $1').trim()}

+
+

{algorithm.replace(/([A-Z])/g, ' $1').trim()}

+
Target: {searchTarget}
- + setIsPlaying(false)} darkMode={darkMode} /> - )} -
- ) : activeTab === 'graphs' ? ( - - -
-

Graph Algorithms

-
- setIsPlaying(false)} darkMode={darkMode} /> -
-
- ) : activeTab === 'linkedlist' ? ( - - -
-

Linked List Visualizer

-
- -
-
- ) : activeTab === 'trees' ? ( - - -
-

Binary Search Tree

-
- -
-
- ) : activeTab === 'heaps' ? ( - - -
-

Heap Visualizer (Max)

-
- -
-
- ) : activeTab === 'dp' ? ( - - -
-

Dynamic Programming

-
- -
-
- ) : ( - -

Under Construction

-
- )} -
-
+
+ ) : activeTab === 'graphs' ? ( + + +
+

Graph Algorithms

+
+ setIsPlaying(false)} darkMode={darkMode} /> +
+
+ ) : activeTab === 'linkedlist' ? ( + + +
+

Linked List Visualizer

+
+ +
+
+ ) : activeTab === 'trees' ? ( + + +
+

Binary Search Tree

+
+ +
+
+ ) : activeTab === 'heaps' ? ( + + +
+

Heap Visualizer (Max)

+
+ +
+
+ ) : activeTab === 'dp' ? ( + + +
+

Dynamic Programming

+
+ +
+
+ ) : ( + +

Under Construction

+
+ ) + } +
+
- - + + ); }; From e803eeaa6cd365c2bc8fb2e8f75aa2797dc3c291 Mon Sep 17 00:00:00 2001 From: ras-al Date: Thu, 8 Jan 2026 22:02:17 +0530 Subject: [PATCH 2/6] Refactor: Address Copilot review feedback (sync safety and formatting) --- src/pages/DsaVisualization.jsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pages/DsaVisualization.jsx b/src/pages/DsaVisualization.jsx index 5132147..994174c 100644 --- a/src/pages/DsaVisualization.jsx +++ b/src/pages/DsaVisualization.jsx @@ -121,6 +121,8 @@ const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, setDescription('Element is sorted'); } else if (step.type === 'found') { setDescription(`Found target ${searchTarget} at index ${step.indices[0]}!`); + } else { + setDescription('Processing step...'); } const bars = document.getElementsByClassName(`bar-${className}`); @@ -527,10 +529,12 @@ const DsaVisualization = () => { }; const removeAlgorithm = (index) => { + if (isPlaying) return; if (sortingAlgorithms.length > 1) { const newAlgos = [...sortingAlgorithms]; newAlgos.splice(index, 1); setSortingAlgorithms(newAlgos); + setFinishedCount(0); } }; @@ -832,11 +836,11 @@ const DsaVisualization = () => { ) } - - + + - - + + ); }; From 4a44ae06fd22340ac0be5c66e80815e2e6fdfaa2 Mon Sep 17 00:00:00 2001 From: ras-al Date: Thu, 8 Jan 2026 22:17:25 +0530 Subject: [PATCH 3/6] Refactor: Remove unused imports and fix minor syntax issues" --- src/pages/DsaVisualization.jsx | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/pages/DsaVisualization.jsx b/src/pages/DsaVisualization.jsx index 994174c..e809806 100644 --- a/src/pages/DsaVisualization.jsx +++ b/src/pages/DsaVisualization.jsx @@ -3,10 +3,10 @@ import React, { useState, useEffect, useRef, useMemo } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Helmet } from 'react-helmet'; import { - Play, Pause, RotateCcw, Settings, ChevronRight, ChevronLeft, - LayoutGrid, List, BarChart2, Activity, Moon, Sun, - GitCompare, SplitSquareHorizontal, ArrowRight, Network, - PlusCircle, Move, MousePointer2, Trash2, StepForward, + Play, Pause, RotateCcw, + List, Activity, Moon, Sun, + Network, + PlusCircle, Move, Trash2, StepForward, StepBack, Binary, BoxSelect, Layers, Search, Github } from 'lucide-react'; import { Button } from '@/components/ui/button'; @@ -79,7 +79,7 @@ const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, }; const animate = (steps) => { - const delay = speed === 100 ? 1 : (101 - speed) * 3; + const delay = Math.max(1, Math.floor(1000 / (speed * 2))); steps.forEach((step, index) => { const timeoutId = setTimeout(() => { setDisplayArray(prev => { @@ -468,7 +468,9 @@ const DsaVisualization = () => { dp: [] }; - const resetArray = () => { + const getBarColor = (isDark) => isDark ? 'rgba(148, 163, 184, 0.5)' : '#64748b'; + + const resetArray = useCallback(() => { setIsPlaying(false); setFinishedCount(0); const newArr = Array.from({ length: arraySize }, () => Math.floor(Math.random() * 100) + 5); @@ -477,10 +479,10 @@ const DsaVisualization = () => { // Reset bar styles const bars = document.querySelectorAll('[class^="bar-"]'); bars.forEach(bar => { - bar.style.backgroundColor = darkMode ? 'rgba(148, 163, 184, 0.5)' : '#64748b'; + bar.style.backgroundColor = getBarColor(darkMode); bar.style.opacity = '1'; }); - }; + }, [arraySize, darkMode]); const handlePlay = () => { setIsPlaying(!isPlaying); }; @@ -502,7 +504,7 @@ const DsaVisualization = () => { if (activeTab === 'sorting' || activeTab === 'searching') { resetArray(); } - }, [arraySize, activeTab]); + }, [resetArray, activeTab]); // Cleanup finishedCount when playing starts or specific changes happen useEffect(() => { @@ -520,7 +522,7 @@ const DsaVisualization = () => { const handleAlgorithmFinished = () => { setFinishedCount(prev => prev + 1); - } + }; const addAlgorithm = () => { if (sortingAlgorithms.length < 6) { From 4e79731a97b354abd516fa10e8e41715ab747db5 Mon Sep 17 00:00:00 2001 From: ras-al Date: Thu, 8 Jan 2026 22:40:52 +0530 Subject: [PATCH 4/6] efactor: Fix sync race condition and extract color logic" --- src/components/dsa/ContributorsSection.jsx | 6 ++-- src/pages/DsaVisualization.jsx | 32 ++++++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/components/dsa/ContributorsSection.jsx b/src/components/dsa/ContributorsSection.jsx index 2c9c304..52f3935 100644 --- a/src/components/dsa/ContributorsSection.jsx +++ b/src/components/dsa/ContributorsSection.jsx @@ -46,9 +46,9 @@ const ContributorsSection = ({ darkMode }) => { asChild variant="ghost" size="sm" - className={cn("text-xs mb-3", darkMode ? "text-slate-500" : "text-slate-600", - "w-full h-8 gap-2 border border-slate-700/20 hover:text-cyan-400", - darkMode ? "hover:bg-slate-700" : "hover:bg-slate-100" + className={cn( + "text-xs mb-3 w-full h-8 gap-2 border border-slate-700/20 hover:text-cyan-400", + darkMode ? "text-slate-500 hover:bg-slate-700" : "text-slate-600 hover:bg-slate-100" )} > diff --git a/src/pages/DsaVisualization.jsx b/src/pages/DsaVisualization.jsx index e809806..a3d2299 100644 --- a/src/pages/DsaVisualization.jsx +++ b/src/pages/DsaVisualization.jsx @@ -1,5 +1,5 @@ -import React, { useState, useEffect, useRef, useMemo } from 'react'; +import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Helmet } from 'react-helmet'; import { @@ -35,6 +35,11 @@ import ContributorsSection from '@/components/dsa/ContributorsSection'; // --- Existing Sorting/Graph Components --- +const getAlgorithmColor = (index) => { + const colors = ["text-cyan-400", "text-purple-400", "text-emerald-400", "text-orange-400"]; + return colors[index % colors.length]; +}; + const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, className, searchTarget, darkMode }) => { const [displayArray, setDisplayArray] = useState([...array]); const [description, setDescription] = useState(''); @@ -506,12 +511,12 @@ const DsaVisualization = () => { } }, [resetArray, activeTab]); - // Cleanup finishedCount when playing starts or specific changes happen + // Cleanup finishedCount when playing starts or when the number of algorithms changes useEffect(() => { if (isPlaying) { setFinishedCount(0); } - }, [isPlaying]); + }, [isPlaying, sortingAlgorithms.length]); // Check if all algorithms finished useEffect(() => { @@ -546,16 +551,7 @@ const DsaVisualization = () => { setSortingAlgorithms(newAlgos); }; - // ... - - // Inside SortingVisualizer (Update style height logic) - // style={{ height: `${(val / Math.max(...array)) * 90}%`, ... }} - - // ... Selection Options Logic ... - // If activeTab === 'sorting', render list of selects - // ... Grid Logic ... - // sortingAlgorithms.map(...) return (
@@ -751,12 +747,18 @@ const DsaVisualization = () => {
{ activeTab === 'sorting' ? ( -
+
{sortingAlgorithms.map((algo, index) => (
-

+

{algo.replace(/([A-Z])/g, ' $1').trim()}

@@ -783,7 +785,7 @@ const DsaVisualization = () => {

{algorithm.replace(/([A-Z])/g, ' $1').trim()}

Target: {searchTarget}
- setIsPlaying(false)} darkMode={darkMode} /> +
From 687c160475c2c2e8e6072aee24ab91f1217bc06d Mon Sep 17 00:00:00 2001 From: ras-al Date: Thu, 8 Jan 2026 22:48:25 +0530 Subject: [PATCH 5/6] Refactor: Use useRef for DOM access and improve robustness --- src/pages/DsaVisualization.jsx | 58 ++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/pages/DsaVisualization.jsx b/src/pages/DsaVisualization.jsx index a3d2299..cec43a7 100644 --- a/src/pages/DsaVisualization.jsx +++ b/src/pages/DsaVisualization.jsx @@ -40,10 +40,11 @@ const getAlgorithmColor = (index) => { return colors[index % colors.length]; }; -const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, className, searchTarget, darkMode }) => { +const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, className, searchTarget, darkMode = false }) => { const [displayArray, setDisplayArray] = useState([...array]); const [description, setDescription] = useState(''); const timeoutsRef = useRef([]); + const containerRef = useRef(null); const showLabels = array.length <= 35; @@ -127,27 +128,31 @@ const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, } else if (step.type === 'found') { setDescription(`Found target ${searchTarget} at index ${step.indices[0]}!`); } else { - setDescription('Processing step...'); + // Fallback for unhandled step types + setDescription(step.message || 'Processing step...'); } - const bars = document.getElementsByClassName(`bar-${className}`); - if (bars.length > 0) { - if (step.type === 'compare') { - step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#ef4444' }); - } else if (step.type === 'swap' || step.type === 'overwrite') { - step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#eab308' }); - } else if (step.type === 'sorted' || step.type === 'found') { - step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#10b981' }); - } else if (step.type === 'revert') { - step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '' }); - } else if (step.type === 'discard') { - if (step.range) { - for (let i = step.range[0]; i <= step.range[1]; i++) { - if (bars[i]) bars[i].style.opacity = '0.2'; + // Use ref for safer DOM manipulation within component scope + if (containerRef.current) { + const bars = containerRef.current.children; + if (bars.length > 0) { + if (step.type === 'compare') { + step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#ef4444' }); + } else if (step.type === 'swap' || step.type === 'overwrite') { + step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#eab308' }); + } else if (step.type === 'sorted' || step.type === 'found') { + step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#10b981' }); + } else if (step.type === 'revert') { + step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '' }); + } else if (step.type === 'discard') { + if (step.range) { + for (let i = step.range[0]; i <= step.range[1]; i++) { + if (bars[i]) bars[i].style.opacity = '0.2'; + } } + } else if (step.type === 'highlight-min' || step.type === 'select') { + step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#a855f7' }); // Purple for special highlights } - } else if (step.type === 'highlight-min' || step.type === 'select') { - step.indices.forEach(idx => { if (bars[idx]) bars[idx].style.backgroundColor = '#a855f7' }); // Purple for special highlights } } @@ -161,10 +166,21 @@ const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, }; return ( -
-
+
+
{displayArray.map((val, idx) => ( -
+
{showLabels && ( Date: Thu, 8 Jan 2026 23:03:15 +0530 Subject: [PATCH 6/6] Fix: Remove overflow-hidden to ensure bar labels are always visible --- src/pages/DsaVisualization.jsx | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/pages/DsaVisualization.jsx b/src/pages/DsaVisualization.jsx index cec43a7..a56c652 100644 --- a/src/pages/DsaVisualization.jsx +++ b/src/pages/DsaVisualization.jsx @@ -40,6 +40,18 @@ const getAlgorithmColor = (index) => { return colors[index % colors.length]; }; +/** + * Component to visualize sorting algorithms. + * @param {Object} props + * @param {Array} props.array - The array to visualize. + * @param {string} props.algorithmName - The name of the algorithm. + * @param {boolean} props.isPlaying - Whether the visualization is running. + * @param {number} props.speed - Speed of animation (1-100). + * @param {Function} [props.onFinished] - Callback when visualization finishes. + * @param {string} props.className - Unique class for this visualizer instance. + * @param {number} [props.searchTarget] - Target number for searching algorithms. + * @param {boolean} [props.darkMode=false] - Whether dark mode is enabled. + */ const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, className, searchTarget, darkMode = false }) => { const [displayArray, setDisplayArray] = useState([...array]); const [description, setDescription] = useState(''); @@ -128,8 +140,12 @@ const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, } else if (step.type === 'found') { setDescription(`Found target ${searchTarget} at index ${step.indices[0]}!`); } else { - // Fallback for unhandled step types - setDescription(step.message || 'Processing step...'); + // Fallback for unhandled step types or general updates + if (step.message) { + setDescription(step.message); + } else { + setDescription('Processing step...'); + } } // Use ref for safer DOM manipulation within component scope @@ -174,7 +190,7 @@ const SortingVisualizer = ({ array, algorithmName, isPlaying, speed, onFinished, {displayArray.map((val, idx) => (