@vesture/react 0.1.0 → 0.2.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.css +172 -17
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +27 -2
- package/dist/index.js +514 -106
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
package/dist/index.js
CHANGED
|
@@ -1079,25 +1079,79 @@ function Alert({
|
|
|
1079
1079
|
}
|
|
1080
1080
|
|
|
1081
1081
|
// src/components/DataGrid/DataGrid.tsx
|
|
1082
|
-
import { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef3, useState as useState8 } from "react";
|
|
1082
|
+
import { useCallback as useCallback2, useEffect, useMemo as useMemo2, useRef as useRef3, useState as useState8 } from "react";
|
|
1083
1083
|
|
|
1084
1084
|
// src/components/DataGrid/DataGrid.css.ts
|
|
1085
|
-
var
|
|
1086
|
-
var
|
|
1087
|
-
var
|
|
1088
|
-
var
|
|
1089
|
-
var
|
|
1090
|
-
var
|
|
1091
|
-
var
|
|
1092
|
-
var
|
|
1093
|
-
var
|
|
1094
|
-
var
|
|
1095
|
-
var
|
|
1085
|
+
var actionsCell = "DataGrid_actionsCell__7xivx7g";
|
|
1086
|
+
var body3 = "DataGrid_body__7xivx77";
|
|
1087
|
+
var cell = "DataGrid_cell__7xivx79";
|
|
1088
|
+
var checkboxCell = "DataGrid_checkboxCell__7xivx7a";
|
|
1089
|
+
var container = "DataGrid_container__7xivx71";
|
|
1090
|
+
var editInput = "DataGrid_editInput__7xivx7o";
|
|
1091
|
+
var emptyState = "DataGrid_emptyState__7xivx7b";
|
|
1092
|
+
var filterCell = "DataGrid_filterCell__7xivx7j";
|
|
1093
|
+
var filterInput = "DataGrid_filterInput__7xivx7k";
|
|
1094
|
+
var filterRow = "DataGrid_filterRow__7xivx7i";
|
|
1095
|
+
var gridWrapper = "DataGrid_gridWrapper__7xivx7l";
|
|
1096
|
+
var headerButton = "DataGrid_headerButton__7xivx74";
|
|
1097
|
+
var headerCell = "DataGrid_headerCell__7xivx73";
|
|
1098
|
+
var headerRow = "DataGrid_headerRow__7xivx72";
|
|
1099
|
+
var iconButton = "DataGrid_iconButton__7xivx7h";
|
|
1100
|
+
var loadingOverlay = "DataGrid_loadingOverlay__7xivx7m";
|
|
1101
|
+
var paginationFooter = "DataGrid_paginationFooter__7xivx7n";
|
|
1102
|
+
var pinnedCell = "DataGrid_pinnedCell__7xivx7c";
|
|
1103
|
+
var pinnedHeaderCell = "DataGrid_pinnedHeaderCell__7xivx7d";
|
|
1104
|
+
var pinnedLeftEdge = "DataGrid_pinnedLeftEdge__7xivx7e";
|
|
1105
|
+
var pinnedRightEdge = "DataGrid_pinnedRightEdge__7xivx7f";
|
|
1106
|
+
var resizeHandle = "DataGrid_resizeHandle__7xivx76";
|
|
1107
|
+
var row = "DataGrid_row__7xivx78";
|
|
1108
|
+
var sortIcon = "DataGrid_sortIcon__7xivx75";
|
|
1109
|
+
var srOnly2 = "DataGrid_srOnly__7xivx70";
|
|
1096
1110
|
|
|
1097
1111
|
// src/components/DataGrid/DataGrid.tsx
|
|
1098
|
-
import { jsx as jsx34, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1112
|
+
import { Fragment as Fragment5, jsx as jsx34, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1099
1113
|
var DEFAULT_COLUMN_WIDTH = 160;
|
|
1100
1114
|
var CHECKBOX_COLUMN_WIDTH = 44;
|
|
1115
|
+
var ACTIONS_COLUMN_WIDTH = 72;
|
|
1116
|
+
var FILTER_DEBOUNCE_MS = 200;
|
|
1117
|
+
function useDebouncedValue(value, delay) {
|
|
1118
|
+
const [debounced, setDebounced] = useState8(value);
|
|
1119
|
+
useEffect(() => {
|
|
1120
|
+
const timer = setTimeout(() => setDebounced(value), delay);
|
|
1121
|
+
return () => clearTimeout(timer);
|
|
1122
|
+
}, [value, delay]);
|
|
1123
|
+
return debounced;
|
|
1124
|
+
}
|
|
1125
|
+
function FilterTextInput({
|
|
1126
|
+
value,
|
|
1127
|
+
onChange,
|
|
1128
|
+
...rest
|
|
1129
|
+
}) {
|
|
1130
|
+
const [draft, setDraft] = useState8(value);
|
|
1131
|
+
const debounced = useDebouncedValue(draft, FILTER_DEBOUNCE_MS);
|
|
1132
|
+
const onChangeRef = useRef3(onChange);
|
|
1133
|
+
onChangeRef.current = onChange;
|
|
1134
|
+
const mounted = useRef3(false);
|
|
1135
|
+
useEffect(() => {
|
|
1136
|
+
if (!mounted.current) {
|
|
1137
|
+
mounted.current = true;
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
onChangeRef.current(debounced);
|
|
1141
|
+
}, [debounced]);
|
|
1142
|
+
useEffect(() => {
|
|
1143
|
+
setDraft(value);
|
|
1144
|
+
}, [value]);
|
|
1145
|
+
return /* @__PURE__ */ jsx34(
|
|
1146
|
+
"input",
|
|
1147
|
+
{
|
|
1148
|
+
type: "text",
|
|
1149
|
+
value: draft,
|
|
1150
|
+
onChange: (e) => setDraft(e.target.value),
|
|
1151
|
+
...rest
|
|
1152
|
+
}
|
|
1153
|
+
);
|
|
1154
|
+
}
|
|
1101
1155
|
function compareValues(a, b) {
|
|
1102
1156
|
if (typeof a === "number" && typeof b === "number") {
|
|
1103
1157
|
return a - b;
|
|
@@ -1122,15 +1176,35 @@ function DataGrid({
|
|
|
1122
1176
|
onSelectionChange,
|
|
1123
1177
|
sort: controlledSort,
|
|
1124
1178
|
onSortChange,
|
|
1125
|
-
|
|
1179
|
+
filters: controlledFilters,
|
|
1180
|
+
onFilterChange,
|
|
1181
|
+
emptyMessage = "No data",
|
|
1182
|
+
onRowEdit,
|
|
1183
|
+
serverSide = false,
|
|
1184
|
+
loading = false,
|
|
1185
|
+
totalRowCount,
|
|
1186
|
+
page,
|
|
1187
|
+
pageSize,
|
|
1188
|
+
onPageChange
|
|
1126
1189
|
}) {
|
|
1127
|
-
const [uncontrolledSort, setUncontrolledSort] = useState8(
|
|
1190
|
+
const [uncontrolledSort, setUncontrolledSort] = useState8(
|
|
1191
|
+
null
|
|
1192
|
+
);
|
|
1193
|
+
const [uncontrolledFilters, setUncontrolledFilters] = useState8(
|
|
1194
|
+
[]
|
|
1195
|
+
);
|
|
1128
1196
|
const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState8(() => /* @__PURE__ */ new Set());
|
|
1129
1197
|
const [columnWidths, setColumnWidths] = useState8(
|
|
1130
|
-
() => Object.fromEntries(
|
|
1198
|
+
() => Object.fromEntries(
|
|
1199
|
+
columns.map((c) => [c.key, c.width ?? DEFAULT_COLUMN_WIDTH])
|
|
1200
|
+
)
|
|
1131
1201
|
);
|
|
1132
1202
|
const [scrollTop, setScrollTop] = useState8(0);
|
|
1203
|
+
const [editingRowId, setEditingRowId] = useState8(null);
|
|
1204
|
+
const [editDraft, setEditDraft] = useState8({});
|
|
1205
|
+
const editingEnabled = Boolean(onRowEdit);
|
|
1133
1206
|
const sort = controlledSort !== void 0 ? controlledSort : uncontrolledSort;
|
|
1207
|
+
const filters = controlledFilters !== void 0 ? controlledFilters : uncontrolledFilters;
|
|
1134
1208
|
const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
|
|
1135
1209
|
const setSort = (next) => {
|
|
1136
1210
|
if (controlledSort === void 0) {
|
|
@@ -1138,6 +1212,17 @@ function DataGrid({
|
|
|
1138
1212
|
}
|
|
1139
1213
|
onSortChange?.(next);
|
|
1140
1214
|
};
|
|
1215
|
+
const setFilters = (next) => {
|
|
1216
|
+
if (controlledFilters === void 0) {
|
|
1217
|
+
setUncontrolledFilters(next);
|
|
1218
|
+
}
|
|
1219
|
+
onFilterChange?.(next);
|
|
1220
|
+
};
|
|
1221
|
+
const handleFilterChange = (key, value) => {
|
|
1222
|
+
const next = value ? [...filters.filter((f) => f.key !== key), { key, value }] : filters.filter((f) => f.key !== key);
|
|
1223
|
+
setFilters(next);
|
|
1224
|
+
};
|
|
1225
|
+
const getFilterValue = (key) => filters.find((f) => f.key === key)?.value ?? "";
|
|
1141
1226
|
const setSelectedIds = (next) => {
|
|
1142
1227
|
if (controlledSelectedIds === void 0) {
|
|
1143
1228
|
setUncontrolledSelectedIds(next);
|
|
@@ -1154,17 +1239,50 @@ function DataGrid({
|
|
|
1154
1239
|
setSort(null);
|
|
1155
1240
|
}
|
|
1156
1241
|
};
|
|
1242
|
+
const filteredData = useMemo2(() => {
|
|
1243
|
+
if (serverSide || filters.length === 0) {
|
|
1244
|
+
return data;
|
|
1245
|
+
}
|
|
1246
|
+
return data.filter(
|
|
1247
|
+
(row2) => filters.every((f) => {
|
|
1248
|
+
if (!f.value) return true;
|
|
1249
|
+
const column = columns.find((c) => c.key === f.key);
|
|
1250
|
+
if (!column) return true;
|
|
1251
|
+
const cellValue = String(getCellValue(column, row2) ?? "").toLowerCase();
|
|
1252
|
+
return cellValue.includes(f.value.toLowerCase());
|
|
1253
|
+
})
|
|
1254
|
+
);
|
|
1255
|
+
}, [data, filters, columns, serverSide]);
|
|
1157
1256
|
const sortedData = useMemo2(() => {
|
|
1158
|
-
if (
|
|
1257
|
+
if (serverSide) {
|
|
1159
1258
|
return data;
|
|
1160
1259
|
}
|
|
1260
|
+
if (!sort || !sort.direction) {
|
|
1261
|
+
return filteredData;
|
|
1262
|
+
}
|
|
1161
1263
|
const column = columns.find((c) => c.key === sort.key);
|
|
1162
1264
|
if (!column) {
|
|
1163
|
-
return
|
|
1265
|
+
return filteredData;
|
|
1164
1266
|
}
|
|
1165
|
-
const sorted = [...
|
|
1267
|
+
const sorted = [...filteredData].sort(
|
|
1268
|
+
(a, b) => compareValues(getCellValue(column, a), getCellValue(column, b))
|
|
1269
|
+
);
|
|
1166
1270
|
return sort.direction === "desc" ? sorted.reverse() : sorted;
|
|
1167
|
-
}, [
|
|
1271
|
+
}, [filteredData, sort, columns, serverSide, data]);
|
|
1272
|
+
const selectFilterOptions = useMemo2(() => {
|
|
1273
|
+
const map = {};
|
|
1274
|
+
for (const column of columns) {
|
|
1275
|
+
if (!column.filterable || column.filterType !== "select") continue;
|
|
1276
|
+
const values = /* @__PURE__ */ new Set();
|
|
1277
|
+
for (const row2 of data) {
|
|
1278
|
+
values.add(String(getCellValue(column, row2) ?? ""));
|
|
1279
|
+
}
|
|
1280
|
+
map[column.key] = Array.from(values).sort();
|
|
1281
|
+
}
|
|
1282
|
+
return map;
|
|
1283
|
+
}, [columns, data]);
|
|
1284
|
+
const hasFilterableColumns = columns.some((c) => c.filterable);
|
|
1285
|
+
const showPagination = page !== void 0 && pageSize !== void 0 && onPageChange !== void 0;
|
|
1168
1286
|
const allSelected = sortedData.length > 0 && sortedData.every((r) => selectedIds.has(getRowId(r)));
|
|
1169
1287
|
const someSelected = !allSelected && sortedData.some((r) => selectedIds.has(getRowId(r)));
|
|
1170
1288
|
const toggleAll = () => {
|
|
@@ -1199,109 +1317,399 @@ function DataGrid({
|
|
|
1199
1317
|
},
|
|
1200
1318
|
[columnWidths]
|
|
1201
1319
|
);
|
|
1202
|
-
const handleResizeMove = useCallback2(
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1320
|
+
const handleResizeMove = useCallback2(
|
|
1321
|
+
(event) => {
|
|
1322
|
+
const state = resizeState.current;
|
|
1323
|
+
if (!state) return;
|
|
1324
|
+
const delta = event.clientX - state.startX;
|
|
1325
|
+
const minWidth = columns.find((c) => c.key === state.key)?.minWidth ?? 60;
|
|
1326
|
+
const nextWidth = Math.max(minWidth, state.startWidth + delta);
|
|
1327
|
+
setColumnWidths((prev) => ({ ...prev, [state.key]: nextWidth }));
|
|
1328
|
+
},
|
|
1329
|
+
[columns]
|
|
1330
|
+
);
|
|
1331
|
+
const handleResizeEnd = useCallback2(
|
|
1332
|
+
(event) => {
|
|
1333
|
+
resizeState.current = null;
|
|
1334
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
1335
|
+
},
|
|
1336
|
+
[]
|
|
1337
|
+
);
|
|
1338
|
+
const widthOf = useCallback2(
|
|
1339
|
+
(column) => columnWidths[column.key] ?? column.width ?? DEFAULT_COLUMN_WIDTH,
|
|
1340
|
+
[columnWidths]
|
|
1341
|
+
);
|
|
1342
|
+
const layout = useMemo2(() => {
|
|
1343
|
+
const leftPinned = columns.filter((c) => c.pinned === "left");
|
|
1344
|
+
const rightPinned = columns.filter((c) => c.pinned === "right");
|
|
1345
|
+
const middle = columns.filter((c) => !c.pinned);
|
|
1346
|
+
const ordered = [...leftPinned, ...middle, ...rightPinned];
|
|
1347
|
+
const leftOffsets = /* @__PURE__ */ new Map();
|
|
1348
|
+
let leftAcc = selectable ? CHECKBOX_COLUMN_WIDTH : 0;
|
|
1349
|
+
for (const column of leftPinned) {
|
|
1350
|
+
leftOffsets.set(column.key, leftAcc);
|
|
1351
|
+
leftAcc += widthOf(column);
|
|
1352
|
+
}
|
|
1353
|
+
const rightOffsets = /* @__PURE__ */ new Map();
|
|
1354
|
+
let rightAcc = editingEnabled ? ACTIONS_COLUMN_WIDTH : 0;
|
|
1355
|
+
for (let i = rightPinned.length - 1; i >= 0; i--) {
|
|
1356
|
+
const column = rightPinned[i];
|
|
1357
|
+
rightOffsets.set(column.key, rightAcc);
|
|
1358
|
+
rightAcc += widthOf(column);
|
|
1359
|
+
}
|
|
1360
|
+
return {
|
|
1361
|
+
ordered,
|
|
1362
|
+
leftOffsets,
|
|
1363
|
+
rightOffsets,
|
|
1364
|
+
lastLeftKey: leftPinned[leftPinned.length - 1]?.key,
|
|
1365
|
+
firstRightKey: rightPinned[0]?.key
|
|
1366
|
+
};
|
|
1367
|
+
}, [columns, selectable, editingEnabled, widthOf]);
|
|
1368
|
+
const pinnedStyle = (column) => {
|
|
1369
|
+
if (column.pinned === "left" && layout.leftOffsets.has(column.key)) {
|
|
1370
|
+
return { left: layout.leftOffsets.get(column.key) };
|
|
1371
|
+
}
|
|
1372
|
+
if (column.pinned === "right" && layout.rightOffsets.has(column.key)) {
|
|
1373
|
+
return { right: layout.rightOffsets.get(column.key) };
|
|
1374
|
+
}
|
|
1375
|
+
return void 0;
|
|
1376
|
+
};
|
|
1377
|
+
const pinnedClass = (column) => {
|
|
1378
|
+
const classes = [];
|
|
1379
|
+
if (column.pinned) {
|
|
1380
|
+
classes.push(pinnedCell);
|
|
1381
|
+
if (column.key === layout.lastLeftKey) classes.push(pinnedLeftEdge);
|
|
1382
|
+
if (column.key === layout.firstRightKey) classes.push(pinnedRightEdge);
|
|
1383
|
+
}
|
|
1384
|
+
return classes.join(" ");
|
|
1385
|
+
};
|
|
1386
|
+
const headerPinnedClass = (column) => {
|
|
1387
|
+
const classes = [];
|
|
1388
|
+
if (column.pinned) {
|
|
1389
|
+
classes.push(pinnedHeaderCell);
|
|
1390
|
+
if (column.key === layout.lastLeftKey) classes.push(pinnedLeftEdge);
|
|
1391
|
+
if (column.key === layout.firstRightKey) classes.push(pinnedRightEdge);
|
|
1392
|
+
}
|
|
1393
|
+
return classes.join(" ");
|
|
1394
|
+
};
|
|
1395
|
+
const startEditing = (rowData) => {
|
|
1396
|
+
const id = getRowId(rowData);
|
|
1397
|
+
const draft = {};
|
|
1398
|
+
for (const column of columns) {
|
|
1399
|
+
if (column.editable) {
|
|
1400
|
+
draft[column.key] = String(getCellValue(column, rowData) ?? "");
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
setEditDraft(draft);
|
|
1404
|
+
setEditingRowId(id);
|
|
1405
|
+
};
|
|
1406
|
+
const cancelEditing = () => {
|
|
1407
|
+
setEditingRowId(null);
|
|
1408
|
+
setEditDraft({});
|
|
1409
|
+
};
|
|
1410
|
+
const saveEditing = () => {
|
|
1411
|
+
if (editingRowId) {
|
|
1412
|
+
onRowEdit?.(editingRowId, editDraft);
|
|
1413
|
+
}
|
|
1414
|
+
setEditingRowId(null);
|
|
1415
|
+
setEditDraft({});
|
|
1416
|
+
};
|
|
1214
1417
|
const totalHeight = sortedData.length * rowHeight;
|
|
1215
1418
|
const visibleCount = Math.ceil(height / rowHeight) + overscan * 2;
|
|
1216
1419
|
const startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
|
|
1217
1420
|
const endIndex = Math.min(sortedData.length, startIndex + visibleCount);
|
|
1218
1421
|
const visibleRows = sortedData.slice(startIndex, endIndex);
|
|
1219
|
-
const totalWidth = (selectable ? CHECKBOX_COLUMN_WIDTH : 0) + columns.reduce((sum, c) => sum + (
|
|
1220
|
-
return /* @__PURE__ */ jsxs17(
|
|
1221
|
-
"div",
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
{
|
|
1232
|
-
type: "checkbox",
|
|
1233
|
-
checked: allSelected,
|
|
1234
|
-
ref: (el) => {
|
|
1235
|
-
if (el) el.indeterminate = someSelected;
|
|
1236
|
-
},
|
|
1237
|
-
onChange: toggleAll,
|
|
1238
|
-
"aria-label": "Select all rows"
|
|
1239
|
-
}
|
|
1240
|
-
) }) : null,
|
|
1241
|
-
columns.map((column) => {
|
|
1242
|
-
const width = columnWidths[column.key] ?? DEFAULT_COLUMN_WIDTH;
|
|
1243
|
-
const isSorted = sort?.key === column.key;
|
|
1244
|
-
const direction2 = isSorted ? sort.direction : null;
|
|
1245
|
-
return /* @__PURE__ */ jsxs17(
|
|
1422
|
+
const totalWidth = (selectable ? CHECKBOX_COLUMN_WIDTH : 0) + (editingEnabled ? ACTIONS_COLUMN_WIDTH : 0) + columns.reduce((sum, c) => sum + widthOf(c), 0);
|
|
1423
|
+
return /* @__PURE__ */ jsxs17(Fragment5, { children: [
|
|
1424
|
+
/* @__PURE__ */ jsxs17("div", { className: gridWrapper, children: [
|
|
1425
|
+
/* @__PURE__ */ jsxs17(
|
|
1426
|
+
"div",
|
|
1427
|
+
{
|
|
1428
|
+
className: container,
|
|
1429
|
+
style: { height },
|
|
1430
|
+
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
1431
|
+
role: "table",
|
|
1432
|
+
children: [
|
|
1433
|
+
/* @__PURE__ */ jsxs17(
|
|
1246
1434
|
"div",
|
|
1247
1435
|
{
|
|
1248
|
-
className:
|
|
1249
|
-
style: { width },
|
|
1250
|
-
role: "
|
|
1251
|
-
"aria-sort": direction2 === "asc" ? "ascending" : direction2 === "desc" ? "descending" : "none",
|
|
1436
|
+
className: headerRow,
|
|
1437
|
+
style: { width: totalWidth, minWidth: "100%" },
|
|
1438
|
+
role: "row",
|
|
1252
1439
|
children: [
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1440
|
+
selectable ? /* @__PURE__ */ jsx34(
|
|
1441
|
+
"div",
|
|
1442
|
+
{
|
|
1443
|
+
className: [checkboxCell, pinnedHeaderCell].join(" "),
|
|
1444
|
+
style: { left: 0 },
|
|
1445
|
+
role: "columnheader",
|
|
1446
|
+
children: /* @__PURE__ */ jsx34(
|
|
1447
|
+
"input",
|
|
1448
|
+
{
|
|
1449
|
+
type: "checkbox",
|
|
1450
|
+
checked: allSelected,
|
|
1451
|
+
ref: (el) => {
|
|
1452
|
+
if (el) el.indeterminate = someSelected;
|
|
1453
|
+
},
|
|
1454
|
+
onChange: toggleAll,
|
|
1455
|
+
"aria-label": "Select all rows"
|
|
1456
|
+
}
|
|
1457
|
+
)
|
|
1458
|
+
}
|
|
1459
|
+
) : null,
|
|
1460
|
+
layout.ordered.map((column) => {
|
|
1461
|
+
const width = widthOf(column);
|
|
1462
|
+
const isSorted = sort?.key === column.key;
|
|
1463
|
+
const direction2 = isSorted ? sort.direction : null;
|
|
1464
|
+
return /* @__PURE__ */ jsxs17(
|
|
1465
|
+
"div",
|
|
1466
|
+
{
|
|
1467
|
+
className: [headerCell, headerPinnedClass(column)].filter(Boolean).join(" "),
|
|
1468
|
+
style: { width, ...pinnedStyle(column) },
|
|
1469
|
+
role: "columnheader",
|
|
1470
|
+
"aria-sort": direction2 === "asc" ? "ascending" : direction2 === "desc" ? "descending" : "none",
|
|
1471
|
+
children: [
|
|
1472
|
+
column.sortable ? /* @__PURE__ */ jsxs17(
|
|
1473
|
+
"button",
|
|
1474
|
+
{
|
|
1475
|
+
type: "button",
|
|
1476
|
+
className: headerButton,
|
|
1477
|
+
onClick: () => handleSortClick(column),
|
|
1478
|
+
children: [
|
|
1479
|
+
column.header,
|
|
1480
|
+
/* @__PURE__ */ jsx34("span", { className: sortIcon, "aria-hidden": "true", children: direction2 === "asc" ? "\u25B2" : direction2 === "desc" ? "\u25BC" : "" })
|
|
1481
|
+
]
|
|
1482
|
+
}
|
|
1483
|
+
) : column.header,
|
|
1484
|
+
column.resizable !== false ? /* @__PURE__ */ jsx34(
|
|
1485
|
+
"div",
|
|
1486
|
+
{
|
|
1487
|
+
className: resizeHandle,
|
|
1488
|
+
onPointerDown: (e) => handleResizeStart(e, column),
|
|
1489
|
+
onPointerMove: handleResizeMove,
|
|
1490
|
+
onPointerUp: handleResizeEnd,
|
|
1491
|
+
role: "separator",
|
|
1492
|
+
"aria-orientation": "vertical",
|
|
1493
|
+
"aria-label": `Resize ${String(column.header)} column`
|
|
1494
|
+
}
|
|
1495
|
+
) : null
|
|
1496
|
+
]
|
|
1497
|
+
},
|
|
1498
|
+
column.key
|
|
1499
|
+
);
|
|
1500
|
+
}),
|
|
1501
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1258
1502
|
"div",
|
|
1259
1503
|
{
|
|
1260
|
-
className:
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
role: "separator",
|
|
1265
|
-
"aria-orientation": "vertical",
|
|
1266
|
-
"aria-label": `Resize ${String(column.header)} column`
|
|
1504
|
+
className: [actionsCell, pinnedHeaderCell].join(" "),
|
|
1505
|
+
style: { right: 0 },
|
|
1506
|
+
role: "columnheader",
|
|
1507
|
+
children: /* @__PURE__ */ jsx34("span", { className: srOnly2, children: "Actions" })
|
|
1267
1508
|
}
|
|
1268
1509
|
) : null
|
|
1269
1510
|
]
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
] }),
|
|
1275
|
-
sortedData.length === 0 ? /* @__PURE__ */ jsx34("div", { className: emptyState, children: emptyMessage }) : /* @__PURE__ */ jsx34("div", { className: body3, style: { height: totalHeight, width: totalWidth, minWidth: "100%" }, children: visibleRows.map((rowData, i) => {
|
|
1276
|
-
const index = startIndex + i;
|
|
1277
|
-
const id = getRowId(rowData);
|
|
1278
|
-
const isSelected = selectedIds.has(id);
|
|
1279
|
-
const style = { top: index * rowHeight, height: rowHeight, width: totalWidth };
|
|
1280
|
-
return /* @__PURE__ */ jsxs17("div", { className: row, style, role: "row", "data-selected": isSelected || void 0, children: [
|
|
1281
|
-
selectable ? /* @__PURE__ */ jsx34("div", { className: checkboxCell, role: "cell", children: /* @__PURE__ */ jsx34(
|
|
1282
|
-
"input",
|
|
1511
|
+
}
|
|
1512
|
+
),
|
|
1513
|
+
hasFilterableColumns ? /* @__PURE__ */ jsxs17(
|
|
1514
|
+
"div",
|
|
1283
1515
|
{
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1516
|
+
className: filterRow,
|
|
1517
|
+
style: { width: totalWidth, minWidth: "100%" },
|
|
1518
|
+
role: "row",
|
|
1519
|
+
children: [
|
|
1520
|
+
selectable ? /* @__PURE__ */ jsx34(
|
|
1521
|
+
"div",
|
|
1522
|
+
{
|
|
1523
|
+
className: [checkboxCell, pinnedHeaderCell].join(" "),
|
|
1524
|
+
style: { left: 0 },
|
|
1525
|
+
role: "cell"
|
|
1526
|
+
}
|
|
1527
|
+
) : null,
|
|
1528
|
+
layout.ordered.map((column) => {
|
|
1529
|
+
const width = widthOf(column);
|
|
1530
|
+
return /* @__PURE__ */ jsx34(
|
|
1531
|
+
"div",
|
|
1532
|
+
{
|
|
1533
|
+
className: [filterCell, headerPinnedClass(column)].filter(Boolean).join(" "),
|
|
1534
|
+
style: { width, ...pinnedStyle(column) },
|
|
1535
|
+
role: "cell",
|
|
1536
|
+
children: column.filterable ? column.filterType === "select" ? /* @__PURE__ */ jsxs17(
|
|
1537
|
+
"select",
|
|
1538
|
+
{
|
|
1539
|
+
className: filterInput,
|
|
1540
|
+
value: getFilterValue(column.key),
|
|
1541
|
+
onChange: (e) => handleFilterChange(column.key, e.target.value),
|
|
1542
|
+
"aria-label": `Filter ${String(column.header)}`,
|
|
1543
|
+
children: [
|
|
1544
|
+
/* @__PURE__ */ jsx34("option", { value: "", children: "All" }),
|
|
1545
|
+
(selectFilterOptions[column.key] ?? []).map(
|
|
1546
|
+
(value) => /* @__PURE__ */ jsx34("option", { value, children: value }, value)
|
|
1547
|
+
)
|
|
1548
|
+
]
|
|
1549
|
+
}
|
|
1550
|
+
) : /* @__PURE__ */ jsx34(
|
|
1551
|
+
FilterTextInput,
|
|
1552
|
+
{
|
|
1553
|
+
className: filterInput,
|
|
1554
|
+
value: getFilterValue(column.key),
|
|
1555
|
+
onChange: (value) => handleFilterChange(column.key, value),
|
|
1556
|
+
placeholder: `Filter ${String(column.header)}`,
|
|
1557
|
+
"aria-label": `Filter ${String(column.header)}`
|
|
1558
|
+
}
|
|
1559
|
+
) : null
|
|
1560
|
+
},
|
|
1561
|
+
column.key
|
|
1562
|
+
);
|
|
1563
|
+
}),
|
|
1564
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1565
|
+
"div",
|
|
1566
|
+
{
|
|
1567
|
+
className: [actionsCell, pinnedHeaderCell].join(" "),
|
|
1568
|
+
style: { right: 0 },
|
|
1569
|
+
role: "cell"
|
|
1570
|
+
}
|
|
1571
|
+
) : null
|
|
1572
|
+
]
|
|
1288
1573
|
}
|
|
1289
|
-
)
|
|
1290
|
-
|
|
1574
|
+
) : null,
|
|
1575
|
+
sortedData.length === 0 ? /* @__PURE__ */ jsx34("div", { className: emptyState, children: emptyMessage }) : /* @__PURE__ */ jsx34(
|
|
1291
1576
|
"div",
|
|
1292
1577
|
{
|
|
1293
|
-
className:
|
|
1294
|
-
style: {
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1578
|
+
className: body3,
|
|
1579
|
+
style: {
|
|
1580
|
+
height: totalHeight,
|
|
1581
|
+
width: totalWidth,
|
|
1582
|
+
minWidth: "100%"
|
|
1583
|
+
},
|
|
1584
|
+
children: visibleRows.map((rowData, i) => {
|
|
1585
|
+
const index = startIndex + i;
|
|
1586
|
+
const id = getRowId(rowData);
|
|
1587
|
+
const isSelected = selectedIds.has(id);
|
|
1588
|
+
const isEditing = editingRowId === id;
|
|
1589
|
+
const style = {
|
|
1590
|
+
top: index * rowHeight,
|
|
1591
|
+
height: rowHeight,
|
|
1592
|
+
width: totalWidth
|
|
1593
|
+
};
|
|
1594
|
+
return /* @__PURE__ */ jsxs17(
|
|
1595
|
+
"div",
|
|
1596
|
+
{
|
|
1597
|
+
className: row,
|
|
1598
|
+
style,
|
|
1599
|
+
role: "row",
|
|
1600
|
+
"data-selected": isSelected || void 0,
|
|
1601
|
+
"data-editing": isEditing || void 0,
|
|
1602
|
+
children: [
|
|
1603
|
+
selectable ? /* @__PURE__ */ jsx34(
|
|
1604
|
+
"div",
|
|
1605
|
+
{
|
|
1606
|
+
className: [checkboxCell, pinnedCell].join(" "),
|
|
1607
|
+
style: { left: 0 },
|
|
1608
|
+
role: "cell",
|
|
1609
|
+
children: /* @__PURE__ */ jsx34(
|
|
1610
|
+
"input",
|
|
1611
|
+
{
|
|
1612
|
+
type: "checkbox",
|
|
1613
|
+
checked: isSelected,
|
|
1614
|
+
onChange: () => toggleRow(id),
|
|
1615
|
+
"aria-label": `Select row ${index + 1}`
|
|
1616
|
+
}
|
|
1617
|
+
)
|
|
1618
|
+
}
|
|
1619
|
+
) : null,
|
|
1620
|
+
layout.ordered.map((column) => /* @__PURE__ */ jsx34(
|
|
1621
|
+
"div",
|
|
1622
|
+
{
|
|
1623
|
+
className: [cell, pinnedClass(column)].filter(Boolean).join(" "),
|
|
1624
|
+
style: {
|
|
1625
|
+
width: widthOf(column),
|
|
1626
|
+
...pinnedStyle(column)
|
|
1627
|
+
},
|
|
1628
|
+
role: "cell",
|
|
1629
|
+
children: isEditing && column.editable ? /* @__PURE__ */ jsx34(
|
|
1630
|
+
"input",
|
|
1631
|
+
{
|
|
1632
|
+
type: "text",
|
|
1633
|
+
className: editInput,
|
|
1634
|
+
value: editDraft[column.key] ?? "",
|
|
1635
|
+
onChange: (e) => setEditDraft((prev) => ({
|
|
1636
|
+
...prev,
|
|
1637
|
+
[column.key]: e.target.value
|
|
1638
|
+
})),
|
|
1639
|
+
onKeyDown: (e) => {
|
|
1640
|
+
if (e.key === "Enter") saveEditing();
|
|
1641
|
+
if (e.key === "Escape") cancelEditing();
|
|
1642
|
+
},
|
|
1643
|
+
"aria-label": `Edit ${String(column.header)}`,
|
|
1644
|
+
autoFocus: column.key === columns.find((c) => c.editable)?.key
|
|
1645
|
+
}
|
|
1646
|
+
) : column.render ? column.render(rowData) : String(getCellValue(column, rowData) ?? "")
|
|
1647
|
+
},
|
|
1648
|
+
column.key
|
|
1649
|
+
)),
|
|
1650
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1651
|
+
"div",
|
|
1652
|
+
{
|
|
1653
|
+
className: [actionsCell, pinnedCell].join(" "),
|
|
1654
|
+
style: { right: 0 },
|
|
1655
|
+
role: "cell",
|
|
1656
|
+
children: isEditing ? /* @__PURE__ */ jsxs17(Fragment5, { children: [
|
|
1657
|
+
/* @__PURE__ */ jsx34(
|
|
1658
|
+
"button",
|
|
1659
|
+
{
|
|
1660
|
+
type: "button",
|
|
1661
|
+
className: iconButton,
|
|
1662
|
+
onClick: saveEditing,
|
|
1663
|
+
"aria-label": `Save row ${index + 1}`,
|
|
1664
|
+
children: "\u2713"
|
|
1665
|
+
}
|
|
1666
|
+
),
|
|
1667
|
+
/* @__PURE__ */ jsx34(
|
|
1668
|
+
"button",
|
|
1669
|
+
{
|
|
1670
|
+
type: "button",
|
|
1671
|
+
className: iconButton,
|
|
1672
|
+
onClick: cancelEditing,
|
|
1673
|
+
"aria-label": `Cancel editing row ${index + 1}`,
|
|
1674
|
+
children: "\u2715"
|
|
1675
|
+
}
|
|
1676
|
+
)
|
|
1677
|
+
] }) : /* @__PURE__ */ jsx34(
|
|
1678
|
+
"button",
|
|
1679
|
+
{
|
|
1680
|
+
type: "button",
|
|
1681
|
+
className: iconButton,
|
|
1682
|
+
onClick: () => startEditing(rowData),
|
|
1683
|
+
"aria-label": `Edit row ${index + 1}`,
|
|
1684
|
+
children: "\u270E"
|
|
1685
|
+
}
|
|
1686
|
+
)
|
|
1687
|
+
}
|
|
1688
|
+
) : null
|
|
1689
|
+
]
|
|
1690
|
+
},
|
|
1691
|
+
id
|
|
1692
|
+
);
|
|
1693
|
+
})
|
|
1694
|
+
}
|
|
1695
|
+
)
|
|
1696
|
+
]
|
|
1697
|
+
}
|
|
1698
|
+
),
|
|
1699
|
+
loading ? /* @__PURE__ */ jsx34("div", { className: loadingOverlay, children: /* @__PURE__ */ jsx34(Spinner, { size: "md" }) }) : null
|
|
1700
|
+
] }),
|
|
1701
|
+
showPagination ? /* @__PURE__ */ jsx34("div", { className: paginationFooter, children: /* @__PURE__ */ jsx34(
|
|
1702
|
+
Pagination,
|
|
1703
|
+
{
|
|
1704
|
+
page,
|
|
1705
|
+
totalPages: Math.max(
|
|
1706
|
+
1,
|
|
1707
|
+
Math.ceil((totalRowCount ?? data.length) / pageSize)
|
|
1708
|
+
),
|
|
1709
|
+
onPageChange
|
|
1710
|
+
}
|
|
1711
|
+
) }) : null
|
|
1712
|
+
] });
|
|
1305
1713
|
}
|
|
1306
1714
|
|
|
1307
1715
|
// src/index.ts
|