@vesture/react 0.1.0 → 0.1.1
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 +106 -17
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +207 -41
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
package/dist/index.js
CHANGED
|
@@ -1082,22 +1082,31 @@ function Alert({
|
|
|
1082
1082
|
import { useCallback as useCallback2, 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__7xivx7i";
|
|
1091
|
+
var emptyState = "DataGrid_emptyState__7xivx7b";
|
|
1092
|
+
var headerButton = "DataGrid_headerButton__7xivx74";
|
|
1093
|
+
var headerCell = "DataGrid_headerCell__7xivx73";
|
|
1094
|
+
var headerRow = "DataGrid_headerRow__7xivx72";
|
|
1095
|
+
var iconButton = "DataGrid_iconButton__7xivx7h";
|
|
1096
|
+
var pinnedCell = "DataGrid_pinnedCell__7xivx7c";
|
|
1097
|
+
var pinnedHeaderCell = "DataGrid_pinnedHeaderCell__7xivx7d";
|
|
1098
|
+
var pinnedLeftEdge = "DataGrid_pinnedLeftEdge__7xivx7e";
|
|
1099
|
+
var pinnedRightEdge = "DataGrid_pinnedRightEdge__7xivx7f";
|
|
1100
|
+
var resizeHandle = "DataGrid_resizeHandle__7xivx76";
|
|
1101
|
+
var row = "DataGrid_row__7xivx78";
|
|
1102
|
+
var sortIcon = "DataGrid_sortIcon__7xivx75";
|
|
1103
|
+
var srOnly2 = "DataGrid_srOnly__7xivx70";
|
|
1096
1104
|
|
|
1097
1105
|
// src/components/DataGrid/DataGrid.tsx
|
|
1098
|
-
import { jsx as jsx34, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1106
|
+
import { Fragment as Fragment5, jsx as jsx34, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1099
1107
|
var DEFAULT_COLUMN_WIDTH = 160;
|
|
1100
1108
|
var CHECKBOX_COLUMN_WIDTH = 44;
|
|
1109
|
+
var ACTIONS_COLUMN_WIDTH = 72;
|
|
1101
1110
|
function compareValues(a, b) {
|
|
1102
1111
|
if (typeof a === "number" && typeof b === "number") {
|
|
1103
1112
|
return a - b;
|
|
@@ -1122,7 +1131,8 @@ function DataGrid({
|
|
|
1122
1131
|
onSelectionChange,
|
|
1123
1132
|
sort: controlledSort,
|
|
1124
1133
|
onSortChange,
|
|
1125
|
-
emptyMessage = "No data"
|
|
1134
|
+
emptyMessage = "No data",
|
|
1135
|
+
onRowEdit
|
|
1126
1136
|
}) {
|
|
1127
1137
|
const [uncontrolledSort, setUncontrolledSort] = useState8(null);
|
|
1128
1138
|
const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState8(() => /* @__PURE__ */ new Set());
|
|
@@ -1130,6 +1140,9 @@ function DataGrid({
|
|
|
1130
1140
|
() => Object.fromEntries(columns.map((c) => [c.key, c.width ?? DEFAULT_COLUMN_WIDTH]))
|
|
1131
1141
|
);
|
|
1132
1142
|
const [scrollTop, setScrollTop] = useState8(0);
|
|
1143
|
+
const [editingRowId, setEditingRowId] = useState8(null);
|
|
1144
|
+
const [editDraft, setEditDraft] = useState8({});
|
|
1145
|
+
const editingEnabled = Boolean(onRowEdit);
|
|
1133
1146
|
const sort = controlledSort !== void 0 ? controlledSort : uncontrolledSort;
|
|
1134
1147
|
const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
|
|
1135
1148
|
const setSort = (next) => {
|
|
@@ -1211,12 +1224,91 @@ function DataGrid({
|
|
|
1211
1224
|
resizeState.current = null;
|
|
1212
1225
|
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
1213
1226
|
}, []);
|
|
1227
|
+
const widthOf = useCallback2(
|
|
1228
|
+
(column) => columnWidths[column.key] ?? column.width ?? DEFAULT_COLUMN_WIDTH,
|
|
1229
|
+
[columnWidths]
|
|
1230
|
+
);
|
|
1231
|
+
const layout = useMemo2(() => {
|
|
1232
|
+
const leftPinned = columns.filter((c) => c.pinned === "left");
|
|
1233
|
+
const rightPinned = columns.filter((c) => c.pinned === "right");
|
|
1234
|
+
const middle = columns.filter((c) => !c.pinned);
|
|
1235
|
+
const ordered = [...leftPinned, ...middle, ...rightPinned];
|
|
1236
|
+
const leftOffsets = /* @__PURE__ */ new Map();
|
|
1237
|
+
let leftAcc = selectable ? CHECKBOX_COLUMN_WIDTH : 0;
|
|
1238
|
+
for (const column of leftPinned) {
|
|
1239
|
+
leftOffsets.set(column.key, leftAcc);
|
|
1240
|
+
leftAcc += widthOf(column);
|
|
1241
|
+
}
|
|
1242
|
+
const rightOffsets = /* @__PURE__ */ new Map();
|
|
1243
|
+
let rightAcc = editingEnabled ? ACTIONS_COLUMN_WIDTH : 0;
|
|
1244
|
+
for (let i = rightPinned.length - 1; i >= 0; i--) {
|
|
1245
|
+
const column = rightPinned[i];
|
|
1246
|
+
rightOffsets.set(column.key, rightAcc);
|
|
1247
|
+
rightAcc += widthOf(column);
|
|
1248
|
+
}
|
|
1249
|
+
return {
|
|
1250
|
+
ordered,
|
|
1251
|
+
leftOffsets,
|
|
1252
|
+
rightOffsets,
|
|
1253
|
+
lastLeftKey: leftPinned[leftPinned.length - 1]?.key,
|
|
1254
|
+
firstRightKey: rightPinned[0]?.key
|
|
1255
|
+
};
|
|
1256
|
+
}, [columns, selectable, editingEnabled, widthOf]);
|
|
1257
|
+
const pinnedStyle = (column) => {
|
|
1258
|
+
if (column.pinned === "left" && layout.leftOffsets.has(column.key)) {
|
|
1259
|
+
return { left: layout.leftOffsets.get(column.key) };
|
|
1260
|
+
}
|
|
1261
|
+
if (column.pinned === "right" && layout.rightOffsets.has(column.key)) {
|
|
1262
|
+
return { right: layout.rightOffsets.get(column.key) };
|
|
1263
|
+
}
|
|
1264
|
+
return void 0;
|
|
1265
|
+
};
|
|
1266
|
+
const pinnedClass = (column) => {
|
|
1267
|
+
const classes = [];
|
|
1268
|
+
if (column.pinned) {
|
|
1269
|
+
classes.push(pinnedCell);
|
|
1270
|
+
if (column.key === layout.lastLeftKey) classes.push(pinnedLeftEdge);
|
|
1271
|
+
if (column.key === layout.firstRightKey) classes.push(pinnedRightEdge);
|
|
1272
|
+
}
|
|
1273
|
+
return classes.join(" ");
|
|
1274
|
+
};
|
|
1275
|
+
const headerPinnedClass = (column) => {
|
|
1276
|
+
const classes = [];
|
|
1277
|
+
if (column.pinned) {
|
|
1278
|
+
classes.push(pinnedHeaderCell);
|
|
1279
|
+
if (column.key === layout.lastLeftKey) classes.push(pinnedLeftEdge);
|
|
1280
|
+
if (column.key === layout.firstRightKey) classes.push(pinnedRightEdge);
|
|
1281
|
+
}
|
|
1282
|
+
return classes.join(" ");
|
|
1283
|
+
};
|
|
1284
|
+
const startEditing = (rowData) => {
|
|
1285
|
+
const id = getRowId(rowData);
|
|
1286
|
+
const draft = {};
|
|
1287
|
+
for (const column of columns) {
|
|
1288
|
+
if (column.editable) {
|
|
1289
|
+
draft[column.key] = String(getCellValue(column, rowData) ?? "");
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
setEditDraft(draft);
|
|
1293
|
+
setEditingRowId(id);
|
|
1294
|
+
};
|
|
1295
|
+
const cancelEditing = () => {
|
|
1296
|
+
setEditingRowId(null);
|
|
1297
|
+
setEditDraft({});
|
|
1298
|
+
};
|
|
1299
|
+
const saveEditing = () => {
|
|
1300
|
+
if (editingRowId) {
|
|
1301
|
+
onRowEdit?.(editingRowId, editDraft);
|
|
1302
|
+
}
|
|
1303
|
+
setEditingRowId(null);
|
|
1304
|
+
setEditDraft({});
|
|
1305
|
+
};
|
|
1214
1306
|
const totalHeight = sortedData.length * rowHeight;
|
|
1215
1307
|
const visibleCount = Math.ceil(height / rowHeight) + overscan * 2;
|
|
1216
1308
|
const startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
|
|
1217
1309
|
const endIndex = Math.min(sortedData.length, startIndex + visibleCount);
|
|
1218
1310
|
const visibleRows = sortedData.slice(startIndex, endIndex);
|
|
1219
|
-
const totalWidth = (selectable ? CHECKBOX_COLUMN_WIDTH : 0) + columns.reduce((sum, c) => sum + (
|
|
1311
|
+
const totalWidth = (selectable ? CHECKBOX_COLUMN_WIDTH : 0) + (editingEnabled ? ACTIONS_COLUMN_WIDTH : 0) + columns.reduce((sum, c) => sum + widthOf(c), 0);
|
|
1220
1312
|
return /* @__PURE__ */ jsxs17(
|
|
1221
1313
|
"div",
|
|
1222
1314
|
{
|
|
@@ -1226,7 +1318,7 @@ function DataGrid({
|
|
|
1226
1318
|
role: "table",
|
|
1227
1319
|
children: [
|
|
1228
1320
|
/* @__PURE__ */ jsxs17("div", { className: headerRow, style: { width: totalWidth, minWidth: "100%" }, role: "row", children: [
|
|
1229
|
-
selectable ? /* @__PURE__ */ jsx34("div", { className: checkboxCell, role: "columnheader", children: /* @__PURE__ */ jsx34(
|
|
1321
|
+
selectable ? /* @__PURE__ */ jsx34("div", { className: [checkboxCell, pinnedHeaderCell].join(" "), style: { left: 0 }, role: "columnheader", children: /* @__PURE__ */ jsx34(
|
|
1230
1322
|
"input",
|
|
1231
1323
|
{
|
|
1232
1324
|
type: "checkbox",
|
|
@@ -1238,15 +1330,15 @@ function DataGrid({
|
|
|
1238
1330
|
"aria-label": "Select all rows"
|
|
1239
1331
|
}
|
|
1240
1332
|
) }) : null,
|
|
1241
|
-
|
|
1242
|
-
const width =
|
|
1333
|
+
layout.ordered.map((column) => {
|
|
1334
|
+
const width = widthOf(column);
|
|
1243
1335
|
const isSorted = sort?.key === column.key;
|
|
1244
1336
|
const direction2 = isSorted ? sort.direction : null;
|
|
1245
1337
|
return /* @__PURE__ */ jsxs17(
|
|
1246
1338
|
"div",
|
|
1247
1339
|
{
|
|
1248
|
-
className: headerCell,
|
|
1249
|
-
style: { width },
|
|
1340
|
+
className: [headerCell, headerPinnedClass(column)].filter(Boolean).join(" "),
|
|
1341
|
+
style: { width, ...pinnedStyle(column) },
|
|
1250
1342
|
role: "columnheader",
|
|
1251
1343
|
"aria-sort": direction2 === "asc" ? "ascending" : direction2 === "desc" ? "descending" : "none",
|
|
1252
1344
|
children: [
|
|
@@ -1270,34 +1362,108 @@ function DataGrid({
|
|
|
1270
1362
|
},
|
|
1271
1363
|
column.key
|
|
1272
1364
|
);
|
|
1273
|
-
})
|
|
1365
|
+
}),
|
|
1366
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1367
|
+
"div",
|
|
1368
|
+
{
|
|
1369
|
+
className: [actionsCell, pinnedHeaderCell].join(" "),
|
|
1370
|
+
style: { right: 0 },
|
|
1371
|
+
role: "columnheader",
|
|
1372
|
+
children: /* @__PURE__ */ jsx34("span", { className: srOnly2, children: "Actions" })
|
|
1373
|
+
}
|
|
1374
|
+
) : null
|
|
1274
1375
|
] }),
|
|
1275
1376
|
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
1377
|
const index = startIndex + i;
|
|
1277
1378
|
const id = getRowId(rowData);
|
|
1278
1379
|
const isSelected = selectedIds.has(id);
|
|
1380
|
+
const isEditing = editingRowId === id;
|
|
1279
1381
|
const style = { top: index * rowHeight, height: rowHeight, width: totalWidth };
|
|
1280
|
-
return /* @__PURE__ */ jsxs17(
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1382
|
+
return /* @__PURE__ */ jsxs17(
|
|
1383
|
+
"div",
|
|
1384
|
+
{
|
|
1385
|
+
className: row,
|
|
1386
|
+
style,
|
|
1387
|
+
role: "row",
|
|
1388
|
+
"data-selected": isSelected || void 0,
|
|
1389
|
+
"data-editing": isEditing || void 0,
|
|
1390
|
+
children: [
|
|
1391
|
+
selectable ? /* @__PURE__ */ jsx34("div", { className: [checkboxCell, pinnedCell].join(" "), style: { left: 0 }, role: "cell", children: /* @__PURE__ */ jsx34(
|
|
1392
|
+
"input",
|
|
1393
|
+
{
|
|
1394
|
+
type: "checkbox",
|
|
1395
|
+
checked: isSelected,
|
|
1396
|
+
onChange: () => toggleRow(id),
|
|
1397
|
+
"aria-label": `Select row ${index + 1}`
|
|
1398
|
+
}
|
|
1399
|
+
) }) : null,
|
|
1400
|
+
layout.ordered.map((column) => /* @__PURE__ */ jsx34(
|
|
1401
|
+
"div",
|
|
1402
|
+
{
|
|
1403
|
+
className: [cell, pinnedClass(column)].filter(Boolean).join(" "),
|
|
1404
|
+
style: { width: widthOf(column), ...pinnedStyle(column) },
|
|
1405
|
+
role: "cell",
|
|
1406
|
+
children: isEditing && column.editable ? /* @__PURE__ */ jsx34(
|
|
1407
|
+
"input",
|
|
1408
|
+
{
|
|
1409
|
+
type: "text",
|
|
1410
|
+
className: editInput,
|
|
1411
|
+
value: editDraft[column.key] ?? "",
|
|
1412
|
+
onChange: (e) => setEditDraft((prev) => ({ ...prev, [column.key]: e.target.value })),
|
|
1413
|
+
onKeyDown: (e) => {
|
|
1414
|
+
if (e.key === "Enter") saveEditing();
|
|
1415
|
+
if (e.key === "Escape") cancelEditing();
|
|
1416
|
+
},
|
|
1417
|
+
"aria-label": `Edit ${String(column.header)}`,
|
|
1418
|
+
autoFocus: column.key === columns.find((c) => c.editable)?.key
|
|
1419
|
+
}
|
|
1420
|
+
) : column.render ? column.render(rowData) : String(getCellValue(column, rowData) ?? "")
|
|
1421
|
+
},
|
|
1422
|
+
column.key
|
|
1423
|
+
)),
|
|
1424
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1425
|
+
"div",
|
|
1426
|
+
{
|
|
1427
|
+
className: [actionsCell, pinnedCell].join(" "),
|
|
1428
|
+
style: { right: 0 },
|
|
1429
|
+
role: "cell",
|
|
1430
|
+
children: isEditing ? /* @__PURE__ */ jsxs17(Fragment5, { children: [
|
|
1431
|
+
/* @__PURE__ */ jsx34(
|
|
1432
|
+
"button",
|
|
1433
|
+
{
|
|
1434
|
+
type: "button",
|
|
1435
|
+
className: iconButton,
|
|
1436
|
+
onClick: saveEditing,
|
|
1437
|
+
"aria-label": `Save row ${index + 1}`,
|
|
1438
|
+
children: "\u2713"
|
|
1439
|
+
}
|
|
1440
|
+
),
|
|
1441
|
+
/* @__PURE__ */ jsx34(
|
|
1442
|
+
"button",
|
|
1443
|
+
{
|
|
1444
|
+
type: "button",
|
|
1445
|
+
className: iconButton,
|
|
1446
|
+
onClick: cancelEditing,
|
|
1447
|
+
"aria-label": `Cancel editing row ${index + 1}`,
|
|
1448
|
+
children: "\u2715"
|
|
1449
|
+
}
|
|
1450
|
+
)
|
|
1451
|
+
] }) : /* @__PURE__ */ jsx34(
|
|
1452
|
+
"button",
|
|
1453
|
+
{
|
|
1454
|
+
type: "button",
|
|
1455
|
+
className: iconButton,
|
|
1456
|
+
onClick: () => startEditing(rowData),
|
|
1457
|
+
"aria-label": `Edit row ${index + 1}`,
|
|
1458
|
+
children: "\u270E"
|
|
1459
|
+
}
|
|
1460
|
+
)
|
|
1461
|
+
}
|
|
1462
|
+
) : null
|
|
1463
|
+
]
|
|
1464
|
+
},
|
|
1465
|
+
id
|
|
1466
|
+
);
|
|
1301
1467
|
}) })
|
|
1302
1468
|
]
|
|
1303
1469
|
}
|