New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

ink-virtual-list

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ink-virtual-list

A virtualized list component for Ink terminal applications

latest
Source
npmnpm
Version
0.2.3
Version published
Weekly downloads
47
-62.7%
Maintainers
1
Weekly downloads
 
Created
Source

ink-virtual-list

A virtualized list component for Ink terminal applications. Only renders visible items for optimal performance with large datasets.

Features

  • Virtualized rendering - Only renders items visible in the viewport
  • Automatic scrolling - Keeps selected item in view as you navigate
  • Terminal-aware - Responds to terminal resize events
  • Flexible height - Fixed height or auto-fill available terminal space
  • Customizable indicators - Override default overflow indicators ("▲ N more")
  • TypeScript first - Full type safety with generics
  • Imperative API - Programmatic scrolling via ref

Installation

# npm
npm install ink-virtual-list

# jsr
npx jsr add @archcorsair/ink-virtual-list

# bun
bun add ink-virtual-list

Usage

Basic Example

import { VirtualList } from 'ink-virtual-list';
import { Text } from 'ink';
import { useState } from 'react';

function App() {
  const [selectedIndex, setSelectedIndex] = useState(0);
  const items = Array.from({ length: 1000 }, (_, i) => `Item ${i + 1}`);

  return (
    <VirtualList
      items={items}
      selectedIndex={selectedIndex}
      height={10}
      renderItem={({ item, isSelected }) => (
        <Text color={isSelected ? 'cyan' : 'white'}>
          {isSelected ? '> ' : '  '}
          {item}
        </Text>
      )}
    />
  );
}

Auto-fill Terminal Height

<VirtualList
  items={items}
  height="auto"
  reservedLines={5}  // Reserve space for header/footer
  renderItem={({ item }) => <Text>{item}</Text>}
/>

Custom Overflow Indicators

<VirtualList
  items={items}
  renderOverflowTop={(count) => <Text dimColor>↑ {count} hidden</Text>}
  renderOverflowBottom={(count) => <Text dimColor>↓ {count} hidden</Text>}
  renderItem={({ item }) => <Text>{item}</Text>}
/>

Imperative Scrolling

import { useRef } from 'react';
import type { VirtualListRef } from 'ink-virtual-list';

function App() {
  const listRef = useRef<VirtualListRef>(null);

  const scrollToTop = () => {
    listRef.current?.scrollToIndex(0, 'top');
  };

  return (
    <VirtualList
      ref={listRef}
      items={items}
      renderItem={({ item }) => <Text>{item}</Text>}
    />
  );
}

API

Props

Required

  • items: T[] - Array of items to render
  • renderItem: (props: RenderItemProps<T>) => ReactNode - Render function for each visible item
    • Receives: { item: T, index: number, isSelected: boolean }

Optional

  • selectedIndex?: number - Index of currently selected item (default: 0)
  • keyExtractor?: (item: T, index: number) => string - Custom key extractor for list items
  • height?: number | "auto" - Fixed height in lines or "auto" to fill terminal (default: 10)
  • reservedLines?: number - Lines to reserve when using height="auto" (default: 0)
  • itemHeight?: number - Height of each item in lines (default: 1)
  • showOverflowIndicators?: boolean - Show "N more" indicators (default: true)
  • renderOverflowTop?: (count: number) => ReactNode - Custom top overflow indicator
  • renderOverflowBottom?: (count: number) => ReactNode - Custom bottom overflow indicator
  • renderScrollBar?: (viewport: ViewportState) => ReactNode - Custom scrollbar renderer
  • onViewportChange?: (viewport: ViewportState) => void - Callback when viewport changes

Ref Methods

interface VirtualListRef {
  scrollToIndex: (index: number, alignment?: 'auto' | 'top' | 'center' | 'bottom') => void;
  getViewport: () => ViewportState;
  remeasure: () => void;
}
  • scrollToIndex(index, alignment?) - Scroll to bring an index into view
    • 'auto' (default) - Only scroll if needed
    • 'top' - Align item to top of viewport
    • 'center' - Center item in viewport
    • 'bottom' - Align item to bottom of viewport
  • getViewport() - Get current viewport state ({ offset, visibleCount, totalCount })
  • remeasure() - Force recalculation of viewport dimensions

Types

interface RenderItemProps<T> {
  item: T;
  index: number;
  isSelected: boolean;
}

interface ViewportState {
  offset: number;       // Items scrolled past
  visibleCount: number; // Items currently visible
  totalCount: number;   // Total items
}

Advanced Example

import { VirtualList } from 'ink-virtual-list';
import { Box, Text } from 'ink';
import { useRef, useState } from 'react';
import type { VirtualListRef } from 'ink-virtual-list';

interface Todo {
  id: string;
  title: string;
  completed: boolean;
}

function TodoApp() {
  const [todos] = useState<Todo[]>([
    { id: '1', title: 'Learn Ink', completed: true },
    { id: '2', title: 'Build CLI', completed: false },
    // ... 1000s more
  ]);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const listRef = useRef<VirtualListRef>(null);

  return (
    <Box flexDirection="column">
      <Text bold>My Todos ({todos.length})</Text>

      <VirtualList
        ref={listRef}
        items={todos}
        selectedIndex={selectedIndex}
        height="auto"
        reservedLines={3}
        keyExtractor={(todo) => todo.id}
        renderItem={({ item, isSelected }) => (
          <Box>
            <Text color={isSelected ? 'cyan' : 'white'}>
              {isSelected ? '❯ ' : '  '}
              {item.completed ? '✓' : '○'} {item.title}
            </Text>
          </Box>
        )}
      />

      <Text dimColor>
        {selectedIndex + 1} / {todos.length}
      </Text>
    </Box>
  );
}

License

MIT

Keywords

ink

FAQs

Package last updated on 02 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts