@tomaszjarosz/react-visualizers 0.2.7 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  Interactive algorithm and data structure visualizers for React.
4
4
 
5
+ [![Storybook](https://img.shields.io/badge/Storybook-Live%20Demo-ff4785?logo=storybook&logoColor=white)](https://6934a2d9e17d1e509a92c935-rdicbxowdr.chromatic.com/)
6
+ [![npm version](https://img.shields.io/npm/v/@tomaszjarosz/react-visualizers)](https://www.npmjs.com/package/@tomaszjarosz/react-visualizers)
7
+
8
+ ## Live Demo
9
+
10
+ **[View all visualizers in Storybook](https://6934a2d9e17d1e509a92c935-rdicbxowdr.chromatic.com/)**
11
+
5
12
  ## Installation
6
13
 
7
14
  ```bash
@@ -10,62 +17,97 @@ npm install @tomaszjarosz/react-visualizers
10
17
 
11
18
  ## Requirements
12
19
 
13
- - React 17+ or 18+
14
- - Tailwind CSS
20
+ - React 17+
21
+ - Tailwind CSS 4+
15
22
 
16
23
  ## Available Visualizers
17
24
 
18
- ### Sorting Algorithms
19
- - `BubbleSortVisualizer`
20
- - `SelectionSortVisualizer`
21
- - `InsertionSortVisualizer`
22
- - `MergeSortVisualizer`
23
- - `QuickSortVisualizer`
24
- - `HeapSortVisualizer`
25
+ ### Algorithms
26
+ | Visualizer | Description |
27
+ |------------|-------------|
28
+ | `BinarySearchVisualizer` | Binary search with O(log n) visualization |
29
+ | `SortingVisualizer` | Step-by-step sorting algorithm |
30
+ | `SortingComparisonVisualizer` | Side-by-side algorithm comparison |
31
+ | `GraphVisualizer` | DFS/BFS graph traversal |
32
+ | `DijkstraVisualizer` | Shortest path algorithm |
33
+ | `DPVisualizer` | Dynamic programming table |
25
34
 
26
35
  ### Data Structures
27
- - `ArrayListVisualizer`
28
- - `LinkedListVisualizer`
29
- - `StackVisualizer`
30
- - `QueueVisualizer`
31
- - `HashMapVisualizer`
32
- - `TreeSetVisualizer`
33
- - `TreeMapVisualizer`
34
- - `PriorityQueueVisualizer`
35
- - `DequeVisualizer`
36
+ | Visualizer | Description |
37
+ |------------|-------------|
38
+ | `ArrayListVisualizer` | Dynamic array with resizing |
39
+ | `LinkedListVisualizer` | Node-based list operations |
40
+ | `HashMapVisualizer` | Hash table with buckets |
41
+ | `HashTableVisualizer` | Hash function internals |
42
+ | `ArrayDequeVisualizer` | Circular buffer deque |
43
+ | `PriorityQueueVisualizer` | Min-heap operations |
44
+ | `TreeSetVisualizer` | Red-Black tree (BST) |
45
+ | `LinkedHashMapVisualizer` | Hash + insertion order |
46
+ | `EnumSetVisualizer` | Bit vector set |
36
47
 
37
48
  ### Concurrency
38
- - `ThreadPoolVisualizer`
39
- - `SemaphoreVisualizer`
40
- - `ReentrantLockVisualizer`
41
- - `ReadWriteLockVisualizer`
49
+ | Visualizer | Description |
50
+ |------------|-------------|
51
+ | `BlockingQueueVisualizer` | Producer-consumer pattern |
52
+ | `ConcurrentHashMapVisualizer` | Segment-based locking |
53
+ | `CopyOnWriteVisualizer` | Copy-on-write pattern |
54
+ | `ImmutableCollectionsVisualizer` | Java 9+ immutable collections |
42
55
 
43
56
  ### Other
44
- - `RecursionTreeVisualizer`
45
- - `BinarySearchVisualizer`
57
+ | Visualizer | Description |
58
+ |------------|-------------|
59
+ | `GCVisualizer` | JVM garbage collection |
60
+ | `SQLJoinVisualizer` | SQL JOIN operations |
46
61
 
47
62
  ## Usage
48
63
 
49
64
  ```tsx
50
- import { BubbleSortVisualizer, HashMapVisualizer } from '@tomaszjarosz/react-visualizers';
65
+ import { BinarySearchVisualizer, HashMapVisualizer } from '@tomaszjarosz/react-visualizers';
51
66
 
52
67
  function App() {
53
68
  return (
54
69
  <div>
55
- <h2>Bubble Sort</h2>
56
- <BubbleSortVisualizer />
57
-
58
- <h2>HashMap Operations</h2>
59
- <HashMapVisualizer />
70
+ <BinarySearchVisualizer showControls={true} showCode={true} />
71
+ <HashMapVisualizer showControls={true} showCode={true} />
60
72
  </div>
61
73
  );
62
74
  }
63
75
  ```
64
76
 
77
+ ### Props
78
+
79
+ All visualizers accept these props:
80
+
81
+ | Prop | Type | Default | Description |
82
+ |------|------|---------|-------------|
83
+ | `showControls` | `boolean` | `true` | Show playback controls |
84
+ | `showCode` | `boolean` | `true` | Show code panel |
85
+ | `className` | `string` | `''` | Additional CSS classes |
86
+
65
87
  ## Shared Components
66
88
 
67
89
  ```tsx
68
- import { ControlPanel, CodePanel, Legend, StatusPanel } from '@tomaszjarosz/react-visualizers';
90
+ import {
91
+ ControlPanel,
92
+ CodePanel,
93
+ Legend,
94
+ StatusPanel,
95
+ VisualizationArea,
96
+ HelpPanel
97
+ } from '@tomaszjarosz/react-visualizers';
98
+ ```
99
+
100
+ ## Development
101
+
102
+ ```bash
103
+ # Run Storybook locally
104
+ pnpm run storybook
105
+
106
+ # Build library
107
+ pnpm run build
108
+
109
+ # Type check
110
+ pnpm run typecheck
69
111
  ```
70
112
 
71
113
  ## License
package/dist/index.cjs CHANGED
@@ -1496,11 +1496,64 @@ const BinarySearchVisualizerComponent = ({
1496
1496
  ] }) }),
1497
1497
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
1498
1498
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 350, children: [
1499
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-green-50 to-emerald-50 rounded-xl border-2 border-green-200", children: [
1500
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-green-800 mb-3 flex items-center gap-2", children: [
1501
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "🎯" }),
1502
+ " Binary Search Invariant"
1503
+ ] }),
1504
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-sm bg-white rounded-lg p-3 border border-green-200", children: [
1505
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center text-green-700 font-bold mb-2", children: "target ∈ arr[left..right]" }),
1506
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500 text-center", children: "If target exists, it must be within current search bounds" })
1507
+ ] }),
1508
+ left <= right && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 p-2 bg-white rounded-lg border border-green-200", children: [
1509
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center text-xs", children: [
1510
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1511
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-green-700", children: "Search space:" }),
1512
+ " ",
1513
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
1514
+ "[",
1515
+ left,
1516
+ "..",
1517
+ right,
1518
+ "]"
1519
+ ] }),
1520
+ " = ",
1521
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-green-600", children: right - left + 1 }),
1522
+ " elements"
1523
+ ] }),
1524
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-500", children: currentStep > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1525
+ "Eliminated: ",
1526
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold text-red-500", children: [
1527
+ Math.round((1 - (right - left + 1) / array.length) * 100),
1528
+ "%"
1529
+ ] })
1530
+ ] }) })
1531
+ ] }),
1532
+ mid >= 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 text-xs text-center text-gray-600", children: [
1533
+ "mid = ⌊(",
1534
+ left,
1535
+ " + ",
1536
+ right,
1537
+ ") / 2⌋ = ",
1538
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-purple-600", children: mid })
1539
+ ] })
1540
+ ] }),
1541
+ found === true && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 p-2 bg-green-100 rounded-lg border border-green-300 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-green-800 font-bold", children: [
1542
+ "✓ Found in ",
1543
+ currentStep,
1544
+ " steps (log₂",
1545
+ array.length,
1546
+ " ≈ ",
1547
+ Math.ceil(Math.log2(array.length)),
1548
+ " max)"
1549
+ ] }) }),
1550
+ found === false && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 p-2 bg-red-100 rounded-lg border border-red-300 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-800 font-bold", children: "✗ Not found - search space exhausted" }) })
1551
+ ] }),
1499
1552
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center gap-1 flex-wrap mb-4", children: array.map((value, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
1500
1553
  /* @__PURE__ */ jsxRuntime.jsx(
1501
1554
  "div",
1502
1555
  {
1503
- className: `w-10 h-10 flex items-center justify-center rounded-lg font-medium text-sm transition-all duration-300 ${getElementStyle(index)}`,
1556
+ className: `w-10 h-10 flex items-center justify-center rounded-lg font-medium text-sm transition-colors duration-300 ${getElementStyle(index)}`,
1504
1557
  children: value
1505
1558
  }
1506
1559
  ),
@@ -2371,7 +2424,7 @@ const SortingVisualizerComponent = ({
2371
2424
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-end justify-center gap-1 h-48 bg-gray-50 rounded-lg p-4", children: bars.map((bar, index) => /* @__PURE__ */ jsxRuntime.jsxs(
2372
2425
  "div",
2373
2426
  {
2374
- className: `${getBarColor(bar.state)} rounded-t transition-all duration-200 flex items-end justify-center relative group`,
2427
+ className: `${getBarColor(bar.state)} rounded-t transition-colors duration-200 flex items-end justify-center relative group`,
2375
2428
  style: {
2376
2429
  height: `${bar.value / maxValue * 100}%`,
2377
2430
  width: `${Math.max(100 / bars.length - 1, 8)}%`,
@@ -2831,7 +2884,7 @@ const SortingComparisonVisualizerComponent = ({
2831
2884
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-end justify-center gap-0.5 h-32 bg-gray-50 rounded p-2", children: step.array.map((value, index) => /* @__PURE__ */ jsxRuntime.jsx(
2832
2885
  "div",
2833
2886
  {
2834
- className: `${getBarColor(step, index)} rounded-t transition-all duration-150`,
2887
+ className: `${getBarColor(step, index)} rounded-t transition-colors duration-150`,
2835
2888
  style: {
2836
2889
  height: `${value / maxValue * 100}%`,
2837
2890
  width: `${Math.max(100 / step.array.length - 1, 6)}%`,
@@ -4142,6 +4195,25 @@ const GraphVisualizerComponent = ({
4142
4195
  ] }) }),
4143
4196
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
4144
4197
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 400, children: [
4198
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl border-2 border-purple-200", children: [
4199
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-purple-800 mb-3 flex items-center gap-2", children: [
4200
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "🔍" }),
4201
+ " DFS vs BFS"
4202
+ ] }),
4203
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 text-xs", children: [
4204
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `p-2 rounded-lg border ${algorithm === "dfs" ? "bg-purple-100 border-purple-300" : "bg-gray-100 border-gray-300"}`, children: [
4205
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-purple-700", children: "Depth-First (DFS)" }),
4206
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-purple-600", children: "Uses: Stack" }),
4207
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-purple-500", children: "Go deep before wide" })
4208
+ ] }),
4209
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `p-2 rounded-lg border ${algorithm === "bfs" ? "bg-indigo-100 border-indigo-300" : "bg-gray-100 border-gray-300"}`, children: [
4210
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-indigo-700", children: "Breadth-First (BFS)" }),
4211
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-indigo-600", children: "Uses: Queue" }),
4212
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-indigo-500", children: "Level by level" })
4213
+ ] })
4214
+ ] }),
4215
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-[10px] text-gray-600 text-center", children: "Both O(V+E) time • DFS for paths/cycles • BFS for shortest path (unweighted)" })
4216
+ ] }),
4145
4217
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
4146
4218
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 bg-gray-50 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 400 300", className: "w-full h-64", children: [
4147
4219
  graph.edges.map((edge, index) => {
@@ -4166,7 +4238,7 @@ const GraphVisualizerComponent = ({
4166
4238
  cx: node.x,
4167
4239
  cy: node.y,
4168
4240
  r: 20,
4169
- className: `${getNodeColor(node.id)} stroke-2 transition-all duration-300`
4241
+ className: `${getNodeColor(node.id)} stroke-2 transition-colors duration-300`
4170
4242
  }
4171
4243
  ),
4172
4244
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4499,6 +4571,40 @@ const HashMapVisualizerComponent = ({
4499
4571
  ] }) }),
4500
4572
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
4501
4573
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 350, className: showCode ? "flex-1" : "w-full", children: [
4574
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-indigo-50 to-purple-50 rounded-xl border-2 border-indigo-200", children: [
4575
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-indigo-800 mb-3 flex items-center gap-2", children: [
4576
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "#️⃣" }),
4577
+ " Hash Function"
4578
+ ] }),
4579
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-sm bg-white rounded-lg p-3 border border-indigo-200", children: [
4580
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center text-indigo-700 font-bold mb-2", children: "index = hashCode(key) % capacity" }),
4581
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500 text-center", children: "Same key → same index (deterministic) • Different keys may collide → chaining" })
4582
+ ] }),
4583
+ stepData.hash !== void 0 && stepData.key && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 p-3 bg-white rounded-lg border border-indigo-200", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-center", children: [
4584
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono mb-1", children: [
4585
+ "hashCode(",
4586
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-indigo-600 font-bold", children: [
4587
+ '"',
4588
+ stepData.key,
4589
+ '"'
4590
+ ] }),
4591
+ ") = ",
4592
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-600 font-bold", children: stepData.hash })
4593
+ ] }),
4594
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono", children: [
4595
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-600", children: stepData.hash }),
4596
+ " % ",
4597
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600", children: BUCKET_COUNT$1 }),
4598
+ " = ",
4599
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-indigo-600 font-bold text-lg", children: stepData.bucketIndex })
4600
+ ] }),
4601
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 text-indigo-600 text-lg", children: [
4602
+ "↓ bucket[",
4603
+ stepData.bucketIndex,
4604
+ "]"
4605
+ ] })
4606
+ ] }) })
4607
+ ] }),
4502
4608
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
4503
4609
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-medium text-gray-700 mb-2", children: [
4504
4610
  "Bucket Array (capacity: ",
@@ -4529,22 +4635,6 @@ const HashMapVisualizerComponent = ({
4529
4635
  ] }, eIdx)) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-gray-400 mt-1", children: "∅" }) })
4530
4636
  ] }, idx)) })
4531
4637
  ] }),
4532
- stepData.hash !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 p-3 bg-gray-100 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-gray-600", children: [
4533
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Hash Calculation:" }),
4534
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 font-mono text-indigo-600", children: [
4535
- 'hashCode("',
4536
- stepData.key,
4537
- '") = ',
4538
- stepData.hash
4539
- ] }),
4540
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-purple-600", children: [
4541
- stepData.hash,
4542
- " % ",
4543
- BUCKET_COUNT$1,
4544
- " = ",
4545
- stepData.bucketIndex
4546
- ] })
4547
- ] }) }),
4548
4638
  /* @__PURE__ */ jsxRuntime.jsx(
4549
4639
  StatusPanel,
4550
4640
  {
@@ -5217,6 +5307,27 @@ const LinkedListVisualizerComponent = ({
5217
5307
  ] }) }),
5218
5308
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
5219
5309
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 350, className: showCode ? "flex-1" : "w-full", children: [
5310
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-xl border-2 border-blue-200", children: [
5311
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-blue-800 mb-3 flex items-center gap-2", children: [
5312
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "🔗" }),
5313
+ " LinkedList vs ArrayList"
5314
+ ] }),
5315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-2 text-xs", children: [
5316
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white p-2 rounded-lg border border-blue-200 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-gray-700 mb-1", children: "Operation" }) }),
5317
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-blue-100 p-2 rounded-lg border border-blue-300 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-blue-700 mb-1", children: "LinkedList" }) }),
5318
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-orange-100 p-2 rounded-lg border border-orange-300 text-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-orange-700 mb-1", children: "ArrayList" }) }),
5319
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white p-2 rounded-lg border border-gray-200 text-center font-medium", children: "add/remove (ends)" }),
5320
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-green-100 p-2 rounded-lg border border-green-300 text-center font-bold text-green-700", children: "O(1)" }),
5321
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-green-100 p-2 rounded-lg border border-green-300 text-center font-bold text-green-700", children: "O(1)*" }),
5322
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white p-2 rounded-lg border border-gray-200 text-center font-medium", children: "add/remove (middle)" }),
5323
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-green-100 p-2 rounded-lg border border-green-300 text-center font-bold text-green-700", children: "O(1)**" }),
5324
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-red-100 p-2 rounded-lg border border-red-300 text-center font-bold text-red-700", children: "O(n)" }),
5325
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white p-2 rounded-lg border border-gray-200 text-center font-medium", children: "get(index)" }),
5326
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-red-100 p-2 rounded-lg border border-red-300 text-center font-bold text-red-700", children: "O(n)" }),
5327
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-green-100 p-2 rounded-lg border border-green-300 text-center font-bold text-green-700", children: "O(1)" })
5328
+ ] }),
5329
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-[10px] text-gray-500 text-center", children: "* amortized | ** if you have the node reference" })
5330
+ ] }),
5220
5331
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
5221
5332
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-gray-700 mb-2", children: "Doubly-Linked List" }),
5222
5333
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-gray-50 rounded-lg p-4 overflow-x-auto", children: nodes.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 min-w-max", children: [
@@ -5225,7 +5336,7 @@ const LinkedListVisualizerComponent = ({
5225
5336
  /* @__PURE__ */ jsxRuntime.jsxs(
5226
5337
  "div",
5227
5338
  {
5228
- className: `flex flex-col items-center transition-all ${node.id === highlightNode ? "scale-110" : ""}`,
5339
+ className: `flex flex-col items-center transition-colors ${node.id === highlightNode ? "scale-110" : ""}`,
5229
5340
  children: [
5230
5341
  /* @__PURE__ */ jsxRuntime.jsx(
5231
5342
  "div",
@@ -6468,7 +6579,7 @@ const ArrayDequeVisualizerComponent = ({
6468
6579
  const isTail = index === tail;
6469
6580
  const isHighlighted = index === highlightIndex;
6470
6581
  const hasValue = array[index] !== null;
6471
- let baseStyle = "border-2 transition-all duration-200 ";
6582
+ let baseStyle = "border-2 transition-colors duration-200 ";
6472
6583
  if (resizing) {
6473
6584
  baseStyle += "bg-yellow-100 border-yellow-400 ";
6474
6585
  } else if (isHighlighted) {
@@ -8337,6 +8448,25 @@ const ConcurrentHashMapVisualizerComponent = ({ showControls = true, showCode =
8337
8448
  ] }) }),
8338
8449
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
8339
8450
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 350, children: [
8451
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-red-50 to-orange-50 rounded-xl border-2 border-red-200", children: [
8452
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-red-800 mb-3 flex items-center gap-2", children: [
8453
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "⚡" }),
8454
+ " Why ConcurrentHashMap?"
8455
+ ] }),
8456
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 text-xs", children: [
8457
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-red-100 p-2 rounded-lg border border-red-300", children: [
8458
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-red-700", children: "synchronized HashMap" }),
8459
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-red-600", children: "❌ Single lock for entire map" }),
8460
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-red-500", children: "All threads wait for one lock" })
8461
+ ] }),
8462
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-green-100 p-2 rounded-lg border border-green-300", children: [
8463
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-green-700", children: "ConcurrentHashMap" }),
8464
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-green-600", children: "✓ Segment-level locking" }),
8465
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-green-500", children: "Threads work in parallel on different segments" })
8466
+ ] })
8467
+ ] }),
8468
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-[10px] text-gray-600 text-center", children: "get() never blocks • put() only locks one segment • Much better concurrency!" })
8469
+ ] }),
8340
8470
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
8341
8471
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-gray-700 mb-2", children: "Segments (independent locks)" }),
8342
8472
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3", children: segments.map((seg, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
@@ -8687,13 +8817,39 @@ const BlockingQueueVisualizerComponent = ({ showControls = true, showCode = true
8687
8817
  ] }) }) }),
8688
8818
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
8689
8819
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 350, children: [
8820
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-cyan-50 to-blue-50 rounded-xl border-2 border-cyan-200", children: [
8821
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-cyan-800 mb-3 flex items-center gap-2", children: [
8822
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "🔄" }),
8823
+ " Producer-Consumer Pattern"
8824
+ ] }),
8825
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-2 text-xs", children: [
8826
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-green-100 p-2 rounded-lg border border-green-300 text-center", children: [
8827
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-green-700", children: "Producers" }),
8828
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-green-600", children: "put() → queue" }),
8829
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-green-500", children: "Block if FULL" })
8830
+ ] }),
8831
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-gray-100 p-2 rounded-lg border border-gray-300 text-center", children: [
8832
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-gray-700", children: "BlockingQueue" }),
8833
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-600", children: "Thread-safe buffer" }),
8834
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] text-gray-500", children: [
8835
+ "Capacity: ",
8836
+ capacity
8837
+ ] })
8838
+ ] }),
8839
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-blue-100 p-2 rounded-lg border border-blue-300 text-center", children: [
8840
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-blue-700", children: "Consumers" }),
8841
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-blue-600", children: "take() ← queue" }),
8842
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-blue-500", children: "Block if EMPTY" })
8843
+ ] })
8844
+ ] })
8845
+ ] }),
8690
8846
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4 mb-4", children: [
8691
8847
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
8692
8848
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-gray-500 mb-2 text-center", children: "Producers" }),
8693
8849
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: ["P1", "P2"].map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
8694
8850
  "div",
8695
8851
  {
8696
- className: `px-3 py-2 rounded-lg text-center text-sm font-medium transition-all ${activeThread === p ? "bg-green-500 text-white scale-105" : blockedProducers.includes(p) ? "bg-red-100 text-red-700 border-2 border-red-300" : "bg-green-100 text-green-700"}`,
8852
+ className: `px-3 py-2 rounded-lg text-center text-sm font-medium transition-colors ${activeThread === p ? "bg-green-500 text-white" : blockedProducers.includes(p) ? "bg-red-100 text-red-700 border-2 border-red-300" : "bg-green-100 text-green-700"}`,
8697
8853
  children: [
8698
8854
  p,
8699
8855
  blockedProducers.includes(p) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-[10px]", children: "BLOCKED" })
@@ -8714,7 +8870,7 @@ const BlockingQueueVisualizerComponent = ({ showControls = true, showCode = true
8714
8870
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: queue.length > 0 ? queue.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsx(
8715
8871
  "div",
8716
8872
  {
8717
- className: `px-2 py-1.5 bg-white rounded border text-xs font-medium text-center transition-all ${idx === 0 ? "border-blue-300 bg-blue-50" : "border-gray-200"}`,
8873
+ className: `px-2 py-1.5 bg-white rounded border text-xs font-medium text-center transition-colors ${idx === 0 ? "border-blue-300 bg-blue-50" : "border-gray-200"}`,
8718
8874
  children: item.value
8719
8875
  },
8720
8876
  item.id
@@ -8722,7 +8878,7 @@ const BlockingQueueVisualizerComponent = ({ showControls = true, showCode = true
8722
8878
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 h-1.5 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
8723
8879
  "div",
8724
8880
  {
8725
- className: `h-full transition-all ${queue.length === capacity ? "bg-red-500" : "bg-cyan-500"}`,
8881
+ className: `h-full transition-colors ${queue.length === capacity ? "bg-red-500" : "bg-cyan-500"}`,
8726
8882
  style: { width: `${queue.length / capacity * 100}%` }
8727
8883
  }
8728
8884
  ) })
@@ -8733,7 +8889,7 @@ const BlockingQueueVisualizerComponent = ({ showControls = true, showCode = true
8733
8889
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: ["C1", "C2"].map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
8734
8890
  "div",
8735
8891
  {
8736
- className: `px-3 py-2 rounded-lg text-center text-sm font-medium transition-all ${activeThread === c ? "bg-blue-500 text-white scale-105" : blockedConsumers.includes(c) ? "bg-red-100 text-red-700 border-2 border-red-300" : "bg-blue-100 text-blue-700"}`,
8892
+ className: `px-3 py-2 rounded-lg text-center text-sm font-medium transition-colors ${activeThread === c ? "bg-blue-500 text-white" : blockedConsumers.includes(c) ? "bg-red-100 text-red-700 border-2 border-red-300" : "bg-blue-100 text-blue-700"}`,
8737
8893
  children: [
8738
8894
  c,
8739
8895
  blockedConsumers.includes(c) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-[10px]", children: "BLOCKED" })
@@ -9017,7 +9173,7 @@ const CopyOnWriteVisualizerComponent = ({
9017
9173
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center gap-1", children: arr.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsx(
9018
9174
  "div",
9019
9175
  {
9020
- className: `w-10 h-10 flex items-center justify-center rounded border-2 font-medium transition-all ${isNew && idx === highlightIndex ? "bg-green-500 border-green-600 text-white scale-110" : isNew ? "bg-green-100 border-green-300 text-green-700" : "bg-gray-100 border-gray-300 text-gray-700"}`,
9176
+ className: `w-10 h-10 flex items-center justify-center rounded border-2 font-medium transition-colors ${isNew && idx === highlightIndex ? "bg-green-500 border-green-600 text-white" : isNew ? "bg-green-100 border-green-300 text-green-700" : "bg-gray-100 border-gray-300 text-gray-700"}`,
9021
9177
  children: item
9022
9178
  },
9023
9179
  idx
@@ -9058,6 +9214,25 @@ const CopyOnWriteVisualizerComponent = ({
9058
9214
  ] }) }),
9059
9215
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
9060
9216
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 350, children: [
9217
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-lime-50 to-green-50 rounded-xl border-2 border-lime-200", children: [
9218
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-lime-800 mb-3 flex items-center gap-2", children: [
9219
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "📋" }),
9220
+ " Copy-on-Write Pattern"
9221
+ ] }),
9222
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 text-xs", children: [
9223
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-blue-100 p-2 rounded-lg border border-blue-300 text-center", children: [
9224
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-blue-700", children: "Read (get)" }),
9225
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-2xl text-blue-600", children: "O(1)" }),
9226
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-blue-500", children: "No lock, no copy" })
9227
+ ] }),
9228
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-orange-100 p-2 rounded-lg border border-orange-300 text-center", children: [
9229
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-orange-700", children: "Write (add/set)" }),
9230
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-2xl text-orange-600", children: "O(n)" }),
9231
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-orange-500", children: "Full array copy" })
9232
+ ] })
9233
+ ] }),
9234
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-[10px] text-gray-600 text-center", children: "Best for: Read-heavy, rarely-modified collections • Iterators never throw ConcurrentModificationException" })
9235
+ ] }),
9061
9236
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 p-4 bg-gray-50 rounded-lg", children: showCopy ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
9062
9237
  renderArray(oldArray, "Old Array (readers use this)"),
9063
9238
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-2xl text-gray-400", children: "→" }),
@@ -9335,7 +9510,7 @@ const ImmutableCollectionsVisualizerComponent = ({ showControls = true, showCode
9335
9510
  original.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsx(
9336
9511
  "div",
9337
9512
  {
9338
- className: `w-12 h-12 flex items-center justify-center rounded-lg border-2 font-bold transition-all ${error ? "bg-red-100 border-red-300 text-red-700 animate-pulse" : "bg-violet-100 border-violet-300 text-violet-700"}`,
9513
+ className: `w-12 h-12 flex items-center justify-center rounded-lg border-2 font-bold transition-colors ${error ? "bg-red-100 border-red-300 text-red-700 animate-pulse" : "bg-violet-100 border-violet-300 text-violet-700"}`,
9339
9514
  children: item
9340
9515
  },
9341
9516
  idx
@@ -9768,14 +9943,14 @@ const GCVisualizerComponent = ({
9768
9943
  /* @__PURE__ */ jsxRuntime.jsx(
9769
9944
  "div",
9770
9945
  {
9771
- className: "absolute inset-y-0 left-0 bg-opacity-30 bg-gray-500 transition-all duration-300",
9946
+ className: "absolute inset-y-0 left-0 bg-opacity-30 bg-gray-500 transition-[width] duration-300",
9772
9947
  style: { width: `${fillPercent}%` }
9773
9948
  }
9774
9949
  ),
9775
9950
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-wrap items-center gap-1 p-1", children: genObjects.map((obj) => /* @__PURE__ */ jsxRuntime.jsxs(
9776
9951
  "div",
9777
9952
  {
9778
- className: `px-1.5 py-0.5 text-[9px] font-medium rounded transition-all duration-200 ${getObjectStyle(obj)}`,
9953
+ className: `px-1.5 py-0.5 text-[9px] font-medium rounded transition-colors duration-200 ${getObjectStyle(obj)}`,
9779
9954
  title: `${obj.id} (age: ${obj.age}, ${obj.reachable ? "reachable" : "garbage"})`,
9780
9955
  children: [
9781
9956
  obj.id.replace("obj", ""),
@@ -9833,6 +10008,28 @@ const GCVisualizerComponent = ({
9833
10008
  ] }) }),
9834
10009
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex gap-4 ${showCode ? "flex-col lg:flex-row" : ""}`, children: [
9835
10010
  /* @__PURE__ */ jsxRuntime.jsxs(VisualizationArea, { minHeight: 400, className: showCode ? "flex-1" : "w-full", children: [
10011
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-4 bg-gradient-to-r from-purple-50 to-pink-50 rounded-xl border-2 border-purple-200", children: [
10012
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-bold text-purple-800 mb-3 flex items-center gap-2", children: [
10013
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg", children: "🧬" }),
10014
+ " Generational Hypothesis"
10015
+ ] }),
10016
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-sm bg-white rounded-lg p-3 border border-purple-200", children: [
10017
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center text-purple-700 font-bold mb-2", children: '"Most objects die young"' }),
10018
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500 text-center", children: "~95% of objects become garbage before first GC • Optimize for the common case" })
10019
+ ] }),
10020
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs", children: [
10021
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-blue-100 p-2 rounded-lg border border-blue-300 text-center", children: [
10022
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-blue-700", children: "Young Gen" }),
10023
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-blue-600", children: "Fast copy collection" }),
10024
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-blue-500", children: "Minor GC (frequent)" })
10025
+ ] }),
10026
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-amber-100 p-2 rounded-lg border border-amber-300 text-center", children: [
10027
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-bold text-amber-700", children: "Old Gen" }),
10028
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-amber-600", children: "Mark-sweep collection" }),
10029
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-amber-500", children: "Major GC (rare, slow)" })
10030
+ ] })
10031
+ ] })
10032
+ ] }),
9836
10033
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4", children: [
9837
10034
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-gray-700 mb-2", children: "JVM Heap Memory" }),
9838
10035
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 p-3 bg-blue-50 rounded-lg", children: [