• CMSnpm version

    • Overview
    • ContentBuilder
    • InviteUserForm
    • LoginForm
    • RenewPasswordForm
  • UInpm version

    • Overview
    • Accordion
    • AlertBubble
    • AnnouncementBar
    • Avatar
    • AvatarFileInput
    • Badge
    • Button
    • ButtonGroup
    • ButtonList
    • Calendar
    • Checkbox
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • Chip
    • ColorRadio
    • ColorRadioGroup
    • Combobox
    • DatePicker
    • DatePickerInput
    • DateRangePicker
    • DateRangePickerInput
    • DatetimePicker
    • DatetimePickerInput
    • Dialog
    • Dropdown
    • Dropzone
    • ErrorMessage
    • FileInput
    • FlashMessages
    • FormComponent
    • Icon
    • IconButton
    • ImageGallery
    • InfoBox
    • Input
    • Label
    • Layout
    • Lightbox
    • ListItem
    • Loader
    • Lozenge
    • Menu
    • Message
    • Modal
    • ✅ ModalDialog
    • ✅ ModalHeader
    • MultiCombobox
    • MultiSelect
    • Pagination
    • Paper
    • Popover
    • Radio
    • RadioGroup
    • RasterImage
    • Select
    • ✅ Tabs
    • TextInput
    • TextLink
    • Textarea
    • TimePicker
    • TimePickerInput
    • Toggle
    • Tooltip
    • Typography
  • Formnpm version

    • Overview
    • AvatarFileInput
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • ColorRadioGroup
    • Combobox
    • DatePickerInput
    • DateRangePickerInput
    • DatetimePickerInput
    • Dropzone
    • FileInput
    • Form
    • FormRenderer
    • GpsInput
    • MoneyInput
    • MultiCombobox
    • MultiSelect
    • NumberInput
    • PasswordInput
    • RadioGroup
    • Select
    • TextInput
    • Textarea
    • TimePickerInput
    • Toggle
  • DataGridnpm version

    • Overview
    • DataGrid
    • DataGridCustomExample
    • ExportButton
    • FilterList
    • Filters
    • FiltersButton
    • FulltextInput
    • HiddenColumns
    • HiddenColumnsButton
    • Pagination
    • RowCounts
    • RowsPerPageSelect
    • SelectedRowsToolbar
    • TableV2
    • ToolbarControl
    • ToolbarCustoms
    • ToolbarTabs
  • Wysiwygnpm version

    • Overview
  • Resizernpm version

    • Overview
  • Routernpm version

    • Overview
  • Corenpm version

    • Overview
  • Core-Reactnpm version

    • Overview
  • Stylesnpm version

    • Overview
  • Localizenpm version

    • Overview
  • Analyticsnpm version

    • Overview
  • Datepickernpm version

    • Overview
  • Icons-generatornpm version

    • Overview
  • Smart-addressnpm version

    • Overview
  • E2Enpm version

    • Overview
  • E2E-Playwrightnpm version

    • Overview

@uxf/data-grid

A schema-driven, server-side data grid: one compound DataGrid component with a built-in toolbar, tabs, filters, sorting, column visibility, row selection, pagination and CSV export.

When to use

Reach for @uxf/data-grid when you have a paginated, filterable, server-fetched table driven by a generated schema (columns, filters, tabs). The grid owns fetching, filtering, sorting and pagination state; you provide a schema and a loader.

It is not a headless table primitive and not a spreadsheet — layout, toolbar and footer are opinionated. For a plain, fully custom table render the internal parts yourself (see Custom composition) rather than reaching for a different library.

Note: This package ships translations. Wrap your app in the TranslationsProvider from @uxf/core-react/translations for correct labels.

Installation

yarn add @uxf/data-grid

Peer dependencies (install if not already present):

yarn add @uxf/core @uxf/core-react @uxf/localize @uxf/styles @uxf/ui \
  @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities dayjs react react-dom

CSS

Import the dependency stylesheets first, then the grid's own stylesheet last. The @uxf/ui component styles are published under the flattened @uxf/ui/css/ directory (the @uxf/ui/<component>/<file>.css source paths do not exist in the published package).

@import url("tailwindcss/components.css");
@import url("@uxf/ui/css/button.css");
@import url("@uxf/ui/css/button-list.css");
@import url("@uxf/ui/css/calendar.css");
@import url("@uxf/ui/css/checkbox.css");
@import url("@uxf/ui/css/chip.css");
@import url("@uxf/ui/css/dialog.css");
@import url("@uxf/ui/css/dropdown.css");
@import url("@uxf/ui/css/icon.css");
@import url("@uxf/ui/css/label.css");
@import url("@uxf/ui/css/form-component.css");
@import url("@uxf/ui/css/input-basic.css");
@import url("@uxf/ui/css/input.css");
@import url("@uxf/ui/css/input-with-popover.css");
@import url("@uxf/ui/css/combobox.css");
@import url("@uxf/ui/css/modal-header.css");
@import url("@uxf/ui/css/multi-select.css");
@import url("@uxf/ui/css/multi-combobox.css");
@import url("@uxf/ui/css/pagination.css");
@import url("@uxf/ui/css/select.css");
@import url("@uxf/ui/css/toggle.css");
@import url("@uxf/ui/css/tabs.css");

/* must be after the component css files */
@import url("@uxf/data-grid/styles.css");

Quick start

useDataGridControl owns grid state and actions; useDataGridFetching runs the loader whenever the request changes. Feed both into DataGrid.

"use client";

import { DataGrid } from "@uxf/data-grid";
import { useDataGridControl } from "@uxf/data-grid/use-data-grid-control";
import { useDataGridFetching } from "@uxf/data-grid/use-data-grid-fetching";
import { schema } from "@generated/data-grid/schema/example";

export function ExampleGrid() {
    const { state, actions } = useDataGridControl({ schema });

    const { isLoading, error, data, reload } = useDataGridFetching({ schema, state });

    return (
        <DataGrid
            actions={actions}
            data={data}
            error={error}
            isLoading={isLoading}
            reload={reload}
            schema={schema}
            state={state}
        />
    );
}

useDataGridFetching uses a default loader that calls the conventional grid endpoint. To fetch yourself, pass a loader:

const { ... } = useDataGridFetching({
    schema,
    state,
    loader: (gridName, request, encodedRequest) => myFetch(gridName, request),
});

Persisting user config

useUserConfigLocalStorageAdapter returns a middleware (persists column visibility, widths, order, etc. to localStorage) and a useUserConfig hook that restores it. Wire the middleware into useDataGridControl and call useUserConfig(actions).

import { useDataGridControl } from "@uxf/data-grid/use-data-grid-control";
import { useUserConfigLocalStorageAdapter } from "@uxf/data-grid/user-config-storage-adapters/local-storage";

const { middleware, useUserConfig } = useUserConfigLocalStorageAdapter(schema);

const { state, actions } = useDataGridControl({
    schema,
    middleware,
    // optional base64-encoded request or a Request object to hydrate initial state
    initialState: encodedRequest,
    // optional default column config
    initialUserConfig: {
        columns: {
            id: { isHidden: true },
        },
    },
});

useUserConfig(actions);

API

Only exports listed below are part of the public surface. Import paths resolve by filesystem (there is no exports map).

Root export — @uxf/data-grid

Name Kind Description
DataGrid component The compound grid. Props: DataGridProps<GridType>.
DataGridProps<GridType> type Grid props = base props + control (state, actions) + data (isLoading, error, data, reload).
InferDataGridRow<Schema> type Derives the row shape from a schema via ColumnTypes.
BaseGridType, Schema, ChangeTabFilterBehavior, DataGridActionCell, … types Re-exported from ./types.
mergeSchemaWithConfig(schema, config) fn Returns a new schema with a frontend config applied (see below).
encodeFilter(request) / decodeFilter(string) fn Base64 (de)serialize a grid request.

Deep imports

Import path Export Description
@uxf/data-grid/use-data-grid-control useDataGridControl(config) Owns grid state + actions. Config: { schema, initialState?, initialUserConfig?, middleware? }.
@uxf/data-grid/use-data-grid-fetching useDataGridFetching(config) Runs the loader on request changes. Config: { schema, state, loader?, isWithTabCounts? }. Returns { isLoading, error, data, reload }.
@uxf/data-grid/user-config-storage-adapters/local-storage useUserConfigLocalStorageAdapter(schema), useClearLocalStorageUserConfig(schema) localStorage persistence of user column config.
@uxf/data-grid/column-types ColumnTypes (interface) Augment to register custom column value types.

Notable optional DataGrid props: actionCell, bodyCells, changeTabFilterBehavior, customActions, filterHandlers, fulltextInputPlaceholder, getCsvDownloadUrl, hasStickyHeader, isRowsSelectable, isRowSelectDisabled, isWithTabCounts, keyExtractor, rowAccent, rowClassName, rowHeight, tabsVariant, HiddenColumnsComponent, NoRowsFallback, SelectedRowsToolbarActions, isDebug.

Column types

A column's type (from the schema) maps to a value type via the ColumnTypes interface, which drives InferDataGridRow. Built-in types:

boolean, chip, chips, date, datetime, email, id, int, money, phone, string, url, uuid.

Register a custom column type with module augmentation. Create a column-types.d.ts at the project root (next to tsconfig.json) — it must be an interface:

declare module "@uxf/data-grid/column-types" {
    export interface ColumnTypes {
        "my-custom-type": MyCustomType;
    }
}

Then infer the row type from a schema:

import { InferDataGridRow } from "@uxf/data-grid";
import { schema } from "@generated/data-grid/schema/example";

type Row = InferDataGridRow<typeof schema>;

Filter handlers

Each filter is rendered by looking up filterHandlers[filter.type]. The grid uses defaultFilterHandlers unless you pass a filterHandlers prop. Built-in handler keys:

filter.type Renders
checkbox Checkbox (value is sent only when checked)
date Date range (from / to date pickers)
datetime Datetime range
entitySelect Single-select combobox (async entity)
entityMultiSelect Multi-select combobox (async entity)
interval Numeric range (min / max inputs)
multiSelect Multi-select
select Select
string Text input

Extend or override by merging into defaultFilterHandlers and passing the result as the filterHandlers prop:

import { defaultFilterHandlers } from "@uxf/data-grid/filter-handler";

<DataGrid filterHandlers={{ ...defaultFilterHandlers, myType: myHandler }} {...rest} />;

Frontend config

mergeSchemaWithConfig returns a new schema with per-column and per-filter overrides and perPage applied — useful for tweaking a generated schema without regenerating it.

import { DataGrid } from "@uxf/data-grid";
import { mergeSchemaWithConfig } from "@uxf/data-grid";
import { useDataGridControl } from "@uxf/data-grid/use-data-grid-control";
import { useDataGridFetching } from "@uxf/data-grid/use-data-grid-fetching";
import { schema as baseSchema } from "@generated/data-grid/schema/example";

const schema = mergeSchemaWithConfig(baseSchema, {
    perPage: 100,
    columns: {
        id: { width: 100, isHidden: true },
    },
    filters: {
        id: { placeholder: "Search by ID..." },
    },
});

export function ConfiguredGrid() {
    const { state, actions } = useDataGridControl({ schema });
    const { isLoading, error, data, reload } = useDataGridFetching({ schema, state });

    return (
        <DataGrid
            actions={actions}
            data={data}
            error={error}
            isLoading={isLoading}
            reload={reload}
            schema={schema}
            state={state}
        />
    );
}

Custom composition

The DataGrid component is a fixed composition of internal parts. For a fully custom layout, import the parts individually and assemble them yourself, still driving them from useDataGridControl / useDataGridFetching:

@uxf/data-grid/root, @uxf/data-grid/toolbar, @uxf/data-grid/toolbar-tabs, @uxf/data-grid/toolbar-control, @uxf/data-grid/toolbar-customs, @uxf/data-grid/filter-list, @uxf/data-grid/table-v2, @uxf/data-grid/footer, @uxf/data-grid/pagination, @uxf/data-grid/row-counts, @uxf/data-grid/rows-per-page-select, @uxf/data-grid/selected-rows-toolbar, @uxf/data-grid/linear-progress, @uxf/data-grid/body-cell, @uxf/data-grid/filter-handler.

See data-grid.tsx (the default composition) and data-grid-custom-example.stories.tsx in the package for a worked example.

Gotchas

  • Client component only. The hooks use React state, effects and localStorage. Render the grid in a client component ("use client").
  • TranslationsProvider required. Labels come from bundled translations via @uxf/core-react/translations.
  • CSS order matters. Import @uxf/data-grid/styles.css after the @uxf/ui/css/* component styles.
  • ColumnTypes augmentation must be an interface, not a type, or the declaration merge will not apply.
  • initialState is a base64-encoded request string (or a Request object) — use encodeFilter / decodeFilter to (de)serialize, e.g. to persist the current view in the URL.
  • isDebug is a DataGrid prop, not a useDataGridControl config option.