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 🙏

© 2025 – Pkg Stats / Ryan Hefner

notion-spark-datatable

v1.0.29

Published

A flexible and customizable data table component built with React and TanStack Table, featuring Notion-style UI components

Readme

Notion Spark Datatable

A modern, modular data table component built with React and TanStack Table, featuring Notion-style UI components and a clean hooks-based architecture.

✨ Features

  • 🏗️ Modular Architecture: Clean separation of concerns with custom hooks for each feature
  • 🎨 Notion-style Components: Built-in status indicators, tags, and buttons with proper Notion colors
  • 🔍 Advanced Filtering: Multi-column filtering with 7 filter operators and localStorage persistence
  • 📊 Smart Grouping: Automatic group expansion with localStorage persistence
  • 📏 Responsive Column Sizing: Compact, overflow-preventing column widths
  • 🔄 Drag & Drop: Column reordering with protected action column
  • 📱 Responsive Design: Works on all screen sizes without horizontal scrolling
  • ⚡ High Performance: Built with TanStack Table for optimal performance
  • 🎯 TypeScript Support: Full type safety and IntelliSense
  • 💾 State Persistence: All table state saved to localStorage automatically

🚀 Quick Start

1. Install the package

npm install notion-spark-datatable

2. Use the component

import { TableComponent } from 'notion-spark-datatable';

function App() {
  return (
    <TableComponent
      tableId="my-table"
      data={yourData}
      columns={yourColumns}
      config={{
        enableSearch: true,
        enableFilters: true,
        enableSorting: true,
        enableGrouping: true,
        enableResizing: true,
        enableDragging: true,
      }}
      onCreate={handleCreate}
      onEdit={handleEdit}
      onDelete={handleDelete}
    />
  );
}

🏗️ Architecture

The component uses a modular hooks architecture for clean separation of concerns:

Core Hooks

  • useColumnOrder - Manages column ordering and drag & drop
  • useGrouping - Handles grouping state and auto-expansion
  • useColumnFormatting - Manages number/percent/currency formatting
  • useFilters - Advanced filtering with 7 operators
  • useColumnSizing - Responsive column sizing and resizing
  • useColumnVisibility - Column visibility management

UI Components

  • HeaderContextMenu - Context menu for column headers
  • ColumnFormattingMenu - Number formatting options
  • FilterPanel - Advanced filtering interface
  • Toolbar - Table controls and actions

📋 Column Types

The component supports various column types with automatic rendering. Each type is designed for specific data patterns:

const columns = [
  {
    id: 'title',
    type: 'title',        // Editable title column (always visible)
    header: 'Task Name',
    accessorKey: 'name'
  },
  {
    id: 'status',
    type: 'status',       // Status indicator with dots
    header: 'Status',
    accessorKey: 'status'
  },
  {
    id: 'tags',
    type: 'tag',          // Colored tag component
    header: 'Tags',
    accessorKey: 'tags'
  },
  {
    id: 'dueDate',
    type: 'date',         // Date formatting with dayjs
    header: 'Due Date',
    accessorKey: 'dueDate'
  },
  {
    id: 'number',
    type: 'number',       // Number formatting (number/percent/currency)
    header: 'Number',
    accessorKey: 'number'
  },
  {
    id: 'boolean',
    type: 'boolean',      // Boolean toggle
    header: 'Boolean',
    accessorKey: 'boolean'
  },
  {
    id: 'url',
    type: 'url',          // Clickable URL links
    header: 'Website',
    accessorKey: 'website'
  },
  {
    id: 'relation',
    type: 'relation',     // Relation picker with search
    header: 'Category',
    accessorKey: 'category'
  }
];

Column Type Guidelines

  • title: Use for the main identifier of each row (e.g., task name, project title, user name)
  • status: Use for state indicators (e.g., active, pending, completed, critical)
  • tag: Use for categorization (e.g., tags, labels, categories, types)
  • date: Use for temporal data (e.g., due dates, creation dates, deadlines)
  • number: Use for numeric values (e.g., numbers, percentages, amounts, quantities)
  • boolean: Use for true/false flags (e.g., boolean values, flags, toggles)
  • url: Use for clickable links (e.g., websites, documentation, resources)
  • relation: Use for related data with search (e.g., categories, users, projects)
  • text: Use for editable text fields
  • custom: Use for custom cell renderers

🔧 Props

Table Configuration

The config prop allows you to control which features are enabled:

const config = {
  enableSearch: true,      // Global search functionality
  enableFilters: true,     // Advanced filtering panel
  enableSorting: true,     // Column sorting
  enableGrouping: true,    // Row grouping
  enableResizing: true,    // Column resizing
  enableDragging: true,    // Column reordering
  enableEditing: false,    // Inline cell editing
};

All options default to true except enableEditing which defaults to false.

| Prop | Type | Required | Description | |------|------|----------|-------------| | tableId | string | ❌ | Unique ID for localStorage persistence (auto-generated if not provided) | | data | T[] | ✅ | Array of data objects | | columns | ColumnDefinition<T>[] | ✅ | Column definitions | | config | TableConfig | ❌ | Global table configuration options | | onCreate | (row: T) => void | ❌ | Handler for creating new items | | onEdit | (row: T) => void | ❌ | Handler for editing items | | onDelete | (id: string) => void | ❌ | Handler for deleting items | | onRelationPick | (field: string, q: string) => Promise<Array<{ id: string; name: string }>> | ❌ | Handler for relation search | | renderActions | (row: T) => React.ReactNode | ❌ | Custom action column renderer | | renderCreateButton | () => React.ReactNode | ❌ | Custom create button renderer |

🎯 Example

import React from 'react';
import { TableComponent } from 'notion-spark-datatable';

const columns = [
  {
    id: 'title',
    type: 'title',
    header: 'Task Name',
    accessorKey: 'name'
  },
  {
    id: 'status',
    type: 'status',
    header: 'Status',
    accessorKey: 'status'
  },
  {
    id: 'tags',
    type: 'tag',
    header: 'Tags',
    accessorKey: 'tags'
  },
  {
    id: 'dueDate',
    type: 'date',
    header: 'Due Date',
    accessorKey: 'dueDate'
  },
  {
    id: 'number',
    type: 'number',
    header: 'Number',
    accessorKey: 'number'
  },
  {
    id: 'boolean',
    type: 'boolean',
    header: 'Boolean',
    accessorKey: 'boolean'
  }
];

const data = [
  { id: '1', name: 'Complete project', status: 'active', tags: 'development', dueDate: '2024-01-15', number: 85, boolean: true },
  { id: '2', name: 'Review code', status: 'pending', tags: 'review', dueDate: '2024-01-20', number: 92, boolean: true },
  { id: '3', name: 'Bug fix', status: 'critical', tags: 'maintenance', dueDate: '2024-01-10', number: 78, boolean: false }
];

function MyTable() {
  return (
    <TableComponent
      tableId="my-tasks-table"
      data={data}
      columns={columns}
      config={{
        enableSearch: true,
        enableFilters: true,
        enableSorting: true,
        enableGrouping: true,
        enableResizing: true,
        enableDragging: true,
      }}
      onCreate={() => console.log('Create new')}
      onEdit={(row) => console.log('Edit', row)}
      onDelete={(id) => console.log('Delete', id)}
    />
  );
}

export default MyTable;

🎨 Features in Detail

🔍 Advanced Filtering

  • 7 Filter Operators: equals, not equals, contains, starts with, ends with, greater than, less than
  • Multi-column Support: Apply multiple filters simultaneously
  • Persistent State: Filters saved to localStorage automatically
  • Smart UI: Filter panel with easy-to-use controls

📊 Smart Grouping

  • Auto-expansion: Groups automatically expand when grouping is applied
  • Persistent State: Grouping and expansion state saved to localStorage
  • Flexible Grouping: Group by any column type
  • Group Sorting: Sort groups by value or count

📏 Responsive Column Sizing

  • Compact Design: Optimized widths to prevent horizontal scrolling
  • Content-aware: Different widths for different column types
  • Resizable: Users can resize columns as needed
  • Protected Columns: Action column always visible and properly sized

🔄 Drag & Drop

  • Column Reordering: Drag columns to reorder them
  • Protected Actions: Action column cannot be moved or hidden
  • Smooth Animations: Built with @dnd-kit for smooth interactions
  • Keyboard Support: Full accessibility support

💾 State Persistence

  • Automatic Saving: All table state saved to localStorage
  • Table-specific: Each table instance has its own storage
  • Persistent Features: Column order, visibility, sizing, filters, grouping, formatting

🎨 Styling

No CSS imports needed! All components include inline styles and work out of the box:

  • Notion Color System: Uses proper Notion colors (gray, blue, green, yellow, red, purple, pink)
  • Flexible Status System: Auto-detects colors from status text or override with color prop
  • Tag Components: All color variants with proper radius and padding
  • Button Styling: Primary, secondary, ghost, destructive variants
  • Table Styling: Headers, rows, gradients, and hover effects
  • Responsive Design: No horizontal scrolling, fits all screen sizes

🔧 Development

Build the package

npm run build

Build library version

npm run build:lib

Development server

npm run dev

📦 Package Contents

  • TableComponent - Main table component with all features
  • NotionStatus - Status indicator component
  • NotionTag - Tag component with color variants
  • NotionButton - Button component with variants
  • Custom Hooks - All core functionality hooks
  • UI Components - Header context menu, filter panel, toolbar
  • TypeScript Types - Full type definitions

🚀 What's New in v1.0.12

  • Modular Hooks Architecture - Clean separation of concerns
  • 🔍 Advanced Filtering System - 7 filter operators with persistence
  • 📊 Smart Grouping - Auto-expansion with localStorage
  • 📏 Responsive Column Sizing - No more horizontal scrolling
  • 🔄 Protected Action Column - Always visible, always on the right
  • 💾 State Persistence - All settings saved automatically
  • 🧹 Clean Code - Removed debug logs, optimized performance
  • 🏷️ Generic Column Names - Clear, non-redundant field naming
  • 🌙 Enhanced Column Types - Added URL, relation, and custom cell types
  • ⚙️ Improved Configuration - Better config prop documentation and examples

🤝 Contributing

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

📄 License

This project is licensed under the MIT License.