@opencorestack/opengridx 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +4 -1
- package/dist/ai.cjs +1 -0
- package/dist/ai.cjs.map +1 -0
- package/dist/ai.d.ts +166 -0
- package/dist/ai.es.js +1 -0
- package/dist/ai.es.js.map +1 -0
- package/dist/index.d.ts +148 -2
- package/dist/opengridx.css +1 -1
- package/dist/opengridx.es.js +6084 -5523
- package/dist/opengridx.es.js.map +1 -1
- package/dist/opengridx.umd.js +17 -15
- package/dist/opengridx.umd.js.map +1 -1
- package/docs/API_REFERENCE.md +98 -1
- package/docs/README.md +3 -1
- package/docs/architecture/datagrid-orchestration.md +10 -1
- package/docs/customization/theming.md +9 -0
- package/docs/features/ai-toolkit.md +119 -0
- package/docs/features/clipboard.md +88 -0
- package/docs/features/editing-reordering.md +50 -0
- package/docs/features/keyboard-navigation.md +11 -0
- package/docs/features/undo-redo.md +79 -0
- package/docs/roadmap.md +1 -1
- package/lib/ai/coerce.ts +90 -0
- package/lib/ai/columns.ts +90 -0
- package/lib/ai/index.ts +16 -0
- package/lib/ai/schema.ts +214 -0
- package/lib/ai/types.ts +88 -0
- package/lib/ai/validate.ts +286 -0
- package/lib/components/Cell/Cell.css +5 -0
- package/lib/components/Cell/GridEditInputCell.css +12 -4
- package/lib/components/Cell/GridEditInputCell.tsx +19 -12
- package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.css +14 -0
- package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.tsx +3 -2
- package/lib/components/DataGrid/DataGrid.tsx +62 -2
- package/lib/components/FilterPanel/FilterPanel.css +14 -0
- package/lib/components/FilterPanel/FilterPanel.tsx +3 -2
- package/lib/components/ListView/ListView.css +2 -4
- package/lib/components/ListView/ListViewRow.tsx +2 -2
- package/lib/components/Toolbar/GlobalSearch.css +16 -0
- package/lib/components/Toolbar/GlobalSearch.tsx +3 -2
- package/lib/components/ui/Checkbox.tsx +16 -5
- package/lib/components/ui/Input.css +43 -0
- package/lib/components/ui/Input.tsx +24 -5
- package/lib/hooks/core/gridApiPlaceholder.ts +8 -1
- package/lib/hooks/core/useDataGrid.ts +27 -0
- package/lib/hooks/core/useGridCellSelection.ts +30 -2
- package/lib/hooks/core/useGridClipboardPaste.ts +283 -0
- package/lib/hooks/core/useGridUndoRedo.ts +220 -0
- package/lib/hooks/features/useGridBatchEdit.ts +217 -0
- package/lib/hooks/features/useGridEditing.ts +24 -45
- package/lib/index.ts +7 -0
- package/lib/styles/opengridx.css +2 -1
- package/lib/types/index.ts +124 -0
- package/lib/utils/editing/commit.ts +69 -0
- package/lib/utils/editing/targets.ts +109 -0
- package/lib/utils/parsing.ts +252 -0
- package/llms.txt +55 -1
- package/package.json +8 -2
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenGridX — AI Agent Context
|
|
2
2
|
# Package: @opencorestack/opengridx
|
|
3
|
-
# Version: 3.
|
|
3
|
+
# Version: 3.4.0
|
|
4
4
|
# Docs: https://opencorestack.github.io/OpenGridX/
|
|
5
5
|
# This file is machine-readable. AI developers: start here.
|
|
6
6
|
|
|
@@ -97,6 +97,12 @@ export default function App() {
|
|
|
97
97
|
| cellSelectionModel | GridCellSelectionModel | Controlled range: readonly { anchor: { id, field }, head: { id, field } }[] (0 or 1 range). Corners are ids/fields: the range follows sorting; cleared ('dataChange') when a corner is no longer displayed |
|
|
98
98
|
| onCellSelectionModelChange | (model, { reason }) => void | reason: 'pointer' | 'keyboard' | 'selectAll' | 'api' | 'clear' | 'dataChange' |
|
|
99
99
|
| showCellSelectionStats | boolean | Status bar: Count (non-empty), Sum and Average (numeric) of the range; slots.cellSelectionStats replaces it |
|
|
100
|
+
| disableClipboardPaste | boolean (3.4.0+) | With cellSelection, Ctrl/Cmd+V pastes TSV (Excel/Sheets) into editable cells: one value fills a range; a block goes from the range's top-left (or focused) cell, cut to the range and grid edges; no rows created. Parsed per column type, then valueSetter + processRowUpdate once per row. true = shortcut off (apiRef.pasteText still works) |
|
|
101
|
+
| onClipboardPaste | (result) => void (3.4.0+) | After every paste: { updated: id[], failed: {id, error}[], skipped: {id, field, reason: 'notEditable'/'invalidValue'}[], text } |
|
|
102
|
+
| onBeforeClipboardPaste | ({ text, anchor }) => boolean / string | Return false to cancel, a string to paste instead; a throw cancels |
|
|
103
|
+
| disableRangeClear | boolean (3.4.0+) | With cellSelection, Delete/Backspace on a multi-cell range empties editable cells ('' strings, null otherwise) as one edit; true = off |
|
|
104
|
+
| undoRedo | boolean / { limit } (3.4.0+) | Undo/redo of edits, pastes, range clears (default off, 100 actions). Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl+Y on a cell with no editor open. Recorded only after processRowUpdate succeeds; replayed through valueSetter + processRowUpdate; cells changed since are skipped ('changed', compared by value), removed rows ('missing') |
|
|
105
|
+
| onHistoryChange | ({ canUndo, canRedo, size }) => void | History change (size = undoable actions) |
|
|
100
106
|
|
|
101
107
|
### Sorting
|
|
102
108
|
| Prop | Type | Description |
|
|
@@ -245,6 +251,7 @@ There are no getRowClassName / getCellClassName / theme props: use GridColDef.ce
|
|
|
245
251
|
| renderEditCell | (params: GridRenderEditCellParams<R>) => ReactNode | Custom editor: call params.onValueChange(v), params.onCommit(), params.onCancel() |
|
|
246
252
|
| valueGetter | ({row, field, value}) => unknown | Computed value; used by sort, filter, quick search, aggregation, copy, export. Must be pure (quick filter caches per row object); a throw reads as undefined + dev warning |
|
|
247
253
|
| valueSetter | ({value, row, field}) => R | Write an edited value back onto the row (editable valueGetter columns) |
|
|
254
|
+
| valueParser | (text, { row, field, colDef }) => unknown | Paste parser for this column (3.4.0+), e.g. "1.234,5" → 1234.5. Throw/undefined skips the cell ('invalidValue'). Default by type: number "1,234.5"/"12%"/"$5"; date ISO or Date.parse (keeps the cell's kind); boolean true/false/yes/no/1/0; singleSelect value or label; empty → null ('' for strings) |
|
|
248
255
|
| valueFormatter | ({value, row, field}) => string | Format display value (value is `unknown`: cast before calling methods) |
|
|
249
256
|
| cellClassName | string / (params) => string | CSS class on cells |
|
|
250
257
|
| headerClassName | string | CSS class on header cell |
|
|
@@ -265,6 +272,7 @@ There are no getRowClassName / getCellClassName / theme props: use GridColDef.ce
|
|
|
265
272
|
| groupingValueFormatter | ({field, value}) => string | Group row label (default "field: value") |
|
|
266
273
|
| aggregable | boolean | false = no aggregation. Summaries panel offers number columns + aggregable: true |
|
|
267
274
|
| availableAggregationFunctions | string[] | Restrict aggregation functions for this column |
|
|
275
|
+
| aiExamples | unknown[] | Example values put into getGridAiSchema's schema (3.4.0+). SENT TO THE MODEL: real data, opt-in. Primitives only, max 10. Unused by the grid |
|
|
268
276
|
|
|
269
277
|
---
|
|
270
278
|
|
|
@@ -321,6 +329,14 @@ apiRef.current.getSelectedCells() // → { id, field, value }[]; synthetic
|
|
|
321
329
|
apiRef.current.copySelectedCells() // → Promise<void>; TSV, no header line
|
|
322
330
|
apiRef.current.clearCellSelection()
|
|
323
331
|
|
|
332
|
+
// Paste and undo/redo (3.4.0+)
|
|
333
|
+
apiRef.current.pasteText(text, anchor?) // → Promise<GridBatchEditResult>; anchor default: range top-left, else focused cell
|
|
334
|
+
apiRef.current.undo() // → Promise<GridBatchEditResult> (undoRedo)
|
|
335
|
+
apiRef.current.redo()
|
|
336
|
+
apiRef.current.canUndo() // → boolean
|
|
337
|
+
apiRef.current.canRedo()
|
|
338
|
+
apiRef.current.clearHistory()
|
|
339
|
+
|
|
324
340
|
// Aggregation
|
|
325
341
|
apiRef.current.getAggregationResult() // → Record<string, unknown> | null (null in pivot mode)
|
|
326
342
|
apiRef.current.getAggregationModel() // → GridAggregationModel | null
|
|
@@ -356,6 +372,22 @@ const processRowUpdate = (newRow: Person) => {
|
|
|
356
372
|
|
|
357
373
|
Double-click or Enter opens the editor; Enter / Tab / blur commits; Escape cancels. An edit whose row scrolls, pages or filters away is committed, not dropped.
|
|
358
374
|
|
|
375
|
+
Custom editors (3.3.1+): build them on the exported `Input` with `variant="cell"` — it fills the cell with no border/background/focus ring, like the built-in editors. `ref` reaches the `<input>` (forwardRef, React 18 + 19), `inputClassName` styles the `<input>` (`className` the wrapper), `startAdornment` / `endAdornment` add a unit, `error` adds an inset error edge and `aria-invalid`. Stop propagation of the Enter/Escape you handle.
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
import { Input } from '@opencorestack/opengridx';
|
|
379
|
+
function PriceEditor({ value, onValueChange, onCommit, onCancel }: GridRenderEditCellParams) {
|
|
380
|
+
const [text, setText] = useState(String(value ?? ''));
|
|
381
|
+
const ref = useRef<HTMLInputElement>(null);
|
|
382
|
+
useEffect(() => { ref.current?.focus(); ref.current?.select(); }, []);
|
|
383
|
+
const valid = text.trim() !== '' && Number(text) >= 0;
|
|
384
|
+
return <Input ref={ref} variant="cell" startAdornment="$" error={!valid} value={text}
|
|
385
|
+
onChange={e => { setText(e.target.value); const n = Number(e.target.value); if (e.target.value.trim() !== '' && n >= 0) onValueChange(n); }}
|
|
386
|
+
onKeyDown={e => { if (e.key === 'Enter') { e.stopPropagation(); if (valid) onCommit(); } if (e.key === 'Escape') { e.stopPropagation(); onCancel(); } }}
|
|
387
|
+
onBlur={() => (valid ? onCommit() : onCancel())} />;
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
359
391
|
---
|
|
360
392
|
|
|
361
393
|
## SERVER-SIDE DATA SOURCE
|
|
@@ -524,6 +556,27 @@ await printGrid(rows, columns, 'My Report Title');
|
|
|
524
556
|
|
|
525
557
|
---
|
|
526
558
|
|
|
559
|
+
## AI TOOLKIT (@opencorestack/opengridx/ai, 3.4.0+)
|
|
560
|
+
|
|
561
|
+
Separate entry point: no React, no dependencies, ~4.5 kB gzip; never loaded by the core import. OpenGridX calls no AI service: the app sends { prompt, schema, currentState } to its own model (structured output) and validates the reply.
|
|
562
|
+
|
|
563
|
+
```ts
|
|
564
|
+
import { getGridAiSchema, validateGridAiState } from '@opencorestack/opengridx/ai';
|
|
565
|
+
|
|
566
|
+
const schema = getGridAiSchema(columns, { include: ['filter', 'sort', 'grouping', 'aggregation'] });
|
|
567
|
+
const reply = await fetch('/api/grid-assistant', { method: 'POST', body: JSON.stringify({ prompt, schema, currentState }) });
|
|
568
|
+
const { state, errors } = validateGridAiState(await reply.text(), columns);
|
|
569
|
+
if (state.filterModel) setFilterModel(state.filterModel); // apply only the parts present
|
|
570
|
+
if (state.sortModel) setSortModel(state.sortModel);
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
- getGridAiSchema(columns, { include?, exclude?, descriptions = true, examples = true }) → JSON Schema draft 2020-12 with `schemaVersion: 1`. Parts (option name → key): filter → filterModel (items as oneOf per field, AND/OR groups ≤ 3 levels, quickFilterValues), sort → sortModel, grouping → rowGroupingModel, aggregation → aggregationModel, pivot → pivotModel, columnVisibility → columnVisibilityModel. Fields from filterable / sortable / groupable / hideable / aggregable !== false; operators = the column type's filter operators; aggregation: number (or aggregable: true) columns get sum/avg/count/min/max/unique, others count, limited by availableAggregationFunctions; singleSelect valueOptions become enums. Fields starting with `__` are skipped. Deterministic; reads no rows.
|
|
574
|
+
- validateGridAiState(json | jsonString, columns, { include?, exclude? }) → { state: GridAiState, errors: { path, message }[] }. Drops unknown parts, fields, disallowed fields, wrong operators, enum values outside the list; coerces values like clipboard paste ("1,200"/"$1,200" → 1200, "12%" → 0.12, yes/no/1/0 → boolean, dates → "YYYY-MM-DD", singleSelect by value or label, case-insensitive); removes empty groups; lists capped at 200 entries, errors at 100. Never throws; never reads `__proto__`.
|
|
575
|
+
- Privacy: no row data by default; `aiExamples` and `valueOptions` ARE sent; always apply `state`, never the raw reply.
|
|
576
|
+
- Types (from /ai): GridAiColumn, GridAiPart, GridAiSchema, GridAiSchemaOptions, GridAiState, GridAiValidateOptions, GridAiValidationError, GridAiValidationResult.
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
527
580
|
## CSS CUSTOMIZATION
|
|
528
581
|
|
|
529
582
|
All CSS variables use the `--ogx-` prefix and are declared on `:root` by the stylesheet. Override them on a wrapper (or use DataGridThemeProvider, which sets the same variables):
|
|
@@ -547,6 +600,7 @@ Class names use the `ogx__` BEM prefix, e.g.:
|
|
|
547
600
|
- Cell ranges (3.3.0+): `ogx__cell--range`, `ogx__cell--range-top|bottom|left|right` (inset box-shadow outline), `ogx--range-dragging` on the root during a drag; variables `--ogx-range-background`, `--ogx-range-border` (theme keys `grid.rangeBackground`, `grid.rangeBorder`)
|
|
548
601
|
- `ogx__header-cell`, `ogx__header-cell--sorted`, `ogx__header-cell--wrap` (wrapHeaderText, 3.3.0+)
|
|
549
602
|
- Sticky wrappers: `ogx__sticky-top` (header + top-pinned rows), `ogx__sticky-bottom` (bottom-pinned rows + aggregation footer)
|
|
603
|
+
- Form controls (3.3.1+): the toolbar search, column-panel search, filter value box and text/number/date editors render through `Input`: the `<input>` keeps its class (`ogx-global-search__input`, `ogx-column-visibility-panel__search-input`, `ogx-filter__value-input`, `ogx__edit-input`) inside a `div.ogx-input-wrapper` (`ogx-input-wrapper--cell` for editors) — use descendant selectors (`.ogx-global-search input`), not `> input`. The boolean editor and list-view row checkbox are the shared `Checkbox` (`.ogx-checkbox__box`; hidden `<input>`)
|
|
550
604
|
|
|
551
605
|
---
|
|
552
606
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opencorestack/opengridx",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "OpenGridX: High-performance React data infrastructure. Unlock advanced Row Grouping, Excel Export, and Column Pinning without the usual \"Pro\" gatekeeping. Built for speed, scale, and complete architectural freedom. Fully open, virtualization-ready, and feature-complete.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/opengridx.umd.js",
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"import": "./dist/opengridx.es.js",
|
|
13
13
|
"require": "./dist/opengridx.umd.js"
|
|
14
14
|
},
|
|
15
|
+
"./ai": {
|
|
16
|
+
"types": "./dist/ai.d.ts",
|
|
17
|
+
"import": "./dist/ai.es.js",
|
|
18
|
+
"require": "./dist/ai.cjs"
|
|
19
|
+
},
|
|
15
20
|
"./styles": {
|
|
16
21
|
"types": "./dist/opengridx.css.d.ts",
|
|
17
22
|
"default": "./dist/opengridx.css"
|
|
@@ -23,6 +28,7 @@
|
|
|
23
28
|
"!lib/**/*.test.ts",
|
|
24
29
|
"!lib/**/*.test.tsx",
|
|
25
30
|
"!lib/**/__screenshots__",
|
|
31
|
+
"!lib/**/__snapshots__",
|
|
26
32
|
"docs/architecture",
|
|
27
33
|
"docs/assets",
|
|
28
34
|
"docs/components",
|
|
@@ -45,7 +51,7 @@
|
|
|
45
51
|
"scripts": {
|
|
46
52
|
"dev": "vite",
|
|
47
53
|
"build": "tsc --project tsconfig.build.json && vite build",
|
|
48
|
-
"build:lib": "tsc --project tsconfig.build.json && vite build --config vite.config.lib.js && cp lib/styles/opengridx.css.d.ts dist/opengridx.css.d.ts && node scripts/check-bundle.mjs",
|
|
54
|
+
"build:lib": "tsc --project tsconfig.build.json && vite build --config vite.config.lib.js && vite build --config vite.config.lib.js --mode ai && cp lib/styles/opengridx.css.d.ts dist/opengridx.css.d.ts && node scripts/check-bundle.mjs",
|
|
49
55
|
"lint": "eslint .",
|
|
50
56
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit && tsc -p e2e/tsconfig.json",
|
|
51
57
|
"preview": "vite preview",
|