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

@fooxit/tab-data

v1.1.1

Published

Librairie React générique pour afficher et gérer des tableaux de données avec tri, filtrage et pagination.

Readme

tab-data

Librairie React générique pour afficher et gérer des tableaux de données avec tri, filtrage et pagination.


Sommaire


Installation

npm install tab-data

Prérequis : React 19+


Utilisation rapide

import TabData from '@fooxit/tab-data';
import '../node_modules/@fooxit/tab-data/dist/main.css';
import type { RowModelType } from '../../../tab-data/dist/type/type';

type Employee = {
    id: string;
    firstName: string;
    lastName: string;
    department: string;
};

const employees: Employee[] = [
    { id: '1', firstName: 'Alice', lastName: 'Martin', department: 'RH' },
    { id: '2', firstName: 'Bob', lastName: 'Dupont', department: 'IT' },
];

const rowModel: RowModelType<Employee> = {
    columns: [
        { dataKey: 'firstName', label: 'Prénom' },
        { dataKey: 'lastName', label: 'Nom' },
        { dataKey: 'department', label: 'Département' },
    ],
    idKey: 'id',
    sort: true,
    filter: true,
};

export default function App() {
    return <TabData id="employees-table" datas={employees} rowModel={rowModel} maxRow={10} />;
}

Composants

TabData

Composant principal qui orchestre le tableau complet (en-têtes, lignes, pagination, filtres, tri,recherche).

<TabData id="my-table" datas={data} rowModel={rowModel} maxRow={10} className="my-table" />

| Prop | Type | Obligatoire | Description | | ----------- | ------------------- | ----------- | ------------------------------------------------------- | | id | string | Oui | Identifiant unique du tableau | | datas | D[] | Oui | Tableau de données génériques | | rowModel | RowModelType<D> | Oui | Modèle de colonnes (voir Types) | | maxRow | number | Non | Nombre maximum de lignes par page (par défaut : toutes) | | search | { label: string } | Non | Objet de recherche contenant le libellé du champ | | className | string | Non | Préfixe de classe CSS appliqué aux éléments |


DataRow

Rend une ligne <tr> à partir d'un objet de données et d'un modèle de colonnes.

<DataRow id={item.id} data={item} rowModel={{ ...rowModel, tabId: 'my-table' }} className="my-table" />

| Prop | Type | Description | | ----------- | ------------------------- | ---------------------------------------- | | id | unknown | Clé unique de la ligne | | data | Record<string, unknown> | Données de la ligne | | rowModel | RowModelTypeExtend<D> | Modèle de colonnes étendu (avec tabId) | | className | string | Préfixe de classe CSS |


FilterSelector

Menu déroulant de filtrage avec barre de recherche interne. S'affiche automatiquement dans les en-têtes de colonnes lorsque rowModel.filter === true.

<FilterSelector
    option={[
        ['Alice', true],
        ['Bob', false],
    ]}
    onFilterSelect={(value) => console.log(value)}
    className="my-table"
/>

| Prop | Type | Description | | ---------------- | -------------------------- | -------------------------------------------- | | option | [unknown, boolean][] | Liste des options avec leur état sélectionné | | onFilterSelect | (value: unknown) => void | Callback au clic sur une option | | className | string | Préfixe de classe CSS |

Retourne undefined si aucune option n'est fournie.


PageControl

Contrôles de pagination (boutons Précédent / Suivant, numéro de page). Utilise le contexte TabDataContext — doit être placé à l'intérieur d'un TabData.

<PageControl colSpan={4} className="my-table" />

| Prop | Type | Description | | ----------- | -------- | --------------------------------------------------------- | | colSpan | number | Nombre de colonnes couvertes par la cellule de pagination | | className | string | Préfixe de classe CSS |

Retourne null si le contexte de pages n'est pas disponible.


RowLabel

Rend la ligne d'en-têtes <thead> avec les libellés, indicateurs de tri et filtres.

<RowLabel rowModel={rowModel} className="my-table" />

| Prop | Type | Description | | ----------- | ----------------- | --------------------- | | rowModel | RowModelType<D> | Modèle de colonnes | | className | string | Préfixe de classe CSS |


SearchBar

Barre de recherche globale qui permet de filtrer les lignes du tableau en fonction du texte saisi. Pour l'activer dans le composant TabData passer la props "search"

<SearchBar value={searchValue} onChange={(value) => setSearchValue(value)} placeholder="Rechercher dans le tableau..." className="my-table" />

| Prop | Type | Description | | ------------- | -------------------------------------------------- | ------------------------------------- | | value | string | Texte de recherche actuel | | onChange | (e: React.ChangeEvent<HTMLInputElement>) => void | Callback appelé à chaque modification | | placeholder | string | Texte d'aide affiché dans l'input | | className | string | Préfixe de classe CSS |


Hooks

useTabData

Hook principal qui applique le filtrage, le tri et la pagination sur un tableau de données.

const { filtedDatas } = useTabData({
    datas,
    isSort: true,
    isFilter: true,
    maxRow: 10,
    filter,
    sortByValue,
    page: currentPage,
});

| Paramètre | Type | Description | | ------------- | ---------------------------- | --------------------------- | | datas | D[] | Données sources | | isSort | boolean | Active le tri | | isFilter | boolean | Active le filtrage | | maxRow | number | Lignes max par page | | filter | Map<keyof D, Set<unknown>> | Filtres actifs | | sortByValue | SortBy<D> \| null | Colonne et direction de tri | | page | number | Page courante |

Retourne : { filtedDatas: D[] }


useFilter

Gère l'état des filtres actifs. Chaque appel à filterBy active ou désactive un filtre (comportement de bascule).

const { filter, filterBy } = useFilter<Employee>();

// Activer/désactiver le filtre "IT" sur la colonne "department"
filterBy('department', 'IT');

Retourne :

| Propriété | Type | Description | | ---------- | ---------------------------------------- | ------------------ | | filter | Map<keyof D, Set<unknown>> | Filtres actifs | | filterBy | (key: keyof D, value: unknown) => void | Basculer un filtre |


useSelectSort

Gère l'état du tri en faisant cycler les directions : ascdesc → aucun.

const { sortByValue, sortBy } = useSelectSort<Employee>();

sortBy('lastName'); // Premier appel : tri ASC
sortBy('lastName'); // Second appel : tri DESC
sortBy('lastName'); // Troisième appel : pas de tri

Retourne :

| Propriété | Type | Description | | ------------- | ------------------------ | ---------------------------- | | sortByValue | SortBy<D> \| null | Colonne et direction actives | | sortBy | (key: keyof D) => void | Changer/cycler le tri |


usePageSelector

Gère la pagination : page courante, page maximale et contrôles de navigation.

const { currentPage, maxPage, Control } = usePageSelector(
    employees.length, // longueur totale
    10, // lignes par page
    1, // page initiale
);

Control.next(); // page suivante
Control.prev(); // page précédente
Control.set(3); // aller à la page 3

Retourne :

| Propriété | Type | Description | | -------------- | ------------------------ | -------------------------- | | currentPage | number | Page actuelle | | maxPage | number | Nombre total de pages | | Control.next | () => void | Aller à la page suivante | | Control.prev | () => void | Aller à la page précédente | | Control.set | (page: number) => void | Aller à une page précise |


useSearch

Filtre une liste de données selon une valeur de recherche saisie, avec un debounce de 250 ms.

const { searchValue, searchResult, onSearchChange } = useSearch(employees, (item, value) => item.firstName.toLowerCase().includes(value.toLowerCase()));

<input value={searchValue} onChange={onSearchChange} />;

Retourne :

| Propriété | Type | Description | | ---------------- | -------------------------------------------- | ------------------------------------- | | searchValue | string | Valeur courante du champ de recherche | | searchResult | D[] | Données filtrées | | onSearchChange | (e: ChangeEvent<HTMLInputElement>) => void | Handler du champ de recherche |


useExtractFilterOption

Extrait les valeurs uniques de chaque colonne pour alimenter les menus de filtres.

const filterOptions = useExtractFilterOption(employees, true);
// Map { 'department' => Set { 'RH', 'IT' }, 'firstName' => Set { 'Alice', 'Bob' } }

Retourne null si isFilter est false ou undefined.


useExpend

Gère un état d'expansion / réduction (utilisé en interne par FilterSelector).

const [isExpend, { expend, collapse, toggle }] = useExpend(false);

Retourne : [boolean, { expend: () => void, collapse: () => void, toggle: () => void }]


useTabDataContext

Accède au contexte partagé TabDataContext. Doit être utilisé à l'intérieur d'un composant TabData.

const { filterBy, sortBy, pages } = useTabDataContext();

Lance une erreur si utilisé en dehors du contexte.


Types

RowModelType<D>

Définit la structure du tableau : colonnes à afficher, clé d'identification, et options de tri/filtrage.

interface RowModelType<D> {
    columns: { dataKey: keyof D; label: string }[];
    idKey: keyof D;
    sort?: boolean;
    filter?: boolean;
}

SortBy<D>

type SortBy<D extends Record<string, string>> = {
    key: keyof D;
    direction: 'asc' | 'desc';
};

ArrayElement<T>

Utilitaire TypeScript pour extraire le type d'élément d'un tableau.

type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;

Personnalisation des styles

Chaque composant accepte une prop className qui est utilisée comme préfixe sur les éléments internes. Par exemple, avec className="my-table" :

<table class="my-table">
    <thead>
        <tr class="my-table__header-row">
            <th class="my-table__header-cell">...</th>
        </tr>
    </thead>
    <tbody>
        <tr class="my-table__row">
            ...
        </tr>
    </tbody>
</table>

Les styles par défaut sont importés automatiquement via les fichiers CSS internes (data-table.css, data-row.css, row-label.css, page-controller.css). Vous pouvez les surcharger avec vos propres règles CSS.