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 🙏

© 2024 – Pkg Stats / Ryan Hefner

tabulous

v0.0.15

Published

A customizable, responsive data table component for React with sorting, filtering, and pagination.

Downloads

799

Readme

tabulous

A customizable, responsive data table component for React with sorting, filtering, and pagination.

Table of Contents

Prop Definitions

| Prop | Type | Description | | --- | --- | --- | | columns | ColumnDef<any, any>[] | An array of column definitions. Each column must have a header (column title) and accessorKey (key to access the column data). | | data | Record<string, any>[] | An array of data objects to be displayed in the table. | | onRowSelect | (selectedIndices: string[] \| number[]) => void | Callback function to handle row selection. | | filterOptions | any[] | List of filter options available for use in the table filtering. | | clearFilters | () => void | Function to clear all filters applied to the table. | | onClickNext | () => void | Callback function to handle 'Next' button click in pagination. | | onClickPrevious | () => void | Callback function to handle 'Previous' button click in pagination. | | totalCount | number | Total number of items in the table. | | pageSize | number | Number of items per page for pagination. | | page | number | Current page number for pagination. | | tabs | ITabs | List of tabs to display for segmenting the data (e.g., for filtering or categorizing). | | onTabChange | (index: number, tab: any) => void | Callback when a tab is selected. Receives the index of the tab and the tab object. | | onDownload | (event: any) => void | Callback for downloading the data in the table. | | headerConfig | HeaderConfig | Configuration for the table header, which includes heading, description, and label. | | classNames | IClassName | Custom class names for styling different parts of the table, header, filter, etc. | | filterContent | ReactNode | Optional content that can be added to the filter toolbar (e.g., a button). |

Customization (classNames)

| Section | Customization (className) | Description | | --- | --- | --- | | Filter Chip | filterChip | Class for customizing the appearance of the filter chips. | | Filter Chip Icon | filterChipIcon | Class for customizing the icon inside the filter chip. | | Filter Chip Label | filterChipLabel | Class for customizing the label inside the filter chip. | | Table Wrapper | tableWrapper | Class for customizing the wrapper around the table. | | DataTable | dataTable | Class for customizing the main data table container. | | Table Header Cell | tableHeaderCell | Class for customizing the header cells. | | Table Row Cell | tableRowCell | Class for customizing the individual row cells. | | Sorting Arrow Icon | sortingArrowIcon | Class for customizing the sorting arrow icon in the header cells. | | Header Wrapper | headerWrapper | Class for customizing the wrapper around the table header. | | Heading | heading | Class for customizing the main heading (title). | | Subheading | subHeading | Class for customizing the subheading under the title. | | Badge | badge | Class for customizing the badges, if used. | | Download Button | downloadButton | Class for customizing the download button. | | Download Button Icon | downloadButtonIcon | Class for customizing the icon inside the download button. | | Tabs Panel | tabsPanel | Class for customizing the panel of tabs. | | Tab Item | tabItem | Class for customizing the individual tab items. | | Selected Tab | selectedTab | Class for customizing the selected tab. | | Pagination Wrapper | paginationWrapper | Class for customizing the pagination wrapper. | | Pagination Info | paginationInfo | Class for customizing the pagination information display. (1-10 of 100 items) | | Pagination Button Wrapper | paginationButtonWrapper | Class for customizing the pagination button container. | | Pagination Button Previous | paginationButtonPrevious | Class for customizing the "Previous" button in pagination. | | Pagination Button Next | paginationButtonNext | Class for customizing the "Next" button in pagination. |

Example Usage

import React, { useState, useEffect, useCallback } from "react";
import { DataTable, DataTableColumn, ITabs } from "tabulous";
import styles from "./index.module.scss";

const pageSize = 10;

export interface OrderRecord {
  id: string;
  orderAmount: number;
  orderStatus: string;
  city: string;
  state: string;
  processed: boolean;
}

export default function Home() {
  const [data, setData] = useState<OrderRecord[]>([]);
  const [loading, setLoading] = useState(true);
  const [count, setCount] = useState(0);
  const [page, setPage] = useState(1);
  const [count, setCount] = useState(0);
  const [page, setPage] = useState(1);
  const [filters, setFilters] = useState<any>({});
  const [selectedRows, setSelectedRows] = useState<number[]>([]);

  const fetchData = useCallback(async () => {
    // API call to fetch data here
  }, []);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const columns: DataTableColumn[] = [
    { header: "ID", accessorKey: "id" },
    { header: "Order Status", accessorKey: "orderStatus" },
    { header: "City", accessorKey: "city", size: 20 },
    { header: "Processed", accessorFn: (row) => (row.processed ? "Yes" : "No") },
  ];

  const orderData = useMemo(() => data, [data]);

  const handleApiDownload = async () => {
    // Make API call for downloading or use default download functionality
  };

  const filterOptions = useMemo(() => [
    {
      label: "Order Status",
      options: ["success", "inprogress", "pending", "failed", "paid"],
      id: "orderStatus",
      value: filters.orderStatus,
      onOptionChange: (value: any) => 
          setFilters((prev: any) => ({ ...prev, orderStatus: value })),,
    },
    {
      label: "Processed",
      id: "processed",
      options: ["true", "false"],
      value: filters.processed,
     onOptionChange: (value: any) =>
          setFilters((prev: any) => ({ ...prev, processed: value === "true" })),
    },
    {
      label: "City",
      id: "city",
      options: ["Delhi", "BOM", "Patna"],
      value: filters.city,
        onOptionChange: (value) =>
          setFilters((prev: any) => ({ ...prev, city: value })),
    },
  ], [filters]);

  const tabs: ITabs = [
    { label: "All", value: undefined },
    { label: "Processed", value: "true" },
    { label: "Not Processed", value: "false" },
  ];

  const onTabChange = (index: number, tab: any) => {
    setFilters((p: any) => ({ ...p, processed: tab.value }));
  };

  const handleRowSelect = (selectedIndices: any) => {
    setSelectedRows(selectedIndices);
  };

  const handleNext = () => {
    setPage((p) => p + 1);
  };

  const handlePrevious = () => {
    setPage((p) => Math.max(p - 1, 1));
  };

  const clearFilters = () => setFilters({});

   const handleDelete = () => {
    console.log("Deleting selected rows:", selectedRows);
  };

  const headerConfig: HeaderConfig = {
    headline: "My Data Table",
    label: "Company Orders",
    description: "Default description text comes here.",
  };

  return (
    <div>
      <DataTable
        columns={columns}
        data={orderData}
        onRowSelect={handleRowSelect}
        filterOptions={filterOptions}
        tabs={tabs}
        onDownload={handleApiDownload}
        clearFilters={clearFilters}
        onTabChange={onTabChange}
        onClickNext={handleNext}
        onClickPrevious={handlePrevious}
        page={page}
        totalCount={count}
        pageSize={pageSize}
        headerConfig={headerConfig}
        classNames={{
          filterChip: styles.filterChip,
          filterChipIcon: styles.filterChipIcon,
          filterChipLabel: styles.filterChipLabel,
          tableWrapper: styles.tableWrapper,
          dataTable: styles.dataTable,
          tableHeaderCell: styles.tableHeaderCell,
          tableRowCell: styles.tableRowCell,
          headerWrapper: styles.headerWrapper,
          heading: styles.heading,
          subHeading: styles.subHeading,
          badge: styles.badge,
          downloadButton: styles.downloadButton,
          downloadButtonIcon: styles.downloadButtonIcon,
          tabsPanel: styles.tabsPanel,
          tabItem: styles.tabItem,
          selectedTab: styles.selectedTab,
          paginationWrapper: styles.paginationWrapper,
          paginationInfo: styles.paginationInfo,
          paginationButtonWrapper: styles.pagintaionButtonWrapper,
          paginationButtonPrevious: styles.paginationButtonPrevious,
          paginationButtonNext: styles.paginationButtonNext,
        }}
        filterContent={
          selectedRows.length > 0 && (
            <button onClick={handleDelete} style={{ marginLeft: "auto" }}>
              Delete Selected
            </button>
          )
        }
      />
    </div>
  );
}