📅 You're Invited: Meet the Socket team at RSAC (April 28 – May 1).RSVP
Socket
Sign inDemoInstall
Socket

fuzzy-tables

Package Overview
Dependencies
Maintainers
0
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fuzzy-tables

A modern React component library for fuzzy tables

1.0.1
latest
npm
Version published
Weekly downloads
11
-21.43%
Maintainers
0
Weekly downloads
 
Created
Source

Fuzzy Tables

A simple, flexible, and fast table component for React with built-in sorting, filtering, and customization options.

Installation

npm install fuzzy-tables
# or
yarn add fuzzy-tables

After installing the package you just need to add the styles on the root layout of your project:

import 'fuzzy-tables/styles.css';

Basic Usage

This library is built around the concept of store-component factories. A function that returns a React component binded to a state store. This allows flexibility and easy access to the internal state of the table.

There are multiple ways to build a table:

1. From a list of fields

The simplest way to create a table is by providing an array of field names:

const Table = buildTable(['name', 'email', 'status'])

Basic Image

2. From column definitions

For more control, you can define columns with custom headers and rendering:

const Table = buildTable([
  {
    header: 'Name',
    field: 'name',
  },
  {
    header: 'Email',
    field: 'email',
    render: (row) => <a href={`mailto:${row.email}`}>{row.email}</a>
  },
  {
    header: 'Status',
    field: 'status',
    render: (row) => <StatusBadge status={row.status} />
  }
])

Which can look like this:

Advanced usage

3. From Zod Object

You can also build a table from a Zod object. Fuzzy Tables will automatically infer the type of each field and render it accordingly as single line, date, checkbox, multiple select, single select, or object array.

import { z } from 'zod'
const Table = buildTable(z.object({
  id: z.string(),
  name: z.string(),
  email: z.string().email(),
  status: z.enum(['active', 'inactive']),
  tags: z.array(z.string()),
  lastLogin: z.date(),
  isVerified: z.boolean(),
  metadata: z.object({
    role: z.string(),
    level: z.number(),
  }),
}))

Zod Usage

Props

Using the onRowClick prop, you can give more functionality to your table

Click table

Popup open

Hooks

Fuzzy Tables provides several custom hooks for advanced table manipulation:

useTableStore

Access and manipulate the table's internal state directly:

const Table = buildTable(['name', 'email', 'status']);

function TableControls() {
  const { 
    rowSelection,      // Record of selected row IDs
    toggleRowSelection,// Function to toggle row selection
    setRowSelection,   // Function to set row selection
    sortingFields,     // Current sorting configuration
    toggleSortingField // Function to toggle field sorting
  } = Table.useTableStore();

  return (
    <div>
      <button onClick={() => toggleSortingField('name')}>
        Sort by Name
      </button>
      <div>Selected Rows: {Object.keys(rowSelection).length}</div>
    </div>
  );
}

useSelected

Get the currently selected rows from your data:

function SelectedRowsDisplay({ data }) {
  const selectedRows = Table.useSelected(data);
  
  return (
    <div>
      <h3>Selected Items ({selectedRows.length})</h3>
      <ul>
        {selectedRows.map(row => (
          <li key={row.id}>{row.name}</li>
        ))}
      </ul>
    </div>
  );
}

useHandler

Register event handlers for custom table actions:

const Table = buildTable(['name', 'email'], ['edit', 'delete']);

function TableWithActions({ data }) {
  // Register handler for edit action

  // Important! The handler must not mutate along renders if not needed!!
  const editHandler = useCallback((row) => {
    console.log('Editing row:', row);
    // Open edit modal, etc.
  }, []);
  Table.useHandler('edit', editHandler);

  // Important! The handler must not mutate along renders if not needed!!
  const deleteHandler = useCallback((row) => {
    console.log('Deleting row:', row);
    // Show confirmation dialog, etc.
  }, []);
  Table.useHandler('delete', deleteHandler);

  return <Table data={data} />;
}

Complete Example with Hooks

Here's a more complex example showing how to use all the hooks together:

const UserTable = buildTable(['name', 'email', 'status'], ['edit', 'delete']);

function UserManagement() {
  const [users, setUsers] = useState([]);
  
  // Get selected rows
  const selectedUsers = UserTable.useSelected(users);
  
  // Register handlers
  UserTable.useHandler('edit', (user) => {
    // Handle edit
  });
  
  UserTable.useHandler('delete', (user) => {
    // Handle delete
  });
  
  // Access table store for custom controls
  const { sortingFields, toggleRowSelection } = UserTable.useTableStore();
  
  return (
    <div>
      <div className="controls">
        <button 
          disabled={selectedUsers.length === 0}
          onClick={() => console.log('Selected:', selectedUsers)}
        >
          Process Selected ({selectedUsers.length})
        </button>
      </div>
      
      <UserTable data={users} />
      
      <div className="info">
        Current Sort: {sortingFields.map(f => `${f.field} ${f.direction}`).join(', ')}
      </div>
    </div>
  );
}

Forms Features

Forms image

Fuzzy Tables seamlessly integrates table and form functionality, recognizing that applications often need to create and update records with fields that mirror table columns. This unified approach simplifies development by maintaining consistency between your data display and input interfaces.

Fuzzy Tables provides two forms components: CreateForm and UpdateForm. These forms will render each field accordingly based on fields prop. Currently displaying fields are:

  • Text input
  • Date input
  • Checkbox

Support for more fields will be released soon.

These are the mappings for each zod object type:

  • z.string() -> Text input
  • z.boolean() -> Checkbox
  • z.date() -> Date input

Optional fields are supported. Adding .optional() to a field will not enforce the field to be filled.

CreateForm Example

The CreateForm component is used to create new records. It takes a list of fields and a submit handler.

import { zodFromFields } from 'fuzzy-tables/types';
import { z } from 'zod';

// These same fields can be used to build a table!!!
const tableFields = [
  { field: 'name', header: 'Name', z: z.string() },
  { field: 'email', header: 'Email', z: z.string().email() },
  { field: 'status', header: 'Status', z: z.enum(['active', 'inactive']) },
]
const upsertSchema = zodFromFields(tableFields);

const App = () => {
  const createFormRef = useRef<CreateFormRef>(null);
  return (
    <>
      <button onClick={() => createFormRef.current?.open()}>Create</button>
      <CreateForm<z.infer<typeof upsertSchema>>
        fields={tableFields}
        ref={createFormRef}
        title='New Record'
        description='Create a new record by filling the fields below'
        onSubmit={async (id, formData) => {
          // Your submit logic here
        }}
        getErrorMessage={(error) => {
          // Your error message logic here
          // error could be TRPCClientError, ZodError, NetworkError, etc.
          // Individual field errors are already handled by default, this function
          // is only used for parsing global errors into a string message
          return 'An error occurred';
        }}
      />
    </>
  )
}

Do not loose typings on your forms! formData will be typed from z.infer<typeof upsertSchema>

Currently missing features

TODO'S:

  • Improve installation experience by getting rid of the need to import css on root
  • Add useBuildTable hook
  • Add support for more fields types
  • Add support for custom fields
  • Add support for custom validation
  • Add testing
  • Build documentation website

Keywords

react

FAQs

Package last updated on 04 Mar 2025

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