@jielga/tmdatagrid 2.4.0 → 2.5.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/docs/columns.md CHANGED
@@ -125,6 +125,7 @@ meta: {
125
125
  | `editor` | `TMDataGridEditorComponent` | By `type` | Replaces the cell editor. See [Editors](/docs/editors#writing-your-own). |
126
126
  | `validate` | `TMDataGridFieldValidate` | - | Per-cell validation. See [Validation](/docs/editors#validation). |
127
127
  | `mapValue` | `TMDataGridEditValueMap` | - | Maps each value an editor writes. See [Mapping the value](/docs/editors#mapping-the-value-as-it-is-typed). |
128
+ | `mapCommitValue` | `TMDataGridEditCommitMap` | - | Maps each changed field once, as its row commits. See [Mapping the value at commit](/docs/editors#mapping-the-value-at-commit). |
128
129
 
129
130
  ```tsx
130
131
  meta: {
package/docs/editors.md CHANGED
@@ -134,6 +134,35 @@ A custom editor rendering its own input has the same problem, and solves it the
134
134
  same way: record `selectionStart` as the value is handed over, and restore it in
135
135
  a layout effect once the mapped value has rendered.
136
136
 
137
+ ## Mapping the value at commit
138
+
139
+ `meta.edit.mapCommitValue` maps a field once, as its row commits, instead of on every write.
140
+ Use it for a rule the user must be free to break while typing, such as trimming a string: with `mapValue`, a trailing space could never be typed.
141
+
142
+ ```tsx
143
+ meta: {
144
+ edit: {
145
+ mapCommitValue: ({ value }) =>
146
+ typeof value === "string" ? value.trim() : value,
147
+ },
148
+ }
149
+ ```
150
+
151
+ It runs before the validators of the submit, so a field that trims to `""` fails a required rule.
152
+ The result is written back into the form, so the draft, `changes` and `onCommit` all hold the mapped value.
153
+ An editor still open after the commit shows it too: in row mode, or after a commit the validators refused.
154
+ When a draft is held for `saveDrafts`, the mapped value is what the pending change shows.
155
+
156
+ It runs for the fields the user changed.
157
+ A stored value nobody edited is left as it is.
158
+ A row being added has no stored value, so every editable field of it is mapped, a field `meta.edit.enabled` keeps the user out of included.
159
+ A field written by `edit.setCellValue()`, `edit.setRowValues()`, `edit.clearCell()` or the Delete key is not mapped, because the caller passes the stored value itself; the other fields the user changed in the same row still are.
160
+ The rows of `edit.addRows({ commit: true })` are not mapped at all.
161
+
162
+ The map receives `TMDataGridEditCommitMapArgs`: `{ value, previous, row, column, table }`.
163
+ `previous` is the value the field held when editing began, and `row` is `undefined` for a row being added.
164
+ `mapValue` runs first, and its result is what `value` holds here.
165
+
137
166
  ## Validation
138
167
 
139
168
  The validators are TanStack Form's own: a Standard Schema (Zod, Valibot,
@@ -240,11 +269,13 @@ validator instead. See [A query builder form](/docs/query-builder).
240
269
  | `meta.edit.editor` | Column meta | `TMDataGridEditorComponent` | By `meta.type` | Replaces the cell editor. |
241
270
  | `meta.edit.validate` | Column meta | `TMDataGridFieldValidate` | – | Field-level validation. A bare schema or function means `onChange`. |
242
271
  | `meta.edit.mapValue` | Column meta | `TMDataGridEditValueMap` | – | Maps each value an editor writes, before it reaches the draft. |
272
+ | `meta.edit.mapCommitValue` | Column meta | `TMDataGridEditCommitMap` | – | Maps each changed field once, as its row commits. See [Mapping the value at commit](#mapping-the-value-at-commit). |
243
273
  | `editing.rowValidators` | Option | `TMDataGridRowValidators` | – | Form-level validation, for cross-field rules. |
244
274
  | `editing.tableValidators` | Option | `TMDataGridTableValidators` | – | Cross-row rules, handed the collection with every draft overlaid. See [Cross-row rules](#cross-row-rules). |
245
275
  | `TMDataGridTableValidateArgs` | Export | type | – | What a table validator receives: `value`, `rowId`, `isNew`, `rows`. |
246
276
  | `TMDataGridEditorArgs` | Export | type | – | What an editor component receives: `field`, `commit`, `cancel`, `row`, `column`. |
247
277
  | `TMDataGridEditValueMapArgs` | Export | type | – | What `mapValue` receives: `value`, `previous`, `row`, `column`, `table`. |
278
+ | `TMDataGridEditCommitMapArgs` | Export | type | – | What `mapCommitValue` receives: `value`, `previous`, `row`, `column`, `table`. |
248
279
  | `TMDataGridStringEditor` · `NumberEditor` · `BooleanEditor` · `DateEditor` · `SelectEditor` · `MultiSelectEditor` | Exports | components | – | The six built-ins, for wrapping. |
249
280
  | `normalizeFieldValidate` | Export | `(validate) => validators` | – | Turns a bare schema into TanStack Form's validator shape. |
250
281
  | `getEditFieldName` | Export | `(column) => string` | – | The data path a column's edits write to. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jielga/tmdatagrid",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "A React data grid built on TanStack Table v9 and Mantine - always virtualized, with resizable, reorderable, sortable, filterable, hideable and pinnable columns.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,7 +18,7 @@ description: >
18
18
  metadata:
19
19
  type: core
20
20
  library: '@jielga/tmdatagrid'
21
- library_version: '2.4.0'
21
+ library_version: '2.5.0'
22
22
  sources:
23
23
  - 'Jielga/react:packages/tmdatagrid/docs/styling.md'
24
24
  - 'Jielga/react:packages/tmdatagrid/docs/toolbar.md'
@@ -14,7 +14,7 @@ description: >
14
14
  metadata:
15
15
  type: core
16
16
  library: '@jielga/tmdatagrid'
17
- library_version: '2.4.0'
17
+ library_version: '2.5.0'
18
18
  sources:
19
19
  - 'Jielga/react:packages/tmdatagrid/docs/cell-selection.md'
20
20
  - 'Jielga/react:packages/tmdatagrid/src/core/cellNavigation.ts'
@@ -16,7 +16,7 @@ description: >
16
16
  metadata:
17
17
  type: core
18
18
  library: '@jielga/tmdatagrid'
19
- library_version: '2.4.0'
19
+ library_version: '2.5.0'
20
20
  sources:
21
21
  - 'Jielga/react:packages/tmdatagrid/docs/columns.md'
22
22
  - 'Jielga/react:packages/tmdatagrid/docs/column-layout.md'
@@ -98,7 +98,7 @@ with it sits in their namespaces. `type` and `options` are read by both stages,
98
98
  which is why they are in neither.
99
99
 
100
100
  `meta.filter` holds `operators`, `defaultOperator`, `control` and `url`; `meta.edit`
101
- holds `enabled`, `field`, `editor`, `validate` and `mapValue`. Their fields are
101
+ holds `enabled`, `field`, `editor`, `validate`, `mapValue` and `mapCommitValue`. Their fields are
102
102
  in [references/columns-api.md](references/columns-api.md).
103
103
 
104
104
  ```tsx
@@ -22,6 +22,7 @@ Reference for the `columns` skill.
22
22
  | `editor` | `TMDataGridEditorComponent` | By `meta.type` | Replaces the cell editor. Module scope. |
23
23
  | `validate` | `TMDataGridFieldValidate` | – | Field-level validation. A bare schema means `onChange`. |
24
24
  | `mapValue` | `TMDataGridEditValueMap` | – | Maps each value an editor writes, on every keystroke. |
25
+ | `mapCommitValue` | `TMDataGridEditCommitMap` | – | Maps each changed field once, as its row commits. |
25
26
 
26
27
  ## Column-level feature options
27
28
 
@@ -18,7 +18,7 @@ description: >
18
18
  metadata:
19
19
  type: core
20
20
  library: '@jielga/tmdatagrid'
21
- library_version: '2.4.0'
21
+ library_version: '2.5.0'
22
22
  sources:
23
23
  - 'Jielga/react:packages/tmdatagrid/docs/pagination.md'
24
24
  - 'Jielga/react:packages/tmdatagrid/docs/scrolling.md'
@@ -6,7 +6,7 @@ description: >
6
6
  and editing.onSaveDrafts, why the grid never mutates data, gating with
7
7
  editing.columns, meta.edit.enabled and meta.edit.field, the built-in editors
8
8
  picked by meta.type, custom editors via meta.edit.editor, value mapping with
9
- meta.edit.mapValue, validation at every level - meta.edit.validate,
9
+ mapValue and mapCommitValue, validation at every level - meta.edit.validate,
10
10
  cross-field editing.rowValidators, cross-row editing.tableValidators over the
11
11
  draft-overlaid collection - adding and deleting rows (edit.addRow,
12
12
  newRowDefaults, onRowAdd, onRowDelete), the edit lane, TMDataGrid.DraftActions
@@ -18,7 +18,7 @@ description: >
18
18
  metadata:
19
19
  type: core
20
20
  library: '@jielga/tmdatagrid'
21
- library_version: '2.4.0'
21
+ library_version: '2.5.0'
22
22
  sources:
23
23
  - 'Jielga/react:packages/tmdatagrid/docs/editing.md'
24
24
  - 'Jielga/react:packages/tmdatagrid/docs/draft-store.md'
@@ -274,6 +274,19 @@ validators check and what is committed.
274
274
  meta: { edit: { mapValue: ({ value }) => String(value).toUpperCase() } }
275
275
  ```
276
276
 
277
+ `meta.edit.mapCommitValue` maps once, as the row commits, for a rule the user must be free to break while typing: trimming a string.
278
+ It runs before the submit validators on the fields the user changed, and writes the result back into the form, so the draft store, `changes` and `onCommit` all hold the mapped value.
279
+ Trimming only in `onCommit` or on the server leaves the grid's own state untrimmed.
280
+
281
+ ```tsx
282
+ meta: {
283
+ edit: {
284
+ mapCommitValue: ({ value }) =>
285
+ typeof value === "string" ? value.trim() : value,
286
+ },
287
+ }
288
+ ```
289
+
277
290
  Detail for all three: [references/editors-and-validation.md](references/editors-and-validation.md).
278
291
 
279
292
  ## Adding and deleting rows
@@ -133,7 +133,8 @@ Types: `TMDataGridEditMode`, `TMDataGridEditApi`, `TMDataGridEditState`,
133
133
  `TMDataGridRowValidators`, `TMDataGridRowEditForm`, `TMDataGridRowAddArgs`,
134
134
  `TMDataGridRowDeleteArgs`, `TMDataGridEditingOptions`,
135
135
  `TMDataGridSaveOutcomes`, `TMDataGridAddRowsOptions`,
136
- `TMDataGridEditValueMapArgs`, `TMDataGridTableValidateArgs`.
136
+ `TMDataGridEditValueMapArgs`, `TMDataGridEditCommitMapArgs`,
137
+ `TMDataGridTableValidateArgs`.
137
138
 
138
139
  ## The edit lane
139
140
 
@@ -182,6 +182,30 @@ otherwise drops the caret at the end of the field. A custom editor rendering its
182
182
  own input has to do the same: record `selectionStart` on change, restore it in a
183
183
  layout effect.
184
184
 
185
+ ## Mapping the value at commit
186
+
187
+ `meta.edit.mapCommitValue` maps a field once, as its row commits, where `mapValue` runs on every write.
188
+ Use it for a rule the user must be free to break while typing: trimming a string, because with `mapValue` a trailing space could never be typed.
189
+
190
+ ```tsx
191
+ meta: {
192
+ edit: {
193
+ mapCommitValue: ({ value }) =>
194
+ typeof value === "string" ? value.trim() : value,
195
+ },
196
+ }
197
+ ```
198
+
199
+ - It runs before the submit validators, so `" "` trimmed to `""` fails a required rule.
200
+ - The result is written back into the form: the draft store, `changes` and `onCommit` hold the mapped value, and so does an editor still open after the commit (row mode, or a refused commit).
201
+ Trimming in `onCommit` or on the server instead leaves the grid's own state untrimmed.
202
+ - It maps only the fields the user changed.
203
+ A row being added maps every editable field.
204
+ - A field written by `edit.setCellValue()`, `edit.setRowValues()`, `edit.clearCell()` or the Delete key is not mapped; the other fields the user changed in that row still are.
205
+ The rows of `edit.addRows({ commit: true })` are not mapped at all.
206
+ - The map receives `TMDataGridEditCommitMapArgs`: `{ value, previous, row, column, table }`.
207
+ `previous` is the value when editing began; `row` is `undefined` for a row being added.
208
+
185
209
  ## Field validation
186
210
 
187
211
  `meta.edit.validate` takes TanStack Form's field-validator vocabulary. A bare schema
@@ -18,7 +18,7 @@ description: >
18
18
  metadata:
19
19
  type: core
20
20
  library: '@jielga/tmdatagrid'
21
- library_version: '2.4.0'
21
+ library_version: '2.5.0'
22
22
  sources:
23
23
  - 'Jielga/react:packages/tmdatagrid/docs/filtering.md'
24
24
  - 'Jielga/react:packages/tmdatagrid/docs/quick-search.md'
@@ -13,7 +13,7 @@ description: >
13
13
  metadata:
14
14
  type: core
15
15
  library: '@jielga/tmdatagrid'
16
- library_version: '2.4.0'
16
+ library_version: '2.5.0'
17
17
  sources:
18
18
  - 'Jielga/react:packages/tmdatagrid/docs/getting-started.md'
19
19
  - 'Jielga/react:packages/tmdatagrid/docs/anatomy.md'
@@ -14,7 +14,7 @@ description: >
14
14
  metadata:
15
15
  type: core
16
16
  library: '@jielga/tmdatagrid'
17
- library_version: '2.4.0'
17
+ library_version: '2.5.0'
18
18
  sources:
19
19
  - 'Jielga/react:packages/tmdatagrid/docs/grouping.md'
20
20
  - 'Jielga/react:packages/tmdatagrid/docs/summary-row.md'
@@ -15,7 +15,7 @@ description: >
15
15
  metadata:
16
16
  type: lifecycle
17
17
  library: '@jielga/tmdatagrid'
18
- library_version: '2.4.0'
18
+ library_version: '2.5.0'
19
19
  sources:
20
20
  - 'Jielga/react:packages/tmdatagrid/docs/migrating-to-2.md'
21
21
  - 'Jielga/react:packages/tmdatagrid/src/index.ts'
@@ -18,7 +18,7 @@ description: >
18
18
  metadata:
19
19
  type: core
20
20
  library: '@jielga/tmdatagrid'
21
- library_version: '2.4.0'
21
+ library_version: '2.5.0'
22
22
  sources:
23
23
  - 'Jielga/react:packages/tmdatagrid/docs/use-tm-data-grid.md'
24
24
  - 'Jielga/react:packages/tmdatagrid/docs/persistence.md'
@@ -17,7 +17,7 @@ description: >
17
17
  metadata:
18
18
  type: core
19
19
  library: '@jielga/tmdatagrid'
20
- library_version: '2.4.0'
20
+ library_version: '2.5.0'
21
21
  sources:
22
22
  - 'Jielga/react:packages/tmdatagrid/docs/row-selection.md'
23
23
  - 'Jielga/react:packages/tmdatagrid/docs/row-interaction.md'
@@ -15,7 +15,7 @@ description: >
15
15
  metadata:
16
16
  type: core
17
17
  library: '@jielga/tmdatagrid'
18
- library_version: '2.4.0'
18
+ library_version: '2.5.0'
19
19
  sources:
20
20
  - 'Jielga/react:packages/tmdatagrid/docs/server-side.md'
21
21
  - 'Jielga/react:packages/tmdatagrid/docs/server-query.md'
@@ -13,7 +13,7 @@ description: >
13
13
  metadata:
14
14
  type: core
15
15
  library: '@jielga/tmdatagrid'
16
- library_version: '2.4.0'
16
+ library_version: '2.5.0'
17
17
  sources:
18
18
  - 'Jielga/react:packages/tmdatagrid/docs/testing.md'
19
19
  - 'Jielga/react:playwright/support/DataGrid.ts'
@@ -12,7 +12,7 @@ description: >
12
12
  metadata:
13
13
  type: core
14
14
  library: '@jielga/tmdatagrid'
15
- library_version: '2.4.0'
15
+ library_version: '2.5.0'
16
16
  sources:
17
17
  - 'Jielga/react:packages/tmdatagrid/docs/testing.md'
18
18
  - 'Jielga/react:packages/tmdatagrid/test/gallery/main.tsx'
@@ -12,7 +12,7 @@ description: >
12
12
  metadata:
13
13
  type: core
14
14
  library: '@jielga/tmdatagrid'
15
- library_version: '2.4.0'
15
+ library_version: '2.5.0'
16
16
  sources:
17
17
  - 'Jielga/react:packages/tmdatagrid/docs/testing.md'
18
18
  - 'Jielga/react:packages/tmdatagrid/docs/editing.md'
@@ -367,6 +367,28 @@ export type TMDataGridEditValueMap = (
367
367
  args: TMDataGridEditValueMapArgs,
368
368
  ) => unknown;
369
369
 
370
+ /** What `meta.edit.mapCommitValue` is handed for one field of a row being committed. */
371
+ export type TMDataGridEditCommitMapArgs = {
372
+ /** The value the field holds as the row is committed. */
373
+ value: unknown;
374
+ /** What the field held when editing began. */
375
+ previous: unknown;
376
+ /** The row being committed. `undefined` for a row that is being added. */
377
+ row: ErasedRow | undefined;
378
+ column: ErasedColumn;
379
+ table: TMDataGridTable<TMDataGridRowData>;
380
+ };
381
+
382
+ /**
383
+ * `meta.edit.mapCommitValue` - the value as the row commits, mapped.
384
+ *
385
+ * Runs once per field, not per keystroke, so the user can type what the
386
+ * mapped value would not allow, like a trailing space.
387
+ */
388
+ export type TMDataGridEditCommitMap = (
389
+ args: TMDataGridEditCommitMapArgs,
390
+ ) => unknown;
391
+
370
392
  /**
371
393
  * `meta.edit` - everything about how this column is edited, in one place,
372
394
  * mirroring the `edit.*` engine the grid exposes at runtime.
@@ -419,6 +441,14 @@ export type TMDataGridColumnEditOptions<
419
441
  * {@link TMDataGridEditValueMap}.
420
442
  */
421
443
  mapValue?: TMDataGridEditValueMap;
444
+ /**
445
+ * Maps the value of each field the user changed, once, as its row commits -
446
+ * trim a string the user was free to type spaces into. It runs before the
447
+ * validators of the submit, and its result is written back into the form,
448
+ * so the draft, `changes` and `onCommit` hold the mapped value. See
449
+ * {@link TMDataGridEditCommitMap}.
450
+ */
451
+ mapCommitValue?: TMDataGridEditCommitMap;
422
452
  };
423
453
 
424
454
  /** A new row being committed - `onRowAdd`, and `saveDrafts`'s `created`. */
@@ -1822,7 +1852,64 @@ export function createEditEngine(
1822
1852
  );
1823
1853
  };
1824
1854
 
1825
- const commit = async (rowId: string): Promise<boolean> => {
1855
+ /**
1856
+ * Runs every `meta.edit.mapCommitValue` over the row's form and writes the
1857
+ * results back. An open row maps the fields the user changed - a value that
1858
+ * was already stored is not the user's to have rewritten; a row being added
1859
+ * has no stored value, so every editable field of it is mapped. A field in
1860
+ * `callerFields` holds a value the caller wrote, not the user, and is left
1861
+ * as written. Written without validation: the submit that follows judges
1862
+ * the mapped values.
1863
+ */
1864
+ const applyCommitMaps = (
1865
+ entry: FormEntry,
1866
+ rowId: string,
1867
+ callerFields: ReadonlySet<string>,
1868
+ ) => {
1869
+ const { table } = getContext();
1870
+ const values = entry.form.state.values as TMDataGridRowData;
1871
+ const changed = entry.isNew
1872
+ ? null
1873
+ : new Set(diff(entry.original, values).map((change) => change.columnId));
1874
+ const row = entry.isNew ? undefined : getRow(rowId);
1875
+ for (const column of editableColumns()) {
1876
+ const map = column.columnDef.meta?.edit?.mapCommitValue;
1877
+ if (map === undefined) continue;
1878
+ if (changed !== null && !changed.has(column.id)) continue;
1879
+ const field = getEditFieldName(column);
1880
+ if (field === null || callerFields.has(field)) continue;
1881
+ const value: unknown = getBy(
1882
+ entry.form.state.values as TMDataGridRowData,
1883
+ field,
1884
+ );
1885
+ const mapped = map({
1886
+ value,
1887
+ previous: getBy(entry.original, field),
1888
+ row,
1889
+ column,
1890
+ table,
1891
+ });
1892
+ if (sameValue(value, mapped)) continue;
1893
+ entry.form.setFieldValue(field as never, mapped as never, {
1894
+ dontValidate: true,
1895
+ });
1896
+ }
1897
+ };
1898
+
1899
+ const commit = (rowId: string): Promise<boolean> =>
1900
+ commitRow(rowId, new Set());
1901
+
1902
+ /**
1903
+ * `callerFields` names the fields a caller wrote itself, which no editor
1904
+ * touched - `writeFields` passes the ones it writes, the rows of
1905
+ * `addRows({ commit: true })` pass `"all"`. They hold stored values already,
1906
+ * as `meta.edit.mapValue` has always assumed, so `mapCommitValue` leaves
1907
+ * them alone; every other field the user changed is still mapped.
1908
+ */
1909
+ const commitRow = async (
1910
+ rowId: string,
1911
+ callerFields: ReadonlySet<string> | "all",
1912
+ ): Promise<boolean> => {
1826
1913
  const entry = forms.get(rowId);
1827
1914
  // No form: the row is committed already, or the grid never held it.
1828
1915
  // Either way there is nothing left to decide.
@@ -1830,6 +1917,9 @@ export function createEditEngine(
1830
1917
  // Enter and blur race on the same edit; the second caller joins the
1831
1918
  // first's commit instead of submitting the row twice.
1832
1919
  if (entry.pendingCommit !== null) return entry.pendingCommit;
1920
+ // Before the pristine check: a value mapped back to the original leaves
1921
+ // nothing to commit.
1922
+ if (callerFields !== "all") applyCommitMaps(entry, rowId, callerFields);
1833
1923
  // A pristine form has nothing to say - drop it without a consumer call.
1834
1924
  // Not for a new row: adding an untouched entry is still an add.
1835
1925
  if (
@@ -2030,10 +2120,14 @@ export function createEditEngine(
2030
2120
  // validate side by side. Out to `onRowAdd`, one at a time and in
2031
2121
  // order, so the consumer sees the rows as the file had them.
2032
2122
  const results = getContext().draft
2033
- ? await Promise.all(tempIds.map((tempId) => commit(tempId)))
2123
+ ? await Promise.all(
2124
+ tempIds.map((tempId) => commitRow(tempId, "all")),
2125
+ )
2034
2126
  : [];
2035
2127
  if (!getContext().draft) {
2036
- for (const tempId of tempIds) results.push(await commit(tempId));
2128
+ for (const tempId of tempIds) {
2129
+ results.push(await commitRow(tempId, "all"));
2130
+ }
2037
2131
  }
2038
2132
  return splitCommitted(tempIds, results);
2039
2133
  });
@@ -2382,7 +2476,9 @@ export function createEditEngine(
2382
2476
  * round trip would stall every other row's markers and the caret.
2383
2477
  *
2384
2478
  * No editor is involved, so `meta.edit.mapValue` does not run - the caller
2385
- * writes the stored value itself. Validation is untouched: this is the same
2479
+ * writes the stored value itself - and `meta.edit.mapCommitValue` skips the
2480
+ * fields written here, while still mapping what the user typed elsewhere in
2481
+ * an open row. Validation is untouched: this is the same
2386
2482
  * `commit`, so `meta.edit.validate` and `editing.rowValidators` still decide
2387
2483
  * whether the row lands, and a failure leaves the row open carrying its
2388
2484
  * errors.
@@ -2400,7 +2496,7 @@ export function createEditEngine(
2400
2496
  for (const { field, value } of writes) {
2401
2497
  entry.form.setFieldValue(field as never, value as never);
2402
2498
  }
2403
- return commit(rowId);
2499
+ return commitRow(rowId, new Set(writes.map(({ field }) => field)));
2404
2500
  };
2405
2501
  const open = forms.get(rowId);
2406
2502
  if (open !== undefined) return write(open);
package/src/index.ts CHANGED
@@ -110,6 +110,8 @@ export {
110
110
  type TMDataGridEditRowProjection,
111
111
  type TMDataGridEditRowSnapshot,
112
112
  type TMDataGridEditState,
113
+ type TMDataGridEditCommitMap,
114
+ type TMDataGridEditCommitMapArgs,
113
115
  type TMDataGridEditValueMap,
114
116
  type TMDataGridEditValueMapArgs,
115
117
  type TMDataGridFieldValidate,
@@ -777,7 +777,7 @@ type TMDataGridEditingCallbacks<TData extends RowData> = {
777
777
  * One TanStack Form per editing row; drafts survive scrolling because the
778
778
  * forms live outside the DOM, keyed by row id. Which columns edit, and with
779
779
  * what, is declared per column under `meta.edit`: `meta.type` picks the
780
- * built-in editor, and `enabled`, `field`, `editor`, `validate` and `mapValue`
780
+ * built-in editor, and `enabled`, `field`, `editor`, `validate`, `mapValue` and `mapCommitValue`
781
781
  * override the rest.
782
782
  */
783
783
  export type TMDataGridEditingOptions<TData extends RowData> =