@oshon-ai/data
v0.9.3
Published
Oshon data-adaptive components (commercial tier) — DataTable + future Menu/Multiselect/etc. Auto-adapts across six density regimes (card / standard / paginated / virtualized / server / infinite) per ARCHITECTURE.md §3. Wraps TanStack Table for row-model b
Maintainers
Readme
@oshon-ai/data
Oshon's data-adaptive components — flagship DataTable plus the family of components that auto-scale across the six Phase-5a density regimes:
| Regime | Row count | Behavior |
| -------------- | ----------- | ------------------------------------------------- |
| card | 0–10 | <ul role="list"> with div cards |
| standard | 11–100 | Full <table>, client-side sort + filter |
| paginated | 101–1 000 | <table> + pagination footer (default page 50) |
| virtualized | 1 001–50 k | <table> + windowed rows via @tanstack/react-virtual |
| server | 50 k–1 M | Server pagination + server filter contracts |
| infinite | 1 M+ | Cursor-style infinite-scroll |
The regime auto-selects from data.length unless overridden via densityOverrides.regime.
Status
Shipping. DataTable is feature-complete for Phases A–F (universal ops, grouping, tree + master/detail, column controls, side bar, status bar). See docs/adr/ for the architectural decisions; tests in src/data-table/data-table.test.tsx cover every regime + a11y + permission gating.
License
Commercial. @oshon-ai/data is a paid tier — see LICENSE.md. It freely imports from the MIT free tier (@oshon-ai/{components, primitives, tokens}); the MIT tier may NOT import this package (enforced in CI by @oshon-ai/eslint-plugin's no-commercial-in-core rule).
Pricing: https://oshon.ai/pricing.
Install
pnpm add @oshon-ai/data @oshon-ai/tokensThe @oshon-ai/tokens peer dep provides the CSS custom-property contract DataTable's stylesheet reads. Wire the tokens into your Tailwind v4 stylesheet:
/* app/globals.css */
@import 'tailwindcss';
@import '@oshon-ai/tokens/css';
@import '@oshon-ai/tokens/tailwind';Then:
'use client';
import { DataTable, type DataColumnDef } from '@oshon-ai/data';
type Customer = {
id: string;
name: string;
status: 'active' | 'paused' | 'churned';
arr: number;
};
const columns: DataColumnDef<Customer>[] = [
{ accessorKey: 'id', header: 'ID' },
{ accessorKey: 'name', header: 'Customer', enableColumnFilter: true },
{ accessorKey: 'status', header: 'Status', enableColumnFilter: true },
{ accessorKey: 'arr', header: 'ARR' },
];
export function CustomersPage({ data }: { data: Customer[] }) {
return (
<DataTable<Customer>
data={data}
columns={columns}
rowKey={(row) => row.id}
enableRowSelection
enableQuickSearch
enableColumnFilters
/>
);
}Phases
DataTable ships in feature waves so each one can land + ship without holding up the others:
- Phase A — universal operations.
enableRowSelection,enableQuickSearch,enableColumnFilters, per-columnenableSorting. - Phase B — row grouping.
groupBy: string[], multi-level grouping,groupingAggregations(sum / mean / min / max / count / unique / uniqueCount / extent),defaultExpandedGroups. - Phase C — tree data + master/detail.
getSubRows,treeColumnId,getRowCanExpand,slots.detailRenderer. - Phase D — column controls.
defaultColumnOrder,hiddenColumns,enableColumnReorder. - Phase E — side bar. Tabbed columns / filters panel via
slots.sideBar. - Phase F — status bar. Row counts + aggregations via
slots.statusBar.
Every phase respects the same PermissionContext / onAudit contracts — see ADR-001 and ADR-003.
RBAC + audit
Every interactive operation is permission-gated and emits an audit event:
| Operation | Permission key | Audit event |
| ------------- | ----------------------------------------- | --------------------- |
| Sort | can('data:sort', 'table') | data:sort |
| Filter | can('data:filter', 'table') | data:filter |
| Selection | can('data:select', 'table', { rowId }) | data:select |
| Expand | (free) | data:expand |
| Denied access | — | permission:denied |
Pass permissions per-instance or wire a PermissionContext provider at the page root. Same for onAudit — per-instance prop OR an ambient AuditContext.
Tokens
Every color flows through Tier-2 Oshon semantic tokens (--oshon-color-border, --oshon-color-on-surface, --oshon-color-primary-soft, etc.) so the table flips correctly between light + dark + brand-seed themes without consumer overrides. The local --oshon-dt-* custom properties are the override surface — re-point them on any ancestor to retint a single instance without touching @oshon-ai/tokens.
Compatibility
- React 18.3+ (uses concurrent features in the virtualized regime).
'use client'required — the component owns sort / filter / selection state internally. Render it inside a client tree; the parent page can stay server-only.- TanStack Table v8 is bundled. Don't add it as a direct dependency in consumer code.
See also
apps/docs→/components/datatable— live preview + props table + Do/Don't.docs/adr/— architectural decisions (002 row-model, 003 control flow, etc.).MCP_SCHEMA.md— the manifest schema MCP tools consume.
