diff --git a/src/components/DataTable/__tests__/DataTable.spec.tsx b/src/components/DataTable/__tests__/DataTable.spec.tsx
index 0e16373..b9d34cb 100644
--- a/src/components/DataTable/__tests__/DataTable.spec.tsx
+++ b/src/components/DataTable/__tests__/DataTable.spec.tsx
@@ -3,7 +3,7 @@ import { useState } from 'react';
import { faker } from '@faker-js/faker';
import type { ColumnDef } from '@tanstack/table-core';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
-import { range } from 'lodash-es';
+import { noop, range } from 'lodash-es';
import { describe, expect, it } from 'vitest';
import { DataTable } from '../DataTable.tsx';
@@ -152,3 +152,25 @@ describe('DataTable pagination', () => {
expect(screen.getAllByTestId('data-table-row').length).toBe(1);
});
});
+
+describe('DataTable server mode', () => {
+ const serverProps = {
+ columns,
+ data: data.slice(0, 10),
+ mode: 'server',
+ onPaginationChange: noop,
+ pageCount: 3
+ } as const;
+
+ it('should pin a column named by its initial state, so a server-mode table can size it', () => {
+ render();
+ expect(screen.getByText('Amount')).toHaveStyle({ position: 'sticky' });
+ expect(screen.getByText('Status')).not.toHaveStyle({ position: 'sticky' });
+ expect(screen.getByText('Email')).not.toHaveStyle({ position: 'sticky' });
+ });
+
+ it('should pin nothing when given no initial state', () => {
+ render();
+ expect(screen.getByText('Amount')).not.toHaveStyle({ position: 'sticky' });
+ });
+});
diff --git a/src/components/DataTable/types.ts b/src/components/DataTable/types.ts
index a35c9eb..7ea4e68 100644
--- a/src/components/DataTable/types.ts
+++ b/src/components/DataTable/types.ts
@@ -96,11 +96,12 @@ export type MemoizedHandle any> = T & {
* CLIENT
*********************************************************************/
-export type ClientDataTableInitialState = {
- columnFilters?: ColumnFiltersState;
- columnPinning?: ColumnPinningState;
- sorting?: SortingState;
-};
+export type ClientDataTableInitialState = Simplify<
+ ServerDataTableInitialState & {
+ columnFilters?: ColumnFiltersState;
+ sorting?: SortingState;
+ }
+>;
export type ClientDataTableStoreParams = Simplify<
BaseDataTableStoreParams & {
@@ -117,9 +118,19 @@ export type ClientDataTableProps = Simplify<
* SERVER
*********************************************************************/
+/**
+ * Pinning is layout rather than a view of the data: `calculateColumnSizing` honours `size` on a
+ * pinned column and splits what is left between the rest, so it is how a table of any mode gives
+ * one column the room its content needs. Filtering and sorting in server mode belong to the
+ * request, so they stay out.
+ */
+export type ServerDataTableInitialState = {
+ columnPinning?: ColumnPinningState;
+};
+
export type ServerDataTableStoreParams = Simplify<
BaseDataTableStoreParams & {
- initialState?: never;
+ initialState?: ServerDataTableInitialState;
mode: 'server';
onPaginationChange: (state: PaginationState) => void;
onSortingChange?: (state: SortingState) => void;
diff --git a/src/components/DataTable/utils.tsx b/src/components/DataTable/utils.tsx
index 69171ba..0992229 100644
--- a/src/components/DataTable/utils.tsx
+++ b/src/components/DataTable/utils.tsx
@@ -14,6 +14,7 @@ import { DataTableRowActionCell } from './DataTableRowActionCell.tsx';
import type {
BaseDataTableStoreParams,
+ ClientDataTableInitialState,
DataTableColumnBreakpoints,
DataTableRowAction,
DataTableStoreParams,
@@ -136,7 +137,10 @@ function getColumnPinningWithActions(
}
function getTanstackTableState({ initialState, rowActions }: DataTableStoreParams): TableState {
- const { columnFilters = [], columnPinning = {}, sorting = [] } = initialState ?? {};
+ // Widened to the client shape, which the server one is a subset of, so the union's narrower
+ // member does not make `columnFilters` and `sorting` unreadable here.
+ const initial: ClientDataTableInitialState = initialState ?? {};
+ const { columnFilters = [], columnPinning = {}, sorting = [] } = initial;
const state: TableState = {
columnFilters,
columnOrder: [],