An open API service indexing awesome lists of open source software.

https://github.com/vatesfr/flexi-table


https://github.com/vatesfr/flexi-table

Last synced: 27 days ago
JSON representation

Awesome Lists containing this project

README

          

# flexi-table

[![CI](https://github.com/vatesfr/flexi-table/actions/workflows/ci.yml/badge.svg)](https://github.com/vatesfr/flexi-table/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/@vates/flexi-table-react?label=react)](https://www.npmjs.com/package/@vates/flexi-table-react)
[![npm](https://img.shields.io/npm/v/@vates/flexi-table-vue?label=vue)](https://www.npmjs.com/package/@vates/flexi-table-vue)
[![npm](https://img.shields.io/npm/v/@vates/flexi-table-vanilla?label=vanilla)](https://www.npmjs.com/package/@vates/flexi-table-vanilla)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

A flexible, fully-typed data table for React, Vue 3, and vanilla JS — with sorting, filtering, column visibility, and row grouping built in.

## Live demo

[React demo](https://vatesfr.github.io/flexi-table/react/) · [Vue demo](https://vatesfr.github.io/flexi-table/vue/) · [Vanilla demo](https://vatesfr.github.io/flexi-table/vanilla/)

## Packages

| Package | Description |
| -------------------------------------------------- | ---------------------------------- |
| [`@vates/flexi-table-react`](./packages/react) | React component and hook |
| [`@vates/flexi-table-vue`](./packages/vue) | Vue 3 component and composable |
| [`@vates/flexi-table-vanilla`](./packages/vanilla) | Vanilla JS, no framework required |
| [`@vates/flexi-table-core`](./packages/core) | Framework-agnostic logic (pure TS) |

## Features

- Multi-column sort
- Value checklist filters and numeric range filters
- Column visibility toggle
- Row grouping (grouped column hides from the table automatically)
- Row selection with checkboxes — select all (across pages), group selection, indeterminate state
- Client-side pagination
- i18n via a `labels` prop — defaults to English, with built-in locales for FR, ES, DE, PT
- Custom cell rendering via render props (React), scoped slots (Vue), or `format` string functions (vanilla)
- Fully typed with TypeScript generics (`TRow extends object`)

## Quick start

### React

```bash
npm install @vates/flexi-table-react
```

```tsx
import { DataTable, type ColumnDef } from '@vates/flexi-table-react'

interface User {
id: number
name: string
role: string
salary: number
}

const COLUMNS: ColumnDef[] = [
{ key: 'name', label: 'Name', type: 'string' },
{ key: 'role', label: 'Role', type: 'string', groupable: true },
{
key: 'salary',
label: 'Salary',
type: 'number',
format: (v) => Number(v).toLocaleString() + ' €',
},
]

export default function App() {
return
}
```

Custom cell rendering with render props:

```tsx
{ key: 'role', label: 'Role', type: 'string',
render: (value, row) => ,
renderFilterLabel: value => }
```

### Vue

```bash
npm install @vates/flexi-table-vue
```

```vue

import { DataTable, type ColumnDef } from '@vates/flexi-table-vue'

interface User {
id: number
name: string
role: string
salary: number
}

const COLUMNS: ColumnDef<User>[] = [
{ key: 'name', label: 'Name', type: 'string' },
{ key: 'role', label: 'Role', type: 'string', groupable: true },
{
key: 'salary',
label: 'Salary',
type: 'number',
format: (v) => Number(v).toLocaleString() + ' €',
},
]











```

### Vanilla JS

```bash
npm install @vates/flexi-table-vanilla
```

```ts
import { createFlexiTable, type ColumnDef } from '@vates/flexi-table-vanilla'

const COLUMNS: ColumnDef[] = [
{ key: 'name', label: 'Name', type: 'string' },
{ key: 'role', label: 'Role', type: 'string', groupable: true },
{
key: 'salary',
label: 'Salary',
type: 'number',
format: (v) => Number(v).toLocaleString() + ' €',
},
]

const table = createFlexiTable(document.getElementById('table')!, {
data: users,
columns: COLUMNS,
rowKey: 'id',
})

// Update later
table.setData(newUsers)
table.destroy()
```

CSS is injected automatically into ``. Cell output is string-only — use `format` to control rendering.

## i18n

All UI strings are in English by default. Use a built-in locale or supply any overrides via the `labels` prop:

```tsx
import { LABELS_FR } from '@vates/flexi-table-react' // or -vue or -vanilla

```

Built-in locales: `LABELS_EN` (default), `LABELS_FR`, `LABELS_ES`, `LABELS_DE`, `LABELS_PT`.

You can also pass a `Partial` to override individual strings — it is shallow-merged over the default English labels.

## Theming

All colors are CSS custom properties (`--color-background-primary`, `--color-text-primary`, etc.). Dark mode activates automatically via `prefers-color-scheme: dark` and can be forced with `data-theme="dark"` or `data-theme="light"` on any ancestor element.

**Vanilla** — tokens and dark-mode rules are injected automatically. No setup required.

**React / Vue** — define the tokens in your own global stylesheet. See the [vanilla README](./packages/vanilla/README.md#theming) for the full token list and default values.

```js
// Force dark / light / follow OS preference
document.documentElement.dataset.theme = 'dark'
document.documentElement.dataset.theme = 'light'
delete document.documentElement.dataset.theme
```

## Column definition

```ts
interface ColumnDefBase {
key: keyof TRow & string // must be a key of TRow
label: string
type?: 'string' | 'number' | 'date' // controls filter UI; default: 'string'
width?: number
format?: (value: unknown) => string // plain-string formatter (both adapters)
sortable?: boolean // default: true
filterable?: boolean // default: true
groupable?: boolean // default: false
}
```

React extends this with `render?` and `renderFilterLabel?`. Vue uses scoped slots instead.

## Development

See [CONTRIBUTING.md](./CONTRIBUTING.md).

## License

MIT