@gridkitjs/react 0.4.0 → 0.6.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/dist/index.d.ts +57 -4
- package/dist/index.js +478 -319
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// src/DataGrid/DataGrid.tsx
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useImperativeHandle,
|
|
4
|
+
useMemo as useMemo2,
|
|
5
|
+
useRef as useRef4,
|
|
6
|
+
useState as useState5
|
|
7
|
+
} from "react";
|
|
3
8
|
import {
|
|
4
9
|
applyColumnOrder,
|
|
5
10
|
defineColumnsFromRows,
|
|
@@ -7,12 +12,23 @@ import {
|
|
|
7
12
|
moveColumnBefore,
|
|
8
13
|
resolveColumnWidths,
|
|
9
14
|
resolveRowId,
|
|
15
|
+
resolveShownRows,
|
|
10
16
|
totalColumnWidth
|
|
11
17
|
} from "@gridkitjs/core";
|
|
12
18
|
|
|
13
19
|
// src/DataGrid/components/GridHeader.tsx
|
|
14
20
|
import { createPortal } from "react-dom";
|
|
15
|
-
import { KEYBOARD_STEP } from "@gridkitjs/core";
|
|
21
|
+
import { buildKeyShortcuts, intentOf, KEYBOARD_STEP } from "@gridkitjs/core";
|
|
22
|
+
|
|
23
|
+
// src/DataGrid/ariaAttr.ts
|
|
24
|
+
function ariaAttr(condition, key, value) {
|
|
25
|
+
return condition ? { [key]: value } : {};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/DataGrid/classNames.ts
|
|
29
|
+
function classNames(...values) {
|
|
30
|
+
return values.filter(Boolean).join(" ");
|
|
31
|
+
}
|
|
16
32
|
|
|
17
33
|
// src/DataGrid/useGridNavigation.ts
|
|
18
34
|
import {
|
|
@@ -20,16 +36,14 @@ import {
|
|
|
20
36
|
useRef,
|
|
21
37
|
useState
|
|
22
38
|
} from "react";
|
|
23
|
-
|
|
39
|
+
import {
|
|
40
|
+
clampFocus,
|
|
41
|
+
nextFocusForKey,
|
|
42
|
+
HEADER_ROW
|
|
43
|
+
} from "@gridkitjs/core";
|
|
24
44
|
var FALLBACK_PAGE = 10;
|
|
25
|
-
function
|
|
26
|
-
return
|
|
27
|
-
rowIndex: Math.min(Math.max(focus.rowIndex, HEADER_ROW), rowCount - 1),
|
|
28
|
-
columnIndex: Math.min(
|
|
29
|
-
Math.max(focus.columnIndex, 0),
|
|
30
|
-
Math.max(columnCount - 1, 0)
|
|
31
|
-
)
|
|
32
|
-
};
|
|
45
|
+
function tabIndexFor(columnIndex, focusedColumnIndex) {
|
|
46
|
+
return columnIndex === focusedColumnIndex ? 0 : -1;
|
|
33
47
|
}
|
|
34
48
|
function cellAt(table, focus) {
|
|
35
49
|
const row = focus.rowIndex === HEADER_ROW ? table.tHead?.rows[0] ?? null : table.tBodies[0]?.rows[focus.rowIndex] ?? null;
|
|
@@ -77,83 +91,71 @@ function useGridNavigation({
|
|
|
77
91
|
pending.current = true;
|
|
78
92
|
setStored(next);
|
|
79
93
|
}
|
|
80
|
-
function tabIndexFor(rowIndex, columnIndex) {
|
|
81
|
-
return rowIndex === focus.rowIndex && columnIndex === focus.columnIndex ? 0 : -1;
|
|
82
|
-
}
|
|
83
94
|
function onKeyDown(event) {
|
|
84
|
-
|
|
95
|
+
const next = nextFocusForKey(
|
|
96
|
+
event.key,
|
|
97
|
+
{
|
|
98
|
+
ctrlKey: event.ctrlKey,
|
|
99
|
+
metaKey: event.metaKey,
|
|
100
|
+
altKey: event.altKey,
|
|
101
|
+
shiftKey: event.shiftKey
|
|
102
|
+
},
|
|
103
|
+
focus,
|
|
104
|
+
rowCount,
|
|
105
|
+
columnCount,
|
|
106
|
+
pageSize()
|
|
107
|
+
);
|
|
108
|
+
if (next === null) {
|
|
85
109
|
return;
|
|
86
110
|
}
|
|
87
|
-
const { rowIndex, columnIndex } = focus;
|
|
88
|
-
let next;
|
|
89
|
-
switch (event.key) {
|
|
90
|
-
case "ArrowLeft":
|
|
91
|
-
if (event.ctrlKey) return;
|
|
92
|
-
next = { rowIndex, columnIndex: columnIndex - 1 };
|
|
93
|
-
break;
|
|
94
|
-
case "ArrowRight":
|
|
95
|
-
if (event.ctrlKey) return;
|
|
96
|
-
next = { rowIndex, columnIndex: columnIndex + 1 };
|
|
97
|
-
break;
|
|
98
|
-
case "ArrowUp":
|
|
99
|
-
next = { rowIndex: rowIndex - 1, columnIndex };
|
|
100
|
-
break;
|
|
101
|
-
case "ArrowDown":
|
|
102
|
-
next = { rowIndex: rowIndex + 1, columnIndex };
|
|
103
|
-
break;
|
|
104
|
-
// Ctrl takes Home and End to the grid's ends rather than the row's, which
|
|
105
|
-
// is the one place Ctrl is navigation rather than reorder.
|
|
106
|
-
case "Home":
|
|
107
|
-
next = event.ctrlKey ? { rowIndex: HEADER_ROW, columnIndex: 0 } : { rowIndex, columnIndex: 0 };
|
|
108
|
-
break;
|
|
109
|
-
case "End":
|
|
110
|
-
next = event.ctrlKey ? { rowIndex: rowCount - 1, columnIndex: columnCount - 1 } : { rowIndex, columnIndex: columnCount - 1 };
|
|
111
|
-
break;
|
|
112
|
-
case "PageUp":
|
|
113
|
-
next = { rowIndex: rowIndex - pageSize(), columnIndex };
|
|
114
|
-
break;
|
|
115
|
-
case "PageDown":
|
|
116
|
-
next = { rowIndex: rowIndex + pageSize(), columnIndex };
|
|
117
|
-
break;
|
|
118
|
-
default:
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
111
|
event.preventDefault();
|
|
122
112
|
focusCell(next.rowIndex, next.columnIndex);
|
|
123
113
|
}
|
|
124
|
-
return {
|
|
114
|
+
return {
|
|
115
|
+
focus,
|
|
116
|
+
tabIndexFor: (rowIndex, columnIndex) => tabIndexFor(
|
|
117
|
+
columnIndex,
|
|
118
|
+
rowIndex === focus.rowIndex ? focus.columnIndex : null
|
|
119
|
+
),
|
|
120
|
+
focusCell,
|
|
121
|
+
onKeyDown
|
|
122
|
+
};
|
|
125
123
|
}
|
|
126
124
|
|
|
127
125
|
// src/DataGrid/useGridSelection.ts
|
|
128
|
-
import { useMemo, useRef as useRef2 } from "react";
|
|
129
126
|
import {
|
|
130
|
-
|
|
127
|
+
useMemo,
|
|
128
|
+
useRef as useRef2
|
|
129
|
+
} from "react";
|
|
130
|
+
import {
|
|
131
|
+
applySelectionIntent,
|
|
131
132
|
clearSelection,
|
|
132
133
|
diffSelection,
|
|
134
|
+
resolveCell,
|
|
135
|
+
resolveColumns,
|
|
136
|
+
resolveRows,
|
|
133
137
|
selectAll,
|
|
134
138
|
selectCell,
|
|
135
|
-
|
|
136
|
-
selectRange,
|
|
137
|
-
toggleCellSelection,
|
|
138
|
-
toggleSelection
|
|
139
|
+
toggleCellSelection
|
|
139
140
|
} from "@gridkitjs/core";
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
|
|
142
|
+
// src/DataGrid/commitIfChanged.ts
|
|
143
|
+
function commitIfChanged(current, next, setState, onCommit) {
|
|
144
|
+
if (next === current) {
|
|
145
|
+
return false;
|
|
143
146
|
}
|
|
144
|
-
|
|
147
|
+
setState(next);
|
|
148
|
+
onCommit?.(next);
|
|
149
|
+
return true;
|
|
145
150
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
default:
|
|
155
|
-
return selectOnly(selection, id, mode);
|
|
156
|
-
}
|
|
151
|
+
|
|
152
|
+
// src/DataGrid/useGridSelection.ts
|
|
153
|
+
function keyboardSelectIntent(event) {
|
|
154
|
+
return {
|
|
155
|
+
ctrlKey: event.key === " " || event.ctrlKey,
|
|
156
|
+
metaKey: event.metaKey,
|
|
157
|
+
shiftKey: event.shiftKey
|
|
158
|
+
};
|
|
157
159
|
}
|
|
158
160
|
function countMessage(count, noun) {
|
|
159
161
|
if (count === 0) {
|
|
@@ -161,6 +163,18 @@ function countMessage(count, noun) {
|
|
|
161
163
|
}
|
|
162
164
|
return count === 1 ? `1 ${noun} selected` : `${String(count)} ${noun}s selected`;
|
|
163
165
|
}
|
|
166
|
+
function useAsSet(values) {
|
|
167
|
+
return useMemo(() => new Set(values), [values]);
|
|
168
|
+
}
|
|
169
|
+
function useIndexedBy(values, key) {
|
|
170
|
+
return useMemo(
|
|
171
|
+
() => new Map(values.map((value) => [value[key], value])),
|
|
172
|
+
[values, key]
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
function useMappedArray(values, key) {
|
|
176
|
+
return useMemo(() => values.map((value) => value[key]), [values, key]);
|
|
177
|
+
}
|
|
164
178
|
function useGridSelection({
|
|
165
179
|
rows,
|
|
166
180
|
columns,
|
|
@@ -172,141 +186,106 @@ function useGridSelection({
|
|
|
172
186
|
cellSelection,
|
|
173
187
|
setCellSelection,
|
|
174
188
|
callbacks,
|
|
175
|
-
announce
|
|
189
|
+
announce,
|
|
190
|
+
columnName
|
|
176
191
|
}) {
|
|
177
192
|
const rowMode = selectable?.rows ?? false;
|
|
178
193
|
const columnMode = selectable?.columns ?? false;
|
|
179
194
|
const cellMode = selectable?.cells ?? false;
|
|
180
|
-
const rowsById =
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
);
|
|
184
|
-
const
|
|
185
|
-
const columnIds = useMemo(() => columns.map((entry) => entry.id), [columns]);
|
|
186
|
-
const selectedRowIds = useMemo(() => new Set(rowSelection), [rowSelection]);
|
|
187
|
-
const selectedColumnIds = useMemo(
|
|
188
|
-
() => new Set(columnSelection),
|
|
189
|
-
[columnSelection]
|
|
190
|
-
);
|
|
195
|
+
const rowsById = useIndexedBy(rows, "rowId");
|
|
196
|
+
const rowIds = useMappedArray(rows, "rowId");
|
|
197
|
+
const columnIds = useMappedArray(columns, "id");
|
|
198
|
+
const selectedRowIds = useAsSet(rowSelection);
|
|
199
|
+
const selectedColumnIds = useAsSet(columnSelection);
|
|
191
200
|
const rowAnchor = useRef2(null);
|
|
192
201
|
const columnAnchor = useRef2(null);
|
|
193
|
-
function resolveRows(ids) {
|
|
194
|
-
return ids.map((id) => rowsById.get(id)).filter((row) => row !== void 0);
|
|
195
|
-
}
|
|
196
|
-
function resolveColumns(ids) {
|
|
197
|
-
return ids.map((id) => {
|
|
198
|
-
const columnIndex = columns.findIndex((entry) => entry.id === id);
|
|
199
|
-
const column = columns[columnIndex];
|
|
200
|
-
return column === void 0 ? void 0 : { columnId: id, column, columnIndex };
|
|
201
|
-
}).filter((column) => column !== void 0);
|
|
202
|
-
}
|
|
203
|
-
function resolveCell(ref) {
|
|
204
|
-
if (ref === null) {
|
|
205
|
-
return null;
|
|
206
|
-
}
|
|
207
|
-
const entry = rowsById.get(ref.rowId);
|
|
208
|
-
const columnIndex = columns.findIndex(
|
|
209
|
-
(candidate) => candidate.id === ref.columnId
|
|
210
|
-
);
|
|
211
|
-
const column = columns[columnIndex];
|
|
212
|
-
if (entry === void 0 || column === void 0) {
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
return {
|
|
216
|
-
rowId: ref.rowId,
|
|
217
|
-
columnId: ref.columnId,
|
|
218
|
-
row: entry.row,
|
|
219
|
-
column,
|
|
220
|
-
rowIndex: entry.rowIndex,
|
|
221
|
-
columnIndex,
|
|
222
|
-
value: accessDotted(entry.row, column.column.field)
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
202
|
function announceCount(changed, total, noun) {
|
|
226
203
|
if (changed > 1) {
|
|
227
204
|
announce(countMessage(total, noun));
|
|
228
205
|
}
|
|
229
206
|
}
|
|
230
207
|
function commitRows(next) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
selection: next
|
|
208
|
+
commitIfChanged(rowSelection, next, setRowSelection, (committed) => {
|
|
209
|
+
const { added, removed } = diffSelection(rowSelection, committed);
|
|
210
|
+
const addedRows = resolveRows(rowsById, added);
|
|
211
|
+
const removedRows = resolveRows(rowsById, removed);
|
|
212
|
+
for (const row of addedRows) {
|
|
213
|
+
callbacks.onRowSelect?.({ row, selection: committed });
|
|
214
|
+
}
|
|
215
|
+
if (addedRows.length > 0) {
|
|
216
|
+
callbacks.onRowsSelect?.({ rows: addedRows, selection: committed });
|
|
217
|
+
}
|
|
218
|
+
for (const row of removedRows) {
|
|
219
|
+
callbacks.onRowDeselect?.({ row, selection: committed });
|
|
220
|
+
}
|
|
221
|
+
if (removedRows.length > 0) {
|
|
222
|
+
callbacks.onRowsDeselect?.({ rows: removedRows, selection: committed });
|
|
223
|
+
}
|
|
224
|
+
callbacks.onRowSelectionChange?.({
|
|
225
|
+
added: addedRows,
|
|
226
|
+
removed: removedRows,
|
|
227
|
+
selected: resolveRows(rowsById, committed),
|
|
228
|
+
selection: committed
|
|
229
|
+
});
|
|
230
|
+
announceCount(added.length + removed.length, committed.length, "row");
|
|
255
231
|
});
|
|
256
|
-
announceCount(added.length + removed.length, next.length, "row");
|
|
257
232
|
}
|
|
258
233
|
function commitColumns(next) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
234
|
+
commitIfChanged(columnSelection, next, setColumnSelection, (committed) => {
|
|
235
|
+
const { added, removed } = diffSelection(columnSelection, committed);
|
|
236
|
+
const addedColumns = resolveColumns(columns, added);
|
|
237
|
+
const removedColumns = resolveColumns(columns, removed);
|
|
238
|
+
for (const column of addedColumns) {
|
|
239
|
+
callbacks.onColumnSelect?.({ column, selection: committed });
|
|
240
|
+
}
|
|
241
|
+
if (addedColumns.length > 0) {
|
|
242
|
+
callbacks.onColumnsSelect?.({
|
|
243
|
+
columns: addedColumns,
|
|
244
|
+
selection: committed
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
for (const column of removedColumns) {
|
|
248
|
+
callbacks.onColumnDeselect?.({ column, selection: committed });
|
|
249
|
+
}
|
|
250
|
+
if (removedColumns.length > 0) {
|
|
251
|
+
callbacks.onColumnsDeselect?.({
|
|
252
|
+
columns: removedColumns,
|
|
253
|
+
selection: committed
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
callbacks.onColumnSelectionChange?.({
|
|
257
|
+
added: addedColumns,
|
|
258
|
+
removed: removedColumns,
|
|
259
|
+
selected: resolveColumns(columns, committed),
|
|
260
|
+
selection: committed
|
|
279
261
|
});
|
|
280
|
-
|
|
281
|
-
callbacks.onColumnSelectionChange?.({
|
|
282
|
-
added: addedColumns,
|
|
283
|
-
removed: removedColumns,
|
|
284
|
-
selected: resolveColumns(next),
|
|
285
|
-
selection: next
|
|
262
|
+
announceCount(added.length + removed.length, committed.length, "column");
|
|
286
263
|
});
|
|
287
|
-
announceCount(added.length + removed.length, next.length, "column");
|
|
288
264
|
}
|
|
289
265
|
function commitCell(next) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
266
|
+
commitIfChanged(cellSelection, next, setCellSelection, (committed) => {
|
|
267
|
+
const selected = resolveCell(rowsById, columns, committed);
|
|
268
|
+
const deselected = resolveCell(rowsById, columns, cellSelection);
|
|
269
|
+
if (deselected !== null) {
|
|
270
|
+
callbacks.onCellDeselect?.({ cell: deselected, selection: committed });
|
|
271
|
+
}
|
|
272
|
+
if (selected !== null) {
|
|
273
|
+
callbacks.onCellSelect?.({ cell: selected, selection: committed });
|
|
274
|
+
}
|
|
275
|
+
callbacks.onCellSelectionChange?.({
|
|
276
|
+
selected,
|
|
277
|
+
deselected,
|
|
278
|
+
selection: committed
|
|
279
|
+
});
|
|
280
|
+
if (selected !== null) {
|
|
281
|
+
announce(
|
|
282
|
+
`${columnName(selected.columnId)}, row ${String(selected.rowIndex + 1)}, selected`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
306
285
|
});
|
|
307
286
|
}
|
|
308
287
|
function selectRow(rowId, intent) {
|
|
309
|
-
const next =
|
|
288
|
+
const next = applySelectionIntent(
|
|
310
289
|
rowSelection,
|
|
311
290
|
rowIds,
|
|
312
291
|
rowAnchor.current,
|
|
@@ -320,7 +299,7 @@ function useGridSelection({
|
|
|
320
299
|
commitRows(next);
|
|
321
300
|
}
|
|
322
301
|
function selectColumn(columnId, intent) {
|
|
323
|
-
const next =
|
|
302
|
+
const next = applySelectionIntent(
|
|
324
303
|
columnSelection,
|
|
325
304
|
columnIds,
|
|
326
305
|
columnAnchor.current,
|
|
@@ -363,10 +342,36 @@ function useGridSelection({
|
|
|
363
342
|
|
|
364
343
|
// src/DataGrid/components/GridHeader.tsx
|
|
365
344
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
345
|
+
function Icon({ children }) {
|
|
346
|
+
return /* @__PURE__ */ jsx(
|
|
347
|
+
"svg",
|
|
348
|
+
{
|
|
349
|
+
viewBox: "0 0 24 24",
|
|
350
|
+
fill: "none",
|
|
351
|
+
stroke: "currentColor",
|
|
352
|
+
strokeWidth: 2,
|
|
353
|
+
strokeLinecap: "round",
|
|
354
|
+
strokeLinejoin: "round",
|
|
355
|
+
"aria-hidden": "true",
|
|
356
|
+
children
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
function ChevronsUpDownIcon() {
|
|
361
|
+
return /* @__PURE__ */ jsxs(Icon, { children: [
|
|
362
|
+
/* @__PURE__ */ jsx("path", { d: "m7 15 5 5 5-5" }),
|
|
363
|
+
/* @__PURE__ */ jsx("path", { d: "m7 9 5-5 5 5" })
|
|
364
|
+
] });
|
|
365
|
+
}
|
|
366
|
+
function ChevronUpIcon() {
|
|
367
|
+
return /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx("path", { d: "m18 15-6-6-6 6" }) });
|
|
368
|
+
}
|
|
366
369
|
function GridHeader({
|
|
367
370
|
columns,
|
|
368
371
|
resize,
|
|
369
372
|
drag,
|
|
373
|
+
sort,
|
|
374
|
+
sortableColumns,
|
|
370
375
|
nav,
|
|
371
376
|
selection
|
|
372
377
|
}) {
|
|
@@ -380,20 +385,27 @@ function GridHeader({
|
|
|
380
385
|
const dropBefore = beforeId !== void 0 && beforeId === entry.id;
|
|
381
386
|
const dropAfter = beforeId === null && index === columns.length - 1;
|
|
382
387
|
const selected = selection.selectedColumnIds.has(entry.id);
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
388
|
+
const sortable = column.sortable ?? sortableColumns;
|
|
389
|
+
const sortDirection = sort.directionFor(entry.id);
|
|
390
|
+
const sortPriority = sort.priorityFor(entry.id);
|
|
391
|
+
const shortcuts = buildKeyShortcuts({
|
|
392
|
+
reorderable: entry.reorderable,
|
|
393
|
+
resizable: entry.resizable,
|
|
394
|
+
sortable
|
|
395
|
+
});
|
|
387
396
|
return /* @__PURE__ */ jsxs(
|
|
388
397
|
"th",
|
|
389
398
|
{
|
|
390
399
|
scope: "col",
|
|
400
|
+
role: "columnheader",
|
|
391
401
|
"data-gridkit-column": entry.id,
|
|
392
402
|
"aria-colindex": index + 1,
|
|
393
403
|
tabIndex: nav.tabIndexFor(HEADER_ROW, index),
|
|
394
|
-
...
|
|
395
|
-
|
|
396
|
-
|
|
404
|
+
...ariaAttr(
|
|
405
|
+
selection.columnMode !== false,
|
|
406
|
+
"aria-selected",
|
|
407
|
+
selected
|
|
408
|
+
),
|
|
397
409
|
onFocus: () => {
|
|
398
410
|
nav.focusCell(HEADER_ROW, index);
|
|
399
411
|
},
|
|
@@ -401,7 +413,7 @@ function GridHeader({
|
|
|
401
413
|
if (drag.justDragged()) {
|
|
402
414
|
return;
|
|
403
415
|
}
|
|
404
|
-
if (event.target instanceof Element && event.target.closest(".header-resize-handle") !== null) {
|
|
416
|
+
if (event.target instanceof Element && (event.target.closest(".header-resize-handle") !== null || event.target.closest(".header-sort-toggle") !== null)) {
|
|
405
417
|
return;
|
|
406
418
|
}
|
|
407
419
|
selection.selectColumn(entry.id, intentOf(event));
|
|
@@ -419,21 +431,27 @@ function GridHeader({
|
|
|
419
431
|
resize.nudge(entry, direction * KEYBOARD_STEP);
|
|
420
432
|
return;
|
|
421
433
|
}
|
|
434
|
+
if (event.key === "Enter" && event.altKey && entry.resizable) {
|
|
435
|
+
event.preventDefault();
|
|
436
|
+
resize.sizeToContent(entry);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (event.key === "ArrowUp" && event.altKey && sortable) {
|
|
440
|
+
event.preventDefault();
|
|
441
|
+
sort.toggle(entry, { shiftKey: event.shiftKey });
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
422
444
|
if (event.key === " " || event.key === "Enter") {
|
|
423
445
|
event.preventDefault();
|
|
424
446
|
selection.selectColumn(
|
|
425
447
|
entry.id,
|
|
426
|
-
intentOf(
|
|
427
|
-
ctrlKey: event.key === " " || event.ctrlKey,
|
|
428
|
-
metaKey: event.metaKey,
|
|
429
|
-
shiftKey: event.shiftKey
|
|
430
|
-
})
|
|
448
|
+
intentOf(keyboardSelectIntent(event))
|
|
431
449
|
);
|
|
432
450
|
return;
|
|
433
451
|
}
|
|
434
452
|
nav.onKeyDown(event);
|
|
435
453
|
},
|
|
436
|
-
className:
|
|
454
|
+
className: classNames(
|
|
437
455
|
"header-cell",
|
|
438
456
|
entry.reorderable ? "is-reorderable" : "",
|
|
439
457
|
selected ? "is-selected" : "",
|
|
@@ -443,8 +461,13 @@ function GridHeader({
|
|
|
443
461
|
dropAfter ? "is-drop-after" : "",
|
|
444
462
|
column.wrap?.header ? "is-wrapped" : "",
|
|
445
463
|
column.headerClassName ?? ""
|
|
446
|
-
|
|
447
|
-
...shortcuts !== ""
|
|
464
|
+
),
|
|
465
|
+
...ariaAttr(shortcuts !== "", "aria-keyshortcuts", shortcuts),
|
|
466
|
+
...ariaAttr(
|
|
467
|
+
sortable && sortDirection !== null,
|
|
468
|
+
"aria-sort",
|
|
469
|
+
sortDirection === "asc" ? "ascending" : "descending"
|
|
470
|
+
),
|
|
448
471
|
...entry.reorderable && {
|
|
449
472
|
onPointerDown: (event) => {
|
|
450
473
|
drag.startDrag(entry, event);
|
|
@@ -452,6 +475,33 @@ function GridHeader({
|
|
|
452
475
|
},
|
|
453
476
|
children: [
|
|
454
477
|
entry.label,
|
|
478
|
+
sortable && /*
|
|
479
|
+
* A pointer affordance only, and hidden from assistive
|
|
480
|
+
* technology like the resize handle: the keyboard equivalent
|
|
481
|
+
* lives on the header itself, under Alt+ArrowUp (plain) /
|
|
482
|
+
* Alt+Shift+ArrowUp (stacking).
|
|
483
|
+
*/
|
|
484
|
+
/* @__PURE__ */ jsxs(
|
|
485
|
+
"span",
|
|
486
|
+
{
|
|
487
|
+
className: classNames(
|
|
488
|
+
"header-sort-toggle",
|
|
489
|
+
sortDirection !== null ? `is-sorted-${sortDirection}` : ""
|
|
490
|
+
),
|
|
491
|
+
"aria-hidden": "true",
|
|
492
|
+
tabIndex: -1,
|
|
493
|
+
onPointerDown: (event) => {
|
|
494
|
+
event.stopPropagation();
|
|
495
|
+
},
|
|
496
|
+
onClick: (event) => {
|
|
497
|
+
sort.toggle(entry, { shiftKey: event.shiftKey });
|
|
498
|
+
},
|
|
499
|
+
children: [
|
|
500
|
+
sortDirection === null ? /* @__PURE__ */ jsx(ChevronsUpDownIcon, {}) : /* @__PURE__ */ jsx(ChevronUpIcon, {}),
|
|
501
|
+
sortPriority !== null && sortPriority > 1 && /* @__PURE__ */ jsx("span", { className: "header-sort-priority", children: sortPriority })
|
|
502
|
+
]
|
|
503
|
+
}
|
|
504
|
+
),
|
|
455
505
|
entry.resizable && /*
|
|
456
506
|
* A pointer affordance only, and hidden from assistive
|
|
457
507
|
* technology accordingly: a focusable handle per column would
|
|
@@ -495,8 +545,11 @@ function GridHeader({
|
|
|
495
545
|
] });
|
|
496
546
|
}
|
|
497
547
|
|
|
548
|
+
// src/DataGrid/components/GridBody.tsx
|
|
549
|
+
import { intentOf as intentOf2 } from "@gridkitjs/core";
|
|
550
|
+
|
|
498
551
|
// src/DataGrid/components/GridRow.tsx
|
|
499
|
-
import { accessDotted
|
|
552
|
+
import { accessDotted } from "@gridkitjs/core";
|
|
500
553
|
import { memo } from "react";
|
|
501
554
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
502
555
|
function GridRowComponent({
|
|
@@ -517,10 +570,10 @@ function GridRowComponent({
|
|
|
517
570
|
{
|
|
518
571
|
role: "row",
|
|
519
572
|
"aria-rowindex": rowIndex + 2,
|
|
520
|
-
...rowsSelectable
|
|
521
|
-
className:
|
|
573
|
+
...ariaAttr(rowsSelectable, "aria-selected", selected),
|
|
574
|
+
className: classNames("grid-row", selected ? "is-selected" : ""),
|
|
522
575
|
children: columns.map(({ id, column, alignment }, columnIndex) => {
|
|
523
|
-
const value =
|
|
576
|
+
const value = accessDotted(row, column.field);
|
|
524
577
|
const cellSelected = id === selectedColumnId;
|
|
525
578
|
return /* @__PURE__ */ jsx2(
|
|
526
579
|
"td",
|
|
@@ -528,15 +581,16 @@ function GridRowComponent({
|
|
|
528
581
|
role: "gridcell",
|
|
529
582
|
"data-gridkit-column": id,
|
|
530
583
|
"aria-colindex": columnIndex + 1,
|
|
531
|
-
tabIndex: columnIndex
|
|
532
|
-
...cellsSelectable
|
|
533
|
-
|
|
584
|
+
tabIndex: tabIndexFor(columnIndex, focusedColumnIndex),
|
|
585
|
+
...ariaAttr(cellsSelectable, "aria-selected", cellSelected),
|
|
586
|
+
...ariaAttr(cellsSelectable, "aria-keyshortcuts", "Space Enter"),
|
|
587
|
+
className: classNames(
|
|
534
588
|
"grid-cell",
|
|
535
589
|
id === activeColumnId ? "is-resizing" : "",
|
|
536
590
|
cellSelected || selectedColumnIds.has(id) ? "is-selected" : "",
|
|
537
591
|
column.wrap?.cells ? "is-wrapped" : "",
|
|
538
592
|
column.cellClassName ?? ""
|
|
539
|
-
|
|
593
|
+
),
|
|
540
594
|
style: { textAlign: alignment },
|
|
541
595
|
children: column.cellTemplate ? column.cellTemplate({ value, row, rowIndex, rowId, selected }) : value
|
|
542
596
|
},
|
|
@@ -581,7 +635,7 @@ function GridBody({
|
|
|
581
635
|
return position === null || entry === void 0 ? null : { position, rowId: entry.rowId };
|
|
582
636
|
}
|
|
583
637
|
function select(rowId, columnId, modifiers) {
|
|
584
|
-
const intent =
|
|
638
|
+
const intent = intentOf2(modifiers);
|
|
585
639
|
if (rowMode !== false) {
|
|
586
640
|
selection.selectRow(rowId, intent);
|
|
587
641
|
}
|
|
@@ -608,11 +662,11 @@ function GridBody({
|
|
|
608
662
|
const found = targetOf(event.target);
|
|
609
663
|
if (found === null) return;
|
|
610
664
|
event.preventDefault();
|
|
611
|
-
select(
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
665
|
+
select(
|
|
666
|
+
found.rowId,
|
|
667
|
+
found.position.columnId,
|
|
668
|
+
keyboardSelectIntent(event)
|
|
669
|
+
);
|
|
616
670
|
return;
|
|
617
671
|
}
|
|
618
672
|
nav.onKeyDown(event);
|
|
@@ -645,8 +699,45 @@ import {
|
|
|
645
699
|
} from "react";
|
|
646
700
|
import {
|
|
647
701
|
movesColumn,
|
|
648
|
-
resolveDropBefore
|
|
702
|
+
resolveDropBefore,
|
|
703
|
+
resolveKeyboardDropTarget
|
|
649
704
|
} from "@gridkitjs/core";
|
|
705
|
+
|
|
706
|
+
// src/DataGrid/pointerGesture.ts
|
|
707
|
+
function startPointerGesture(element, pointerId, handlers) {
|
|
708
|
+
element.setPointerCapture(pointerId);
|
|
709
|
+
function stop() {
|
|
710
|
+
element.removeEventListener("pointermove", move);
|
|
711
|
+
element.removeEventListener("pointerup", end);
|
|
712
|
+
element.removeEventListener("pointercancel", cancel);
|
|
713
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
714
|
+
if (element.hasPointerCapture(pointerId)) {
|
|
715
|
+
element.releasePointerCapture(pointerId);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
function move(event) {
|
|
719
|
+
handlers.onMove(event);
|
|
720
|
+
}
|
|
721
|
+
function end() {
|
|
722
|
+
stop();
|
|
723
|
+
handlers.onEnd();
|
|
724
|
+
}
|
|
725
|
+
function cancel() {
|
|
726
|
+
stop();
|
|
727
|
+
handlers.onCancel();
|
|
728
|
+
}
|
|
729
|
+
function onKeyDown(event) {
|
|
730
|
+
if (event.key === "Escape") {
|
|
731
|
+
cancel();
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
element.addEventListener("pointermove", move);
|
|
735
|
+
element.addEventListener("pointerup", end);
|
|
736
|
+
element.addEventListener("pointercancel", cancel);
|
|
737
|
+
window.addEventListener("keydown", onKeyDown);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// src/DataGrid/useColumnDrag.ts
|
|
650
741
|
var DRAG_THRESHOLD = 4;
|
|
651
742
|
function headerAt(x, y) {
|
|
652
743
|
const element = document.elementFromPoint(x, y);
|
|
@@ -678,70 +769,49 @@ function useColumnDrag({
|
|
|
678
769
|
function placeGhost(x, y) {
|
|
679
770
|
setGhostTransform(`translate(${String(x - grabX)}px, ${String(y)}px)`);
|
|
680
771
|
}
|
|
681
|
-
|
|
682
|
-
function move(moveEvent) {
|
|
683
|
-
const { clientX, clientY } = moveEvent;
|
|
684
|
-
if (!dragging) {
|
|
685
|
-
if (Math.abs(clientX - startX) < DRAG_THRESHOLD) {
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
dragging = true;
|
|
689
|
-
dragged.current = true;
|
|
690
|
-
setDraggedColumnId(entry.id);
|
|
691
|
-
}
|
|
692
|
-
placeGhost(clientX, clientY);
|
|
693
|
-
const over = headerAt(clientX, clientY);
|
|
694
|
-
const overId = over?.getAttribute("data-gridkit-column");
|
|
695
|
-
const beforeId = over && overId ? resolveDropBefore(order, overId, sideOf(over, clientX)) : void 0;
|
|
696
|
-
target = beforeId !== void 0 && movesColumn(order, entry.id, beforeId) ? { kind: "column-order", beforeId } : null;
|
|
697
|
-
setDropTarget(target);
|
|
698
|
-
}
|
|
699
|
-
function stop() {
|
|
700
|
-
header.removeEventListener("pointermove", move);
|
|
701
|
-
header.removeEventListener("pointerup", end);
|
|
702
|
-
header.removeEventListener("pointercancel", cancel);
|
|
703
|
-
window.removeEventListener("keydown", onKeyDown);
|
|
704
|
-
if (header.hasPointerCapture(pointerId)) {
|
|
705
|
-
header.releasePointerCapture(pointerId);
|
|
706
|
-
}
|
|
772
|
+
function reset() {
|
|
707
773
|
setGhostTransform(null);
|
|
708
774
|
setDraggedColumnId(null);
|
|
709
775
|
setDropTarget(null);
|
|
710
776
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
777
|
+
startPointerGesture(header, pointerId, {
|
|
778
|
+
onMove(moveEvent) {
|
|
779
|
+
const { clientX, clientY } = moveEvent;
|
|
780
|
+
if (!dragging) {
|
|
781
|
+
if (Math.abs(clientX - startX) < DRAG_THRESHOLD) {
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
dragging = true;
|
|
785
|
+
dragged.current = true;
|
|
786
|
+
setDraggedColumnId(entry.id);
|
|
787
|
+
}
|
|
788
|
+
placeGhost(clientX, clientY);
|
|
789
|
+
const over = headerAt(clientX, clientY);
|
|
790
|
+
const overId = over?.getAttribute("data-gridkit-column");
|
|
791
|
+
const beforeId = over && overId ? resolveDropBefore(order, overId, sideOf(over, clientX)) : void 0;
|
|
792
|
+
target = beforeId !== void 0 && movesColumn(order, entry.id, beforeId) ? { kind: "column-order", beforeId } : null;
|
|
793
|
+
setDropTarget(target);
|
|
794
|
+
},
|
|
795
|
+
onEnd() {
|
|
796
|
+
const dropped = target;
|
|
797
|
+
reset();
|
|
798
|
+
if (dragging && dropped !== null) {
|
|
799
|
+
onDrop(dropped, entry.id);
|
|
800
|
+
}
|
|
801
|
+
},
|
|
802
|
+
// Escape and a cancelled pointer both leave the order as it was.
|
|
803
|
+
onCancel() {
|
|
804
|
+
target = null;
|
|
805
|
+
reset();
|
|
725
806
|
}
|
|
726
|
-
}
|
|
727
|
-
header.addEventListener("pointermove", move);
|
|
728
|
-
header.addEventListener("pointerup", end);
|
|
729
|
-
header.addEventListener("pointercancel", cancel);
|
|
730
|
-
window.addEventListener("keydown", onKeyDown);
|
|
807
|
+
});
|
|
731
808
|
}
|
|
732
809
|
function moveByKeyboard(entry, direction) {
|
|
733
|
-
const
|
|
734
|
-
if (
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
const targetIndex = direction === -1 ? index - 1 : index + 2;
|
|
738
|
-
if (targetIndex < 0) {
|
|
810
|
+
const beforeId = resolveKeyboardDropTarget(order, entry.id, direction);
|
|
811
|
+
if (beforeId === void 0) {
|
|
739
812
|
return;
|
|
740
813
|
}
|
|
741
|
-
onDrop(
|
|
742
|
-
{ kind: "column-order", beforeId: order[targetIndex] ?? null },
|
|
743
|
-
entry.id
|
|
744
|
-
);
|
|
814
|
+
onDrop({ kind: "column-order", beforeId }, entry.id);
|
|
745
815
|
}
|
|
746
816
|
return {
|
|
747
817
|
draggedColumnId,
|
|
@@ -762,13 +832,14 @@ import {
|
|
|
762
832
|
beginColumnResize,
|
|
763
833
|
clampColumnWidth,
|
|
764
834
|
resolveColumnConstraints,
|
|
835
|
+
revertColumnSize,
|
|
765
836
|
sizeColumnToContent
|
|
766
837
|
} from "@gridkitjs/core";
|
|
767
838
|
|
|
768
839
|
// src/DataGrid/measureColumnContent.ts
|
|
769
840
|
function measureColumnContent(table, columnId) {
|
|
770
841
|
const cells = table.querySelectorAll(
|
|
771
|
-
`[data-gridkit-column="${CSS.escape(columnId)}"]`
|
|
842
|
+
`td[data-gridkit-column="${CSS.escape(columnId)}"]`
|
|
772
843
|
);
|
|
773
844
|
const range = document.createRange();
|
|
774
845
|
let widest = null;
|
|
@@ -810,45 +881,39 @@ function useColumnResize({
|
|
|
810
881
|
let width = session.startWidth;
|
|
811
882
|
event.preventDefault();
|
|
812
883
|
event.stopPropagation();
|
|
813
|
-
handle.setPointerCapture(pointerId);
|
|
814
884
|
setActiveColumnId(session.columnId);
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
cancel();
|
|
885
|
+
startPointerGesture(handle, pointerId, {
|
|
886
|
+
onMove(moveEvent) {
|
|
887
|
+
width = applyColumnResize(session, moveEvent.clientX);
|
|
888
|
+
commit(base, session.columnId, width, "move");
|
|
889
|
+
},
|
|
890
|
+
onEnd() {
|
|
891
|
+
setActiveColumnId(null);
|
|
892
|
+
if (width !== session.startWidth) {
|
|
893
|
+
commit(base, session.columnId, width, "end");
|
|
894
|
+
}
|
|
895
|
+
},
|
|
896
|
+
/**
|
|
897
|
+
* Escape puts back only the dragged column's pre-drag width, merged
|
|
898
|
+
* into whatever the sizing state is *now* — not the `base` snapshot
|
|
899
|
+
* taken at drag-start — so a different column resized via keyboard
|
|
900
|
+
* while this drag was still open keeps its change instead of being
|
|
901
|
+
* clobbered by a stale restore.
|
|
902
|
+
*/
|
|
903
|
+
onCancel() {
|
|
904
|
+
setActiveColumnId(null);
|
|
905
|
+
setSizing((current) => {
|
|
906
|
+
const next = revertColumnSize(current, base, session.columnId);
|
|
907
|
+
onColumnResize?.({
|
|
908
|
+
columnId: session.columnId,
|
|
909
|
+
width: session.startWidth,
|
|
910
|
+
sizing: next,
|
|
911
|
+
phase: "end"
|
|
912
|
+
});
|
|
913
|
+
return next;
|
|
914
|
+
});
|
|
846
915
|
}
|
|
847
|
-
}
|
|
848
|
-
handle.addEventListener("pointermove", move);
|
|
849
|
-
handle.addEventListener("pointerup", end);
|
|
850
|
-
handle.addEventListener("pointercancel", cancel);
|
|
851
|
-
window.addEventListener("keydown", onKeyDown);
|
|
916
|
+
});
|
|
852
917
|
}
|
|
853
918
|
function sizeToContent(entry) {
|
|
854
919
|
const table = tableRef.current;
|
|
@@ -883,6 +948,31 @@ function useColumnResize({
|
|
|
883
948
|
return { activeColumnId, startResize, sizeToContent, nudge };
|
|
884
949
|
}
|
|
885
950
|
|
|
951
|
+
// src/DataGrid/useColumnSort.ts
|
|
952
|
+
import {
|
|
953
|
+
sortDirectionFor,
|
|
954
|
+
sortPriorityFor,
|
|
955
|
+
toggleColumnSort
|
|
956
|
+
} from "@gridkitjs/core";
|
|
957
|
+
function useColumnSort({
|
|
958
|
+
sort,
|
|
959
|
+
setSort,
|
|
960
|
+
onColumnSortChange
|
|
961
|
+
}) {
|
|
962
|
+
function toggle(entry, event) {
|
|
963
|
+
const next = toggleColumnSort(sort, entry.id, { stack: event.shiftKey });
|
|
964
|
+
commitIfChanged(sort, next, setSort, (committed) => {
|
|
965
|
+
onColumnSortChange?.({ columnId: entry.id, sort: committed });
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
return {
|
|
969
|
+
sort,
|
|
970
|
+
directionFor: (columnId) => sortDirectionFor(sort, columnId),
|
|
971
|
+
priorityFor: (columnId) => sortPriorityFor(sort, columnId),
|
|
972
|
+
toggle
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
|
|
886
976
|
// src/DataGrid/useElementWidth.ts
|
|
887
977
|
import { useLayoutEffect, useState as useState4 } from "react";
|
|
888
978
|
function useElementWidth(ref, enabled) {
|
|
@@ -924,8 +1014,13 @@ function DataGridComponent({
|
|
|
924
1014
|
columnSizeDefaults,
|
|
925
1015
|
onColumnResize,
|
|
926
1016
|
onColumnOrderChange,
|
|
1017
|
+
sortableColumns = false,
|
|
1018
|
+
defaultColumnSort,
|
|
1019
|
+
onColumnSortChange,
|
|
1020
|
+
defaultFilter,
|
|
927
1021
|
label,
|
|
928
1022
|
labelledBy,
|
|
1023
|
+
ref,
|
|
929
1024
|
...callbacks
|
|
930
1025
|
}) {
|
|
931
1026
|
const hoverRows = hoverable?.rows ?? true;
|
|
@@ -940,6 +1035,8 @@ function DataGridComponent({
|
|
|
940
1035
|
const [order, setOrder] = useState5(
|
|
941
1036
|
defaultColumnOrder ?? []
|
|
942
1037
|
);
|
|
1038
|
+
const [sort, setSort] = useState5(defaultColumnSort ?? []);
|
|
1039
|
+
const [filter] = useState5(defaultFilter ?? []);
|
|
943
1040
|
const [announcement, setAnnouncement] = useState5("");
|
|
944
1041
|
const [rowSelection, setRowSelection] = useState5(
|
|
945
1042
|
defaultRowSelection ?? []
|
|
@@ -984,6 +1081,10 @@ function DataGridComponent({
|
|
|
984
1081
|
resizableColumns,
|
|
985
1082
|
reorderableColumns
|
|
986
1083
|
]);
|
|
1084
|
+
const shownRows = useMemo2(
|
|
1085
|
+
() => resolveShownRows(rows, filter, sort, resolved),
|
|
1086
|
+
[rows, filter, sort, resolved]
|
|
1087
|
+
);
|
|
987
1088
|
function columnName(columnId) {
|
|
988
1089
|
const entry = resolved.find((candidate) => candidate.id === columnId);
|
|
989
1090
|
if (entry === void 0) {
|
|
@@ -1011,7 +1112,7 @@ function DataGridComponent({
|
|
|
1011
1112
|
});
|
|
1012
1113
|
const nav = useGridNavigation({
|
|
1013
1114
|
tableRef,
|
|
1014
|
-
rowCount:
|
|
1115
|
+
rowCount: shownRows.length,
|
|
1015
1116
|
columnCount: resolved.length
|
|
1016
1117
|
});
|
|
1017
1118
|
const displayedIds = useMemo2(
|
|
@@ -1032,8 +1133,27 @@ function DataGridComponent({
|
|
|
1032
1133
|
nav.focusCell(HEADER_ROW, position);
|
|
1033
1134
|
}
|
|
1034
1135
|
const drag = useColumnDrag({ order: displayedIds, onDrop: handleDrop });
|
|
1136
|
+
function handleColumnSortChange(event) {
|
|
1137
|
+
onColumnSortChange?.(event);
|
|
1138
|
+
const entry = event.sort.find(
|
|
1139
|
+
(candidate) => candidate.columnId === event.columnId
|
|
1140
|
+
);
|
|
1141
|
+
if (entry === void 0) {
|
|
1142
|
+
announce(`${columnName(event.columnId)}, sort cleared`);
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
const direction = entry.direction === "asc" ? "ascending" : "descending";
|
|
1146
|
+
announce(
|
|
1147
|
+
event.sort.length > 1 ? `${columnName(event.columnId)} sorted ${direction}, key ${String(event.sort.indexOf(entry) + 1)} of ${String(event.sort.length)}` : `${columnName(event.columnId)} sorted ${direction}`
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
const columnSort = useColumnSort({
|
|
1151
|
+
sort,
|
|
1152
|
+
setSort,
|
|
1153
|
+
onColumnSortChange: handleColumnSortChange
|
|
1154
|
+
});
|
|
1035
1155
|
const selection = useGridSelection({
|
|
1036
|
-
rows,
|
|
1156
|
+
rows: shownRows,
|
|
1037
1157
|
columns: resolved,
|
|
1038
1158
|
selectable,
|
|
1039
1159
|
rowSelection,
|
|
@@ -1043,20 +1163,57 @@ function DataGridComponent({
|
|
|
1043
1163
|
cellSelection,
|
|
1044
1164
|
setCellSelection,
|
|
1045
1165
|
callbacks,
|
|
1046
|
-
announce
|
|
1166
|
+
announce,
|
|
1167
|
+
columnName
|
|
1047
1168
|
});
|
|
1048
1169
|
const multiselectable = selection.rowMode === "multiple" || selection.columnMode === "multiple";
|
|
1170
|
+
useImperativeHandle(ref, () => ({
|
|
1171
|
+
get element() {
|
|
1172
|
+
return viewportRef.current;
|
|
1173
|
+
},
|
|
1174
|
+
get table() {
|
|
1175
|
+
return tableRef.current;
|
|
1176
|
+
},
|
|
1177
|
+
getRows: () => shownRows,
|
|
1178
|
+
getColumns: () => resolved,
|
|
1179
|
+
getColumnSizing: () => sizing,
|
|
1180
|
+
getColumnOrder: () => order,
|
|
1181
|
+
getColumnSort: () => sort,
|
|
1182
|
+
getRowSelection: () => rowSelection,
|
|
1183
|
+
getColumnSelection: () => columnSelection,
|
|
1184
|
+
getCellSelection: () => cellSelection,
|
|
1185
|
+
getFocusedCell: () => nav.focus,
|
|
1186
|
+
focusCell: nav.focusCell,
|
|
1187
|
+
clearSelection: selection.clear,
|
|
1188
|
+
selectAllRows: selection.selectAllRows,
|
|
1189
|
+
scrollToRow: (rowId, options) => {
|
|
1190
|
+
const index = shownRows.findIndex((entry) => entry.rowId === rowId);
|
|
1191
|
+
if (index === -1) return;
|
|
1192
|
+
tableRef.current?.tBodies[0]?.rows[index]?.scrollIntoView(options);
|
|
1193
|
+
},
|
|
1194
|
+
scrollToColumn: (columnId, options) => {
|
|
1195
|
+
const cells = tableRef.current?.querySelectorAll("[data-gridkit-column]");
|
|
1196
|
+
const cell = cells ? Array.from(cells).find(
|
|
1197
|
+
(entry) => entry.getAttribute("data-gridkit-column") === columnId
|
|
1198
|
+
) : void 0;
|
|
1199
|
+
cell?.scrollIntoView(options);
|
|
1200
|
+
}
|
|
1201
|
+
}));
|
|
1049
1202
|
return /* @__PURE__ */ jsxs2("div", { className: "gridkit-data-grid-viewport", ref: viewportRef, children: [
|
|
1050
1203
|
/* @__PURE__ */ jsxs2(
|
|
1051
1204
|
"table",
|
|
1052
1205
|
{
|
|
1053
1206
|
ref: tableRef,
|
|
1054
1207
|
role: "grid",
|
|
1055
|
-
"aria-rowcount":
|
|
1208
|
+
"aria-rowcount": shownRows.length + 1,
|
|
1056
1209
|
"aria-colcount": resolved.length,
|
|
1057
|
-
...multiselectable
|
|
1058
|
-
...labelledBy !== void 0
|
|
1059
|
-
...
|
|
1210
|
+
...ariaAttr(multiselectable, "aria-multiselectable", true),
|
|
1211
|
+
...ariaAttr(labelledBy !== void 0, "aria-labelledby", labelledBy),
|
|
1212
|
+
...ariaAttr(
|
|
1213
|
+
labelledBy === void 0 && label !== void 0,
|
|
1214
|
+
"aria-label",
|
|
1215
|
+
label
|
|
1216
|
+
),
|
|
1060
1217
|
onKeyDown: (event) => {
|
|
1061
1218
|
if (event.key === "Escape") {
|
|
1062
1219
|
if (drag.draggedColumnId !== null || resize.activeColumnId !== null)
|
|
@@ -1071,7 +1228,7 @@ function DataGridComponent({
|
|
|
1071
1228
|
}
|
|
1072
1229
|
},
|
|
1073
1230
|
style: { width: totalColumnWidth(resolved) },
|
|
1074
|
-
className:
|
|
1231
|
+
className: classNames(
|
|
1075
1232
|
"gridkit-data-grid",
|
|
1076
1233
|
borders ? `borders-${borders}` : "",
|
|
1077
1234
|
// Hover is on by default and selection off, so one set of classes
|
|
@@ -1083,7 +1240,7 @@ function DataGridComponent({
|
|
|
1083
1240
|
selection.rowMode === false ? "" : "selectable-rows",
|
|
1084
1241
|
selection.columnMode === false ? "" : "selectable-columns",
|
|
1085
1242
|
selection.cellMode === false ? "" : "selectable-cells"
|
|
1086
|
-
|
|
1243
|
+
),
|
|
1087
1244
|
children: [
|
|
1088
1245
|
/* @__PURE__ */ jsx4("colgroup", { children: resolved.map((entry) => /* @__PURE__ */ jsx4("col", { style: { width: entry.width } }, entry.id)) }),
|
|
1089
1246
|
/* @__PURE__ */ jsx4(
|
|
@@ -1092,6 +1249,8 @@ function DataGridComponent({
|
|
|
1092
1249
|
columns: resolved,
|
|
1093
1250
|
resize,
|
|
1094
1251
|
drag,
|
|
1252
|
+
sort: columnSort,
|
|
1253
|
+
sortableColumns,
|
|
1095
1254
|
nav,
|
|
1096
1255
|
selection
|
|
1097
1256
|
}
|
|
@@ -1100,7 +1259,7 @@ function DataGridComponent({
|
|
|
1100
1259
|
GridBody,
|
|
1101
1260
|
{
|
|
1102
1261
|
columns: resolved,
|
|
1103
|
-
rows,
|
|
1262
|
+
rows: shownRows,
|
|
1104
1263
|
activeColumnId: resize.activeColumnId,
|
|
1105
1264
|
nav,
|
|
1106
1265
|
selection
|