@mindfiredigital/pivothead
v1.16.0
Published
PivotHead is a powerful and flexible library for creating interactive pivot tables in JavaScript applications. It provides a core engine for data manipulation and, in the future, will be compatible with wrappers for React, Vue, Svelte, and Angular, making
Keywords
Readme
PivotHead Core
Powerful TypeScript Pivot Table Engine for JavaScript Applications
Features • Installation • Quick Start • API Reference • Examples • Support
Screenshots
Features
** Core Capabilities**
- Flexible data pivoting & aggregation
- Multi-level grouping
- Dynamic measures & dimensions
- Custom formulas support
- Sorting (asc/desc)
- Advanced filtering
** Formatting & UI**
- Conditional formatting
- Currency & number formatting
- Custom cell styling
- Column resizing
- Drag & drop for rows/columns
- Responsive design
- Toolbar customization
** Data Management**
- Pagination support
- Large dataset handling
- Export to PDF/Excel/HTML
- Local JSON/CSV file import
- TypeScript support
- Framework agnostic
Supported Aggregations
- Sum - Total of all values
- Average - Mean value
- Count - Number of records
- Min - Minimum value
- Max - Maximum value
- Custom formulas - Define your own calculations
Installation
# npm
npm install @mindfiredigital/pivothead
# yarn
yarn add @mindfiredigital/pivothead
# pnpm
pnpm add @mindfiredigital/pivotheadThat's it! All dependencies including WebAssembly modules are automatically bundled. No additional configuration or manual file copying required.
Requirements
- TypeScript (optional): 4.5.0 or higher
- Node.js: 12.0.0 or higher
Quick Start
Basic Usage
import { PivotEngine } from '@mindfiredigital/pivothead';
// Your sales data
const data = [
{
date: '2024-01-01',
product: 'Widget A',
region: 'North',
sales: 1000,
quantity: 50,
},
{
date: '2024-01-01',
product: 'Widget B',
region: 'South',
sales: 1500,
quantity: 75,
},
// ... more data
];
// Configure your pivot table
const config = {
data: data,
rows: [{ uniqueName: 'product', caption: 'Product' }],
columns: [{ uniqueName: 'region', caption: 'Region' }],
measures: [
{
uniqueName: 'sales',
caption: 'Total Sales',
aggregation: 'sum',
format: {
type: 'currency',
currency: 'USD',
locale: 'en-US',
decimals: 2,
},
},
{
uniqueName: 'quantity',
caption: 'Total Quantity',
aggregation: 'sum',
format: {
type: 'number',
decimals: 0,
locale: 'en-US',
},
},
],
dimensions: [
{ field: 'product', label: 'Product', type: 'string' },
{ field: 'region', label: 'Region', type: 'string' },
{ field: 'date', label: 'Date', type: 'date' },
{ field: 'sales', label: 'Sales', type: 'number' },
{ field: 'quantity', label: 'Quantity', type: 'number' },
],
defaultAggregation: 'sum',
isResponsive: true,
pageSize: 10, // Enable pagination
};
// Create the pivot engine
const engine = new PivotEngine(config);
// Get the current state to render your UI
const state = engine.getState();
console.log('Pivot Data:', state);With TypeScript
import {
PivotEngine,
PivotTableConfig,
MeasureConfig,
} from '@mindfiredigital/pivothead';
interface SalesRecord {
date: string;
product: string;
region: string;
sales: number;
quantity: number;
}
const config: PivotTableConfig<SalesRecord> = {
data: salesData,
rows: [{ uniqueName: 'product', caption: 'Product' }],
columns: [{ uniqueName: 'region', caption: 'Region' }],
measures: [
{
uniqueName: 'sales',
caption: 'Total Sales',
aggregation: 'sum',
format: {
type: 'currency',
currency: 'USD',
locale: 'en-US',
decimals: 2,
},
},
],
dimensions: [
{ field: 'product', label: 'Product', type: 'string' },
{ field: 'region', label: 'Region', type: 'string' },
{ field: 'sales', label: 'Sales', type: 'number' },
],
};
const engine = new PivotEngine<SalesRecord>(config);API Reference
PivotEngine Class
The PivotEngine class is the core of the PivotHead library.
Constructor
constructor(config: PivotTableConfig<T>)Creates a new instance of PivotEngine with the given configuration.
State Management
getState(): PivotTableState<T>
Returns the current state of the pivot table.
const state = engine.getState();
console.log(state.data); // Current data array
console.log(state.sortConfig); // Current sort configuration
console.log(state.filters); // Active filtersreset(): void
Resets the pivot table to its initial state.
engine.reset();
const state = engine.getState();
console.log(state); // Initial state restoredData Manipulation
setMeasures(measureFields: MeasureConfig[]): void
Sets the measures for the pivot table.
engine.setMeasures([
{
uniqueName: 'revenue',
caption: 'Total Revenue',
aggregation: 'sum',
format: { type: 'currency', currency: 'USD' },
},
]);setDimensions(dimensionFields: Dimension[]): void
Sets the dimensions for the pivot table.
engine.setDimensions([
{ field: 'category', label: 'Category', type: 'string' },
{ field: 'date', label: 'Date', type: 'date' },
]);setAggregation(type: AggregationType): void
Sets the default aggregation type.
type AggregationType = 'sum' | 'avg' | 'count' | 'min' | 'max';
engine.setAggregation('avg');Formatting
formatValue(value: any, field: string): string
Formats a value based on the specified field's format configuration.
const formattedValue = engine.formatValue(1000, 'sales');
console.log(formattedValue); // "$1,000.00"Sorting and Grouping
sort(field: string, direction: 'asc' | 'desc'): void
Sorts the pivot table data.
engine.sort('sales', 'desc'); // Sort by sales descendingsetGroupConfig(groupConfig: GroupConfig | null): void
Sets the group configuration for the pivot table.
engine.setGroupConfig({
rowFields: ['product', 'category'],
columnFields: ['region'],
grouper: (item, fields) => fields.map(field => item[field]).join(' - '),
});getGroupedData(): Group[]
Returns the grouped data.
const groupedData = engine.getGroupedData();
console.log(groupedData);Row and Column Manipulation
resizeRow(index: number, height: number): void
Resizes a specific row in the pivot table.
engine.resizeRow(2, 60); // Set row 2 height to 60pxtoggleRowExpansion(rowId: string): void
Toggles the expansion state of a row.
engine.toggleRowExpansion('product-123');isRowExpanded(rowId: string): boolean
Checks if a specific row is expanded.
if (engine.isRowExpanded('product-123')) {
console.log('Row is expanded');
}dragRow(fromIndex: number, toIndex: number): void
Handles dragging a row to a new position.
engine.dragRow(0, 5); // Move row from index 0 to 5dragColumn(fromIndex: number, toIndex: number): void
Handles dragging a column to a new position.
engine.dragColumn(1, 3); // Move column from index 1 to 3Filtering and Pagination
applyFilters(filters: FilterConfig[]): void
Applies filters to the data.
engine.applyFilters([
{ field: 'region', operator: 'equals', value: 'North' },
{ field: 'sales', operator: 'greaterThan', value: 500 },
]);Filter Operators:
equals- Exact matchcontains- String contains (case-insensitive)greaterThan- Numeric greater thanlessThan- Numeric less thanbetween- Value within range (requires array:[min, max])
setPagination(config: PaginationConfig): void
Sets the pagination configuration.
engine.setPagination({
currentPage: 2,
pageSize: 25,
});getFilterState(): FilterConfig[]
Returns the current filter configuration.
const currentFilters = engine.getFilterState();
console.log(currentFilters);getPaginationState(): PaginationConfig
Returns the current pagination configuration.
const paginationInfo = engine.getPaginationState();
console.log(
`Page ${paginationInfo.currentPage} of ${paginationInfo.totalPages}`
);Advanced Features
Conditional Formatting
Apply custom styles to cells based on their values.
const config = {
// ... other configuration
conditionalFormatting: [
{
value: {
type: 'Number',
operator: 'Greater than',
value1: '1000',
value2: '',
},
format: {
font: 'Arial',
size: '14px',
color: '#ffffff',
backgroundColor: '#4CAF50', // Green background for high values
},
},
{
value: {
type: 'Number',
operator: 'Less than',
value1: '500',
value2: '',
},
format: {
font: 'Arial',
size: '14px',
color: '#ffffff',
backgroundColor: '#f44336', // Red background for low values
},
},
],
};Custom Measures with Formulas
Define custom calculated measures:
const config = {
// ... other configuration
measures: [
{
uniqueName: 'sales',
caption: 'Total Sales',
aggregation: 'sum',
},
{
uniqueName: 'quantity',
caption: 'Total Quantity',
aggregation: 'sum',
},
{
uniqueName: 'averageSale',
caption: 'Average Sale Price',
aggregation: 'avg',
format: {
type: 'currency',
currency: 'USD',
locale: 'en-US',
decimals: 2,
},
formula: item => item.sales / item.quantity, // Custom calculation
},
],
};Cell Formatting
Format numbers and currencies:
const config = {
// ... other configuration
measures: [
{
uniqueName: 'sales',
caption: 'Total Sales',
aggregation: 'sum',
format: {
type: 'currency',
currency: 'EUR', // Euro symbol
locale: 'de-DE', // German locale
decimals: 2,
},
},
{
uniqueName: 'percentage',
caption: 'Growth Rate',
aggregation: 'avg',
format: {
type: 'number',
decimals: 2,
locale: 'en-US',
},
},
],
};Initial Sorting
Configure initial sort order:
const config = {
// ... other configuration
initialSort: [
{
field: 'sales',
direction: 'desc',
type: 'measure',
aggregation: 'sum',
},
],
};Toolbar Visibility
Show or hide the toolbar:
const config = {
// ... other configuration
toolbar: true, // or false to hide
};Configuration Interface
interface PivotTableConfig<T> {
data: T[];
rows: { uniqueName: string; caption: string }[];
columns: { uniqueName: string; caption: string }[];
measures: MeasureConfig[];
dimensions: Dimension[];
defaultAggregation?: AggregationType;
isResponsive?: boolean;
pageSize?: number;
toolbar?: boolean;
groupConfig?: GroupConfig;
formatting?: Record<string, FormatConfig>;
conditionalFormatting?: ConditionalFormattingRule[];
initialSort?: SortConfig[];
dataSource?: {
type: 'remote' | 'file';
url?: string;
file?: File;
};
onRowDragEnd?: (fromIndex: number, toIndex: number, data: T[]) => void;
onColumnDragEnd?: (
fromIndex: number,
toIndex: number,
columns: Array<{ uniqueName: string; caption: string }>
) => void;
}Examples
Example 1: Sales Dashboard with Filtering
import { PivotEngine } from '@mindfiredigital/pivothead';
const engine = new PivotEngine(config);
// Apply filters to show only high-value sales in the North region
engine.applyFilters([
{ field: 'region', operator: 'equals', value: 'North' },
{ field: 'sales', operator: 'greaterThan', value: 1000 },
]);
// Set up pagination
engine.setPagination({
currentPage: 1,
pageSize: 10,
});
// Get the filtered, paginated data
const state = engine.getState();
renderPivotTable(state);Example 2: Range Filtering
// Filter sales between $500 and $1500
engine.applyFilters([
{
field: 'sales',
operator: 'between',
value: [500, 1500],
},
]);Example 3: Custom Grouping
const config = {
// ... other configuration
groupConfig: {
rowFields: ['category', 'product'],
columnFields: ['region', 'quarter'],
grouper: (item, fields) => {
return fields.map(field => item[field]).join(' > ');
},
},
};
const engine = new PivotEngine(config);
const groupedData = engine.getGroupedData();Live Examples
Check out complete working examples:
- Vanilla JS Demo - Basic implementation
- React Demo - React integration
- Vue Demo - Vue integration
- Web Component Demo - Web component usage
Running Examples Locally
# Clone the repository
git clone https://github.com/mindfiredigital/PivotHead.git
cd PivotHead
# Navigate to an example (e.g., vanilla-pivot-demo)
cd examples/vanilla-pivot-demo
# Install dependencies
pnpm install
# Build the project
pnpm build
# Start the development server
pnpm start
# Open your browser to the local host address providedRelated Packages
Build pivot tables for any framework:
| Package | Description | Documentation | | ---------------------------------------------------------------- | -------------------------------- | ------------------------------------ | | @mindfiredigital/pivothead-react | React wrapper component | README | | @mindfiredigital/pivothead-web-component | Framework-agnostic web component | README | | @mindfiredigital/pivothead-vue | Vue wrapper | Coming soon |
Show Your Support
If PivotHead helps your project, please consider:
License
Copyright © Mindfiredigital. All rights reserved.
Licensed under the MIT license.
Built with ❤️ by the Mindfiredigital team
