Docyrus

PivotGrid

Cross-tabulation pivot grid with multi-dimension rows and columns, aggregation, conditional cell coloring, expand and collapse, pinned value columns, a drilldown action sheet, a toolbar, and CSV, Excel and PDF export.

iOSAndroid
Preview PivotGrid on your device

Scan with Expo Go

Download Expo Go, then scan the QR code to preview native components.

Installation

pnpm dlx @docyrus/cli add @docyrus/rn-pivot-grid
Required Packages(5 packages)
pnpm add jsonata @shopify/flash-list expo-file-system (optional) expo-sharing (optional) expo-print (optional)

The export modules are optional peers and are loaded lazily. CSV and Excel exports need expo-file-system (SDK 54+ File API) and expo-sharing. PDF export needs expo-print and expo-sharing. When a module is missing, the export does nothing.

For a server-backed pivot, see useDocyrusPivotGrid.

Usage

import { Badge } from '@/components/docyrus-native/badge';
import {
  PivotGrid,
  PivotGridView,
  PivotGridToolbar,
  PivotGridDrilldownModal,
  usePivotGrid,
  type PivotGridDimension,
  type PivotGridMeasure,
} from '@/components/docyrus-native/pivot-grid';

interface SalesRow {
  region: string;
  product: string;
  revenue: number;
}

const data: SalesRow[] = [
  { region: 'North', product: 'Widget A', revenue: 1200 },
  { region: 'North', product: 'Widget B', revenue: 850 },
  { region: 'South', product: 'Widget A', revenue: 960 },
  { region: 'South', product: 'Widget B', revenue: 1100 },
];

const rowDimensions: PivotGridDimension<SalesRow>[] = [
  { id: 'region', label: 'Region', getValue: (row) => row.region },
];

const columnDimensions: PivotGridDimension<SalesRow>[] = [
  { id: 'product', label: 'Product', getValue: (row) => row.product },
];

const measures: PivotGridMeasure<SalesRow>[] = [
  {
    id: 'revenue',
    label: 'Revenue',
    getValue: (row) => row.revenue,
    aggregate: 'sum',
    formatValue: (v) => `$${v.toLocaleString()}`,
  },
];

function SalesPivot() {
  const controller = usePivotGrid({
    data,
    rowDimensions,
    columnDimensions,
    measures,
    height: 400,
    initialState: { columnPinning: { right: [] } },
    exportFileName: 'sales-report'
  });

  return (
    <>
      <PivotGridToolbar
        controller={controller}
        startContent={<Badge>{data.length} rows</Badge>} />
      <PivotGridView controller={controller} />
      <PivotGridDrilldownModal controller={controller} />
    </>
  );
}

// Or self-contained (creates its own controller):
<PivotGrid data={data} rowDimensions={rowDimensions} columnDimensions={columnDimensions} measures={measures} height={400} />

Features

  • Multi-dimension pivoting — 1-3 row/column dimensions with nested grouping
  • Aggregation — sum, count, avg, min, max
  • Expand/collapse — toggle individual rows/columns or expand/collapse all
  • Conditional coloring — JSONata-based cell color rules with Tailwind color support
  • Drilldown — tap a leaf cell to see contributing source rows in an action sheet
  • Toolbar — expand / collapse buttons, the export menu, and startContent / endContent slots
  • Export — CSV, a real .xlsx workbook (merged multi-level headers, frozen panes, styled subtotal and total rows, written by a zero-dependency OOXML writer) and PDF (expo-print). Each export opens the native share sheet.
  • Pinned value columns — pinColumns(ids, 'left' | 'right') keeps columns sticky while you scroll horizontally. Row headers are always pinned.
  • Virtualized scrolling — FlashList windowing for large datasets
  • Synchronized scroll — row headers and column headers stay in sync with the data grid

API Reference

PivotGrid / usePivotGrid props

PivotGrid takes the same props as usePivotGrid (PivotGridProps = UsePivotGridProps) and creates its own controller.

PropTypeDefaultDescription
dataTData[]—Source rows. Required.
rowDimensionsPivotGridDimension<TData>[]—Row grouping dimensions (outermost → innermost). Required.
columnDimensionsPivotGridDimension<TData>[]—Column grouping dimensions. Required.
measuresPivotGridMeasure<TData>[]—Aggregation measures. Required.
getRowId(row: TData, index: number) => string—Stable row id.
initialStatePartial<PivotGridState>—Initial expanded rows and columns, column pinning and column sizing.
cellColorRulesPivotGridCellColorRule[]—JSONata-based conditional cell colors.
drilldownPivotGridDrilldown<TData>—Drilldown columns and title getter.
heightnumber480Grid height in px.
rowHeaderWidthnumber140Width of the first row-header column.
childRowHeaderWidthnumber110Width of the other row-header columns.
valueColumnWidthnumber100Leaf value column width.
subtotalColumnWidthnumber108Subtotal column width.
grandTotalColumnWidthnumber120Grand-total column width.
rowHeightnumber40Data row height.
headerRowHeightnumber40Header row height.
exportFileNamestring'pivot-grid'Base file name for CSV, Excel and PDF exports.
classNamestring—Container classes.
styleViewStyle—Deprecated. Use className.

PivotGridView

Renders a controller from usePivotGrid. Use it to share one controller with the toolbar and the drilldown modal.

PropTypeDefaultDescription
controllerPivotGridController<TData>—Controller instance. Required.
classNamestringcontroller.classNameContainer classes.
styleViewStyle—Deprecated. Use className.

PivotGridToolbar

A horizontally scrolling toolbar with expand rows, collapse rows, expand columns, collapse columns and the export menu.

PropTypeDefaultDescription
controllerPivotGridController<TData>—Controller instance. Required.
startContentReactNode—Rendered before the built-in buttons.
endContentReactNode—Rendered after the export button.
showExportbooleantrueShow the export menu button.
classNamestring—Classes for the scroll container.

PivotGridExportMenu

An export button that opens an action sheet with Export CSV, Export Excel and Export PDF. It replaces the web dropdown.

PropTypeDefaultDescription
controllerPivotGridController<TData>—Controller instance. Required.
classNamestring—Button classes.

PivotGridDrilldownModal

An action sheet that lists the source rows behind a tapped leaf cell.

PropTypeDefaultDescription
controllerPivotGridController<TData>—Controller instance. Required.
columnsNativeDrilldownColumn<TData>[]controller.drilldownColumnsColumns shown for each row.

PivotGridController

Returned by usePivotGrid.

FieldTypeDescription
classNamestring | undefinedContainer classes forwarded from props.
rowHeaderColumnIdsstring[]Synthetic row-header ids (__pivot_row_header_<index>).
valueColumnIdsstring[]Visible value-column ids in render order: left-pinned, center, right-pinned.
visibleLeafColumnsPivotGridLeafColumn<TData>[]Visible value columns in render order.
headerRowsPivotGridHeaderRow[]Column header rows (cells carry pinPosition).
headerDepthnumberNumber of header rows.
visibleRowsPivotGridRenderedRow<TData>[]Rendered rows (group, leaf, subtotal, grand-total).
rowDimensionsPivotGridDimension<TData>[]Row dimensions.
cellColorMapMap<string, string>Cell id → background color from the color rules.
drilldownColumnsNativeDrilldownColumn<TData>[] | undefineddrilldown.columns, or columns derived from the first row's keys.
drilldownStatePivotGridDrilldownState<TData>{ open, cell }.
columnWidthsPivotGridColumnWidths{ rowHeaders: number[]; valueColumns: Map<string, number> }.
columnPinningPivotGridColumnPinningStateCurrent value-column pinning.
getColumnPinPosition(columnId: string) => PivotGridPinPosition'left', 'right' or false.
rowHeight / headerRowHeight / heightnumberResolved sizes.
toggleRow / toggleColumn(nodeId: string) => voidExpand or collapse one group.
expandAllRows / collapseAllRows / expandAllColumns / collapseAllColumns() => voidBulk expand or collapse.
pinColumns(columnIds: string[], position: 'left' | 'right') => voidPin value columns (sticky while scrolling horizontally).
unpinColumns(columnIds: string[]) => voidUnpin value columns.
openDrilldown / closeDrilldown(cell) => void / () => voidDrilldown sheet control.
getDrilldownRows(cell: PivotGridRenderedCell<TData>) => TData[]Source rows of a cell.
getDrilldownTitle(cell: PivotGridRenderedCell<TData>) => stringTitle (custom drilldown.getTitle, or row path x column path).
exportCsv() => Promise<void>Shares a CSV file.
exportExcel() => Promise<void>Shares an .xlsx workbook.
exportPdf() => Promise<void>Shares a PDF rendered by expo-print.

PivotGridState

FieldTypeDescription
expandedRowIdsRecord<string, boolean>Expanded row group ids (default: all expanded).
expandedColumnIdsRecord<string, boolean>Expanded column group ids.
columnPinningPivotGridColumnPinningState{ left?: string[]; right?: string[] }. Value-column ids only; row headers are always pinned.
columnSizingPivotGridColumnSizingStateRecord<columnId, px> width overrides. Row headers use __pivot_row_header_<index>.

PivotGridDimension

FieldTypeDescription
idstringUnique dimension id.
labelstringDisplay label.
getValue(row: TData) => unknownExtracts the dimension value.
formatValue(value: unknown) => stringOptional value formatter.
sort(a: unknown, b: unknown) => numberOptional sort comparator.
emptyLabelstringLabel for empty or null values.

PivotGridMeasure

FieldTypeDescription
idstringUnique measure id.
labelstringDisplay label.
getValue(row: TData) => number | null | undefinedValue accessor (omit to count rows).
aggregatePivotGridAggregate'sum' | 'count' | 'avg' | 'min' | 'max'.
formatValue(value: number) => stringOutput formatter.

PivotGridCellColorRule

FieldTypeDescription
formulastringJSONata expression (receives value, measureId, rowPath, columnPath, …).
colorstringTailwind color name (for example 'green-100') or a hex value.
scopePivotGridColorScopeOptional: 'leaf' | 'subtotal' | 'total' | 'grand-total'.

PivotGridDrilldown / NativeDrilldownColumn

FieldTypeDescription
columnsNativeDrilldownColumn<TData>[]{ id: string; header: string; getValue: (row: TData) => string }[].
getTitle(cell: PivotGridRenderedCell<TData>) => stringCustom drilldown title.

Translations

KeyEnglish fallback
ui.pivotGrid.expandRows / collapseRows / expandColumns / collapseColumnsExpand rows / Collapse rows / Expand columns / Collapse columns
ui.pivotGrid.export / exportCsv / exportExcel / exportPdfExport / Export CSV / Export Excel / Export PDF
ui.pivotGrid.noDataNo data to pivot
ui.pivotGrid.grandTotalGrand Total (drilldown title)
ui.pivotGrid.contributingRows / rowNumber / noRows{count} contributing row(s) / Row {index} / No rows to display

Hooks

usePivotGrid

const controller = usePivotGrid<TData>(props: UsePivotGridProps<TData>);

Returns a PivotGridController with the full view model and every action callback. Use it when PivotGridView, PivotGridToolbar and PivotGridDrilldownModal need to share one controller.

Components

ComponentDescription
PivotGridSelf-contained grid.
PivotGridViewGrid for an external controller.
PivotGridToolbarExpand / collapse / export toolbar.
PivotGridExportMenuExport action sheet.
PivotGridDrilldownModalDrilldown action sheet.

Type Exports

TypeDescription
PivotGridPropsProps for PivotGrid (alias of UsePivotGridProps).
UsePivotGridPropsProps accepted by usePivotGrid.
PivotGridControllerController returned by usePivotGrid.
PivotGridToolbarPropsProps for PivotGridToolbar.
PivotGridExportMenuPropsProps for PivotGridExportMenu.
PivotGridDimensionDimension definition (row or column).
PivotGridMeasureMeasure definition.
PivotGridAggregate'sum' | 'count' | 'avg' | 'min' | 'max'.
PivotGridCellColorRuleConditional cell color rule.
PivotGridColorScope'leaf' | 'subtotal' | 'total' | 'grand-total'.
PivotGridStateExpanded, pinning and sizing state.
PivotGridColumnPinningState{ left?: string[]; right?: string[] }.
PivotGridColumnSizingStateRecord<string, number>.
PivotGridPinPosition'left' | 'right' | false.
PivotGridDrilldownDrilldown configuration.
PivotGridDrilldownStateDrilldown open and cell state.
PivotGridHeaderRow / PivotGridHeaderCellHeader structures.
PivotGridLeafColumnLeaf column structure.
PivotGridRenderedRow / PivotGridRenderedCellRendered row and cell.
PivotGridColumnWidthsRow-header and value-column widths.
NativeDrilldownColumnDrilldown column definition.
PivotGridDemoRowDemo row shape (with createPivotGridDemoRows and the pivotGridDemo* presets).

On this page