@jielga/tmdatagrid 2.1.0 → 2.1.2
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/dist/index.js +1293 -1258
- package/dist/index.js.map +1 -1
- package/docs/column-layout.md +1 -1
- package/docs/column-menu.md +1 -1
- package/docs/localization.md +1 -1
- package/docs/row-details.md +15 -0
- package/docs/row-selection.md +5 -0
- package/docs/testing.md +5 -1
- package/docs/use-tm-data-grid.md +2 -2
- package/package.json +14 -14
- package/skills/appearance/SKILL.md +2 -2
- package/skills/cell-selection/SKILL.md +1 -1
- package/skills/columns/SKILL.md +1 -1
- package/skills/data/SKILL.md +1 -1
- package/skills/editing/SKILL.md +1 -1
- package/skills/filtering/SKILL.md +1 -1
- package/skills/getting-started/SKILL.md +1 -1
- package/skills/grouping/SKILL.md +1 -1
- package/skills/migrating-to-2/SKILL.md +1 -1
- package/skills/options/SKILL.md +2 -2
- package/skills/rows/SKILL.md +1 -1
- package/skills/server-side/SKILL.md +1 -1
- package/skills/testing/SKILL.md +1 -1
- package/skills/testing-components/SKILL.md +1 -1
- package/skills/testing-editing/SKILL.md +1 -1
- package/src/components/TMDataGridDetailsColumn.tsx +3 -0
- package/src/components/TMDataGridSelectColumn.tsx +15 -1
- package/src/components/TMDataGridTable.tsx +42 -9
- package/src/components/generatedColumns.tsx +8 -8
- package/src/core/expanding.ts +4 -1
- package/src/core/labels.ts +3 -3
- package/src/core/labelsSv.ts +22 -22
- package/src/core/quickSearch.ts +52 -0
- package/src/useTMDataGrid.tsx +37 -21
package/src/core/labelsSv.ts
CHANGED
|
@@ -45,7 +45,7 @@ export const TMDATAGRID_LABELS_SV: TMDataGridLabels = {
|
|
|
45
45
|
columnsShowHideAll: "Visa/dölj alla",
|
|
46
46
|
columnsReset: "Återställ layout",
|
|
47
47
|
columnsResetHint:
|
|
48
|
-
"Återställer kolumnernas synlighet, ordning,
|
|
48
|
+
"Återställer kolumnernas synlighet, ordning, bredd, låsning och gruppering",
|
|
49
49
|
rowNumberColumnLabel: "Radnummer",
|
|
50
50
|
noRows: "Inga rader att visa",
|
|
51
51
|
|
|
@@ -70,16 +70,16 @@ export const TMDATAGRID_LABELS_SV: TMDataGridLabels = {
|
|
|
70
70
|
sortAsc: "Sortera stigande",
|
|
71
71
|
sortDesc: "Sortera fallande",
|
|
72
72
|
filterMenuItem: "Filtrera",
|
|
73
|
-
groupBy: (column) => `Gruppera
|
|
74
|
-
ungroup: (column) => `
|
|
73
|
+
groupBy: (column) => `Gruppera efter ${column}`,
|
|
74
|
+
ungroup: (column) => `Sluta gruppera efter ${column}`,
|
|
75
75
|
expandAllGroups: "Expandera alla grupper",
|
|
76
76
|
collapseAllGroups: "Fäll ihop alla grupper",
|
|
77
|
-
pinLeft: "
|
|
78
|
-
pinRight: "
|
|
79
|
-
unpin: "
|
|
77
|
+
pinLeft: "Lås till vänster",
|
|
78
|
+
pinRight: "Lås till höger",
|
|
79
|
+
unpin: "Lås upp",
|
|
80
80
|
moveLeft: "Flytta åt vänster",
|
|
81
81
|
moveRight: "Flytta åt höger",
|
|
82
|
-
autosizeColumn: "
|
|
82
|
+
autosizeColumn: "Autopassa kolumnbredd",
|
|
83
83
|
hideColumn: "Dölj kolumn",
|
|
84
84
|
filterOn: (column) => `Filtrera på ${column}`,
|
|
85
85
|
sortColumn: (column) => `Sortera ${column}`,
|
|
@@ -91,7 +91,7 @@ export const TMDATAGRID_LABELS_SV: TMDataGridLabels = {
|
|
|
91
91
|
pageCount < 0 ? `Sida ${page}` : `Sida ${page} av ${pageCount}`,
|
|
92
92
|
groupedAllRows: (total) => `Grupperad · alla ${total} rader`,
|
|
93
93
|
pagingSuspendedHint:
|
|
94
|
-
"Sidindelningen är avstängd medan raderna är grupperade
|
|
94
|
+
"Sidindelningen är avstängd medan raderna är grupperade, och alla rader visas. Sluta gruppera för att bläddra igen.",
|
|
95
95
|
previousPage: "Föregående sida",
|
|
96
96
|
nextPage: "Nästa sida",
|
|
97
97
|
|
|
@@ -107,11 +107,11 @@ export const TMDATAGRID_LABELS_SV: TMDataGridLabels = {
|
|
|
107
107
|
cancelRowEdit: "Avbryt redigering",
|
|
108
108
|
editRowErrors: "Åtgärda de markerade cellerna",
|
|
109
109
|
saveAllEdits: (rows) => (rows === 1 ? "Spara 1 rad" : `Spara ${rows} rader`),
|
|
110
|
-
discardAllEdits: "
|
|
110
|
+
discardAllEdits: "Ångra alla",
|
|
111
111
|
editRowsStillOpen: (rows) =>
|
|
112
112
|
rows === 1 ? "1 rad redigeras fortfarande" : `${rows} rader redigeras fortfarande`,
|
|
113
113
|
confirmNewRow: "Lägg till rad",
|
|
114
|
-
discardNewRow: "
|
|
114
|
+
discardNewRow: "Avbryt ny rad",
|
|
115
115
|
deleteRow: "Ta bort rad",
|
|
116
116
|
restoreRow: "Återställ rad",
|
|
117
117
|
revertRow: "Ångra ändringar",
|
|
@@ -122,37 +122,37 @@ export const TMDATAGRID_LABELS_SV: TMDataGridLabels = {
|
|
|
122
122
|
cellCount: (count) => (count === 1 ? "1 cell" : `${count} celler`),
|
|
123
123
|
copy: "Kopiera",
|
|
124
124
|
exportCells: "Exportera celler",
|
|
125
|
-
includeHeaders: "
|
|
125
|
+
includeHeaders: "Ta med rubriker",
|
|
126
126
|
|
|
127
127
|
exportAll: "Exportera alla rader",
|
|
128
128
|
exportSelected: (count) =>
|
|
129
|
-
count === 1 ? "Exportera 1
|
|
129
|
+
count === 1 ? "Exportera 1 markerad rad" : `Exportera ${count} markerade rader`,
|
|
130
130
|
exportPickerTitle: (format) => `Exportera som ${format}`,
|
|
131
131
|
exportPickerHint: (selected) =>
|
|
132
132
|
selected === null
|
|
133
133
|
? "Välj kolumner att exportera"
|
|
134
134
|
: selected === 1
|
|
135
|
-
? "Välj kolumner att exportera för den
|
|
136
|
-
: `Välj kolumner att exportera för de ${selected}
|
|
135
|
+
? "Välj kolumner att exportera för den markerade raden"
|
|
136
|
+
: `Välj kolumner att exportera för de ${selected} markerade raderna`,
|
|
137
137
|
exportPickerConfirm: "Exportera",
|
|
138
138
|
exportPickerCancel: "Avbryt",
|
|
139
|
-
exportPickerSelectAll: "
|
|
139
|
+
exportPickerSelectAll: "Markera alla",
|
|
140
140
|
exportPickerCount: (checked, total) => `${checked} av ${total}`,
|
|
141
141
|
exportPickerHidden: "Dold",
|
|
142
142
|
|
|
143
|
-
selectColumnLabel: "
|
|
144
|
-
selectAllRows: "
|
|
145
|
-
selectRow: "
|
|
146
|
-
selectGroup: "
|
|
143
|
+
selectColumnLabel: "Radmarkering",
|
|
144
|
+
selectAllRows: "Markera alla rader",
|
|
145
|
+
selectRow: "Markera rad",
|
|
146
|
+
selectGroup: "Markera grupp",
|
|
147
147
|
|
|
148
148
|
detailsColumnLabel: "Detaljer",
|
|
149
149
|
showDetails: "Visa detaljer",
|
|
150
150
|
hideDetails: "Dölj detaljer",
|
|
151
|
-
expandAllDetails: "
|
|
152
|
-
collapseAllDetails: "
|
|
151
|
+
expandAllDetails: "Visa alla detaljer",
|
|
152
|
+
collapseAllDetails: "Dölj alla detaljer",
|
|
153
153
|
|
|
154
154
|
groupColumnLabel: "Grupp",
|
|
155
|
-
blankGroupValue: "(
|
|
155
|
+
blankGroupValue: "(Tomt)",
|
|
156
156
|
expandGroup: (label) => `Expandera ${label}`,
|
|
157
157
|
collapseGroup: (label) => `Fäll ihop ${label}`,
|
|
158
158
|
};
|
package/src/core/quickSearch.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from "@tanstack/match-sorter-utils";
|
|
6
6
|
import {
|
|
7
7
|
createSortedRowModel,
|
|
8
|
+
type Column,
|
|
8
9
|
type Row,
|
|
9
10
|
type RowData,
|
|
10
11
|
type RowModel,
|
|
@@ -22,6 +23,57 @@ export type TMDataGridQuickSearchMode = "fuzzy" | "contains";
|
|
|
22
23
|
*/
|
|
23
24
|
export const FUZZY_FILTER_FN_NAME = "tmDataGridFuzzy";
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Which columns the quick search reads, per core row model: the answer only
|
|
28
|
+
* changes with the data, and the model's identity changes with the data.
|
|
29
|
+
*/
|
|
30
|
+
const searchableColumns = new WeakMap<object, Map<string, boolean>>();
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The grid's `getColumnCanGlobalFilter`: TanStack's own rule - a column takes
|
|
34
|
+
* part when its first non-empty value is a string or a number, or when it
|
|
35
|
+
* says `enableGlobalFilter: true` - computed once per data change.
|
|
36
|
+
*
|
|
37
|
+
* TanStack's default scans the rows for that first value on every call,
|
|
38
|
+
* building every cell of every row it passes, and the grid asks on every
|
|
39
|
+
* header render. A column empty in every row therefore cost a full scan per
|
|
40
|
+
* header per render. Here the scan reads values only, and its answer is kept
|
|
41
|
+
* until the data changes.
|
|
42
|
+
*/
|
|
43
|
+
export function columnCanQuickSearch<
|
|
44
|
+
TFeatures extends TableFeatures,
|
|
45
|
+
TData extends RowData,
|
|
46
|
+
TValue,
|
|
47
|
+
>(column: Column<TFeatures, TData, TValue>): boolean {
|
|
48
|
+
const { enableGlobalFilter } = column.columnDef as {
|
|
49
|
+
enableGlobalFilter?: boolean;
|
|
50
|
+
};
|
|
51
|
+
if (enableGlobalFilter === true) return true;
|
|
52
|
+
// A display column has no value to search.
|
|
53
|
+
if (!column.accessorFn) return false;
|
|
54
|
+
// Off the table as a plain record, for the same generic-features reason as
|
|
55
|
+
// the options read in isRankingActive.
|
|
56
|
+
const model = (
|
|
57
|
+
column.table as unknown as { getCoreRowModel: () => RowModel<TFeatures, TData> }
|
|
58
|
+
).getCoreRowModel();
|
|
59
|
+
let byColumn = searchableColumns.get(model);
|
|
60
|
+
if (byColumn === undefined) {
|
|
61
|
+
byColumn = new Map();
|
|
62
|
+
searchableColumns.set(model, byColumn);
|
|
63
|
+
}
|
|
64
|
+
const known = byColumn.get(column.id);
|
|
65
|
+
if (known !== undefined) return known;
|
|
66
|
+
let searchable = false;
|
|
67
|
+
for (const row of model.flatRows) {
|
|
68
|
+
const value = row.getValue(column.id);
|
|
69
|
+
if (value == null) continue;
|
|
70
|
+
searchable = typeof value === "string" || typeof value === "number";
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
byColumn.set(column.id, searchable);
|
|
74
|
+
return searchable;
|
|
75
|
+
}
|
|
76
|
+
|
|
25
77
|
/** What {@link fuzzyGlobalFilterFn} records per column via `addMeta`. */
|
|
26
78
|
type FuzzyFilterMeta = { fuzzyRank: RankingInfo };
|
|
27
79
|
|
package/src/useTMDataGrid.tsx
CHANGED
|
@@ -90,6 +90,7 @@ import {
|
|
|
90
90
|
type TMDataGridFiltersSettings,
|
|
91
91
|
} from "./core/filterSurface";
|
|
92
92
|
import {
|
|
93
|
+
columnCanQuickSearch,
|
|
93
94
|
createFuzzyRankedSortedRowModel,
|
|
94
95
|
fuzzyGlobalFilterFn,
|
|
95
96
|
type TMDataGridQuickSearchMode,
|
|
@@ -1082,19 +1083,6 @@ type TMDataGridColumnDef<TData extends RowData> = ColumnDef<
|
|
|
1082
1083
|
unknown
|
|
1083
1084
|
>;
|
|
1084
1085
|
|
|
1085
|
-
/**
|
|
1086
|
-
* Point every column at the operator-dispatching filter function, and take
|
|
1087
|
-
* grouping's aggregation defaults back off, unless the column opted into its
|
|
1088
|
-
* own. Anything the consumer set wins - it is spread over these.
|
|
1089
|
-
*
|
|
1090
|
-
* The aggregation pair needs explaining. TanStack's grouping feature hands
|
|
1091
|
-
* every column `aggregationFn: "auto"` and an `aggregatedCell` that stringifies
|
|
1092
|
-
* whatever comes out, so merely registering the feature would have every
|
|
1093
|
-
* numeric column silently sum itself and every date column show a range the
|
|
1094
|
-
* moment anything is grouped. That is a summary table, and "group by" is not a
|
|
1095
|
-
* request for one. Cleared here, so a grouped grid is a tree until a column
|
|
1096
|
-
* says otherwise - `aggregationFn: "sum"` on the column that wants it.
|
|
1097
|
-
*/
|
|
1098
1086
|
/**
|
|
1099
1087
|
* Drops the control lanes' entries from a visibility map.
|
|
1100
1088
|
*
|
|
@@ -1115,6 +1103,19 @@ function withoutControlColumnVisibility(
|
|
|
1115
1103
|
return scrubbed;
|
|
1116
1104
|
}
|
|
1117
1105
|
|
|
1106
|
+
/**
|
|
1107
|
+
* Point every column at the operator-dispatching filter function, and take
|
|
1108
|
+
* the aggregation defaults back off, unless the column opted into its own.
|
|
1109
|
+
* Anything the consumer set wins - it is spread over these.
|
|
1110
|
+
*
|
|
1111
|
+
* The aggregation pair needs explaining. TanStack's row aggregation feature
|
|
1112
|
+
* hands every column `aggregationFn: "auto"` and an `aggregatedCell` that
|
|
1113
|
+
* stringifies whatever comes out, so merely registering the feature would have
|
|
1114
|
+
* every numeric column silently sum itself and every date column show a range
|
|
1115
|
+
* the moment anything is grouped. That is a summary table, and "group by" is
|
|
1116
|
+
* not a request for one. Cleared here, so a grouped grid is a tree until a
|
|
1117
|
+
* column says otherwise - `aggregationFn: "sum"` on the column that wants it.
|
|
1118
|
+
*/
|
|
1118
1119
|
function withTMDataGridDefaults<TData extends RowData>(
|
|
1119
1120
|
columns: ReadonlyArray<TMDataGridColumnDef<TData>>,
|
|
1120
1121
|
): Array<TMDataGridColumnDef<TData>> {
|
|
@@ -1238,7 +1239,6 @@ export function useTMDataGrid<TData extends RowData>({
|
|
|
1238
1239
|
],
|
|
1239
1240
|
);
|
|
1240
1241
|
|
|
1241
|
-
const pinningEnabled = options.enableColumnPinning !== false;
|
|
1242
1242
|
const selectColumnEnabled = features.selectColumn;
|
|
1243
1243
|
const groupColumnEnabled = features.grouping;
|
|
1244
1244
|
// The lane that opens the panels. Nothing to switch on: a grid with no
|
|
@@ -1270,13 +1270,15 @@ export function useTMDataGrid<TData extends RowData>({
|
|
|
1270
1270
|
// and re-applied on top of anything restored: a snapshot cannot unpin one,
|
|
1271
1271
|
// and a snapshot taken before `detailsColumnPosition` changed cannot pin the
|
|
1272
1272
|
// details lane to the edge it has since left.
|
|
1273
|
+
//
|
|
1274
|
+
// Not gated on `enableColumnPinning`: that switch takes pinning away from the
|
|
1275
|
+
// user, not from the grid's own lanes, which hold the edges either way.
|
|
1273
1276
|
const structuralPinning = (
|
|
1274
1277
|
restored: Partial<ColumnPinningState> | undefined,
|
|
1275
1278
|
): ColumnPinningState => {
|
|
1276
1279
|
const own = (ids: string[] | undefined) =>
|
|
1277
1280
|
(ids ?? []).filter((id) => !isGeneratedColumn(id));
|
|
1278
|
-
const lane = (enabled: boolean, id: string) =>
|
|
1279
|
-
enabled && pinningEnabled ? [id] : [];
|
|
1281
|
+
const lane = (enabled: boolean, id: string) => (enabled ? [id] : []);
|
|
1280
1282
|
const detailsOn = (edge: "left" | "right") =>
|
|
1281
1283
|
detailsColumnEnabled && detailsColumnPosition === edge;
|
|
1282
1284
|
return {
|
|
@@ -1476,6 +1478,11 @@ export function useTMDataGrid<TData extends RowData>({
|
|
|
1476
1478
|
edit.store,
|
|
1477
1479
|
(state) => state.committedValues,
|
|
1478
1480
|
);
|
|
1481
|
+
// Subscribed for the re-render alone - the selection predicate below reads
|
|
1482
|
+
// the marks live. TanStack 9.2 caches a group row's "all / some selected"
|
|
1483
|
+
// on the predicate's identity, and only a render hands it a new one; without
|
|
1484
|
+
// this a mark would leave the group's checkbox on its old answer.
|
|
1485
|
+
useSelector(edit.store, (state) => state.deletedRowIds);
|
|
1479
1486
|
const newRowsSticky = features.editNewRowsSticky;
|
|
1480
1487
|
const editCreatedIds = useSelector(
|
|
1481
1488
|
edit.store,
|
|
@@ -1577,6 +1584,9 @@ export function useTMDataGrid<TData extends RowData>({
|
|
|
1577
1584
|
options.quickSearchMode === "contains"
|
|
1578
1585
|
? "includesString"
|
|
1579
1586
|
: "tmDataGridFuzzy",
|
|
1587
|
+
// Which columns the quick search reads - TanStack's rule, computed once
|
|
1588
|
+
// per data change instead of once per call. See columnCanQuickSearch.
|
|
1589
|
+
getColumnCanGlobalFilter: columnCanQuickSearch,
|
|
1580
1590
|
// Grouping by a column takes it out of the grid, the way AG Grid does it:
|
|
1581
1591
|
// its values have moved into the tree column, so leaving it in place would
|
|
1582
1592
|
// show every row the same value it was grouped under. Overridable - pass
|
|
@@ -1620,11 +1630,17 @@ export function useTMDataGrid<TData extends RowData>({
|
|
|
1620
1630
|
getRowId: shownGetRowId,
|
|
1621
1631
|
// Row details ride on `expanded`, the same state the tree uses - but a data
|
|
1622
1632
|
// row answers `getCanExpand()` false, since TanStack's fallback is
|
|
1623
|
-
// `subRows.length > 0
|
|
1624
|
-
//
|
|
1625
|
-
//
|
|
1626
|
-
|
|
1627
|
-
|
|
1633
|
+
// `subRows.length > 0`, so under `renderDetails` every row can expand.
|
|
1634
|
+
// A consumer's own predicate decides the data rows, never a group row:
|
|
1635
|
+
// TanStack builds a group row on its first child's record, and since 9.2
|
|
1636
|
+
// `toggleExpanded` refuses a row that cannot expand - so a predicate
|
|
1637
|
+
// rejecting that record would leave the group's chevron dead.
|
|
1638
|
+
...(renderDetails !== undefined || options.getRowCanExpand !== undefined
|
|
1639
|
+
? {
|
|
1640
|
+
getRowCanExpand: (row: Row<TMDataGridFeatures, TData>) =>
|
|
1641
|
+
row.getIsGrouped() ||
|
|
1642
|
+
(options.getRowCanExpand?.(row) ?? true),
|
|
1643
|
+
}
|
|
1628
1644
|
: {}),
|
|
1629
1645
|
// Always a predicate, never the passthrough: TanStack defaults the option
|
|
1630
1646
|
// to `true` once the feature is registered, and the grid's default is off.
|