@jielga/tmdatagrid 2.0.0-beta.12 → 2.0.0-beta.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jielga/tmdatagrid",
3
- "version": "2.0.0-beta.12",
3
+ "version": "2.0.0-beta.13",
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",
@@ -17,7 +17,7 @@ description: >
17
17
  metadata:
18
18
  type: core
19
19
  library: '@jielga/tmdatagrid'
20
- library_version: '2.0.0-beta.12'
20
+ library_version: '2.0.0-beta.13'
21
21
  sources:
22
22
  - 'Jielga/TMDataGrid:src/docs/styling.md'
23
23
  - 'Jielga/TMDataGrid:src/docs/toolbar.md'
@@ -14,7 +14,7 @@ description: >
14
14
  metadata:
15
15
  type: core
16
16
  library: '@jielga/tmdatagrid'
17
- library_version: '2.0.0-beta.12'
17
+ library_version: '2.0.0-beta.13'
18
18
  sources:
19
19
  - 'Jielga/TMDataGrid:src/docs/cell-selection.md'
20
20
  - 'Jielga/TMDataGrid:src/tmdatagrid/core/cellNavigation.ts'
@@ -16,7 +16,7 @@ description: >
16
16
  metadata:
17
17
  type: core
18
18
  library: '@jielga/tmdatagrid'
19
- library_version: '2.0.0-beta.12'
19
+ library_version: '2.0.0-beta.13'
20
20
  sources:
21
21
  - 'Jielga/TMDataGrid:src/docs/columns.md'
22
22
  - 'Jielga/TMDataGrid:src/docs/column-layout.md'
@@ -15,7 +15,7 @@ description: >
15
15
  metadata:
16
16
  type: core
17
17
  library: '@jielga/tmdatagrid'
18
- library_version: '2.0.0-beta.12'
18
+ library_version: '2.0.0-beta.13'
19
19
  sources:
20
20
  - 'Jielga/TMDataGrid:src/docs/pagination.md'
21
21
  - 'Jielga/TMDataGrid:src/docs/scrolling.md'
@@ -18,7 +18,7 @@ description: >
18
18
  metadata:
19
19
  type: core
20
20
  library: '@jielga/tmdatagrid'
21
- library_version: '2.0.0-beta.12'
21
+ library_version: '2.0.0-beta.13'
22
22
  sources:
23
23
  - 'Jielga/TMDataGrid:src/docs/editing.md'
24
24
  - 'Jielga/TMDataGrid:src/docs/query-builder.md'
@@ -17,7 +17,7 @@ description: >
17
17
  metadata:
18
18
  type: core
19
19
  library: '@jielga/tmdatagrid'
20
- library_version: '2.0.0-beta.12'
20
+ library_version: '2.0.0-beta.13'
21
21
  sources:
22
22
  - 'Jielga/TMDataGrid:src/docs/filtering.md'
23
23
  - 'Jielga/TMDataGrid:src/docs/quick-search.md'
@@ -11,7 +11,7 @@ description: >
11
11
  metadata:
12
12
  type: core
13
13
  library: '@jielga/tmdatagrid'
14
- library_version: '2.0.0-beta.12'
14
+ library_version: '2.0.0-beta.13'
15
15
  sources:
16
16
  - 'Jielga/TMDataGrid:src/docs/getting-started.md'
17
17
  - 'Jielga/TMDataGrid:src/docs/anatomy.md'
@@ -14,7 +14,7 @@ description: >
14
14
  metadata:
15
15
  type: core
16
16
  library: '@jielga/tmdatagrid'
17
- library_version: '2.0.0-beta.12'
17
+ library_version: '2.0.0-beta.13'
18
18
  sources:
19
19
  - 'Jielga/TMDataGrid:src/docs/grouping.md'
20
20
  - 'Jielga/TMDataGrid:src/docs/summary-row.md'
@@ -14,7 +14,7 @@ description: >
14
14
  metadata:
15
15
  type: core
16
16
  library: '@jielga/tmdatagrid'
17
- library_version: '2.0.0-beta.12'
17
+ library_version: '2.0.0-beta.13'
18
18
  sources:
19
19
  - 'Jielga/TMDataGrid:src/docs/use-tm-data-grid.md'
20
20
  - 'Jielga/TMDataGrid:src/tmdatagrid/useTMDataGrid.tsx'
@@ -17,7 +17,7 @@ description: >
17
17
  metadata:
18
18
  type: core
19
19
  library: '@jielga/tmdatagrid'
20
- library_version: '2.0.0-beta.12'
20
+ library_version: '2.0.0-beta.13'
21
21
  sources:
22
22
  - 'Jielga/TMDataGrid:src/docs/row-selection.md'
23
23
  - 'Jielga/TMDataGrid:src/docs/row-interaction.md'
@@ -11,7 +11,7 @@ description: >
11
11
  metadata:
12
12
  type: core
13
13
  library: '@jielga/tmdatagrid'
14
- library_version: '2.0.0-beta.12'
14
+ library_version: '2.0.0-beta.13'
15
15
  sources:
16
16
  - 'Jielga/TMDataGrid:src/docs/server-side.md'
17
17
  - 'Jielga/TMDataGrid:src/tmdatagrid/useTMDataGrid.tsx'
@@ -11,7 +11,7 @@ description: >
11
11
  metadata:
12
12
  type: core
13
13
  library: '@jielga/tmdatagrid'
14
- library_version: '2.0.0-beta.12'
14
+ library_version: '2.0.0-beta.13'
15
15
  sources:
16
16
  - 'Jielga/TMDataGrid:src/docs/testing.md'
17
17
  - 'Jielga/TMDataGrid:src/tmdatagrid/components/TMDataGrid.tsx'
@@ -239,7 +239,7 @@ function EditLaneCell<TData extends RowData>({
239
239
  data-row-id={rowId}
240
240
  onClick={(event) => {
241
241
  event.stopPropagation();
242
- edit.deleteRow(rowId);
242
+ edit.restoreRow(rowId);
243
243
  }}
244
244
  >
245
245
  <RestoreIcon size={16} stroke={1.6} />
@@ -707,11 +707,26 @@ export type TMDataGridEditApi<
707
707
  ) => Promise<TMDataGridAddRowsResult>;
708
708
  /**
709
709
  * Deletes a row: `onRowDelete` straight away, or under `editing.draft` a
710
- * toggle of the id in `deletedRowIds` - the row renders struck through
711
- * until `saveDrafts` reports it. On an uncommitted entry row it just
712
- * discards the entry.
710
+ * mark in `deletedRowIds` - the row renders struck through until
711
+ * `saveDrafts` reports it. Idempotent: deleting a marked row again leaves
712
+ * it marked, and {@link restoreRow} is the undo. On an entry row,
713
+ * committed or not, it just discards the entry; an id the grid does not
714
+ * know is a no-op.
713
715
  */
714
716
  deleteRow: (rowId: string) => void;
717
+ /**
718
+ * {@link deleteRow} for several rows in one call - one notification for
719
+ * the batch, for a bulk action over a selection. Because `deleteRow` is
720
+ * idempotent and ignores unknown ids, the list may be passed exactly as
721
+ * the selection stands - already-marked rows stay marked, duplicates and
722
+ * stale ids do nothing.
723
+ */
724
+ deleteRows: (rowIds: ReadonlyArray<string>) => void;
725
+ /**
726
+ * Removes a row's deletion mark - the lane's Restore. A no-op on a row
727
+ * that is not marked, and outside `editing.draft`, where no marks exist.
728
+ */
729
+ restoreRow: (rowId: string) => void;
715
730
  /** Whether delete chrome makes sense - the lane's trash gate. */
716
731
  canDeleteRows: () => boolean;
717
732
  };
@@ -875,6 +890,7 @@ export function createEditEngine(
875
890
  };
876
891
  const forms = new Map<string, FormEntry>();
877
892
  let newRowCounter = 0;
893
+ const NEW_ROW_ID_PREFIX = "__new__";
878
894
  /** Lets `commit` tell a `saveDrafts` flush apart from a lone commit. */
879
895
  let savingDrafts = false;
880
896
 
@@ -1428,6 +1444,11 @@ export function createEditEngine(
1428
1444
  } finally {
1429
1445
  entry.pendingCommit = null;
1430
1446
  }
1447
+ // Dropped while the submit was in flight - cancel or deleteRow won the
1448
+ // race. The form is gone, so there is nothing to park or drop; marking
1449
+ // the row committed now would plant an id in `committedRowIds` that no
1450
+ // save or discard could ever clear.
1451
+ if (forms.get(rowId) !== entry) return true;
1431
1452
  if (!entry.lastSubmitOk) {
1432
1453
  // Snapshot before the caller closes the editor: the field errors go
1433
1454
  // with it, and the row is about to be left carrying them.
@@ -1532,7 +1553,7 @@ export function createEditEngine(
1532
1553
 
1533
1554
  const addRow = (values?: TMDataGridRowData): string => {
1534
1555
  newRowCounter += 1;
1535
- const tempId = `__new__${newRowCounter}`;
1556
+ const tempId = `${NEW_ROW_ID_PREFIX}${newRowCounter}`;
1536
1557
  createForm(tempId, seedNewRow(values), true);
1537
1558
  store.setState((prev) => ({
1538
1559
  ...prev,
@@ -1564,7 +1585,7 @@ export function createEditEngine(
1564
1585
  batch(() => {
1565
1586
  for (const values of rows) {
1566
1587
  newRowCounter += 1;
1567
- const tempId = `__new__${newRowCounter}`;
1588
+ const tempId = `${NEW_ROW_ID_PREFIX}${newRowCounter}`;
1568
1589
  createForm(tempId, seedNewRow(values), true);
1569
1590
  tempIds.push(tempId);
1570
1591
  }
@@ -1599,13 +1620,26 @@ export function createEditEngine(
1599
1620
  }
1600
1621
  const context = getContext();
1601
1622
  if (context.draft) {
1602
- // A toggle: the second press unmarks - the mark is a draft too.
1603
- store.setState((prev) => ({
1604
- ...prev,
1605
- deletedRowIds: prev.deletedRowIds.includes(rowId)
1606
- ? prev.deletedRowIds.filter((id) => id !== rowId)
1607
- : [...prev.deletedRowIds, rowId],
1608
- }));
1623
+ // Idempotent: a marked row stays marked - `restoreRow` is the undo.
1624
+ store.setState((prev) => {
1625
+ if (prev.deletedRowIds.includes(rowId)) return prev;
1626
+ // Only a consumer row can be marked. A deletion mark is what
1627
+ // `saveDrafts` reports to the server, so an id it cannot act on -
1628
+ // an engine temp id, a record gone from `data`, an id the grid
1629
+ // never knew - must not live on as a mark inflating the draft
1630
+ // count. Entry rows are dropped above, never marked; the prefix
1631
+ // check also catches one already dropped that a stale selection or
1632
+ // a double-fired handler names again, while the table's data still
1633
+ // shows it for one render. The core model, so a filtered-out row
1634
+ // still takes its mark.
1635
+ if (
1636
+ rowId.startsWith(NEW_ROW_ID_PREFIX) ||
1637
+ !(rowId in context.table.getCoreRowModel().rowsById)
1638
+ ) {
1639
+ return prev;
1640
+ }
1641
+ return { ...prev, deletedRowIds: [...prev.deletedRowIds, rowId] };
1642
+ });
1609
1643
  return;
1610
1644
  }
1611
1645
  const row = getRow(rowId);
@@ -1614,6 +1648,26 @@ export function createEditEngine(
1614
1648
  void context.onRowDelete?.({ rowId, row });
1615
1649
  };
1616
1650
 
1651
+ const deleteRows = (rowIds: ReadonlyArray<string>) => {
1652
+ // One notification for the batch - each id still goes through
1653
+ // `deleteRow`, so entry rows drop and everything else marks or no-ops
1654
+ // by the same rules.
1655
+ batch(() => {
1656
+ for (const rowId of rowIds) deleteRow(rowId);
1657
+ });
1658
+ };
1659
+
1660
+ const restoreRow = (rowId: string) => {
1661
+ store.setState((prev) =>
1662
+ prev.deletedRowIds.includes(rowId)
1663
+ ? {
1664
+ ...prev,
1665
+ deletedRowIds: prev.deletedRowIds.filter((id) => id !== rowId),
1666
+ }
1667
+ : prev,
1668
+ );
1669
+ };
1670
+
1617
1671
  const canDeleteRows = (): boolean => {
1618
1672
  const context = getContext();
1619
1673
  if (context.draft) {
@@ -1903,6 +1957,8 @@ export function createEditEngine(
1903
1957
  addRow,
1904
1958
  addRows,
1905
1959
  deleteRow,
1960
+ deleteRows,
1961
+ restoreRow,
1906
1962
  canDeleteRows,
1907
1963
  };
1908
1964
  }