tri-cli 0.0.52 → 0.0.54

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.
Files changed (3) hide show
  1. package/dist/Treemap.js +56 -20
  2. package/dist/cli.js +166 -26
  3. package/package.json +1 -1
package/dist/Treemap.js CHANGED
@@ -20,6 +20,7 @@ const oneHunter = {
20
20
 
21
21
  // Expanded color palette for directories
22
22
  const dirColors = [oneHunter.blue, oneHunter.cyan, oneHunter.green, oneHunter.yellow, oneHunter.orange, oneHunter.red, oneHunter.purple, oneHunter.magenta, '#4a9eff', '#7ec699', '#e8b339', '#ff7eb6'];
23
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
23
24
 
24
25
  // Function to format bytes to human readable
25
26
  const formatBytes = bytes => {
@@ -30,6 +31,14 @@ const formatBytes = bytes => {
30
31
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
31
32
  };
32
33
 
34
+ // Function to format counts
35
+ const formatCount = count => {
36
+ if (count === 0) return '0';
37
+ if (count < 1000) return count.toString();
38
+ if (count < 1000000) return (count / 1000).toFixed(1) + 'K';
39
+ return (count / 1000000).toFixed(1) + 'M';
40
+ };
41
+
33
42
  // Get color based on file extension
34
43
  const getFileColor = filename => {
35
44
  var _filename$match;
@@ -99,8 +108,19 @@ const assignGroupColors = root => {
99
108
  };
100
109
  export const TreeMapView = ({
101
110
  selectedNode,
102
- stdout
111
+ stdout,
112
+ mode = 'size',
113
+ loadingPaths = new Set(),
114
+ calculatedCounts = new Map(),
115
+ calculatedSizes = new Map()
103
116
  }) => {
117
+ const [spinnerFrame, setSpinnerFrame] = React.useState(0);
118
+
119
+ // Spinner animation loop
120
+ React.useEffect(() => {
121
+ const interval = setInterval(() => setSpinnerFrame(f => (f + 1) % SPINNER_FRAMES.length), 80);
122
+ return () => clearInterval(interval);
123
+ }, []);
104
124
  if (!selectedNode || !selectedNode.data) {
105
125
  return /*#__PURE__*/React.createElement(Box, {
106
126
  flexDirection: "column"
@@ -110,16 +130,20 @@ export const TreeMapView = ({
110
130
  }, "Error: Invalid node selected"), /*#__PURE__*/React.createElement(Text, {
111
131
  dimColor: true,
112
132
  color: oneHunter.textAlt
113
- }, "Press 't' to go back to tree view"));
133
+ }, "Press any key to go back to tree view"));
114
134
  }
115
135
  const width = Math.min((stdout === null || stdout === void 0 ? void 0 : stdout.columns) || 80, 120) - 4;
116
136
  const height = Math.min((stdout === null || stdout === void 0 ? void 0 : stdout.rows) || 24, 40) - 8;
117
137
 
138
+ // Choose formatter based on mode
139
+ const formatValue = mode === 'count' ? formatCount : formatBytes;
140
+ const modeLabel = mode === 'count' ? 'Count' : 'Size';
141
+
118
142
  // If it's a file, show just that file as a big rectangle
119
143
  if (selectedNode.data.isFile) {
120
144
  const color = getFileColor(selectedNode.data.name);
121
145
  const name = selectedNode.data.name;
122
- const sizeStr = selectedNode.data.size ? formatBytes(selectedNode.data.size) : '';
146
+ const valueStr = mode === 'count' ? '1 file' : selectedNode.data.size ? formatBytes(selectedNode.data.size) : '';
123
147
  const grid = Array(height).fill(null).map(() => Array(width).fill(null).map(() => ({
124
148
  char: ' ',
125
149
  color
@@ -149,12 +173,12 @@ export const TreeMapView = ({
149
173
  };
150
174
  }
151
175
  }
152
- if (sizeStr && midY + 2 < height - 2) {
153
- const sizeX = Math.floor((width - sizeStr.length) / 2);
154
- for (let i = 0; i < sizeStr.length && sizeX + i < width - 2; i++) {
176
+ if (valueStr && midY + 2 < height - 2) {
177
+ const sizeX = Math.floor((width - valueStr.length) / 2);
178
+ for (let i = 0; i < valueStr.length && sizeX + i < width - 2; i++) {
155
179
  if (sizeX + i > 0) {
156
180
  grid[midY + 2][sizeX + i] = {
157
- char: sizeStr[i],
181
+ char: valueStr[i],
158
182
  color
159
183
  };
160
184
  }
@@ -194,10 +218,10 @@ export const TreeMapView = ({
194
218
  }, /*#__PURE__*/React.createElement(Text, {
195
219
  bold: true,
196
220
  color: oneHunter.cyan
197
- }, "TreeMap View: ", name, " (File)"), /*#__PURE__*/React.createElement(Text, {
221
+ }, "TreeMap View (", modeLabel, "): ", name, " (File)"), /*#__PURE__*/React.createElement(Text, {
198
222
  dimColor: true,
199
223
  color: oneHunter.textAlt
200
- }, "Press 't' to toggle back to tree view | Ctrl+C: Exit"), /*#__PURE__*/React.createElement(Box, {
224
+ }, "Press any key to go back to tree view | Ctrl+C: Exit"), /*#__PURE__*/React.createElement(Box, {
201
225
  borderStyle: "single",
202
226
  borderColor: oneHunter.textAlt,
203
227
  flexDirection: "column",
@@ -206,7 +230,7 @@ export const TreeMapView = ({
206
230
  dimColor: true,
207
231
  color: oneHunter.textAlt,
208
232
  marginTop: 1
209
- }, "File: ", name, " | Size: ", sizeStr || 'Unknown'));
233
+ }, "File: ", name, " | ", modeLabel, ": ", valueStr || 'Unknown'));
210
234
  }
211
235
 
212
236
  // It's a directory - show treemap of its children
@@ -216,10 +240,10 @@ export const TreeMapView = ({
216
240
  }, /*#__PURE__*/React.createElement(Text, {
217
241
  bold: true,
218
242
  color: oneHunter.cyan
219
- }, "TreeMap View: ", selectedNode.data.name, " (Empty Directory)"), /*#__PURE__*/React.createElement(Text, {
243
+ }, "TreeMap View (", modeLabel, "): ", selectedNode.data.name, " (Empty Directory)"), /*#__PURE__*/React.createElement(Text, {
220
244
  dimColor: true,
221
245
  color: oneHunter.textAlt
222
- }, "Press 't' to toggle back to tree view | Ctrl+C: Exit"), /*#__PURE__*/React.createElement(Box, {
246
+ }, "Press any key to go back to tree view | Ctrl+C: Exit"), /*#__PURE__*/React.createElement(Box, {
223
247
  borderStyle: "single",
224
248
  borderColor: oneHunter.textAlt,
225
249
  marginTop: 1,
@@ -248,12 +272,18 @@ export const TreeMapView = ({
248
272
  const x1 = Math.ceil(node.x1);
249
273
  const y1 = Math.ceil(node.y1);
250
274
  const isFile = node.data.isFile;
275
+ const isNodeLoading = loadingPaths.has(node.data.path);
251
276
  const boxWidth = x1 - x0;
252
277
  const boxHeight = y1 - y0;
253
278
  if (boxWidth < 1 || boxHeight < 1) return;
254
279
 
255
- // Color based on type
256
- const color = isFile ? getFileColor(node.data.name) : node.groupColor || oneHunter.blue;
280
+ // Color based on type (dimmed if loading)
281
+ let color = isFile ? getFileColor(node.data.name) : node.groupColor || oneHunter.blue;
282
+
283
+ // Dim the color if loading
284
+ if (isNodeLoading) {
285
+ color = oneHunter.textAlt;
286
+ }
257
287
 
258
288
  // Draw border
259
289
  for (let y = y0; y < y1 && y < height; y++) {
@@ -277,14 +307,14 @@ export const TreeMapView = ({
277
307
 
278
308
  // Draw label if there's room
279
309
  const name = node.data.name;
280
- const sizeStr = node.value ? ` ${formatBytes(node.value)}` : '';
310
+ const valueStr = isNodeLoading ? ` ${SPINNER_FRAMES[spinnerFrame]}` : node.value ? ` ${formatValue(node.value)}${mode === 'count' ? ' files' : ''}` : '';
281
311
  if (boxWidth >= 8 && boxHeight >= 2) {
282
312
  const labelY = y0 + 1;
283
313
  const labelX = x0 + 1;
284
314
  const maxLength = boxWidth - 2;
285
315
 
286
- // Combine name and size
287
- let label = name + sizeStr;
316
+ // Combine name and value
317
+ let label = name + valueStr;
288
318
  if (label.length > maxLength) {
289
319
  // Try just name
290
320
  if (name.length <= maxLength) {
@@ -374,15 +404,21 @@ export const TreeMapView = ({
374
404
  key: y
375
405
  }, segments);
376
406
  });
407
+ const totalLabel = mode === 'count' ? `${formatCount(root.value || 0)} files` : formatBytes(root.value || 0);
408
+ const isLoading = loadingPaths.size > 0;
377
409
  return /*#__PURE__*/React.createElement(Box, {
378
410
  flexDirection: "column"
379
411
  }, /*#__PURE__*/React.createElement(Text, {
380
412
  bold: true,
381
413
  color: oneHunter.cyan
382
- }, "TreeMap View: ", selectedNode.data.name), /*#__PURE__*/React.createElement(Text, {
414
+ }, "TreeMap View (", modeLabel, "): ", selectedNode.data.name), /*#__PURE__*/React.createElement(Box, {
415
+ justifyContent: "space-between"
416
+ }, /*#__PURE__*/React.createElement(Text, {
383
417
  dimColor: true,
384
418
  color: oneHunter.textAlt
385
- }, "Press 't' to toggle back to tree view | \u2191/\u2193: Navigate in tree | Ctrl+C: Exit"), /*#__PURE__*/React.createElement(Box, {
419
+ }, "Press any key to go back to tree view | \u2191/\u2193: Navigate in tree | Ctrl+C: Exit"), isLoading && /*#__PURE__*/React.createElement(Text, {
420
+ color: oneHunter.yellow
421
+ }, ' ', SPINNER_FRAMES[spinnerFrame], " Loading ", loadingPaths.size, "...")), /*#__PURE__*/React.createElement(Box, {
386
422
  borderStyle: "single",
387
423
  borderColor: oneHunter.textAlt,
388
424
  flexDirection: "column",
@@ -391,5 +427,5 @@ export const TreeMapView = ({
391
427
  dimColor: true,
392
428
  color: oneHunter.textAlt,
393
429
  marginTop: 1
394
- }, "Showing ", firstLevelNodes.length, " items | Total:", ' ', formatBytes(root.value || 0)));
430
+ }, "Showing ", firstLevelNodes.length, " items | Total: ", totalLabel));
395
431
  };
package/dist/cli.js CHANGED
@@ -30,6 +30,12 @@ const formatBytes = bytes => {
30
30
  const i = Math.floor(Math.log(bytes) / Math.log(k));
31
31
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
32
32
  };
33
+ const formatCount = count => {
34
+ if (count === 0) return '0';
35
+ if (count < 1000) return count.toString();
36
+ if (count < 1000000) return (count / 1000).toFixed(1) + 'K';
37
+ return (count / 1000000).toFixed(1) + 'M';
38
+ };
33
39
  const formatDate = timestamp => {
34
40
  const date = new Date(timestamp);
35
41
  const now = new Date();
@@ -66,6 +72,24 @@ const getDirSizeAsync = async dirPath => {
66
72
  return 0;
67
73
  }
68
74
  };
75
+
76
+ // Fast file counting using shell command
77
+ const countFilesAsync = async dirPath => {
78
+ try {
79
+ const stats = fs.statSync(dirPath);
80
+ if (!stats.isDirectory()) return 1;
81
+
82
+ // Use find command for fast counting, excluding hidden files
83
+ const escapedPath = dirPath.replace(/"/g, '\\"');
84
+ const {
85
+ stdout
86
+ } = await execAsync(`find "${escapedPath}" -type f ! -path '*/.*' 2>/dev/null | wc -l`);
87
+ const count = parseInt(stdout.trim(), 10);
88
+ return isNaN(count) ? 0 : count;
89
+ } catch {
90
+ return 0;
91
+ }
92
+ };
69
93
  const readDirTree = (dirPath, noSize = true, currentLevel = 0, maxLevel = Infinity) => {
70
94
  try {
71
95
  const stats = fs.statSync(dirPath);
@@ -182,6 +206,7 @@ const TreeRow = /*#__PURE__*/React.memo(({
182
206
  shortcutInput,
183
207
  noSize,
184
208
  calculatedSizes,
209
+ calculatedCounts,
185
210
  loadingPaths,
186
211
  spinnerFrame,
187
212
  lastModifiedDates
@@ -199,6 +224,7 @@ const TreeRow = /*#__PURE__*/React.memo(({
199
224
  } else {
200
225
  displaySize = node.data.size;
201
226
  }
227
+ const fileCount = calculatedCounts === null || calculatedCounts === void 0 ? void 0 : calculatedCounts.get(node.data.path);
202
228
  const lastModified = lastModifiedDates.get(node.data.path);
203
229
  const treeLines = getTreeLines(node);
204
230
 
@@ -235,7 +261,11 @@ const TreeRow = /*#__PURE__*/React.memo(({
235
261
  backgroundColor: isSelected ? oneHunter.green : undefined
236
262
  }, node.data.name, !node.data.isFile && !isRoot ? '/' : ''), hasChildren && !isCollapsed && /*#__PURE__*/React.createElement(Text, {
237
263
  color: oneHunter.textAlt
238
- }, " (", node.children.length, ")"), isLoading ? /*#__PURE__*/React.createElement(Text, {
264
+ }, " (", node.children.length, ")"), fileCount !== undefined && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
265
+ color: oneHunter.purple
266
+ }, " [", formatCount(fileCount), " files]"), isLoading && /*#__PURE__*/React.createElement(Text, {
267
+ color: oneHunter.yellow
268
+ }, " ", SPINNER_FRAMES[spinnerFrame])), isLoading ? /*#__PURE__*/React.createElement(Text, {
239
269
  color: oneHunter.yellow
240
270
  }, " ", SPINNER_FRAMES[spinnerFrame]) : displaySize > 0 ? /*#__PURE__*/React.createElement(Text, {
241
271
  color: oneHunter.cyan
@@ -253,8 +283,10 @@ const TreeVisualization = ({
253
283
  const [collapsed, setCollapsed] = useState(new Set());
254
284
  const [shortcutInput, setShortcutInput] = useState('');
255
285
  const [showTreeMap, setShowTreeMap] = useState(false);
286
+ const [treeMapMode, setTreeMapMode] = useState('size'); // 'size' or 'count'
256
287
  const [initialized, setInitialized] = useState(false);
257
288
  const [calculatedSizes, setCalculatedSizes] = useState(new Map());
289
+ const [calculatedCounts, setCalculatedCounts] = useState(new Map());
258
290
  const [loadingPaths, setLoadingPaths] = useState(new Set());
259
291
  const [spinnerFrame, setSpinnerFrame] = useState(0);
260
292
  const [rootTree, setRootTree] = useState(() => hierarchy(readDirTree(dirPath, noSize, 0, maxLevel)));
@@ -385,6 +417,50 @@ const TreeVisualization = ({
385
417
  await new Promise(r => setTimeout(r, 0));
386
418
  }
387
419
  };
420
+ const countFilesInTreeAsync = async node => {
421
+ // Collect node and all its descendants
422
+ const nodesToCount = [];
423
+ const collectNodes = n => {
424
+ // Skip if already counted
425
+ if (calculatedCounts.has(n.data.path)) {
426
+ // Still recurse to children in case they need counting
427
+ if (n.children) {
428
+ n.children.forEach(collectNodes);
429
+ }
430
+ return;
431
+ }
432
+ nodesToCount.push(n);
433
+ if (n.children) {
434
+ n.children.forEach(collectNodes);
435
+ }
436
+ };
437
+ collectNodes(node);
438
+ if (nodesToCount.length === 0) return; // Nothing to count
439
+
440
+ // Sort nodes by depth (shallowest first) for top-down display
441
+ nodesToCount.sort((a, b) => a.depth - b.depth);
442
+
443
+ // Mark all nodes as loading
444
+ const loadingSet = new Set(nodesToCount.map(n => n.data.path));
445
+ setLoadingPaths(loadingSet);
446
+ const newMap = new Map(calculatedCounts);
447
+
448
+ // Process all nodes in parallel, but update UI as each completes
449
+ const promises = nodesToCount.map(async targetNode => {
450
+ const count = await countFilesAsync(targetNode.data.path);
451
+
452
+ // Update immediately when this specific node completes
453
+ newMap.set(targetNode.data.path, count);
454
+ loadingSet.delete(targetNode.data.path);
455
+
456
+ // Trigger UI update
457
+ setCalculatedCounts(new Map(newMap));
458
+ setLoadingPaths(new Set(loadingSet));
459
+ });
460
+
461
+ // Wait for all counts to complete
462
+ await Promise.all(promises);
463
+ };
388
464
  const getLastModifiedAsync = async node => {
389
465
  // Collect node and all its descendants
390
466
  const nodesToProcess = [];
@@ -460,8 +536,8 @@ const TreeVisualization = ({
460
536
  return;
461
537
  }
462
538
  if (input === 'q') process.exit(0);
463
- if (input === 'C') {
464
- // Toggle collapse/expand all children of the selected node's PARENT
539
+ if (input === 'C' && !key.shift) {
540
+ // Toggle collapse/expand all children of the selected node's PARENT (lowercase handling moved)
465
541
  const selectedNode = visibleNodes[selectedIndex];
466
542
  if (!selectedNode || !selectedNode.parent) return;
467
543
  const parentNode = selectedNode.parent;
@@ -492,6 +568,40 @@ const TreeVisualization = ({
492
568
  });
493
569
  return;
494
570
  }
571
+ if (key.shift && input === 'C') {
572
+ // Shift+C: Show count treemap
573
+ const node = visibleNodes[selectedIndex];
574
+ if (!node) return;
575
+
576
+ // Collect all nodes that need counting
577
+ const nodesToCount = [];
578
+ const collectNodes = n => {
579
+ if (calculatedCounts.has(n.data.path)) {
580
+ if (n.children) {
581
+ n.children.forEach(collectNodes);
582
+ }
583
+ return;
584
+ }
585
+ nodesToCount.push(n);
586
+ if (n.children) {
587
+ n.children.forEach(collectNodes);
588
+ }
589
+ };
590
+ collectNodes(node);
591
+
592
+ // Mark nodes as loading before starting
593
+ if (nodesToCount.length > 0) {
594
+ const pathsToLoad = nodesToCount.map(n => n.data.path);
595
+ setLoadingPaths(prev => new Set([...prev, ...pathsToLoad]));
596
+ }
597
+
598
+ // Start calculating counts in the background
599
+ countFilesInTreeAsync(node);
600
+ // Show count treemap immediately
601
+ setTreeMapMode('count');
602
+ setShowTreeMap(true);
603
+ return;
604
+ }
495
605
  if (input === 'O') {
496
606
  // Toggle collapse/expand ALL nodes in the entire tree
497
607
  const allNodesWithChildren = [];
@@ -524,7 +634,8 @@ const TreeVisualization = ({
524
634
  if (!node) return;
525
635
  // Always start calculating sizes in the background (calculateSizeAsync skips already-calculated nodes)
526
636
  calculateSizeAsync(node);
527
- // Show treemap immediately
637
+ // Show size treemap immediately
638
+ setTreeMapMode('size');
528
639
  setShowTreeMap(true);
529
640
  return;
530
641
  }
@@ -533,6 +644,11 @@ const TreeVisualization = ({
533
644
  if (node) await calculateSizeAsync(node);
534
645
  return;
535
646
  }
647
+ if (input === 'c') {
648
+ const node = visibleNodes[selectedIndex];
649
+ if (node) await countFilesInTreeAsync(node);
650
+ return;
651
+ }
536
652
  if (input === 'l') {
537
653
  const node = visibleNodes[selectedIndex];
538
654
  if (node) await getLastModifiedAsync(node);
@@ -597,31 +713,52 @@ const TreeVisualization = ({
597
713
 
598
714
  // Set value on the DATA object
599
715
  const data = hierarchyNode.data;
600
- if (data.isFile) {
601
- // Files: use calculatedSize or read from disk
602
- const calcSize = calculatedSizes.get(data.path);
603
- if (calcSize !== undefined) {
604
- data.value = calcSize;
605
- } else {
606
- try {
607
- data.value = fs.statSync(data.path).size;
608
- } catch {
716
+ if (treeMapMode === 'count') {
717
+ // COUNT MODE: Use file counts
718
+ if (data.isFile) {
719
+ // Files always count as 1
720
+ data.value = 1;
721
+ } else if (data.children === undefined || !hierarchyNode.children || hierarchyNode.children.length === 0) {
722
+ // Directory with no children loaded OR empty directory
723
+ // Use calculatedCount if available
724
+ const calcCount = calculatedCounts.get(data.path);
725
+ if (calcCount !== undefined) {
726
+ data.value = calcCount;
727
+ } else {
609
728
  data.value = 0;
610
729
  }
611
- }
612
- } else if (data.children === undefined || !hierarchyNode.children || hierarchyNode.children.length === 0) {
613
- // Directory with no children loaded OR empty directory
614
- // Use calculatedSize if available
615
- const calcSize = calculatedSizes.get(data.path);
616
- if (calcSize !== undefined) {
617
- data.value = calcSize;
618
730
  } else {
619
- // For unloaded directories without calculated size, will show as 0
620
- data.value = data.size || 0;
731
+ // Directory with loaded children - let d3's .sum() aggregate from children
732
+ data.value = undefined;
621
733
  }
622
734
  } else {
623
- // Directory with loaded children - let d3's .sum() aggregate from children
624
- data.value = undefined;
735
+ // SIZE MODE: Use file sizes
736
+ if (data.isFile) {
737
+ // Files: use calculatedSize or read from disk
738
+ const calcSize = calculatedSizes.get(data.path);
739
+ if (calcSize !== undefined) {
740
+ data.value = calcSize;
741
+ } else {
742
+ try {
743
+ data.value = fs.statSync(data.path).size;
744
+ } catch {
745
+ data.value = 0;
746
+ }
747
+ }
748
+ } else if (data.children === undefined || !hierarchyNode.children || hierarchyNode.children.length === 0) {
749
+ // Directory with no children loaded OR empty directory
750
+ // Use calculatedSize if available
751
+ const calcSize = calculatedSizes.get(data.path);
752
+ if (calcSize !== undefined) {
753
+ data.value = calcSize;
754
+ } else {
755
+ // For unloaded directories without calculated size, will show as 0
756
+ data.value = data.size || 0;
757
+ }
758
+ } else {
759
+ // Directory with loaded children - let d3's .sum() aggregate from children
760
+ data.value = undefined;
761
+ }
625
762
  }
626
763
  };
627
764
  populateValues(node);
@@ -629,7 +766,9 @@ const TreeVisualization = ({
629
766
  selectedNode: node,
630
767
  stdout: stdout,
631
768
  calculatedSizes: calculatedSizes,
632
- loadingPaths: loadingPaths
769
+ calculatedCounts: calculatedCounts,
770
+ loadingPaths: loadingPaths,
771
+ mode: treeMapMode
633
772
  });
634
773
  }
635
774
  const start = Math.max(0, selectedIndex - Math.floor(viewportHeight / 2));
@@ -643,7 +782,7 @@ const TreeVisualization = ({
643
782
  }, /*#__PURE__*/React.createElement(Text, {
644
783
  color: oneHunter.textAlt,
645
784
  dimColor: true
646
- }, "\u2191/\u2193: Navigate | Enter: Expand/Traverse | d: Size | l: Date | m: Map | q: Quit"), loadingPaths.size > 0 && /*#__PURE__*/React.createElement(Text, {
785
+ }, "\u2191/\u2193: Navigate | Enter: Expand/Traverse | c: Count | d: Size | l: Date | m: Map | Shift+C: CountMap | q: Quit"), loadingPaths.size > 0 && /*#__PURE__*/React.createElement(Text, {
647
786
  color: oneHunter.yellow
648
787
  }, ' ', SPINNER_FRAMES[spinnerFrame], " Loading ", loadingPaths.size, "...")), viewportNodes.map((node, i) => /*#__PURE__*/React.createElement(TreeRow, {
649
788
  key: start + i,
@@ -653,6 +792,7 @@ const TreeVisualization = ({
653
792
  shortcutInput: shortcutInput,
654
793
  noSize: noSize,
655
794
  calculatedSizes: calculatedSizes,
795
+ calculatedCounts: calculatedCounts,
656
796
  loadingPaths: loadingPaths,
657
797
  spinnerFrame: spinnerFrame,
658
798
  lastModifiedDates: lastModifiedDates
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tri-cli",
3
- "version": "0.0.52",
3
+ "version": "0.0.54",
4
4
  "description": "Interactive CLI directory tree visualizer with treemap view",
5
5
  "author": "Jared Wilber",
6
6
  "license": "MIT",