Skip to content

Customization and Export

Pivot Charts separate portable model presentation from renderer-wide styling. Use presentation and chartOptions when the choice must persist with one chart. Configure createPivotChartsRenderer when an application needs a shared palette, typography, tooltip, or export pipeline.

The Data and Customize inspectors group related controls into collapsible sections. Data starts with ordered row and column fields and checkbox measure selection; sorting, ranking, member filters, and the Pivot connection are separate sections. Valid query edits update automatically. Customize starts with labels and legend, with appearance, axes, colors, navigation, interaction, and references available in their own sections. Collapsing a section preserves its draft edits. Switching tabs also preserves Customize drafts and expanded sections. Presentation, colors, annotations and query edits update automatically. Incomplete numeric or reference edits stay local with validation feedback until valid. Color controls use the shared Pro palette and native color chooser, without a free-text color field. Automatic restores the default color where supported. Reset colors preserves combination layer and axis assignments, including changes still being processed.

The picker captions and swatch names are customizable through localeText.colors.picker.customColor and localeText.colors.picker.colorLabels. Each existing color control policy continues to hide or disable its picker. Legacy Apply policy and translation keys remain accepted for compatibility; the inspector no longer renders those actions.

Rename section titles with localeText.inspector. Hide or disable a whole section with pivotChartsUi.controls['inspector.<section>']; existing leaf control policies continue to apply. Section IDs are source, fields, sort, filters, connection, presentation, appearance, axes, colors, navigation, interaction, and annotations.

grid.pivotChartsUi = {
localeText: {
inspector: { fields: 'Fields to compare', annotations: 'Notes and targets' },
},
controls: {
'inspector.navigation': 'hidden',
'inspector.axes': 'disabled',
},
};

Existing chartOptions.heading, colors.heading, annotations.heading, navigation.heading, and interaction.heading overrides remain section-title fallbacks. An explicit inspector title takes precedence.

Interactive example

Chart presentation

Change titles, legend placement, and data labels to compare the chart's presentation.

The example loads when visible.

await chart.update({
presentation: {
title: 'Quarterly sales',
subtitle: 'Committed orders only',
legendPosition: 'bottom',
dataLabels: true,
xAxisTitle: 'Region',
yAxisTitle: 'Revenue',
},
theme: 'material',
});

legendPosition accepts top, right, bottom, left, or none. theme accepts auto or a renderer-supported theme string. The standard UI offers follow-grid, default, material, compact, dark material, and dark compact choices, plus high contrast and dark high contrast.

The catalog generates a typed option schema for every chart:

OptionAvailabilityValid values
showGridLinesCharts with axes.Boolean.
markOpacityEvery built-in type.0.2–1 in 0.05 steps.
strokeWidthLine, area, combination, radar line, and radar area.1–6 in 0.5 steps.
fillOpacityArea-family, area-line, radar area, confidence band, and range area.0.1–0.9 in 0.01 steps.
facetScaleModeSmall multiples.independent (default) or shared.
await chart.update({
chartOptions: {
showGridLines: false,
markOpacity: 0.9,
strokeWidth: 2.5,
},
});

Unsupported keys, out-of-range values, and values that do not align with the declared step are rejected during update and restore.

Small multiples use independent value domains by default. This emphasizes each series’ trend; equal panel heights can represent very different values. Choose shared scales when comparing magnitudes:

await chart.update({
chartType: 'smallMultiples',
chartOptions: { facetScaleMode: 'shared' },
});

Panels show their scale mode and value ticks. Shared domains use the complete visible series data, including values omitted by path sampling or outside the current viewport. Independent domains use each series’ complete values. Changing visibility can change these domains. Reference lines and notes follow the same panel scales as the plotted data.

Portable colors settings complement the renderer palette. The default paletteMode: 'index' preserves palette order; opt into 'semantic' to assign colors by measure and field-qualified member identity across reordering and refresh. Labels do not determine identity. Semantic mode requires field metadata for nonempty member paths; providers supply it through hierarchy definitions or selection fields. Missing metadata is rejected instead of reverting to an unstable index color.

Configured measure IDs keep semantic colors stable when measures are reordered. Without a configured ID, measure identity includes its original configured index to distinguish repeated measures; reordering that configuration can therefore change its palette assignment.

await chart.update({
colors: {
paletteMode: 'semantic',
measures: [{
measure: { prop: 'sales', aggregator: 'sum', valueIndex: 0 },
color: '#2563eb',
}],
members: [{
axis: 'row',
path: [{ field: 'region', value: 'North' }],
color: '#f97316',
pattern: 'diagonal',
}],
},
});

Member overrides match the exact field-qualified path; they do not implicitly color descendants or synthetic Other members with a matching label. Authored colors accept #RGB or #RRGGBB. Unavailable identities remain dormant so styling can return when a member or series reappears. When measure selectors overlap, the first matching measure-color entry wins. Duplicate exact member paths or measure selectors are rejected.

Supported discrete marks can map their analytical value to color:

await chart.update({
colors: {
valueMap: {
type: 'diverging',
min: -100,
midpoint: 0,
max: 100,
colors: ['#2563eb', '#ffffff', '#dc2626'],
},
},
});

continuous maps between two colors. conditional applies the first matching numeric gt, lt, equal, or inclusive between rule, with an optional fallback color. Mappings use analytical values, preserve missing observations, and clamp outside explicit domains. Automatic domains use the visible series’ full data, independently of viewport sampling.

Numeric mappings display a separate color key even when the ordinary legend is hidden. Gradient keys show their domain; conditional keys show a bounded set of swatches and the number of additional rules. The Customize controls retain the complete rule list.

Value mapping takes precedence over explicit series/member colors, followed by measure colors and the palette. Mapping is supported for grouped bar and column, heatmap/calendar heatmap, and pie/donut/semi-donut charts. Line colors represent series; numeric mapping of an entire line is unsupported. Aggregated heatmap buckets cannot receive canonical member or value mappings.

For independently visible series, seriesOverrides can persist color and visible. Line-bearing charts also support lineDash and marker:

await chart.update({
seriesOverrides: {
[forecastSeriesId]: {
color: '#475569',
visible: true,
lineDash: 'dash',
marker: 'diamond',
},
},
presentation: { legendAction: 'toggleVisibility' },
});

Visibility removes a series from plotted geometry, scales, stacks, tooltips, and rendered exports while retaining the canonical chart dataset. Hidden series remain available in the legend and Customize controls. Hiding every series leaves a recoverable empty plot. Appearance and visibility changes do not request new provider data or change the shared Pivot.

Series visibility is supported by bar/column and line/area families, combination charts, annotated time series, and small multiples. Required relationship or financial channels cannot be hidden as independent series. Unsupported authored settings are rejected according to chart capabilities.

colors and seriesOverrides updates replace their whole authored objects; omit them to preserve settings or pass {} to reset. Custom renderers must opt into the new appearance and visibility capabilities.

Persist thresholds and notes in annotations. References use logical axes: category, primary, or secondary. On horizontal bars, the primary value axis runs horizontally. Secondary references require a combination chart.

await chart.update({
annotations: {
references: [
{
id: 'target',
kind: 'line',
axis: 'primary',
value: 2500,
label: 'Sales target',
color: '#dc2626',
lineDash: 'dash',
},
{
id: 'expected-range',
kind: 'band',
axis: 'primary',
min: 1000,
max: 2000,
color: '#2563eb',
opacity: 0.2,
},
],
notes: [{
id: 'launch',
target: {
row: [{ field: 'region', value: 'North' }],
column: [],
measure: { prop: 'sales', aggregator: 'sum' },
},
text: 'New product launch',
placement: 'above',
}],
},
});

Category lines use at; category bands use from and to. Each coordinate is either { scale: 'category', path: [{ field, value }], measure? } or { scale: 'time', value: utcEpochMilliseconds }. Time coordinates require an actual time axis. Category bands span the centers of their semantic endpoints in the current order. They do not create extra category buckets.

References use the existing plot domain: off-domain lines disappear and bands are clipped. They never stretch the scale. Numeric bounds must be finite and ordered; references on logarithmic axes must be positive. In small multiples, a primary reference applies the same authored value to each panel’s own scale.

Notes match exact field-qualified row and column paths plus a measure, rather than labels or array indexes. Use a configured measure ID to distinguish repeated measures; an explicit valueIndex further constrains the match. Group and collapsed aggregate points can have notes. Subtotals, grand totals, synthetic Other members, and ambiguous targets are unavailable.

A missing, hidden, null, off-screen, or omitted-panel target keeps its authored note dormant. When that exact observation returns, the note follows its current value. Drilling to children never reassigns a parent’s note. Nonempty paths require provider field metadata. Notes can anchor observations omitted by visual sampling, and do not intercept chart selection or drill actions.

The Customize tab applies valid edits automatically and provides Clear controls for editing references and notes. Annotation edits preserve provider data and survive refresh, unlink, and JSON restoration. Pass annotations: {} to clear them; omit the field to preserve them. Updates replace the whole annotation object. Each array accepts up to 32 entries, IDs up to 128 characters, reference labels up to 256 characters, and nonblank note text up to 512 characters.

Supported families are grouped bar/column, unstacked line/area variants, combination charts, annotated time series, and small multiples. Unsupported families reject authored annotations. Custom renderers opt in through capabilities.annotations. Existing automatic extrema labels are independent of authored notes. Rendered references and notes follow the chart’s label, theme, and image/document export pipeline. The label formatter receives annotationId and annotationKind (reference or note) for authored labels. Notes retain their canonical datum context; numeric reference labels expose the threshold value without pretending to be a data observation. Long labels wrap within the panel, with complete text retained in accessible titles.

Interactive example

Chart styling and labels

Compare label formatting, typography, and presentation in the chart.

The example loads when visible.

const renderer = createPivotChartsRenderer({
className: 'sales-chart',
fontFamily: '"IBM Plex Sans", sans-serif',
categorySeparator: ' / ',
palette: ['#2563eb', '#f97316', '#16a34a'],
theme: ({ theme }) => ({
...theme,
background: '#fffdf8',
foreground: '#292524',
grid: '#e7e5e4',
}),
});

The theme callback receives the resolved light/dark base theme and current render input. Renderer classes, theme colors, palette, fonts, labels, and visible chart options are retained in image and document exports.

Every visible label passes through one formatter. Kinds are title, subtitle, axisTitle, axisTick, category, legend, data, annotation, summary, and specialized.

const renderer = createPivotChartsRenderer({
labels: {
styles: {
title: { fontSize: 20, fontWeight: 700 },
category: { fill: '#475569', fontSize: 11 },
data: { fontWeight: 600 },
},
formatter(context) {
if (context.kind === 'legend') {
return `Measure: ${context.defaultText}`;
}
if (context.kind === 'axisTick' && context.axis === 'y') {
return null;
}
if (context.kind === 'data' && context.formattedValue) {
return {
text: context.formattedValue,
ariaLabel:
`${context.category?.label}: ${context.formattedValue}`,
className: 'sales-chart-value',
};
}
return undefined;
},
},
});

Return a string, a structured result, null to suppress one label, or undefined to retain the default. Structured results can override text, accessible text, classes, safe SVG typography, opacity, and visibility.

Annotated time series automatically arranges endpoint and extrema labels inside the plot after applying your formatter and typography. Labels move apart with leaders pointing to their observations. If no clear position fits, the optional label is omitted; the full value remains available on the point’s tooltip and accessible label. Zooming uses the visible observations. Return null for context.kind === 'annotation' to hide these labels and their leaders.

const renderer = createPivotChartsRenderer({
tooltip: {
showDelayMs: 100,
hideDelayMs: 60,
followPointer: true,
className: 'sales-chart-tooltip',
formatter(context, defaultContent) {
return {
...defaultContent,
footer: context.drillable
? 'Open the next sales level'
: 'Leaf value',
};
},
},
});

The formatter receives raw and formatted values, category and series metadata, relationship channels, mark color, and drillability. Return structured content, plain text, an HTMLElement, or null to suppress one tooltip. Set tooltip: false to disable tooltips.

pivotCharts.localeText supports deep partial overrides for dialog actions, status and errors, breadcrumbs, gallery tabs/families, all chart names and descriptions, compatibility reasons, chart options, data controls and table, legend overflow, tooltips, accessibility text, context actions, themes, totals, and number formatting.

grid.pivotCharts = {
renderer: createPivotChartsRenderer(),
localeText: {
actions: {
exportChart: 'Exportar',
downloadPdf: 'Transferir PDF',
viewData: 'Ver dados',
viewChart: 'Ver gráfico',
},
chartTypes: {
groupedColumn: 'Colunas agrupadas',
boxPlot: 'Diagrama de caixa',
},
renderer: {
formatNumber: (value) =>
new Intl.NumberFormat('pt-PT').format(value),
},
},
};

The built-in SVG renderer exports PNG, SVG, and PDF. CSV is provided by the chart plugin independently of the graphics backend. Use charts.getChartDownloadCapabilities(chart.id) to discover the formats available for an existing chart; custom renderers advertise only the formats they implement. The Canvas adapter provides PNG graphics and chart-data CSV.

Graphics capture the committed rendered chart, including its resolved theme, viewport, series visibility, labels, and annotations. SVG remains vector output. Font-family styles are captured, but font files are not embedded in SVG, PNG, or the default raster PDF. A web font loaded only into the page may be unavailable when the browser rasterizes the exported SVG, causing a fallback font. Use a system font or an application-supplied imageEncoder that embeds the needed fonts when exact raster typography is required. See the browser’s SVG image restrictions. The default PDF contains a raster image; an optional local vector encoder is shown below. pdfEncoding reports raster, vector, or custom when known. Programmatic downloads default to PNG:

await charts.downloadChart(chart.id, {
fileName: 'quarterly-sales',
fileFormat: 'pdf',
width: 1_600,
height: 900,
});
const dataUrl = await charts.getChartImageDataURL(chart.id, {
width: 1_200,
height: 675,
});
Interactive example

Chart exports

Compare CSV from the current chart window with the full dataset, using raw or formatted values.

The example loads when visible.

await charts.downloadChart(chart.id, {
fileName: 'quarterly-sales',
fileFormat: 'csv',
dataScope: 'current',
});
// Include hidden series and categories outside the current viewport.
const csv = charts.getChartCSV(chart.id, {
dataScope: 'all',
valueFormat: 'raw',
});

current exports every canonical value in the current viewport for visible series. Sampling and View data virtualization do not reduce the CSV. all exports the complete committed chart frame, including hidden series and categories outside the viewport. Both scopes retain the chart’s query, drill frame, and selected measures; neither fetches original transactions or reloads the provider. The data table’s temporary sort does not reorder the export.

CSV uses numeric values and blank missing cells by default. Choose valueFormat: 'formatted' to use display values and localized number formatting. Hierarchy labels and series labels form the headers; they are presentation text, not a lossless identity interchange format. CSV preserves Unicode and quotes commas, newlines, and double quotes. escapeFormulas: true prefixes spreadsheet formula-like strings with an apostrophe while preserving numeric negative values. This option defaults to false. Comma and CRLF are the default delimiters; columnDelimiter, rowDelimiter, and bom can override the output. The BOM is omitted by default. Width and height are graphics options and are rejected for CSV.

Install and import jspdf and svg2pdf.js in your application, then inject a local encoder. Pivot does not fetch these libraries or fonts automatically.

import { jsPDF } from 'jspdf';
import 'svg2pdf.js';
import {
createPivotChartsRenderer,
createPivotChartsVectorPdfEncoder,
} from '@revolist/pivot';
const pdfEncoder = createPivotChartsVectorPdfEncoder({
createDocument: options => new jsPDF({
...options,
format: [...options.format],
}),
}, {
fonts: [
{
fileName: 'Report-Regular.ttf',
fontFamily: 'Report',
fontStyle: 'normal',
dataBase64: reportRegularTtfBase64,
},
{
fileName: 'Report-Bold.ttf',
fontFamily: 'Report',
fontStyle: 'bold',
dataBase64: reportBoldTtfBase64,
},
],
});
const renderer = createPivotChartsRenderer({
fontFamily: 'Report',
pdfEncoder,
});

Supply the base64 contents of licensed TTF files whose glyphs cover your chart’s text, and register the font styles your labels use. The vector helper maps CSS weights and oblique styles to the registered normal, bold, italic, or bold-italic PDF style and matches family names without regard to case. Registered family names may contain spaces and commas; quotes, backslashes, and control characters are rejected because the converter cannot reliably parse them. SVG and PNG keep the original CSS styles. Standard PDF fonts do not provide general Unicode coverage. Language shaping, font coverage, and converter support determine the result; this is not a universal Unicode or PDF/UA guarantee.

The helper creates a fresh document per export and converts the captured SVG to vector PDF locally. It preserves the SVG’s drawing, including supported patterns and clipping, and converts CSS pixels to PDF points. Conversion errors propagate without falling back to a raster image or a remote server. An arbitrary custom pdfEncoder reports custom; the first-party vector helper reports vector.

Graphics dimensions must be positive and finite. Output is limited to 16,384 pixels per dimension and 64 × 1,024 × 1,024 pixels in total; omitted dimensions use the rendered chart size.

Listen to pivot-chart-before-download and call preventDefault() to cancel a download before encoding. The detail contains the chart ID, format, operation ID, and owned model/options snapshots. Changing those snapshots does not update the chart or alter the download. pivot-chart-downloaded reports completion of the download action; it cannot confirm that the user saved the file. pivot-chart-download-error reports failures and aborted operations.

Pass an AbortSignal in download options to cancel an operation. Graphics are captured before asynchronous encoding, and the renderer checks cancellation and disposal again before starting a download. Updating the chart while encoding does not change the captured graphics. Injected encoders may finish their own work after cancellation, but the renderer will not start a later download. A canceled before-download event produces no completion event. Invalid options are rejected before a download operation is created, so they do not emit download lifecycle events.

The first-party renderer also accepts imageEncoder and pdfEncoder callbacks for applications that need a different rasterization or PDF pipeline. These callbacks receive an owned SVG snapshot. They must return the encoded data URL and propagate failures; the plugin does not send chart data to an export server.

Previous: Drill-down and interactions · Next: Headless API and persistence · API reference

pivotCharts.localeText supplies shared chart and renderer text. pivotChartsUi.localeText supplies UI overrides, merged deeply over that text. Both properties are reactive: replacing either configuration updates existing chart dialogs and embedded chart panels. Partial overrides retain all other labels, descriptions, option labels, accessible names, and formatter functions.

grid.pivotCharts = {
renderer,
localeText: {
controls: { totals: 'Totales' },
dataTable: { categoryHeader: 'Categoría', emptyValue: 'Sin valor' },
renderer: { formatNumber: value => numberFormatter.format(value) },
},
};
grid.pivotChartsUi = {
localeText: {
context: {
heading: 'Detalles de los datos',
close: 'Cerrar detalles',
rows: 'Filas',
columns: 'Columnas',
frame: (categories, series) => `${categories} categorías · ${series} métricas`,
formatFilterValue: value => String(value),
},
actions: { chartLabel: 'Gráfico', dataLabel: 'Tabla', viewData: 'Ver datos', viewChart: 'Ver gráfico' },
chartOptions: { labels: { strokeWidth: 'Grosor de línea' } },
gallery: { tabs: { chart: 'Gráfico', data: 'Datos', customize: 'Estilo' } },
},
controls: {
'context.note': 'hidden',
'controls.keepLinked': 'hidden',
'controls.totals': 'disabled',
'tabs.chart': 'hidden',
'chartTypes.pie': 'hidden',
'chartOptions.showGridLines': 'hidden',
'chartOptions.strokeWidth': 'disabled',
annotations: 'hidden',
'export.pdf': 'disabled',
},
dataGrid: {
sorting: true,
range: true,
resize: true,
columnGrouping: true,
rowSize: 36,
categoryColumn: { name: 'Categoría', size: 220 },
seriesColumn: series => ({ name: series.measure?.label ?? series.label, size: 180 }),
filter: false,
},
};

controls accepts enabled, disabled, or hidden. Unspecified controls are enabled when their data and renderer capabilities permit them. Hidden controls are not rendered; disabled controls remain visible and cannot be activated. A parent restriction wins over an enabled child. For example, disabling navigation also disables navigation.enabled, even if the child is explicitly enabled. A UI policy never enables an unsupported renderer capability or removes a loading/read-only restriction.

The close policy also gates Escape, and drill.navigate gates Alt+Left and Home in the chart area. Re-enabling these controls restores their shortcuts.

For the transient data-details popup, context.close controls its close button; Escape and clicking outside still dismiss the popup. Restrict context or context.heading to disable access. Restricting the details or export trigger also closes its already-open popup or menu. Disabled tabs stay visible; if no tab is enabled, no settings panel is active. Hiding every tab removes the sidebar.

Visible numeric option values can be localized independently of the numeric API:

grid.pivotChartsUi = {
localeText: {
chartOptions: {
formatValue: (value, key, step) => new Intl.NumberFormat('de-DE', {
maximumFractionDigits: step < 1 ? 2 : 0,
}).format(value),
},
},
};

formatValue(value, key, step) affects range-value captions. Option updates still use numbers. Omit it to retain the default step-based decimal formatting.

The policy changes available UI actions. It does not rewrite the chart model, disable model-defined rendering behavior, or restrict programmatic API calls. Use ref.update(...) to configure chart behavior, and the UI policy to control which settings users may change. Disable reset actions too when their broader scope is inappropriate for your application.

Interactive example

Chart controls

Change the visible category or time window, then reset the chart navigation.

The example loads when visible.

For a chart type whose catalog definition advertises navigation, configure its rendered toolbar and plot gestures through the chart model:

ref.update({
navigation: {
enabled: true,
navigator: true,
crosshair: true,
tooltipMode: 'shared',
actions: {
zoomIn: 'enabled',
zoomOut: 'disabled',
reset: 'hidden',
},
gestures: { wheel: false, pan: true, pinch: false },
},
});

Each action accepts enabled, disabled, or hidden; omitted actions default to enabled. Disabled actions cannot activate through pointer or keyboard input. Plot gestures require enabled: true, and each omitted gesture defaults to allowed. Navigator handles and its range band remain independent of that flag. Action policies alone do not create a toolbar; toolbar availability still follows the enabled, navigator, and viewport configuration.

A supplied navigation record replaces the previous record, including its nested action and gesture policies. Omitting it from an update preserves the current configuration; supplying {} restores defaults. These policies survive model serialization and restoration. Unsupported chart types reject a nonempty navigation record with a localizable error.

Use localeText.navigation to rename toolbar actions, navigator accessible names, instructions, and range summaries. Visible button text is independent of its accessible action name:

const localeText = {
navigation: {
zoomInButtonText: 'Zoom in',
zoomOutButtonText: 'Zoom out',
panLeftButtonText: 'Earlier',
panRightButtonText: 'Later',
resetViewportButtonText: 'Reset',
formatNavigatorValue: (value, scale, handle, defaultText) =>
`${handle}: ${defaultText}`,
},
};

Translated text is measured and shortened with an ellipsis when space is limited. If no text prefix fits, the button shows its distinct default action glyph instead. The full text remains in the button title, and accessible action names remain independently configurable. Default glyph buttons retain their compact geometry. formatNavigatorValue customizes slider aria-valuetext; value matches numeric aria-valuenow (epoch milliseconds for time, a boundary ordinal for categories). The category end boundary is exclusive, while its defaultText names the last included category. Numeric slider bounds and behavior remain unchanged. localeText.renderer.invalidNavigation and navigationUnsupported(chartType) customize validation messages. These renderer/model policies also work through the standalone charts API, without a RevoGrid host.

ID or prefixControlled UI
settingsEntire settings sidebar; hiding it gives the chart the full width
tabs.chart, tabs.data, tabs.customizeIndividual settings tabs; selection and arrow navigation skip unavailable tabs
inspector, inspector.<section>All collapsible inspector sections, or one section listed above; restrictions cascade to its controls
gallery, chartTypes.<type>Gallery and individual chart types, including recommendations
data, query, relationship.x/y/sizeData settings, independent query editor, and relationship bindings
query.rows/columns/filtersHierarchy and member-filter editors
controls.<key>Individual presentation/data controls: title, subtitle, description, legend, dataLabels, xAxisTitle, yAxisTitle, totals, drillSyncMode, keepLinked, valueSeries, theme
presentation, customizePresentation controls or all customization settings
chartOptions.<key>Each catalog option, including its reset action
chartOptions.resetAllReset all chart options
axes.y.<field>, axes.ySecondary.<field>Primary/secondary axis scale, min, max, title, unit, notation and precision
axes.seriesLayer, axes.seriesAxisCombination series layers and axis assignment
navigation, interaction, annotations, colorsWhole feature groups; individual controls use the same prefix
actions.viewData, dataViewChart/data switch or the data view itself; hiding an active data view returns to the chart
dataView.sorting/selection/resize/filteringNative data-grid interaction features
context, context.heading, context.closeData details popup, trigger and close action
context.overview/rows/columns/totals/filters/localFilters/noteIndividual information groups within the popup
export, export.png/pdf/svg/csv, actions.exportChartExport menu, formats and trigger
drill, drill.navigate, drill.retryDrill navigation controls
actions.retry, actions.closeChart retry and close actions

Import PIVOT_CHART_UI_CONTROLS, PivotChartUiControlId, PivotChartUiControlState, PivotChartsUiConfig, and PivotChartDataGridConfig from @revolist/pivot or @revolist/pivot/charts for the concrete control inventory and public types. Each rendered control also exposes its stable ID in data-pivot-chart-control; IDs are independent of translated labels.

The current-frame RevoGrid is always read-only. Its source and formatting stay owned by the chart. dataGrid exposes sorting, selection (range), resizing, focus, clipboard, row/column sizes, theme, and category/series column names, sizes, bounds, sortability, and pinning. Global sorting restrictions win over a column’s sortable: true setting.

Column-axis members use native grouped headers: Q1 › Revenue becomes a Q1 group with a Revenue child column. Nested paths and multiple measures share their adjacent parent groups without changing series order. Standalone series without a column path retain their flat names. Values-on-rows layouts use the last column member as the leaf name. columnGrouping: false restores full flat series labels; groupLabel(label, series, level) overrides group names, and seriesColumn overrides leaf names. Groups use semantic member keys, so equal display names do not merge distinct members. Labels come from the dataset; display text is never split to infer a hierarchy.

Sorting and Pro filtering are enabled by default. Category columns offer text conditions and series columns offer numeric conditions against raw values, independent of formatted cell text. The native filter popup is supplied by AdvanceFilterPlugin. Pass RevoGrid’s ColumnFilterConfig through dataGrid.filter, including its localization captions and filter names. Setting filter: false, or disabling dataView.filtering, removes filtering. RevoGrid’s native filter-localization contract is retained rather than introducing a second set of filter strings. categoryColumn.filter and seriesColumn(...).filter can select Pro filter types (such as ['selection']) or disable individual column filters. Global filtering and sorting restrictions win over column overrides. Sorting/filtering affect only the current data grid; they do not change the chart dataset, Pivot report, or exports. They refresh against new frame values and reset when the series schema changes.

The data view uses localeText.dataTable for its accessible name, category header, missing values, and sort actions/announcements. Series names come from the dataset and may be overridden with seriesColumn. Numbers use the supplied formatted dataset values or localeText.renderer.formatNumber.

Function overrides cover dynamic strings as well as fixed labels. In addition to number and data-table formatting, context.frame, context.more, and context.formatFilterValue customize data details. Annotation target/path text and the UTC input hint use annotations.targetLabel, annotations.pathLabel, and annotations.utcPlaceholder.

For a stacked-axis tick whose mathematical value exceeds JavaScript’s finite number range, renderer.formatScaledNumber(value, multiplier) formats the value without requiring their product to fit in a number. The default uses scientific notation, such as 2.697 × 10^308. Override this callback through pivotCharts.localeText to control the complete plotted label. Ordinary representable ticks continue to use renderer.formatNumber. Shared renderer formatters belong in pivotCharts.localeText; pivotChartsUi.localeText overrides inspector and data-view UI text without replacing the plot/export locale.

Radar’s category prerequisite message is customizable with renderer.minimumCategoriesRequired(chartTypeLabel, minimum). Both radar types require three non-total categories; empty frames retain the no-data view.

Use query.formatMemberValue for member-picker values and context.formatFieldLabel for row and column dimension headings and filter headings in data details. The latter receives the configured dimension label when available, otherwise the field name. Their defaults are String(value) and the unchanged resolved field label.

Generated inspector labels also expose formatter callbacks: query.formatMeasureLabel(prop, aggregator) controls the fallback caption when a measure has no configured label, colors.measureLabel(prop, aggregator) controls measure-color captions, colors.memberPathLabel(path) formats member paths, and annotations.coordinateLabel(label, path) formats category reference choices. Configured field and measure names remain application data; rename those in the Pivot configuration.

grid.pivotChartsUi = {
localeText: {
query: { formatMemberValue: value => `Member: ${String(value)}` },
context: { formatFieldLabel: label => `Field: ${label}` },
},
};

A zero-grid chart created with createStandalonePivotChart accepts the same localeText options for its renderer and export text. It does not render the settings sidebar or data-details popup, so UI policies belong to PivotChartsUiPlugin; standalone behavior is configured through the controller’s model/update API and renderer capabilities.

Numeric color-map keys expose localeText.colors.formatValueMapValue(value, role) for the complete displayed number. role is minimum, midpoint, or maximum. An explicit callback is used unchanged, including localized small or long values. When omitted, keys use renderer.formatNumber with the existing compact scientific fallback for small values or long labels. For example:

import type { PivotChartsLocaleTextOptions } from '@revolist/pivot';
const localeText: PivotChartsLocaleTextOptions = {
colors: {
formatValueMapValue: (value, role) => `${role}: ${new Intl.NumberFormat('de-DE').format(value)}`,
},
};

The toolbar’s short captions use actions.chartLabel and actions.dataLabel; actions.viewChart and actions.viewData name their accessible actions. Configure the buttons independently with controls['actions.viewChart'] and controls['actions.viewData']. dataView controls the entire view switch. Legacy gallery.tabs.chart/data caption overrides remain fallbacks when the corresponding short caption is not supplied.

Every native dropdown choice supports <controlId>.options.<value>, for example:

grid.pivotChartsUi = {
controls: {
'controls.totals.options.all': 'hidden',
'controls.totals.options.grand': 'disabled',
'query.sortDirection.options.desc': 'disabled',
},
};

These policies configure the editor, without rewriting the chart model. A hidden current choice retains its selected value and label but cannot be chosen from the menu. Parent restrictions and existing capability restrictions still apply. For dynamic choices, use the option’s native value, exposed alongside its full ID in data-pivot-chart-control.

Automatic category grouping and authored axis formatting are also translatable:

grid.pivotCharts = {
renderer,
localeText: {
renderer: {
otherCategoryLabel: 'Autres',
groupedCategoryLabel: (label, index) => `${label} (groupe ${index})`,
formatAxisTick: (value, format) => new Intl.NumberFormat('fr-FR', format).format(value),
formatTimeAxisTick: (epochMilliseconds, dateOnly) =>
new Intl.DateTimeFormat('fr-FR', dateOnly
? { dateStyle: 'medium', timeZone: 'UTC' }
: { dateStyle: 'short', timeStyle: 'short', timeZone: 'UTC' }).format(epochMilliseconds),
},
},
};

Axis formatter callbacks also receive the built-in text as their last argument, so an application can selectively override formats. User-authored titles, field and series labels, units and notes remain application data; use their existing model, column-label and formatter APIs to translate them. Backend diagnostic text can be mapped through status.formatError and drill.formatError.