Changelog
All notable changes to Elyra DataGrid are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Packages are versioned together and released from git tags. A single tag (e.g.
v0.1.3) publishes all four Composer packages — elyra/datagrid-protocol,
elyra/datagrid-server, elyra/datagrid-livewire, and elyra/datagrid-js.
0.2.1 - 2026-07-21
Added
- Natural-language filtering in the Vue and Svelte clients. Pass an
askfunction in the grid options (typically POSTing to an endpoint that callsGridDefinition::ask()) and both clients render an "ask" box in the toolbar. Submitting calls the newgrid.askFilter()on the client core, which applies the returned filter and refetches, trackingasking/askErrorstate. Omitaskto hide the box. NewMessageskeysaskPlaceholder/ask/askFailed. Verified end-to-end in the Vue starter.
Fixed
- Inter-package version constraints. Sibling packages required each other at
^0.1.0, which excludes0.2.xand brokecomposer require/updateon the 0.2 line. They now use>=0.1.0 <1.0.0, so the lock-stepped 0.x packages always resolve together across minor bumps.
0.2.0 - 2026-07-21
Added
- Natural-language filtering ("ask the grid"). Users can type a question
("revenue over 50k in region Nord last quarter") and the grid translates it,
server-side, into a
FilterGroupvia an LLM whose JSON-schema output is restricted to the grid's own declared columns and operators.- Safe by design: the result is re-validated against the allow-list (unknown fields/operators dropped) and compiled through the ordinary FilterCompiler (columns allow-listed, values bound) — it can only produce filters the grid already permits. No row data is sent to the model, only column metadata.
GridDefinition::ask(string $query, ?callable $engine = null): FilterGroup. The LLM call sits behind an injectable engine, so the validation/assembly is fully unit-tested without an API key (19 assertions).- Optional dependency on
laravel/ai(asuggest); with no provider configured,ask()degrades gracefully. - Livewire client: opt-in
public bool $assistant = true;renders an "ask" box in the toolbar that applies the translated filter to the builder. - Config:
datagrid.assistant. Docs: guides/natural-language-filtering.md. - Verified end-to-end against Anthropic: correct
AND/nested-ORtrees.
Fixed
- Protocol autoloading. The DTOs that share
GridRequest.php/GridMutation.php(FilterCondition, FilterGroup, Viewport, Search, …) were only reachable onceGridRequest/GridMutationhad been referenced (PSR-4 maps class name to file name). Added aclassmapautoload so every protocol class resolves on its own.
Tooling
- New
test:assistantsuite and a schema-consistency check that the assistant's operator allow-list matches the protocolFilterOpenum. Both run in CI.
0.1.5 - 2026-07-21
Second hardening pass from the code review: Svelte parity, server guard rails, race protection on auxiliary fetches, and dependency/process fixes.
Fixed
- Svelte client leaked on unmount —
DataGrid.sveltenow callsGridController.destroy()viaonDestroy(Vue already cleaned up viaonScopeDispose). - Livewire row-id comparisons were loose (
in_array($id, …, false)), so int-from-DB vs string-from-JS ids could mismatch. Selection/expanded/pinned membership now compares on the string form (isSelected/idIn/idIndex). perPage <= 0raisedDivisionByZeroError— now clamped to ≥ 1 inupdatedPerPage,pageCount, and the request builder.
Security
- Request guard rails via
GridLimits(config('datagrid.limits')orGridDefinition::limits()):max_take(1000),max_skip(100k, deep OFFSET was unbounded),max_filter_depth(15, filter recursion was unbounded),max_in_values(1000, IN lists were unbounded),max_export_rows(null = unlimited). aggregatableis now enforced — aggregates on non-aggregatable columns are rejected (the flag was declared but never checked).- LIKE wildcards escaped —
%/_incontains/startsWith/endsWithinput are escaped with anESCAPEclause, so "50%" matches literally.
Added
- Column virtualization in the Svelte client (was missing entirely): renders
only frozen columns plus the horizontal window, with spacer cells and
onScrollX, matching the Vue client. - Race protection extended to auxiliary fetches (facets, tree roots, tree children, group detail): each discards its result if a superseding refresh changed the filter/search/sort mid-flight.
Dependencies / tooling
elyra/datagrid-servernow requiresilluminate/validation(theValidatorfacade was used but not declared).elyra/datagrid-livewirenow requireslivewire/flux(the Blade usesflux:*components).package-lock.jsonis now committed (was git-ignored) for reproducible CI.- New
scripts/release.sh(npm run release <version>) automates the version bump, lockfile, bundle rebuild, test run, commit and tag.
0.1.4 - 2026-07-21
Hardening release following a full code review. Notably repairs the Svelte client, which was broken in 0.1.3.
Fixed
- Svelte client was broken in 0.1.3.
DataGrid.sveltereferencedgrid.featuresin the temporal dead zone (before its declaration), throwingReferenceErroron mount; the keyboard handler shadowed theGridControllerwith a local boolean, throwingTypeErroron Space/Enter/F2/Escape; andFilterBuilder.svelteimportedFilterCondition/FilterOp, which@elyra/datagrid-client-corenever re-exported. All fixed, and the shippeddatagrid-jsbundle rebuilt.
Security
- Create validation bypass. On create, every editable column's rules are now
applied, so
requiredfires for omitted fields (previously only submitted fields were validated). Updates remain partial. - Hybrid-search
vectorFieldallow-list. The client-supplied embedding column was quoted into SQL without an allow-list check; it is now resolved through the grid definition (rejected if undeclared) and passed as a driver-quoted reference. - XSS hardening. Row ids embedded into JS-evaluated attributes (Alpine
dblclick, Livewirewire:click) are encoded withIlluminate\Support\Js, so string primary keys containing quotes or markup cannot break out. - Authorization gate. New
GridDefinition::authorize()guards create/update/delete/export; denials throwGridException::unauthorized().
Added
debounceMsgrid option (default 250): free-text search and column-filter values now debounce instead of firing a request per keystroke. Explicit actions (sort/paging/operator changes) are never debounced and cancel a pending typed refetch. (Response race protection already existed.)isActiveRow(r)andFilterCondition/FilterOpre-exports on client-core.
Changed / Tooling
- CI now typechecks the Vue and Svelte clients (
vue-tsc+svelte-check), runs a PHP compiler/allow-list/authorization test suite (packages/server-laravel/tests/compilers.php), a protocol schema-consistency check (schema ↔ TS ↔ PHP), and a JS-bundle drift gate that fails ifdatagrid-js/distis out of sync with the client sources. - Protocol docs now describe the contract honestly (hand-mirrored + checked in CI, not code-generated).
0.1.3 - 2026-07-21
Added
- Double-click a row to edit. Double-clicking anywhere on a row now enters edit mode across all three clients (Livewire, Vue, Svelte). In in-cell mode it opens the cell you double-clicked when that cell is editable, otherwise the first editable cell of the row; in modal/slideover/inline modes it opens the row editor.
- Tooltips on row command icons. The edit, pin/unpin, and delete icons now
show hover tooltips. New localization keys
pinRow,unpinRow, anddeleteRow(English and Norwegian bundled). isActiveRow(r)on the client-core grid controller.
Changed
- Active-cell marker removed in favour of an active-row highlight. The boxed
active-cell outline (and its heavy
2pxfocus ring) felt too dominant, especially with a dark accent colour in light mode. The active position is now conveyed by tinting the whole active row a quiet grey (.dg-row-active). The multi-cell range highlight used for copy is retained. - The aggregate footer can now stick to the bottom of a fixed-height scroll
viewport (
.dg-vscroll tfoot td). For virtual scroll, paged mode remains the reliable way to keep the footer always visible.
Fixed
- In-cell editor never opened on double-click.
editCellreceives the row id as a string from the client ($wire.editCell('0', …)) while the row id is an integer, so the strict===comparison in the Livewire view never matched and the editor silently failed to render (no console error). Both sides are now compared as strings. Verified end-to-end with realdblclickevents. - Row double-click now dispatches through a dedicated Alpine method
(
editRowCell→$wire.editCell) instead of a fragile inline expression, and reads the double-clicked cell viadata-editable.
0.1.2 - 2026-07-21
Fixed
- Replaced inline
@php(...)in shipped Blade with block@php … @endphp, which caused a fatal parse error on Laravel 13 + Livewire (including the license notice partial). Never use inline@php()in shipped Blade.
0.1.1 - 2026-07-21
Fixed
- Additional Blade parsing fixes in the filter-builder partials on Laravel 13 + Livewire.
0.1.0 - 2026-07-21
Added
- Initial release. One JSON protocol powering three clients (Livewire + Flux, Vue + Inertia, Svelte + Inertia) on a PHP server package with first-class ElyraSQL support and a MySQL fallback driver.
- Columns, sorting (index-friendly stable tiebreaker), column filter row with operator picker, advanced AND/OR filter builder, global search.
- Grouping with per-level aggregates (including non-additive avg/median/ percentile/countDistinct), detail rows, and roll-ups.
- Paging with a numbered pager and page-size selector; opt-in totals, facets and aggregates cached per filter.
- Editing in inline, modal, slideover and in-cell modes, plus batch/in-cell editing with dirty tracking.
- Row selection, a full keyboard model, master-detail and self-referencing tree grids, left/right frozen columns with auto-fit, and virtual scroll.
- Streaming XLSX/CSV export via bounded key-range windows.
- Themeable via
--dg-*variables that inherit the host app palette and Flux accent, with light/dark support. - Offline RSA-2048 license verification with graceful degradation and a discreet unlicensed notice. Commercial distribution via Private Packagist.