npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bways-grid

v0.1.20

Published

High-performance enterprise Angular Data Grid with Web Worker computing, in-grid formula calculations, AI chat assistant, row merging, and enterprise export.

Downloads

1,320

Readme

bways-grid

A high-performance, extreme-scale enterprise Angular Data Grid engineered for smoothly rendering 1,000,000+ rows with Server-Side Rendering (SSR) support. Built from scratch using Angular CDK with Web Worker computing, in-grid AST formula calculations, AI chat assistant, row merging, and enterprise export/print capabilities.

npm version license Angular


📑 Table of Contents

  1. Overview & Key Features
  2. Installation
  3. Quick Start & Setup
  4. Complete Working Example
  5. Column Configuration & Hierarchies
  6. In-Grid Formula Engine
  7. Row Merging (Invoice Style)
  8. Enterprise Export & Printing
  9. Server-Side Data Source & Infinite Scrolling
  10. AI Chat Assistant Integration
  11. Conditional Formatting & Highlighting
  12. Grid Analytics & ECharts (bways-grid/charts)
  13. State Persistence & Report Management
  14. Component API Reference
  15. Global Configuration Reference (UltraGridConfig)
  16. License

🚀 Overview & Key Features

  • Extreme Scale Engine: Smoothly renders 1,000,000+ rows with minimal memory usage via Angular CDK virtual scrolling and row recycling.
  • Web Worker Acceleration: Offloads multi-column sorting, row filtering, and background Excel file generation to Web Workers for a stutter-free 60fps UI.
  • In-Grid Formula Engine: Built-in AST formula parser and calculator for dynamic calculated columns and running ledger totals (= {PreviousBalance} + {Credit} - {Debit}). Features inline insertion between columns with dynamic edge-anchored buttons and live evaluation previews.
  • Row Merging: Visual duplicate suppression for invoices, vouchers, and grouped transactions (enableRowMerging: true).
  • AI Chat Assistant: Integrated LLM chat assistant panel (Ctrl+Shift+K) supporting streaming answers across grid rows with Gemini, Claude, Groq, OpenAI, and custom proxies.
  • Column Hierarchies: Multi-level nested column header groups (ColumnDef[]) with collapsible states (open / closed), pinning (left / right), and drag-and-drop reordering.
  • Advanced Export & Print Suite: Background worker export to Excel (.xlsx), PDF (.pdf), and CSV with an adaptive options modal (colored headers, header text color, font size, cell padding, scope selection, and browser print).
  • Global Search: Real-time multi-column search with match highlighting, count badges, and keyboard navigation.
  • Condition & Set Filtering: Multi-condition filters (AND / OR), column header distinct value filters, and saved report state persistence.
  • Conditional Highlighting & Styling: Custom background and text color formatting for cells, rows, and columns with contrast presets (Auto, Dark, Light) and live preview.
  • Decoupled Analytics: Optional secondary entry point (bways-grid/charts) powered by ECharts for bar, line, pie, and area charts.
  • SSR Ready: Strict platform checks (isPlatformBrowser) for seamless Angular Universal integration.

📦 Installation

Install bways-grid along with Angular CDK:

npm install bways-grid @angular/cdk

(Optional: For Grid Analytics & ECharts)

npm install echarts ngx-echarts

⚡ Quick Start & Setup

1. Modern Angular 18+ Standalone Setup (Recommended)

In modern Angular applications using standalone routing, configure global grid defaults in app.config.ts using provideBwaysGrid():

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideBwaysGrid } from 'bways-grid';

export const appConfig: ApplicationConfig = {
  providers: [
    provideBwaysGrid({
      theme: 'ag-theme-alpine',
      rowHeight: 30,
      headerHeight: 36,
      locale: 'en-IN'
    })
  ]
};

2. Standalone Component Usage

Import UltraGridComponent or BwaysGridModule directly in your component's imports:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UltraGridComponent, UltraGridColumn, UltraGridConfig } from 'bways-grid';

@Component({
  selector: 'app-grid-demo',
  standalone: true,
  imports: [CommonModule, UltraGridComponent],
  template: `
    <div style="height: 600px; width: 100%;">
      <bways-grid
        [columns]="columns"
        [rowData]="rowData"
        [config]="gridConfig">
      </bways-grid>
    </div>
  `
})
export class GridDemoComponent {
  columns: UltraGridColumn[] = [
    { field: 'id', headerName: 'ID', width: 80, sortable: true },
    { field: 'name', headerName: 'Customer Name', width: 220, sortable: true },
    { field: 'category', headerName: 'Category', width: 150, enableRowGroup: true },
    { field: 'amount', headerName: 'Amount', width: 140, numberFormat: 'currency', total: true }
  ];

  rowData = [
    { id: 1, name: 'Acme Corp', category: 'Enterprise', amount: 15400.50 },
    { id: 2, name: 'Global Tech', category: 'Retail', amount: 8200.00 }
  ];

  gridConfig: UltraGridConfig = {
    theme: 'ag-theme-alpine',
    sideBar: true,
    statusBar: true,
    globalSearch: true
  };
}

3. NgModule Setup

For traditional NgModule applications, import BwaysGridModule into your AppModule:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BwaysGridModule } from 'bways-grid';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BwaysGridModule.forRoot({
      theme: 'ag-theme-alpine',
      rowHeight: 30
    })
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

💻 Complete Working Example

import { Component, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UltraGridComponent, BwaysGridModule, UltraGridColumn, UltraGridConfig } from 'bways-grid';

@Component({
  selector: 'app-sales-report',
  standalone: true,
  imports: [CommonModule, BwaysGridModule],
  template: `
    <div style="padding: 16px;">
      <!-- Toolbar Controls -->
      <div style="margin-bottom: 12px; display: flex; gap: 8px;">
        <button (click)="exportExcel()">Export Excel</button>
        <button (click)="exportPdf()">Export PDF</button>
        <button (click)="printReport()">Print Report</button>
      </div>

      <!-- UltraGrid Component -->
      <div style="height: 650px; width: 100%;">
        <bways-grid #grid
          [columns]="columns"
          [rowData]="rowData"
          [config]="gridConfig"
          (cellClicked)="onCellClick($event)">
        </bways-grid>
      </div>
    </div>
  `
})
export class SalesReportComponent {
  @ViewChild('grid') grid!: UltraGridComponent;

  columns: UltraGridColumn[] = [
    { field: 'invoiceNo', headerName: 'Invoice #', width: 120, pinned: 'left' },
    { field: 'client', headerName: 'Client', width: 220, sortable: true },
    { field: 'region', headerName: 'Region', width: 140, enableRowGroup: true },
    { field: 'units', headerName: 'Units Sold', width: 120, numberFormat: 'integer', total: true },
    { field: 'revenue', headerName: 'Revenue', width: 150, numberFormat: 'currency', total: true }
  ];

  rowData = Array.from({ length: 5000 }).map((_, i) => ({
    invoiceNo: `INV-${1000 + i}`,
    client: `Client ${(i % 50) + 1}`,
    region: ['North', 'South', 'East', 'West'][i % 4],
    units: Math.floor(Math.random() * 50) + 1,
    revenue: Math.round((Math.random() * 10000 + 500) * 100) / 100
  }));

  gridConfig: UltraGridConfig = {
    theme: 'ag-theme-alpine',
    sideBar: true,
    statusBar: true,
    globalSearch: true,
    multiSort: true,
    rowSelection: 'multiple',
    locale: 'en-IN'
  };

  async exportExcel() {
    await this.grid.exportData('excel', { fileName: 'sales_report.xlsx', expandAll: true });
  }

  async exportPdf() {
    await this.grid.exportData('pdf', {
      fileName: 'sales_report.pdf',
      coloredHeaders: true,
      headerBgColor: '#0f172a',
      headerTextColor: '#ffffff'
    });
  }

  async printReport() {
    await this.grid.printData({ expandAll: true });
  }

  onCellClick(event: any) {
    console.log('Cell clicked:', event);
  }
}

📊 Column Configuration & Hierarchies

Multi-Level Column Groups (ColumnDef)

Group columns under unified header categories with collapsible buttons and nested hierarchy:

import { ColumnDef } from 'bways-grid';

columnDefs: ColumnDef[] = [
  {
    headerName: 'General Information',
    children: [
      { field: 'id', headerName: 'ID', width: 80, pinned: 'left' },
      { field: 'accountCode', headerName: 'Account Code', width: 120 },
      { field: 'clientName', headerName: 'Client Name', width: 220 }
    ]
  },
  {
    headerName: 'Financial Metrics',
    children: [
      { field: 'openingBalance', headerName: 'Opening Bal', width: 140, numberFormat: 'currency' },
      { field: 'debit', headerName: 'Debit', width: 130, numberFormat: 'currency', total: true },
      { field: 'credit', headerName: 'Credit', width: 130, numberFormat: 'currency', total: true },
      { field: 'closingBalance', headerName: 'Closing Bal', width: 150, numberFormat: 'currency', total: true }
    ]
  }
];

Pass [columnDefs]="columnDefs" into <bways-grid>.

Column Properties Reference

| Property | Type | Description | | :--- | :--- | :--- | | field | string | Data object field key. | | headerName | string | Display label for column header. | | width | number | Initial column width in pixels (default: 200). | | minWidth | number | Minimum resize width (default: 50). | | maxWidth | number | Maximum resize width. | | pinned | 'left' \| 'right' \| null | Pinned sticky column position. | | hide | boolean | Initial column visibility. | | sortable | boolean | Enables header click sorting. | | resizable | boolean | Enables drag resizing. | | align | 'left' \| 'center' \| 'right' | Horizontal text alignment for data cells. | | headerAlign | 'left' \| 'center' \| 'right' | Independent horizontal alignment for header text. | | numberFormat | 'comma' \| 'no-comma' \| 'currency' \| 'integer' \| 'cr-dr' | Formats numeric values according to locale. | | total | boolean | Computes column sum for status and total footer rows. | | enableRowGroup| boolean | Allows dragging into the row grouping zone. | | enablePivot | boolean | Allows column to be pivoted. | | isMergeColumn | boolean | Column subject to row merging when enableRowMerging is true. |


🧮 In-Grid Formula Engine

bways-grid includes an in-grid AST formula engine that computes formulas with sub-millisecond overhead:

// Enable formula columns in gridConfig
gridConfig: UltraGridConfig = {
  enableFormulaColumns: true
};

Formula Types:

  1. Simple Formula (Per-row):
    • Example: {Quantity} * {UnitPrice} * (1 - {Discount})
  2. Running Balance (Sequential Ledger):
    • Example: {PreviousBalance} + {Credit} - {Debit}
    • Automatically maintains a running accumulator across rows.

Supported Syntax:

  • Arithmetic: +, -, *, /, %
  • Math Functions: ROUND(), ABS(), MIN(), MAX(), CEIL(), FLOOR()
  • Conditions: IF({debit} > 0, {debit}, 0)
  • Formatters: Currency, Integer, Comma, CR/DR Indicator (1,250.00 Cr)

📑 Row Merging (Invoice Style)

Suppress visual duplicates and merge recurring fields across consecutive rows for ledger statements and invoices:

gridConfig: UltraGridConfig = {
  enableRowMerging: true
};

columns: UltraGridColumn[] = [
  { field: 'invoiceNo', headerName: 'Invoice #', isMergeColumn: true },
  { field: 'date', headerName: 'Date', isMergeColumn: true },
  { field: 'item', headerName: 'Item' },
  { field: 'amount', headerName: 'Amount' }
];

📤 Enterprise Export & Printing

Export formatted grids directly without server processing:

// Excel Export (.xlsx)
await this.grid.exportData('excel', {
  fileName: 'Financial_Ledger.xlsx',
  expandAll: true // Export full nested tree
});

// PDF Export (.pdf)
await this.grid.exportData('pdf', {
  fileName: 'Financial_Ledger.pdf',
  coloredHeaders: true,
  headerBgColor: '#0f172a',
  headerTextColor: '#ffffff',
  fontSize: 9,
  cellPadding: 3
});

// Native Browser Print
await this.grid.printData({
  expandAll: true,
  coloredHeaders: true
});

🌐 Server-Side Data Source & Infinite Scrolling

For databases with millions of rows, connect remote endpoints using ServerDataSource:

import { ServerDataSource, GetRowsParams, ServerResponse } from 'bways-grid';
import { Observable } from 'rxjs';

export class RemoteGridComponent {
  dataSource: ServerDataSource = {
    getRows: (params: GetRowsParams): Observable<ServerResponse> => {
      const { startRow, endRow, sortModel, filterModel } = params;
      return this.http.post<ServerResponse>('/api/reports/query', {
        offset: startRow,
        limit: endRow - startRow,
        sort: sortModel,
        filter: filterModel
      });
    }
  };
}
<bways-grid
  [columns]="columns"
  [serverDataSource]="dataSource"
  [config]="gridConfig">
</bways-grid>

🤖 AI Chat Assistant Integration

Embed an in-grid AI copilot to explain data, detect anomalies, and filter tables via natural language:

import { ProxyChatAdapter } from 'bways-grid';

gridConfig: UltraGridConfig = {
  aiChat: {
    enabled: true,
    shortcut: 'Ctrl+Shift+K',
    adapter: new ProxyChatAdapter({
      endpointUrl: 'https://api.yourcompany.com/ai/grid-chat',
      model: 'gemini-1.5-pro'
    })
  }
};

🎨 Conditional Formatting & Highlighting

Highlight cells, rows, or columns based on dynamic rule conditions:

gridConfig: UltraGridConfig = {
  enableColorFilter: true,
  highlightRules: [
    {
      id: 'high-value',
      field: 'revenue',
      operator: 'greaterThan',
      value: 50000,
      backgroundColor: '#dcfce7',
      textColor: '#166534',
      target: 'row'
    },
    {
      id: 'overdue-alert',
      field: 'status',
      operator: 'equals',
      value: 'Overdue',
      backgroundColor: '#fee2e2',
      textColor: '#991b1b',
      target: 'cell'
    }
  ]
};

📈 Grid Analytics & ECharts (bways-grid/charts)

Visual charting is separated into a secondary entry point to keep consumer bundles lightweight.

npm install echarts ngx-echarts
// Import secondary entry point to activate chart capabilities
import 'bways-grid/charts';

When active, users can click Analytics in the sidebar to visualize grouped and pivoted rows across dynamic bar, line, pie, and area charts.


💾 State Persistence & Report Management

Persist column widths, reordered positions, pinned columns, active filters, and highlight rules across browser sessions:

// Save current state
const state = this.grid.getReportState();

// Save to localStorage automatically by specifying stateKey
gridConfig: UltraGridConfig = {
  stateKey: 'user-sales-report',
  enableLocalStorage: true
};

// Re-apply state programmatically
this.grid.applyReportState(savedState);

📖 Component API Reference

Inputs

| Input | Type | Description | | :--- | :--- | :--- | | [columns] | UltraGridColumn[] | Flat column definitions. | | [columnDefs] | ColumnDef[] | Hierarchical column groups and definitions. | | [rowData] | any[] | Array of row data objects for in-memory grid mode. | | [serverDataSource] | ServerDataSource | Remote data source interface for pagination and infinite scroll. | | [config] | UltraGridConfig | Grid configuration object. |

Outputs

| Output | Event Payload | Description | | :--- | :--- | :--- | | (cellClicked) | { row: any, col: UltraGridColumn, event: MouseEvent } | Fired when a cell is clicked. | | (rowClicked) | any | Fired when a row is clicked. | | (selectionChanged) | any[] | Fired when selected rows change. | | (sortChanged) | { field: string, direction: 'asc' \| 'desc' }[] | Fired when sorting changes. | | (filterChanged) | Map<string, Set<any>> | Fired when active filters change. | | (columnResized) | { field: string, width: number } | Fired when a column is resized. | | (gridReady) | UltraGridComponent | Fired when the grid is initialized. | | (reportStateChange) | UltraGridReportState | Fired whenever grid filters, sorting, or columns change. |

Public Methods

Access methods using #grid or @ViewChild(UltraGridComponent):

@ViewChild('grid') grid!: UltraGridComponent;

// Get selected rows
const rows = this.grid.getSelectedRows();

// Export grid
await this.grid.exportData('excel', { expandAll: true });
await this.grid.exportData('pdf', { expandAll: true });
await this.grid.exportData('csv', { expandAll: true });

// Print
await this.grid.printData({ expandAll: true });

// State Management
const state = this.grid.getReportState();
this.grid.saveStateToLocalStorage();
this.grid.loadStateFromLocalStorage();

⚙️ Global Configuration Reference (UltraGridConfig)

| Property | Type | Default | Description | | :--- | :--- | :--- | :--- | | theme | 'ag-theme-alpine' \| 'ag-theme-balham' \| 'custom' | 'ag-theme-alpine' | Grid CSS theme. | | rowHeight | number | 30 | Row height in pixels. | | headerHeight | number | 36 | Column header height in pixels. | | multiSort | boolean | true | Allows sorting across multiple columns. | | rowSelection | 'single' \| 'multiple' | undefined | Checkbox / row selection mode. | | sideBar | boolean \| object | true | Enables sidebar tool panels. | | statusBar | boolean | true | Enables aggregate status bar at bottom. | | globalSearch | boolean | true | Enables quick search across all columns. | | locale | string | 'en-IN' | Locale for currency and numeric formatting. | | enableRowMerging | boolean | false | Enables invoice-style row merging. | | enableFormulaColumns| boolean | false | Enables in-grid formula builder dialog. | | pivotMode | boolean | false | Enables pivot cross-tabulation. | | stateKey | string | 'bways-grid' | Key used to namespace localStorage state. |


📜 License

BWays-Report Software License Agreement

Copyright (c) 2026 CCPL / BWays Team. All rights reserved.

1. GRANT OF LICENSE
Subject to the terms and conditions of this Agreement, CCPL / BWays Team ("Licensor") hereby grants to the individual or entity ("Licensee") a personal, non-exclusive, non-transferable, revocable license to install, import, and execute this library ("Software") solely as an integrated component in Licensee's software applications and projects.

2. RESTRICTIONS ON USE
Except as expressly permitted in Section 1, Licensee shall not, and shall not permit or assist any third party to:
(a) Modify, adapt, alter, translate, or create derivative works based upon the Software or any part thereof.
(b) Copy, duplicate, replicate, or extract the source code, stylesheets, templates, assets, or binary files of the Software.
(c) Decompile, disassemble, reverse engineer, or otherwise attempt to derive or reconstruct the underlying source code, ideas, algorithms, file formats, or programming interfaces of the Software.
(d) Distribute, sub-license, lease, rent, loan, sell, resell, assign, or otherwise transfer the Software or any rights therein to any third party.
(e) Sublicense, host, or make available the Software on any software-as-a-service (SaaS), platform-as-a-service (PaaS), application service provider (ASP) basis, or cloud service bureau for the benefit of any third party.
(f) Remove, obscure, deface, or alter any copyright, trademark, patent, or other proprietary rights notices displayed on, within, or embedded in the Software.
(g) Publish or publicly disclose benchmark, performance, or competitive analysis results without prior written permission from the Licensor.

3. INTELLECTUAL PROPERTY RIGHTS
The Software and all intellectual property rights therein are and shall remain the exclusive property of CCPL / BWays Team. Nothing in this Agreement shall be construed to convey to Licensee any ownership interest in the Software.

4. TERMINATION
This Agreement is effective until terminated. Any breach of this Agreement immediately terminates Licensee's rights. Upon termination, Licensee shall immediately destroy all copies of the Software in its possession.

5. WARRANTY DISCLAIMER
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.

6. LIMITATION OF LIABILITY
IN NO EVENT SHALL CCPL / BWAYS TEAM BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.