Package: @opencorestack/opengridx
License: MIT © 2026 Open Core Stack
- API reference expanded to full surface coverage:
docs/API_REFERENCE.mdgrew from 188 to 1,132 lines. Added 8 new top-level sections — server-side data source (GridDataSource,GridGetRowsParams,GridGetRowsResponse), all event callback param types (GridRowParams,GridCellParams,GridColumnOrderChangeParams,GridRowOrderChangeParams,GridDetailPanelParams), column and row pinning types, full filter model deep reference (per-type operator table,GridFilterGroupnesting), grid state and initial state slice reference, aggregation reference (all 6 built-in functions,getAggregationPositionsemantics), row grouping, column group headers, and list view. DataGrid props section restructured into 13 feature-area sub-tables covering every previously undocumented prop. Developers building server-side sorting + aggregation + pinned columns no longer need to read TypeScript source.
GridColDefdocumentation: Added all previously undocumented column properties —flex,minWidth,maxWidth,align,headerAlign,description,editable,renderHeader,renderEditCell,cellClassName,headerClassName,disableColumnMenu,groupable,aggregable,availableAggregationFunctions,valueOptions(forsingleSelect),colSpan,rowSpan. BothREADME.mdanddocs/API_REFERENCE.mdnow carry the complete table.- Hooks documentation: Expanded the stubs in
docs/API_REFERENCE.mdinto full reference entries.usePivot(was entirely missing),useGridStateStorage(was one sentence — now has a full options + return table and code example),useAggregation(now has params/return tables and built-in function list),useGridApiRef(corrected description and added usage example).
- Bundled documentation accuracy: All doc files shipped inside the npm package (
docs/) have been corrected to match the actual v1.0.0 API. Key fixes: removed non-existentpageSizestandalone prop (correct API ispaginationModel+pageSizeOptions), fixedheighttype tonumber | string, correctedonColumnOrderChangeparams shape, removed non-existentisRowSelectableandreorderableprops, fixedGridFilterModel.itemstype, added missingGridApimethods (getFilterModel,getAllColumns,setPageSize,getAggregationResult,getAggregationModel,copySelectedRows), and correctedGridInitialStatepersisted state fields. AI agents (Cursor, Copilot, Windsurf) reading bundled docs will now generate accurate code. - README API reference: Same prop and type corrections applied — complete
apiRefmethod list, new prop tables for Events, Columns, Pinning, Inline Editing, Row Reordering, and updated comparison table.
First stable public release. All 32 demo pages ship with a live source viewer. npm publish workflow is live.
- npm publish workflow: GitHub Actions workflow (
.github/workflows/npm-publish.yml) triggers on anyv*.*.*tag push — runs lint, build, thennpm publish. The package is now publicly available as@opencorestack/opengridxon the npm registry. - Source viewer on all 32 demos: Every demo page now uses
DocsLayoutwith a collapsible "View Source" tab showing the full component source code. Previously only 7 of 32 demos had this; the remaining 25 have been migrated.
- Version:
0.1.xpre-release series →1.0.0stable. The public API (DataGridProps,GridColDef,GridApi, all hooks and types) is now considered stable. - Demo consistency: All 32 demos share the same
DocsLayoutshell — consistent title, description, live preview, and source viewer. Inline<h1>/<h2>+<p>manual headers removed from every migrated demo.
PivotModeDemo—apiRef: any,fallbackRows: any[],props: anytoolbar → fully typedInfiniteScrollDemo— introducedPersonRowinterface, allanyin data source and sort params replacedServerSideAggregationDemo—(a as any)[field]field access →keyof Employeekeyed accessAggregationFooter+ServerSideAggregationDemo—valueFormatter: { value: any }→unknownwith narrowingSlotsDemo— addedEmployeeRowinterface,renderCell: (params: any)× 2 replacedCRUDTutorial—renderCell: (params: any)→GridRenderCellParams<User>RealEstatePortfolio—useState<any>for pinnedColumns →useState<GridColumnPinning>ExportDemo—apiRef: any→ReturnType<typeof useGridApiRef>,rowsToPrint: any[]→ typedCustomPagination—(props: any)component signature → explicit typed interfaceEditing—handleProcessRowUpdate = (newRow: any)→MockRowinferred from data
onRowClicknever fired whenonCellClickwas registered:Cell.tsxwas callinge.stopPropagation()inside its click handler wheneveronCellClickwas provided. This silently ate the event before it could bubble to the row'sonClickhandler, makingonRowClickpermanently unreachable from cell clicks. Removed the stopPropagation — both callbacks now fire in the natural bubble order (cell first, then row), matching standard data grid behavior.- Column visibility panel list not updating after column reorder: The toolbar was receiving
effectiveColumns(the pre-ordering array, in original definition order) instead oforderedColumns(the reordered array). After a drag-reorder in the panel, the grid columns reordered correctly but the panel list stayed frozen in definition order. FixedtoolbarProps.columnsto useorderedColumns. - Reset button ignoring column sequence: The Reset button in the column visibility panel called
onShowAllonly (restoring visibility), leaving any user-reordered sequence in place. AddedonColumnOrderResetprop threaded fromColumnVisibilityPanel→ColumnsPanelWrapper→GridToolbar→DataGrid. DataGrid provides() => setInternalColumnOrder(columns.map(c => c.field))to restore original definition order on reset. FilterPanelDemofilter panel inaccessible: The demo had noslots={{ toolbar: GridToolbar }}, so the toolbar never rendered and the filter icon never appeared. Added the toolbar slot and rewrote the demo to useDocsLayout(consistent with all other demos).EventsDemoevent handlers never fired:onRowClickwas broken by the stopPropagation bug above.onFilterModelChangeandonColumnOrderChangewere dead — no toolbar existed to trigger them. Fixed by addingslots={{ toolbar: GridToolbar }}. Also replaced threeany-typed handler signatures withGridSortItem[],GridFilterModel, andGridColumnOrderChangeParams.FilterPaneldebounce stale-closure bug: The 300 ms debounceuseEffectreaditem,col.field, andcurrentOperatordirectly from closure (stale values after operator or field changes), suppressed witheslint-disable-next-line. Replaced with a refs-sync pattern (useLayoutEffectwritingitemRef,colFieldRef,operatorRefeach render) so the effect reads current values without the lint suppression and without stale closures.
- Type safety — full
anyelimination: Everyanyacrosslib/replaced with explicit types orunknown. Key changes:GridRowModelindex signatureany → unknown(with explicit internal row fields added to the type), all cell/value/error params typed asunknown, aggregation functions typed as(values: unknown[]) => unknown,GridAggregationResulttyped asRecord<string, unknown>, slot component types useRecord<string, unknown>, export utilities narrowed withinstanceof Errorguards. - No more lint suppressions: Removed all
eslint-disable-next-line react-hooks/exhaustive-depscomments — every case fixed at the root cause rather than suppressed. Methods include: state refactors (scrollTickanti-pattern →scrollTop/scrollLeftstate), ref patterns for stable callbacks, and correct dep arrays. - DataGrid.tsx continued decomposition: Further hooks and components extracted —
useGridScrollSync(RAF-batched scroll state),useGridVirtualization,useGridVisibleRows,useGridColumns,GridAggregationFooter,GridEmptyState,GridErrorOverlay,GridVirtualRows,GridPinnedRows,GridStandaloneColumnPanel,GridListView. Each module has a single clear responsibility and typed params/return interface.
GridApi.scrollToIndexes: New imperative API methodapiRef.current.scrollToIndexes({ rowIndex?, colIndex? })scrolls the viewport to bring any row and/or column into view. Column index addresses all data columns (left-pinned + unpinned + right-pinned); pinned columns are always visible so they are silently skipped. Row scrolling accounts for variable-height rows (expanded detail panels, grouped rows).useGridKeyboardNavigationhook: Extracted ~370 lines of keyboard navigation state and handlers fromDataGrid.tsxinto a standaloneuseGridKeyboardNavigationhook. Fixes a previously dead code path where pressing Enter/Space on a header cell never triggered column sort (the edit handler ran first). The hook is part of the publiclib/source.useLayouthook: Extracted all layout-computation logic fromDataGrid.tsxinto a standaloneuseLayouthook, reducing the main component by ~350 lines.- Test suite: Added Vitest +
@testing-library/reactinfrastructure with 65 unit tests coveringfilterRows,sortRows,useAggregation, and a DataGrid smoke test. - ScrollToIndexes demo: New
/scroll-todemo page showcasing thescrollToIndexesAPI with live row/column index controls.
- Excel export file format error:
exportToExcelgenerates an HTML-table file withapplication/vnd.ms-excelMIME type (the legacy XLS trick). All demo call-sites were passing explicit.xlsxfilenames, causing Excel 2007+ to reject the download with "file format or file extension is not valid". Changed allexportToExcelusages to.xls.exportToExcelAdvanced(ExcelJS, real OOXML) is unaffected and correctly keeps.xlsx. - Keyboard sort on column headers: Enter/Space on a focused header cell now correctly triggers sort. Previously the generic Enter-edit handler ran first, making header sort unreachable via keyboard.
- ESLint errors: Resolved all lint errors across the library — hooks called after conditional early returns (
Cell.tsx,Row.tsx), ref mutations in the render phase moved touseLayoutEffect, and portal targets readingref.currentduring render moved touseState + useLayoutEffect.
- Toolbar Component Identity: Fixed a major bug where defining the
GridToolbarwithin a component's render body produced a new React component reference on every render, causing the toolbar to constantly unmount and remount (destroying all internal states like open panels or typed search text). ReplacedReact.createElementwith direct function invocation in theStableWrapperto bypass React's component-identity check and persist internal DOM state. - Global Search Focus Preservation: Refactored
GlobalSearchinto an uncontrolled component to prevent continuous data re-renders from stealing focus. Added auseLayoutEffectto automatically restore browser focus to the input field if a React virtual DOM diff incidentally drops it mid-keystroke. - Filter Panel Auto-Dismiss: The Advanced Filter panel no longer collapses indiscriminately when clicking into numeric filter fields or during parent re-renders. Implemented a stable callback ref that prevents the underlying event listeners from rehooking during typing. Click-outside auto-close has been structurally disabled in favor of an explicit "Close" button.
- Pivot Mode Aggregation: Addressed a critical bug where
aggregationModelwas trying to read base columns (e.g.revenue) on pivot rows that use synthetic column keys (e.g.Q1\u001frevenue\u001fsum), resulting in broken totals.- The aggregation footer now renders synthetic pivot totals correctly.
- The
GridToolbarnow actively provisionseffectiveColumnsto theAggregationPanelto allow users to build summaries on pivot dimensions. - Added a built-in "Grand Total" row appended directly to the
usePivotoutput to generate automatic baseline column totals.
- Exporting Selected Rows: Corrected data omission in the Demo files where print exports were grabbing the entire dataset instead of respecting active row selection. Used
apiRef.current.getSelectedRows()to extract standard export data without requiring explicit prop-threading.
exportableProperty: Addedexportable?: booleantoGridColDef. This allows excluding specific columns (like action buttons, menus, or images) from all export formats (CSV, Excel, JSON, and Print).- AI-Native Integration: The published npm package now includes raw source code (
lib/) and full documentation (docs/). This allows AI agents (Cursor, Windsurf, Copilot) to "see" the implementation patterns and documentation insidenode_modules, leading to significantly better code generation for downstream users.
- Fixed an issue where the main wrapper
classNamewould erroneously include extra whitespace (e.g.ogx) when no optional classes were active. - Fixed an issue where
onRowOrderChangedrag-and-drop visuals didn't actually update in theEventsDemocomponent examples because it was referencing a static array instead of React State. - Corrected a TypeScript regression where
headerClassNamecomment structure was accidentally broken during the previous update.
- Refined the npm package publication files:
docs/researchanddocs/assets(large binary images) are now excluded to keep the package size lean while retaining all high-value documentation for humans and AI.
- Complete theming support for all advanced dropdown panels (Column Visibiity, Filter Editor, Pivot Mode, Global Search) so they correctly adapt to custom themes via
<DataGridThemeProvider>. - Aggregation, Pivot, filtering, and export capability options now appear directly in the
ThemingDemoexample.
- Replaced the hardcoded portal mounting (
document.body) on popovers to instead intelligently hunt for.ogx-theme-providerto organically inherit user themes in overlay panels. - Fixed GlobalSearch input focus shadow not fully respecting CSS variables.
- Exported missing public types (
GridSortItem,GridApi,GridRowSelectionModel,GridColumnVisibilityModel, etc.) inlib/index.tsto prevent developers from having to derive them manually usingNonNullable.
- Column Visibility Reorder: Added a drag handle to the
ColumnVisibilityPanelletting users seamlessly reorder columns directly via the Visibility Panel dropdown checkbox list. Uses native HTML Drag and Drop API with no external dependencies. - Added
onColumnReordersupport toColumnVisibilityPanelandGridToolbar.
import '@opencorestack/opengridx/styles'now resolves correctly in TypeScript projects. The./stylessubpath export inpackage.jsonnow includes atypespointer todist/opengridx.css.d.ts, eliminating the "Cannot find module" TS error.build:libscript now copiesopengridx.css.d.tsintodist/automatically so it's always included in published packages.
llms.txtbundled inside the npm package — a machine-readable AI agent API context file with complete props reference, type definitions, and usage examples. Located atnode_modules/@opencorestack/opengridx/llms.txtafter installation.
- CSS now explicitly imported at the barrel entry (
lib/index.ts), ensuring styles are never silently dropped by bundlers (Vite, Webpack, Next.js App Router) that don't auto-resolve side-effect CSS from library packages. - Column resize:
ColumnResizeHandlenow uses the logical stored width (currentWidthprop) instead of reading DOMgetBoundingClientRect(), fixing resize jitter and incorrect delta calculations on second+ drag. - Pinned column resize: Resizing a pinned (sticky) column no longer corrupts its displayed width — the DOM measurement was previously offset by the sticky
left/rightposition, causing an erroneous width jump on first drag.
- Updated
README.mdto accurately describe CSS handling and provide a clear fallback import instruction for all environments.
- Cell editing state now correctly pushes to internal state (
baseRows) instead of being overridden by rigidprops.rowsbindings, preventing data loss on successive edits.
- ExcelJS correctly marked as external in Vite build config (consistent with
peerDependencies) - Clipboard programmatic copy button now correctly reads live selection state via
apiRef.getSelectedRows() Ctrl+Ckeyboard shortcut now works when grid checkboxes are focused
- Package size reduced from 8.4 MB → 1.8 MB unpacked (ExcelJS no longer bundled)
- README rewritten with Getting Started first, basic example, and full API reference table
- Cleaned devDependencies (removed unused
strip-comment,strip-comments)
Status: ✅ RELEASE READY — 100% feature-complete for v0.1.0 scope
This is the initial public release of OpenGridX. All planned v0.1.0 features are implemented, tested, and included in the production bundle.
- High-Performance Virtualization — Custom row + column virtual scrolling engine, 60fps at 100k+ rows
- Multi-Column Sorting — Client-side and server-side; stable multi-field sort
- Advanced Filtering — 11+ operators (contains, equals, startsWith, etc.) with AND/OR filter builder UI
- Pagination — Client-side and server-side modes with configurable page sizes
- Row Selection — Single and multi-row checkbox selection with
rowSelectionModelcontrolled/uncontrolled API
- Column Pinning — Left and right sticky columns with correct z-index layering
- Row Pinning — Top and bottom pinned rows with visual separation
- Column Resizing — Throttled drag-to-resize at 60fps with minimum width enforcement
- Column Reordering — Drag-and-drop column reorder
- Row Reordering — Drag-and-drop row reorder with
onRowOrderChangecallback - Detail Panels — Expandable master-detail rows via
getDetailPanelContent - Cell & Row Spanning —
colSpanandrowSpansupport for merged-cell layouts - List View Mode — Card-based responsive layout via
listView/listViewColumn - Column Grouping — Multi-level column header groups via
columnGroupingModel - Toolbar — Built-in toolbar with column visibility, filter, and density controls; fully replaceable via
slots
- Inline Cell Editing — Double-click or Enter to edit;
editableper column;processRowUpdatecallback - Tree Data — Client-side hierarchical rows via
treeData+getTreeDataPath - Row Grouping — Group rows by column value with collapsible groups and aggregation summaries
- Aggregation — SUM, AVG, COUNT, MIN, MAX in group footers and global sticky footer
- Pivot Mode — Multidimensional data pivoting via
pivotMode+pivotModel
- Data Source API —
useGridDataSourcehook for unified server-side fetching - Server-Side Sorting, Filtering & Pagination — All offloaded cleanly to the backend
- Infinite Scroll — Viewport-triggered batch-loading (
paginationMode="infinite") - Server-Side Tree Data — Lazy children loading via
dataSource.getChildren - Server-Side Aggregation — Fetch summary totals directly from API responses
- CSV Export —
exportToCsv()utility, respectsvalueFormatter - Excel Export — Basic
.xlsxviaexportToExcel(); advanced pixel-perfect image-embedded export viaexportToExcelAdvanced()(lazy-loads ExcelJS) - JSON Export —
exportToJson() - Print —
printGrid()with print-optimised CSS
- Keyboard Copy —
Ctrl+C/Cmd+Ccopies selected rows as TSV (tab-separated values) - Programmatic Copy —
apiRef.current.copySelectedRows()for button-triggered copying - Excel/Sheets Compatible — TSV output pastes cleanly into any spreadsheet app
- Smart Focus Handling — Does not intercept
Ctrl+Cin text inputs; correctly handles checkbox-focused grid cells
DataGridThemeProvider— React context-based global theming- 5 Built-in Themes —
darkTheme,roseTheme,emeraldTheme,amberTheme,compactTheme - CSS Variables — Full
--ogx-*token system; Shadow DOM compatible cellClassName/headerClassName— Per-column custom class injection
- Semantic ARIA roles:
grid,row,gridcell,columnheader aria-sort,aria-selected,aria-expanded,aria-readonly,aria-labelthroughout- Full keyboard navigation: Arrow keys, Tab, Enter, Escape, Home/End, PageUp/PageDown
- Visible focus ring in keyboard mode (CSS classname-toggled, zero React state overhead)
initialStateprop — Restore column widths, visibility, sort, and filter on mountuseGridStateStorage(key)hook — Auto-saves tolocalStorage; pluggable storage backend
apiRef— Full imperative API:getSelectedRows,copySelectedRows,selectRow,sortColumn,setFilterModel,getVisibleRows,scrollToIndexes, and moreslotsSystem — Replace Toolbar, Pagination, NoRowsOverlay, LoadingOverlay, FooterslotProps— Pass custom props to slot components- TypeScript — 100% typed; full
index.d.tsoutput viavite-plugin-dts - Zero UI Dependencies — No Ant Design, MUI, or Radix. Pure React + vanilla CSS (BEM)
| Artifact | Minified | Gzipped |
|---|---|---|
opengridx.es.js (ES Module) |
226 KB | 52 KB |
opengridx.umd.js (UMD) |
1,089 KB | 315 KB |
opengridx.css |
59 KB | 10 KB |
exceljs (lazy, Excel export only) |
1,385 KB | 302 KB |
- Rich Excel Styling — Bold headers, background fill, border styles natively via ExcelJS (no post-processing)
- Cell Range Clipboard — Select a rectangular cell region (mouse drag), copy to clipboard, paste from Excel back into editable cells
Last Updated: March 18, 2026