npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vello/react-table

v1.0.4

Published

A high-performance, highly interactive, and easily customizable data table library for React

Downloads

393

Readme

Vello React Table - Official Documentation

⚠️ DEPRECATION & MIGRATION NOTICE ⚠️
The @Vellogrid/react package has been officially deprecated and rebranded to Vello. Please migrate your projects to use @vello/react-table and @vello/core to receive the latest updates, premium features, and security patches.

Welcome to the official Vello documentation! Vello is a high-performance, modern, highly interactive, and easily customizable data table library built exclusively for the React.js and Next.js ecosystem (supports both App Router & Pages Router).


🚀 Installation Guide

1. Standard Installation via NPM Registry

Install the core and react packages into your React project using your preferred package manager:

# Using npm
npm install @vello/core @vello/react

# Using pnpm
pnpm add @vello/core @vello/react

# Using yarn
yarn add @vello/core @vello/react

💡 Quick Start

Here is a basic example of implementing VelloGrid in your React application. If you are using Next.js (App Router), make sure to add the "use client"; directive at the top of your file.

"use client";

import React, { useState } from 'react';
import { VelloGrid, ColumnConfig } from '@vello/react-table';

// 1. Define your data type
interface Product {
    id: number;
    name: string;
    category: string;
    price: number;
}

// 2. Prepare initial data
const initialProducts: Product[] = [
    { id: 1, name: 'MacBook Pro M3', category: 'Laptop', price: 2500 },
    { id: 2, name: 'iPhone 15 Pro', category: 'Smartphone', price: 1200 },
    { id: 3, name: 'iPad Air', category: 'Tablet', price: 600 },
];

export default function App() {
    const [products, setProducts] = useState<Product[]>(initialProducts);

    // 3. Configure columns
    const columns: ColumnConfig<Product>[] = [
        { 
            id: 'id', 
            header: 'ID', 
            width: 80, 
            pinned: 'left',
            sortable: true
        },
        { 
            id: 'name', 
            header: 'Product Name', 
            sortable: true, 
            filterable: true, 
            copyable: true 
        },
        { 
            id: 'category', 
            header: 'Category', 
            sortable: true, 
            filterable: true 
        },
        { 
            id: 'price', 
            header: 'Price', 
            align: 'right',
            sortable: true,
            render: (row) => `$${row.price.toLocaleString()}` 
        }
    ];

    return (
        <div style={{ padding: '24px', maxWidth: '1200px', margin: '0 auto' }}>
            <VelloGrid 
                tableName="MAIN PRODUCT TABLE"
                data={products} 
                columns={columns}
            />
        </div>
    );
}

🌟 Comprehensive Feature Guide & Code Examples

VelloGrid is packed with enterprise-grade premium features ready to be integrated. Below is an in-depth guide for each feature along with code examples.

1. Virtualization & Performance

VelloGrid uses advanced DOM Windowing techniques where only the rows visible on the screen are physically rendered into the DOM.

  • Requirement: The enableVirtualization property is set to true and the maxHeight property must be defined (e.g., "500px").
<VelloGrid
    tableName="MASSIVE DATA MANAGEMENT"
    data={massiveProductsList}
    columns={columns}
    enableVirtualization={true}
    maxHeight="500px" // Maximum height of the scroll area
/>

2. Data Editing Module (Inline & Cell Editing)

VelloGrid provides two highly flexible alternatives for direct inline editing within cells:

A. Excel-Style Cell Editing (editMode="cell")

  • How it works: The user double-clicks on a cell that has the editable: true configuration. The cell instantly turns into an active input box.
  • Keyboard Shortcuts:
    • Enter: Saves changes and closes the editor.
    • Escape: Cancels changes.
    • Tab: Saves current cell changes and smartly jumps to the next editable cell to the right.
    • Blur (Auto-Save): Automatically saves changes when the cursor leaves or focus shifts.

B. Row-level Inline Editing (editMode="row")

  • How it works: Provides a dedicated edit control column that is stickily pinned to the left side.
  • Actions:
    • Pencil ✏️ Button: Turns all editable cells in the row into input mode simultaneously. The actively edited row receives a premium purple highlight .vello-row-editing-active.
    • Save ✔️ Button: Performs batch validation. If successful, triggers a batch update callback. Input boxes that fail validation glow red (invalid border glow) and display a red warning tooltip balloon above them.
    • Cancel ❌ Button: Cancels all row edits in a single click.
<VelloGrid
    tableName="PRODUCT SALES"
    data={products}
    columns={[
        { id: 'id', header: 'ID', width: 60 },
        { id: 'name', header: 'Item Name', editable: true, dataType: 'string' },
        { 
            id: 'category', 
            header: 'Category', 
            editable: true, 
            dataType: 'string',
            editOptions: {
                type: 'select',
                options: ['Laptop', 'Smartphone', 'Tablet', 'Accessories']
            }
        },
        { id: 'price', header: 'Price ($)', editable: true, dataType: 'number' }
    ]}

    editMode="row" // Options: 'cell' | 'row'
    
    // Callback triggered when the Save ✔️ button is clicked (Row-level)
    onRowEditSubmit={(rowId, newRowData, originalRow) => {
        setProducts(prev => prev.map(p => 
            String(p.id) === String(rowId) ? { ...p, ...newRowData } : p
        ));
    }}
    
    // Callback triggered when a Cell is done editing (Excel-style)
    onCellEditSubmit={(rowId, columnId, newValue, originalRow) => {
        setProducts(prev => prev.map(p => 
            String(p.id) === String(rowId) ? { ...p, [columnId]: newValue } : p
        ));
    }}

    // Real-time input validation
    onCellEditValidate={(columnId, value, row) => {
        if (columnId === 'price') {
            if (value === null || value === undefined || value === '') {
                return 'Price cannot be empty';
            }
            if (value < 0) {
                return 'Price cannot be less than 0';
            }
        }
        if (columnId === 'name' && (!value || String(value).trim() === '')) {
            return 'Product name cannot be empty';
        }
        return true; // Return true if valid, string error if invalid
    }}
/>

3. Premium Action Column (Column Actions)

VelloGrid provides an interactive action column dynamically pinned to the left or right side for operations such as View Details, Edit, Delete, and Custom Actions.

  • Beautiful Design: Buttons are elegantly designed with a lifting hover effect (shadow lift & micro-scale) and harmoniously change colors following hover or selection on the table row.
<VelloGrid
    data={products}
    columns={columns}
    actionConfig={{
        headerLabel: "Actions",         // Action column title
        width: 120,                     // Column width (px)
        pinned: "left",                 // Pinning position: "left" | "right" | "none"
        onView: (row) => alert(`Details: ${row.name}`),
        onEdit: (row) => alert(`Edit: ${row.name}`),
        onDelete: (row) => {
            if (confirm(`Delete "${row.name}"?`)) {
                // Delete logic
            }
        },
        customActions: [
            {
                key: 'star',
                label: 'Favorite',
                icon: <span style={{ fontSize: '14px' }}>⭐</span>,
                onClick: (row) => alert(`${row.name} added to favorites!`),
                style: { color: '#fbbf24' } // Custom styling support
            }
        ]
    }}
/>

4. Row Selection & Rules (Row Selection)

Displays a checkbox in each row for multi-selection of data.

  • selectMode: Can be configured to return an array of full row objects ('row'), an array of unique strings/IDs ('id'), or any other specific field.
  • isSelectable: You can disable checkboxes on specific rows based on data conditions.
<VelloGrid
    data={products}
    columns={columns}
    enableRowSelection={true}
    selectMode="row" // Options: 'row' | 'id' | keyof T
    onSelectionChange={(selectedRows) => {
        console.log("Selected rows:", selectedRows);
    }}
    rowConfig={{
        // Only rows with a price above $500 can be selected
        isSelectable: (row) => row.price > 500
    }}
/>

5. Row Details Expansion (Row Details Expansion)

Allows users to expand a row (accordion-style) to display detailed information without leaving the table page.

<VelloGrid
    data={products}
    columns={columns}
    showExpandedRows={true}
    renderRowDetails={(row) => (
        <div style={{ padding: '16px', backgroundColor: '#f8fafc', borderLeft: '4px solid #6366f1' }}>
            <h4 style={{ margin: '0 0 8px 0', color: '#1e293b' }}>Technical Specifications: {row.name}</h4>
            <p style={{ margin: '0 0 4px 0', fontSize: '14px', color: '#475569' }}>
                Category: <strong>{row.category}</strong>
            </p>
            <p style={{ margin: '0', fontSize: '13px', color: '#64748b' }}>
                Official Manufacturer Warranty: 1 Year | Guaranteed Spare Parts.
            </p>
        </div>
    )}
/>

6. Smart Column Filtering

Displays a dedicated input filter row below the column headers that dynamically adapts based on the column data type:

  • string: Searches for substring text matches (contains).
  • number: Provides mathematical comparison operator inputs (equals, greater than, less than).
  • boolean: Custom boolean dropdown (e.g., Active / Inactive) with label customization options.
  • date: Date range picker calendar.
const columns: ColumnConfig<Product>[] = [
    { 
        id: 'name', 
        header: 'Name', 
        dataType: 'string', 
        filterable: true 
    },
    { 
        id: 'price', 
        header: 'Price', 
        dataType: 'number', 
        filterable: true 
    },
    { 
        id: 'inStock', 
        header: 'Status', 
        dataType: 'boolean', 
        filterable: true,
        booleanLabels: { true: 'Available', false: 'Out of Stock' } 
    },
    { 
        id: 'releaseDate', 
        header: 'Release Date', 
        dataType: 'date', 
        filterable: true 
    }
];

// In VelloGrid
<VelloGrid
    data={products}
    columns={columns}
    showFilters={true} // Display the filter input row immediately by default
    showGlobalFilter={true} // Toggle filter button in the TopBar
/>

7. Custom Header, Footer, & Data Aggregation Summary

You can fully customize the rendering of column headers and footers to present summary aggregation data (e.g., Total Count, Average, or Status).

const columns: ColumnConfig<Product>[] = [
    {
        id: 'category',
        header: 'Category',
        renderHeader: (col) => (
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: '6px' }}>
                📁 {col.header}
            </span>
        )
    },
    {
        id: 'price',
        header: 'Price',
        align: 'right',
        render: (row) => `$${row.price.toLocaleString()}`,
        renderFooter: (col, filteredData) => {
            const total = filteredData.reduce((sum, item) => sum + item.price, 0);
            return `Total: $${total.toLocaleString()}`;
        }
    }
];

8. Server-Side Fetch API Integration (Manual Mode)

VelloGrid fully supports integration with external API calls (Server-Side Pagination, Sorting, & Filtering). By using the Controlled Component pattern, VelloGrid acts merely as a state emitter, while the client application (parent component) is responsible for fetching data.

Crucial Requirement: You must turn on all three manual properties (enableManualPagination, enableManualSorting, enableManualFiltering) so the Grid stops processing data on the client side.

<VelloGrid
    data={products}
    columns={columns}
    
    // 1. Turn off internal processing (Required for Server-Side)
    enableManualPagination={true}
    enableManualSorting={true}
    enableManualFiltering={true}
    
    // 2. Control Loading and Total Data Count from API
    isLoading={loading}
    totalItems={totalRowsFromApi}
    
    // 3. Catch every table state change to send to API
    onStateChange={(newState: VTableState) => {
        // A. Pagination
        const page = newState.pagination.pageIndex + 1;
        const limit = newState.pagination.pageSize;

        // B. Global Search
        const search = newState.globalFilter;

        // C. Sorting (Example output: "price:desc")
        const sort = newState.sorting
            .map(s => `${s.id}:${s.desc ? 'desc' : 'asc'}`)
            .join(',');

        // D. Active Column Filters
        const filters = newState.columnFilters
            .filter(f => f.value !== "" && f.value !== undefined)
            .map(f => ({ field: f.id, value: f.value, operator: f.operator }));

        // E. Execute API call
        fetchMyApi({ page, limit, search, sort, filters });
    }}
/>

9. Top Bar Custom Button Customization (topBarActions)

You can insert your own custom UI elements (such as Add New, Import action buttons, etc.) directly into the table Header (Top Bar) using the topBarActions property. These elements will appear neatly in the top right corner of the table.

<VelloGrid
    topBarActions={
        <div style={{ display: 'flex', gap: '8px' }}>
            <button onClick={() => alert("Importing...")}>Import CSV</button>
            <button onClick={() => alert("Adding...")}>+ Add Data</button>
        </div>
    }
/>

10. State Persistence (Saving Table State)

VelloGrid can automatically save and restore table state (such as pagination, search, hidden columns, and sorting) using various storage mechanisms.

Available Modes

  1. localStorage & sessionStorage: Works out of the box synchronously.
  2. url: Automatically synchronizes the critical table state (pagination, sorting, filtering) with the browser's URL query parameters without reloading the page. This is incredibly useful for creating shareable links where another user opening the link will see the exact same table configuration.
  3. custom: Ideal for storing state in an external Database or API. Use the onSave callback to catch state changes and push them to your server. When fetching the state back asynchronously, you should use the Controlled Mode (state prop) rather than initialState to handle the asynchronous delay properly.
<VelloGrid
    // 1. Local Storage (Default - Active)
    persistenceConfig={{
        enabled: true,
        mode: 'localStorage', // or 'sessionStorage'
        key: 'vello-my-table-state' // Unique storage key (required)
    }}

    // 2. URL Query Parameters (Auto-syncs with Address Bar)
    // persistenceConfig={{
    //     enabled: true,
    //     mode: 'url',
    //     key: 'vg-state'
    // }}

    // 3. Custom Storage (e.g., saving to database/API)
    // persistenceConfig={{
    //     enabled: true,
    //     mode: 'custom',
    //     onSave(state) {
    //         console.log("Saving state custom:", state);
    //         // perform fetch/API call here
    //     }
    // }}
/>

11. Row Grouping (Drag & Drop Column Grouping)

The grouping feature allows users to drag column headers to the Top Bar to group rows based on the values in that column.

<VelloGrid
    grouping={{
        enabled: true
    }}
/>

12. Error State Banner (Network/API Error Handling)

VelloGrid comes with an integrated Top-Alert Banner to elegantly display API network errors or data fetching failures without destroying the existing table layout or data. The banner features a smooth slide-down accordion animation.

<VelloGrid
    data={products}
    columns={columns}
    errorConfig={{
        isError: true, // Trigger to show/hide the banner
        message: "500 Internal Server Error. Failed to fetch latest data.",
        type: 'error', // Options: 'error' | 'warning' | 'info' (Affects background color)
        actionNode: (
            <button onClick={() => retryFetch()}>Retry</button>
        ),
        // style: { backgroundColor: '#333', color: '#fff' } // Support for custom CSS
    }}
/>

🎨 Theming & Icon Customization

VelloGrid uses local CSS Variables to easily customize color palettes instantly without bloating your application bundle size.

A. Configuring the theme Property Object

You can pass a theme configuration object directly to the theme property:

<VelloGrid
    data={products}
    columns={columns}
    theme={{
        primary: '#8b5cf6',          // Main accent color (Violet)
        primaryRgb: '139, 92, 246',   // RGB format for transition opacity
        background: '#fafafa',       // Table background
        text: '#1e293b',             // Main text color
        border: '#cbd5e1',            // Border line color
        borderTable: true            // Show outer table border lines
    }}
/>

B. Custom CSS Configuration (Global / Variables)

You can also define custom CSS variables globally in your project's .css file to seamlessly align VelloGrid with your application theme:

:root {
  --vello-primary: #6366f1;
  --vello-primary-rgb: 99, 102, 241;
  --vello-bg: #ffffff;
  --vello-text: #18181b;
  --vello-border: #e4e4e7;
  --vello-hover: #f4f4f5;
  --vello-header-bg: #f8f8fa;
  --vello-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}

C. Icon Customization

You can replace all built-in VelloGrid SVG icons with custom icons from your preferred icon library (e.g., Lucide-React, React-Icons, etc.):

import { SearchIcon, TrashIcon, CheckIcon } from 'lucide-react';

<VelloGrid
    data={products}
    columns={columns}
    icons={{
        Search: <SearchIcon size={14} />,
        Check: <CheckIcon size={14} />,
        EmptyState: <div style={{ textAlign: 'center', padding: '20px' }}>No data found 😭</div>
    }}
/>

📝 Comprehensive API Reference

1. <VelloGrid /> Properties (VelloGridProps)

| Property | Data Type | Default Value | Description | | :--- | :--- | :--- | :--- | | tableName | string | "VelloGRID" | Datatable title displayed in the top left corner of the TopBar. | | data | T[] | Required | Array of raw data objects to display in the table. | | columns | ColumnConfig<T>[] | Required | Array of column configurations. | | editMode | 'cell' \| 'row' | 'cell' | Editing mode option: single cell (double click) or simultaneous row (✏️ button). | | onCellEditSubmit | (rowId, colId, val, row) => void | undefined | Callback triggered when a single cell is finished editing and saved (Excel-Style). | | onRowEditSubmit | (rowId, data, row) => void | undefined | Callback triggered when a single row is finished editing and saved (Row-level). | | onCellEditValidate| (colId, val, row) => boolean \| string | undefined | Custom validator function. Return true if valid or string error message. | | enableRowSelection | boolean | false | Displays row selection checkboxes (multi selection). | | selectMode | 'row' \| 'id' \| keyof T | 'row' | Return format of selection data (id = array of IDs, row = array of row objects). | | onSelectionChange | (selectedData: any[]) => void | undefined | Callback triggered when the list of selected rows changes. | | rowConfig | RowConfig<T> | undefined | Configure condition functions for which rows can be selected (isSelectable). | | showExpandedRows | boolean | false | Enables row expansion button (Row Detail Expansion). | | renderRowDetails | (row: T) => ReactNode | undefined | Render function to display detailed information panel below the row. | | showFilters | boolean | false | Displays per-column filter input row below the headers. | | showGlobalFilter | boolean | false | Displays filter visibility toggle button in TopBar. | | showGlobalSearch | boolean | true | Displays global text search box in TopBar. | | searchPlaceholder | string | "Search..." | Placeholder text for global search input. | | showDensitySwitcher| boolean | true | Displays row density switcher button (sm, md, lg) in TopBar. | | showDownloadCsv | boolean | true | Displays filtered data export button to .csv file format. | | actionConfig | GridActionConfig<T> | undefined | Configures row action operation buttons (Edit, View, Delete, Custom). | | enableVirtualization| boolean | undefined | Enables high-performance virtual scroll (automatic if data > 1000). | | maxHeight | string | "450px" | Maximum height of the table scroll area (required if virtualization is active). | | isLoading | boolean | false | Displays premium data loading indicator (skeleton loading). | | theme | VelloGridTheme | undefined | Configures custom main table theme colors. | | icons | VelloGridIcons | undefined | Replaces built-in SVG icons with your custom icons. | | initialState | Partial<VTableState> | undefined | Sets initial table state such as pagination (pageIndex, pageSize). | | state | Partial<VTableState> | undefined | Controls the table state entirely from the outside (Fully Controlled Mode). | | enableColumnResizing| boolean | true | Enables boundary drag feature to resize column widths. | | defaultColumn | Partial<ColumnConfig>| undefined | Default properties to apply automatically to all columns. | | virtualRowHeight| number | 48 | Specific height of each row in pixels when virtualization is enabled. | | virtualScrollMaxHeight | string | "450px" | Specific maximum height for the virtual scroll viewport area. | | density | 'sm' \| 'md' \| 'lg' | 'sm' | Initial density/spacing size of cells in the table. | | showVisibleColumn | boolean | false | Displays column visibility toggle menu in the TopBar. | | className | string | undefined | Custom CSS class to apply to the root wrapper of the grid. | | enablePagination | boolean | true | Disables both the data slicing and hides the pagination UI footer, rendering all data at once. | | enableManualPagination | boolean | false | Disables client-side pagination processing (Server-Side Mode). | | enableManualSorting | boolean | false | Disables client-side sorting processing (Server-Side Mode). | | enableManualFiltering | boolean | false | Disables client-side filtering processing (Server-Side Mode). | | totalItems | number | undefined | Total number of data items on the server (Required if enableManualPagination=true). | | errorConfig | VelloGridErrorConfig | undefined | Configuration to display an integrated top-alert error banner. | | onStateChange | (state: VTableState) => void | undefined | Callback when pagination, sorting, or filtering changes (Server-Side Mode). | | topBarActions | ReactNode | undefined | Custom UI elements/buttons to be inserted on the right side of the Header (Top Bar). | | persistenceConfig | VelloGridPersistenceConfig | undefined | Configuration for automatic table state saving to localStorage or sessionStorage. | | groupingConfig | { enabled: boolean; defaultGroups?: string[] } | undefined | Enables drag-and-drop row grouping based on columns. | | localeText | Partial<GridLocaleText> | undefined | Custom translation object to override built-in table texts (i18n). | | getRowClassName | (row: T) => string | undefined | Custom function to dynamically assign specific CSS classes per row. | | getRowStyle | (row: T) => React.CSSProperties | undefined | Custom function to dynamically inject inline styles specific per row. | | collapsible | boolean | false | Enables the collapse/expand toggle arrow button in the Top Bar. | | defaultCollapsed| boolean | false | Sets the default collapsed state of the table on initial render. |


2. Column Configuration Properties (ColumnConfig)

| Property | Type | Default Value | Description | | :--- | :--- | :--- | :--- | | id | string | Required | Unique ID for the column (usually matches a key in the data). | | header | string | Required | Column title to be displayed in the header. | | render | (row: T) => ReactNode | undefined | Custom function to render cell content in this column. | | renderHeader| (col: ColumnConfig) => ReactNode | undefined | Custom function to render column title in the header. | | renderFooter| (col, data) => ReactNode | undefined | Custom function to render content in the bottom row (footer). Receives array of filtered data. | | sortable | boolean | true | Allows data sorting feature when column title is clicked. | | filterable | boolean | false | Displays specific filter input below this column title. | | dataType | 'string' \| 'number' \| 'boolean' \| 'date' | 'string' | Determines column data type to match validation and filter input shapes. | | booleanLabels| { true: string, false: string } | undefined | Customizes filter dropdown texts if the column data type is boolean. | | pinned | 'left' \| 'right' | undefined | Pins the column stickily to the left or right edge. | | align | 'left' \| 'center' \| 'right' | 'left' | Text alignment of column cell content. | | width | number \| string | undefined | Default column width (in px or percentage string). | | minWidth | number | 80 | Minimum column width limit during resizing. | | resizable | boolean | true | Allows this column boundary width to be resized by the user. | | editable | boolean | false | Allows cells in this column to be edited. | | editOptions | GridEditOptions | undefined | Additional editor input configuration, such as { type: 'select', options: [...] } for select types. | | copyable | boolean | false | Displays a quick copy button (copy-to-clipboard) when the cell is hovered. |


3. Action Configuration Properties (GridActionConfig<T>)

| Property | Type | Default Value | Description | | :--- | :--- | :--- | :--- | | headerLabel | string | "Actions" | Action column title in the header row. | | width | number | 75 | Action column width in pixels (px). | | pinned | 'left' \| 'right' \| 'none' | 'left' | Determines which side the action column is stickily pinned to. | | onView | (row: T) => void | undefined | Callback triggered when the eye 👁️ view details icon button is clicked. | | onEdit | (row: T) => void | undefined | Callback triggered when the pencil ✏️ edit icon button is clicked (only appears if editMode="cell"). | | onDelete | (row: T) => void | undefined | Callback triggered when the trash 🗑️ delete icon button is clicked. | | customActions | Array<CustomAction> | undefined | List of additional custom actions complete with their own icons and event handlers. |


🛠️ Tips & Best Practices

1. Next.js App Router Handling (Client Components)

VelloGrid components use interactive React states such as useState and event handlers. Always add the "use client"; line at the very top of your wrapper component file when using Next.js App Router.

2. Asynchronous Validation (API Side Validation)

You can perform asynchronous validation by capturing data in the onRowEditSubmit or onCellEditSubmit callbacks, and then sending it to your backend server. If the server replies with an invalid status, revert the state data to its original value (rollback).

const handleRowEditSubmit = async (rowId, newRowData, originalRow) => {
    try {
        const response = await fetch(`/api/products/${rowId}`, {
            method: 'PUT',
            body: JSON.stringify(newRowData),
            headers: { 'Content-Type': 'application/json' }
        });
        
        if (!response.ok) {
            throw new Error('Server validation failed');
        }
        
        // Save changes to local state if successful
        setProducts(prev => prev.map(p => String(p.id) === String(rowId) ? { ...p, ...newRowData } : p));
    } catch (error) {
        alert(error.message);
        // Maintain originalRow / do not update local state
    }
};

3. Setting Optimal Column Widths

Use a combination of width and minWidth properties in column configuration. For long text columns like "Name" or "Description", it is recommended to give a minimum width of 150 or 200 so content is not cut off when the screen shrinks.

4. Fully Controlled Mode

For advanced cases like synchronizing table state to URL Query Parameters or creating external navigation buttons outside the table component, use the state prop.

Use the Partial<VTableState> type so you only need to inject the state you want to control (e.g., only pagination), and let VelloGrid handle the rest of the state automatically.

import { useState } from 'react';
import { VelloGrid, VTableState } from '@vello/react-table';

export default function App() {
    const [tableState, setTableState] = useState<Partial<VTableState>>({
        pagination: { pageIndex: 0, pageSize: 10 }
    });

    return (
        <>
            <button onClick={() => setTableState(prev => ({ 
                ...prev, 
                pagination: { ...prev.pagination, pageIndex: 4 } 
            }))}>
                Jump to Pg. 3
            </button>
            
            <VelloGrid
                data={data}
                columns={columns}
                state={tableState} // Injecting state from outside
                onStateChange={(newState) => {
                    setTableState(newState); // Required reverse synchronization
                    fetchDataFromServerApi(newState);
                }}
            />
        </>
    );
}