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

@zentto/datagrid-core

v1.7.0

Published

Pure logic engine for ZenttoDataGrid — sort, filter, group, pivot, aggregate, export. Zero UI dependencies.

Downloads

1,863

Readme

@zentto/datagrid-core

Motor de logica puro para ZenttoDataGrid — ordenamiento, filtrado, agrupacion, pivot, agregacion, formulas, exportacion y mas. Sin dependencias de UI.

Este paquete es el nucleo sin interfaz del ecosistema @zentto/datagrid. Puede usarse de forma independiente en cualquier entorno JavaScript/TypeScript para procesar datos tabulares, o como base para integraciones en frameworks propios.

Paquete privado — pertenece a la organizacion npm @zentto. Para instalarlo necesitas autenticarte con un token npm de la org.

Instalacion

# Configurar el token de la org (una sola vez)
npm config set //registry.npmjs.org/:_authToken <TOKEN_NPM_ZENTTO>

# Instalar el paquete
npm install @zentto/datagrid-core

Uso basico

import {
  sortRows,
  filterRows,
  groupRows,
  pivotRows,
  aggregate,
  computeTotals,
} from '@zentto/datagrid-core';
import type { ColumnDef, GridRow, FilterRule, SortEntry } from '@zentto/datagrid-core';

const columns: ColumnDef[] = [
  { field: 'nombre', header: 'Producto', sortable: true, filterable: true },
  { field: 'precio', header: 'Precio', type: 'number', aggregation: 'sum' },
  { field: 'categoria', header: 'Categoria', sortable: true, groupable: true },
];

const rows: GridRow[] = [
  { id: 1, nombre: 'Arroz Premium', precio: 45.00, categoria: 'Alimentos' },
  { id: 2, nombre: 'Aceite de Oliva', precio: 120.00, categoria: 'Alimentos' },
  { id: 3, nombre: 'Detergente', precio: 75.00, categoria: 'Limpieza' },
];

// Ordenar por precio descendente
const sorted = sortRows(rows, [{ field: 'precio', direction: 'desc' }]);

// Filtrar por categoria
const filtered = filterRows(rows, [
  { field: 'categoria', operator: 'equals', value: 'Alimentos' },
]);

// Calcular totales
const totals = computeTotals(rows, columns);
// { precio: 240, __zentto_totals__: true, ... }

API

Funciones de datos

| Funcion | Descripcion | Parametros | Retorno | |---------|-------------|------------|---------| | sortRows(rows, sorts) | Ordena filas por multiples columnas (sort estable, locale-aware) | rows: GridRow[], sorts: SortEntry[] | GridRow[] | | filterRows(rows, rules) | Aplica reglas de filtro combinadas con AND | rows: GridRow[], rules: FilterRule[] | GridRow[] | | quickSearch(rows, query, fields?) | Busqueda de texto libre en todos los campos | rows: GridRow[], query: string, fields?: string[] | GridRow[] | | aggregate(rows, field, fn) | Calcula una agregacion numerica sobre un campo | rows: GridRow[], field: string, fn: AggregationType | number | | computeTotals(rows, columns, label?) | Genera la fila de totales para columnas con aggregation | rows: GridRow[], columns: ColumnDef[], label?: string | GridRow | | groupRows(rows, config) | Agrupa filas con subtotales opcionales | rows: GridRow[], config: RowGroupingConfig | GroupedResult | | pivotRows(rows, config) | Transforma filas planas en tabla pivot | rows: GridRow[], config: PivotConfig | PivotResult | | paginateRows(rows, model) | Pagina filas del lado del cliente | rows: GridRow[], model: PaginationModel | PaginationResult |

Formulas

| Funcion | Descripcion | Parametros | Retorno | |---------|-------------|------------|---------| | evaluateFormula(formula, row, allRows) | Evalua una expresion tipo Excel para una fila | formula: string, row: GridRow, allRows: GridRow[] | unknown | | applyFormulas(rows, formulas) | Aplica multiples definiciones de formula a todas las filas | rows: GridRow[], formulas: FormulaDefinition[] | GridRow[] |

Exportacion

| Funcion | Descripcion | Parametros | Retorno | |---------|-------------|------------|---------| | toCsv(rows, columns) | Genera string CSV con encabezados | rows: GridRow[], columns: ColumnDef[] | string | | downloadCsv(rows, columns, filename?) | Descarga CSV como archivo (browser) | rows: GridRow[], columns: ColumnDef[], filename?: string | void | | toJson(rows, columns) | Serializa a JSON | rows: GridRow[], columns: ColumnDef[] | string | | downloadJson(rows, columns, filename?) | Descarga JSON como archivo (browser) | mismos que arriba | void | | toExcelHtml(rows, columns) | Genera HTML compatible con Excel | rows: GridRow[], columns: ColumnDef[] | string | | downloadExcel(rows, columns, filename?) | Descarga archivo .xls (browser) | mismos que arriba | void | | toMarkdown(rows, columns) | Genera tabla Markdown | rows: GridRow[], columns: ColumnDef[] | string | | generatePrintHtml(rows, columns, options?) | Genera HTML optimizado para imprimir/PDF | rows: GridRow[], columns: ColumnDef[], options?: PrintOptions | string |

Busqueda y seleccion

| Funcion | Descripcion | Parametros | Retorno | |---------|-------------|------------|---------| | findInGrid(rows, columns, query) | Encuentra celdas que coinciden con el query (tipo Ctrl+F) | rows: GridRow[], columns: ColumnDef[], query: string | FindMatch[] | | copyToClipboard(rows, columns) | Copia filas al portapapeles como texto tabulado | rows: GridRow[], columns: ColumnDef[] | Promise<void> | | copyRangeToClipboard(rows, columns, range) | Copia un rango de celdas seleccionado | rows: GridRow[], columns: ColumnDef[], range: NormalizedRange | Promise<void> | | parseClipboardData(text) | Parsea texto del portapapeles en formato tabular | text: string | PasteData | | applyPasteData(rows, paste, startRow, startCol, columns) | Aplica datos pegados desde portapapeles | multiples parametros | GridRow[] | | normalizeRange(range) | Normaliza un rango de seleccion (garantiza start <= end) | range: SelectionRange | NormalizedRange | | isCellInRange(range, row, col) | Verifica si una celda esta dentro de un rango | range: NormalizedRange, row: number, col: number | boolean |

Edicion avanzada

| Funcion / Clase | Descripcion | Uso principal | |-----------------|-------------|---------------| | applyBatchEdit(rows, changes) | Aplica multiples cambios de celda en una operacion | Edicion masiva sin mutacion | | validateValue(value, rule) | Valida un valor contra una regla de validacion | Edicion inline con validacion | | evaluateConditionalFormat(value, rules) | Evalua reglas de formato condicional para una celda | Estilo dinamico por condicion | | UndoRedoStack | Clase para historial de ediciones (undo/redo) | new UndoRedoStack(maxSize?) |

Virtualizacion y layout

| Funcion | Descripcion | Retorno | |---------|-------------|---------| | calculateVirtualScroll(config) | Calcula ventana de filas visibles para scroll virtual | VirtualScrollResult | | calculateDynamicVirtualScroll(config) | Virtualizacion con alturas de fila variables | VirtualScrollResult | | saveLayout(gridId, layout) | Guarda layout en localStorage + zentto-cache remoto | void | | loadLayout(gridId) | Carga layout desde localStorage (sync) con sync remoto en background | GridLayout \| null | | clearLayout(gridId) | Elimina layout guardado | void |

Visualizacion (SVG, sin dependencias)

| Funcion | Descripcion | |---------|-------------| | generateChartSvg(rows, columns, config) | Genera SVG de grafico (bar, line, pie, area, donut, scatter, stacked, combo) | | generateQrSvg(value) | Genera SVG de codigo QR (ISO 18004, usa qrcode-generator) | | generateBarcodeSvg(value, type) | Genera SVG de codigo de barras (code128, ean13, code39) | | generateTimelineSvg(entries) | Genera SVG de linea de tiempo horizontal | | processSparklineData(data, type) | Prepara datos para sparklines (line, bar, area) |

Datos jerarquicos y estructurales

| Funcion | Descripcion | |---------|-------------| | buildTreeRows(rows, idField, parentField) | Construye estructura de arbol para datos jerarquicos | | getDescendantIds(nodes, id) | Obtiene todos los IDs descendientes de un nodo | | computeMergeMap(rows, columns) | Calcula mapa de celdas fusionadas para columnas con merge: true |

Auditoria

| Clase | Descripcion | |-------|-------------| | AuditTrail | Registra historial de cambios con usuario, timestamp y valores anterior/nuevo |

Ejemplos

Ordenamiento multi-columna

import { sortRows } from '@zentto/datagrid-core';
import type { GridRow, SortEntry } from '@zentto/datagrid-core';

const rows: GridRow[] = [
  { id: 1, nombre: 'Arroz Premium', precio: 45, categoria: 'Alimentos' },
  { id: 2, nombre: 'Aceite de Oliva', precio: 120, categoria: 'Alimentos' },
  { id: 3, nombre: 'Detergente', precio: 75, categoria: 'Limpieza' },
  { id: 4, nombre: 'Papel Higienico', precio: 30, categoria: 'Limpieza' },
];

// Ordenar por categoria ascendente, luego por precio descendente
const sorts: SortEntry[] = [
  { field: 'categoria', direction: 'asc' },
  { field: 'precio', direction: 'desc' },
];

const sorted = sortRows(rows, sorts);
// Alimentos: Aceite(120), Arroz(45) → Limpieza: Detergente(75), Papel(30)

Filtrado combinado con busqueda rapida

import { filterRows, quickSearch } from '@zentto/datagrid-core';
import type { GridRow, FilterRule } from '@zentto/datagrid-core';

const rows: GridRow[] = [
  { id: 1, nombre: 'Widget A', precio: 29.99, activo: true },
  { id: 2, nombre: 'Gadget B', precio: 49.99, activo: false },
  { id: 3, nombre: 'Widget Pro', precio: 99.99, activo: true },
];

// Filtrar por precio mayor a 25 Y activo igual a true
const rules: FilterRule[] = [
  { field: 'precio', operator: 'gt', value: 25 },
  { field: 'activo', operator: 'equals', value: 'true' },
];
const filtered = filterRows(rows, rules);

// Busqueda de texto libre
const searched = quickSearch(rows, 'widget');
// Retorna filas que contienen "widget" en cualquier campo

Tabla pivot con totales

import { pivotRows } from '@zentto/datagrid-core';
import type { GridRow, PivotConfig } from '@zentto/datagrid-core';

const ventas: GridRow[] = [
  { id: 1, vendedor: 'Maria', region: 'Norte', monto: 100 },
  { id: 2, vendedor: 'Maria', region: 'Sur',   monto: 80  },
  { id: 3, vendedor: 'Pedro', region: 'Norte', monto: 150 },
  { id: 4, vendedor: 'Pedro', region: 'Sur',   monto: 120 },
  { id: 5, vendedor: 'Ana',   region: 'Norte', monto: 200 },
];

const config: PivotConfig = {
  rowField: 'vendedor',
  columnField: 'region',
  valueField: 'monto',
  aggregation: 'sum',
  showGrandTotals: true,
  showRowTotals: true,
};

const { rows, columns } = pivotRows(ventas, config);
// rows: [{ vendedor:'Ana', Norte:200, Sur:0, __total__:200 }, ...]
// La fila TOTAL agrega todas las columnas

Formulas tipo Excel

import { applyFormulas } from '@zentto/datagrid-core';
import type { GridRow, FormulaDefinition } from '@zentto/datagrid-core';

const rows: GridRow[] = [
  { id: 1, precioVenta: 100, precioCompra: 60 },
  { id: 2, precioVenta: 200, precioCompra: 140 },
];

const formulas: FormulaDefinition[] = [
  // Margen bruto por fila
  { field: 'margen', formula: '={precioVenta}-{precioCompra}' },
  // Porcentaje de margen redondeado a 2 decimales
  { field: 'margenPct', formula: '=ROUND(({precioVenta}-{precioCompra})/{precioCompra}*100, 2)' },
  // Etiqueta condicional
  { field: 'clasificacion', formula: '=IF({margenPct} > 30, "Alta", "Normal")' },
];

const enrichedRows = applyFormulas(rows, formulas);
// rows[0]: { ..., margen: 40, margenPct: 66.67, clasificacion: 'Alta' }

Historial de ediciones (Undo/Redo)

import { UndoRedoStack } from '@zentto/datagrid-core';
import type { EditAction } from '@zentto/datagrid-core';

const history = new UndoRedoStack(50); // max 50 acciones

// Registrar una edicion
const action: EditAction = {
  type: 'cell-edit',
  timestamp: Date.now(),
  rowKey: '1',
  field: 'precio',
  oldValue: 100,
  newValue: 120,
};
history.push(action);

// Deshacer
if (history.canUndo) {
  const undone = history.undo();
  console.log(undone?.field); // 'precio'
}

// Rehacer
if (history.canRedo) {
  history.redo();
}

Persistencia de layout con zentto-cache

import { saveLayout, loadLayout, configureRemoteCache } from '@zentto/datagrid-core';
import type { GridLayout } from '@zentto/datagrid-core';

// Configurar cache remoto una vez al iniciar la app
configureRemoteCache({
  baseUrl: 'https://cache.zentto.net',
  companyId: 'empresa-001',
  userId: 'usuario-42',
});

// Guardar layout (sincronico local + async remoto)
const layout: GridLayout = {
  columnOrder: ['nombre', 'precio', 'categoria'],
  density: 'compact',
  sorts: [{ field: 'precio', direction: 'desc' }],
  pageSize: 25,
};
saveLayout('grid-productos', layout);

// Cargar layout (sincronico desde localStorage, sync remoto en background)
const saved = loadLayout('grid-productos');
if (saved) {
  console.log(saved.density); // 'compact'
}

Tipos principales

GridRow

type GridRow = Record<string, unknown>;

Representa una fila de datos. Los campos se acceden por nombre.

ColumnDef

Definicion completa de una columna. Campos destacados:

interface ColumnDef {
  field: string;                  // Nombre del campo en el row (obligatorio)
  header?: string;                // Etiqueta visible
  type?: 'string' | 'number' | 'date' | 'datetime' | 'boolean' | 'actions' | 'color' | 'percentage';
  sortable?: boolean;
  filterable?: boolean;
  aggregation?: 'sum' | 'avg' | 'count' | 'min' | 'max';
  formula?: string;               // Formula tipo Excel: '={campo1}*{campo2}'
  statusColors?: Record<string, string>;  // { Activo: 'success', Inactivo: 'error' }
  conditionalFormat?: ConditionalFormatRule[];
  validation?: ValidationRule;
  sparkline?: 'line' | 'bar' | 'area';
  barcode?: 'qr' | 'code128' | 'ean13' | 'code39';
  merge?: boolean;                // Fusionar celdas consecutivas con el mismo valor
  renderCell?: (value: unknown, row: GridRow) => string;
}

FilterRule

interface FilterRule {
  field: string;
  operator: 'contains' | 'notContains' | 'equals' | 'notEquals' |
            'startsWith' | 'endsWith' | 'gt' | 'gte' | 'lt' | 'lte' |
            'isEmpty' | 'isNotEmpty' | 'between' | 'inList';
  value: unknown;
}

PivotConfig

interface PivotConfig {
  rowField: string;               // Campo para las filas del pivot
  columnField: string;            // Campo cuyos valores se convierten en columnas
  valueField: string;             // Campo numerico que se agrega
  aggregation?: 'sum' | 'avg' | 'count' | 'min' | 'max';  // Default: 'sum'
  showGrandTotals?: boolean;      // Agrega fila TOTAL al final
  showRowTotals?: boolean;        // Agrega columna __total__ por fila
}

GridLayout

interface GridLayout {
  columnOrder?: string[];
  columnWidths?: Record<string, number>;
  columnVisibility?: Record<string, boolean>;
  density?: 'compact' | 'standard' | 'comfortable';
  groupByField?: string;
  sorts?: Array<{ field: string; direction: string }>;
  pageSize?: number;
  viewMode?: 'table' | 'form' | 'cards' | 'kanban' | 'chart';
  pivotConfig?: PivotConfig;
}

GridOptions

Opciones completas disponibles al configurar el grid (usadas por @zentto/datagrid internamente):

interface GridOptions {
  columns: ColumnDef[];
  rows: GridRow[];
  sortModel?: SortEntry[];
  filters?: FilterRule[];
  pagination?: PaginationModel;
  paginationMode?: 'client' | 'server';
  enableGrouping?: boolean;
  enablePivot?: boolean;
  showTotals?: boolean;
  theme?: 'light' | 'dark' | 'zentto';
  locale?: 'es' | 'en' | 'pt';
  gridId?: string;               // Para persistencia de layout
  // ... y mas de 30 opciones adicionales
}

Changelog

Ver CHANGELOG.md para el historial completo de versiones.

Paquetes relacionados

Repositorio

https://github.com/zentto-erp/zentto-datagrid