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

ginv-react-table

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ginv-react-table

react-table base on @tanstack/react-table and shadcn

beta
latest
npmnpm
Version
1.0.0-beta.1
Version published
Maintainers
1
Created
Source

React Table

A powerful and customizable React table component built on top of @tanstack/react-table, featuring sticky headers, columns, and advanced data table functionality.

Table of Contents

Features

  • 📌 Sticky header and footer
  • 📍 Sticky columns (left and/or right pinning)
  • 🎨 Fully customizable styling
  • 🔍 Built-in filtering and search
  • 📊 Sorting support
  • 📄 Pagination with URL state management
  • ✅ Row selection and bulk actions
  • 📱 Responsive design
  • ⚡ Optimized scrolling with fixed headers and columns

Installation

npm install @ginv/react-table @tanstack/react-table
# or
yarn add @ginv/react-table @tanstack/react-table
# or
pnpm add @ginv/react-table @tanstack/react-table

Quick Start

Follow these steps to implement a basic data table:

  • Wrap your table with TableProvider component
  • Define columns with field configurations, sorting, and visibility options
  • Configure pagination with page size and total count
  • Add filtering using DataTableToolbar component
  • Enable row selection for batch operations
  • Configure scrolling with sticky headers and columns

Full Example

import type { ColumnPinningState, SortingState, VisibilityState } from '@tanstack/react-table'
import { TableCell, TableRow } from '@/components/ui/table'
import {
  DataTablePagination,
  DataTableToolbar,
  getPinnedColumnCellClassName,
  getPinnedColumnStyle,
  TableProvider,
} from '@ginv/react-table'

interface ColumnMeta {
  className?: string
  tdClassName?: string
  thClassName?: string
}

interface ScheduleTableProps {
  data: ScheduleListResponse
  loading?: boolean
}

export function ScheduleTable({ data, loading = false }: ScheduleTableProps) {
  const { content, totalElements: total } = data
  const { currentRow } = useSchedules()

  // Configure row selection state based on current row
  const rowSelection = useMemo(
    () =>
      currentRow !== null
        ? { [String(currentRow.id)]: true }
        : {},
    [currentRow],
  )

  const [sorting, setSorting] = useState<SortingState>([])
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
  const [columnPinning] = useState<ColumnPinningState>({
    left: ['name'],
    right: ['actions'],
  })

  // User options for filtering
  const [userOptionsList, setUserOptionsList] = useState<{ label: string, value: number }[]>([])

  // Manage URL query string state
  const {
    globalFilter,
    onGlobalFilterChange,
    columnFilters,
    onColumnFiltersChange,
    pagination,
    onPaginationChange,
    ensurePageInRange,
  } = useTableUrlStateWithNuqs({
    pagination: { defaultPage: 1, defaultPageSize: 10 },
    globalFilter: { enabled: true, key: 'filter' },
    columnFilters: [
      { columnId: 'type', searchKey: 'type', type: 'array' },
      { columnId: 'runState', searchKey: 'runState', type: 'array' },
      {
        columnId: 'commitBy',
        searchKey: 'commitBy',
        type: 'array',
      },
    ],
  })

  // Calculate total page count (server-side pagination)
  const pageCount = Math.ceil(total / pagination.pageSize)

  const table = useReactTable({
    data: content,
    columns,
    state: {
      sorting,
      columnVisibility,
      rowSelection,
      columnFilters,
      globalFilter,
      pagination,
      columnPinning,
    },
    enableRowSelection: true,
    onSortingChange: setSorting,
    onColumnVisibilityChange: setColumnVisibility,
    getCoreRowModel: getCoreRowModel(),
    manualPagination: true,
    manualFiltering: true,
    pageCount,
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    onPaginationChange,
    onGlobalFilterChange,
    onColumnFiltersChange,
    getRowId: row => String(row.id),
  })
  useEffect(() => {
    ensurePageInRange(pageCount)
  }, [pageCount, ensurePageInRange])

  useEffect(() => {
    const loadUserOptions = async () => {
      try {
        const options = await fetchUserOptions({ workspaceId: 1 })
        setUserOptionsList(options)
      }
      catch (error) {
        console.error('Failed to fetch user options:', error)
        setUserOptionsList([])
      }
    }
    loadUserOptions()
  }, [])

  return (
    <div
      className={cn(
        'p-4',
        // Add margin bottom on mobile when toolbar is visible
        'max-sm:has-[div[role="toolbar"]]:mb-16',
        'flex flex-1 flex-col gap-4 w-full overflow-hidden',
      )}
    >
      <DataTableToolbar
        table={table}
        searchPlaceholder="search..."
        filters={[
          {
            columnId: 'type',
            title: 'Task Types',
            options: types,
            popoverContentClassName: 'w-[230px]',
          },
          {
            columnId: 'commitBy',
            title: 'Commit User',
            options: userOptionsList,
          },
        ]}
      />
      <TableProvider
        table={table}
        loading={loading}
        renderWrapper
        scrollArea={{
          className: 'max-h-[calc(100vh-(--spacing(47)))]',
          tableClass: 'min-w-[1200px]',
          resetScrollDeps: [pagination.pageIndex, columnFilters, globalFilter],
        }}
      >
        {row => (
          <TableRow key={row.id} data-state={row.getIsSelected() && 'selected'} className="group">
            {row.getVisibleCells().map((cell) => {
              const isPinned = cell.column.getIsPinned()
              return (
                <TableCell
                  key={cell.id}
                  style={{
                    zIndex: isPinned ? 1 : undefined,
                    ...getPinnedColumnStyle(isPinned),
                  }}
                  className={cn(
                    (cell.column.columnDef.meta as ColumnMeta | undefined)?.className,
                    (cell.column.columnDef.meta as ColumnMeta | undefined)?.tdClassName,
                    getPinnedColumnCellClassName(isPinned),
                  )}
                >
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </TableCell>
              )
            })}
          </TableRow>
        )}
      </TableProvider>
      <DataTablePagination table={table} className="mt-auto" />
    </div>
  )
}

API Reference

TableProvider

The main wrapper component for the data table.

Props:

PropTypeDescription
tableTable<TData>TanStack table instance
loadingbooleanShow loading state
renderWrapperbooleanWrap table with scroll area
scrollAreaobjectScroll area configuration
children(row: Row<TData>) => ReactNodeRender function for table rows

DataTableToolbar

Toolbar component with search and filter functionality.

Props:

PropTypeDescription
tableTable<TData>TanStack table instance
searchPlaceholderstringSearch input placeholder text
filtersFilterConfig[]Array of filter configurations

DataTablePagination

Pagination component with page size selector.

Props:

PropTypeDescription
tableTable<TData>TanStack table instance
classNamestringAdditional CSS classes

Utility Functions

  • getPinnedColumnStyle(pinned: ColumnPinningPosition): Returns inline styles for pinned columns
  • getPinnedColumnCellClassName(pinned: ColumnPinningPosition): Returns className for pinned column cells

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Keywords

react-table

FAQs

Package last updated on 09 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