bolt-table 0.1.13 → 0.1.14
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/README.md +228 -2
- package/dist/index.d.mts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +475 -149
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +475 -149
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -76,6 +76,10 @@ var PinOffIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgB
|
|
|
76
76
|
/* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "17", y2: "22" }),
|
|
77
77
|
/* @__PURE__ */ jsx("path", { d: "M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4" })
|
|
78
78
|
] });
|
|
79
|
+
var CopyIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase, style, className, children: [
|
|
80
|
+
/* @__PURE__ */ jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
|
|
81
|
+
/* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
|
|
82
|
+
] });
|
|
79
83
|
var EyeOffIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase, style, className, children: [
|
|
80
84
|
/* @__PURE__ */ jsx("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }),
|
|
81
85
|
/* @__PURE__ */ jsx("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }),
|
|
@@ -131,21 +135,49 @@ var DraggableHeader = React.memo(
|
|
|
131
135
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
132
136
|
}
|
|
133
137
|
}, [contextMenu]);
|
|
134
|
-
const
|
|
135
|
-
e.preventDefault();
|
|
136
|
-
e.stopPropagation();
|
|
138
|
+
const showContextMenuAt = (clientX, clientY) => {
|
|
137
139
|
const menuWidth = 160;
|
|
138
140
|
const menuHeight = 180;
|
|
139
|
-
let x =
|
|
140
|
-
let y =
|
|
141
|
-
if (x + menuWidth > window.innerWidth)
|
|
141
|
+
let x = clientX;
|
|
142
|
+
let y = clientY;
|
|
143
|
+
if (x + menuWidth > window.innerWidth)
|
|
142
144
|
x = window.innerWidth - menuWidth - 10;
|
|
143
|
-
|
|
144
|
-
if (y + menuHeight > window.innerHeight) {
|
|
145
|
+
if (y + menuHeight > window.innerHeight)
|
|
145
146
|
y = window.innerHeight - menuHeight - 10;
|
|
146
|
-
}
|
|
147
147
|
setContextMenu({ x, y });
|
|
148
148
|
};
|
|
149
|
+
const handleContextMenu = (e) => {
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
e.stopPropagation();
|
|
152
|
+
showContextMenuAt(e.clientX, e.clientY);
|
|
153
|
+
};
|
|
154
|
+
const longPressTimerRef = useRef(
|
|
155
|
+
null
|
|
156
|
+
);
|
|
157
|
+
const touchStartRef = useRef(null);
|
|
158
|
+
const cancelLongPress = () => {
|
|
159
|
+
if (longPressTimerRef.current) {
|
|
160
|
+
clearTimeout(longPressTimerRef.current);
|
|
161
|
+
longPressTimerRef.current = null;
|
|
162
|
+
}
|
|
163
|
+
touchStartRef.current = null;
|
|
164
|
+
};
|
|
165
|
+
const handleTouchStart = (e) => {
|
|
166
|
+
cancelLongPress();
|
|
167
|
+
const touch = e.touches[0];
|
|
168
|
+
touchStartRef.current = { x: touch.clientX, y: touch.clientY };
|
|
169
|
+
longPressTimerRef.current = setTimeout(() => {
|
|
170
|
+
longPressTimerRef.current = null;
|
|
171
|
+
showContextMenuAt(touch.clientX, touch.clientY);
|
|
172
|
+
}, 500);
|
|
173
|
+
};
|
|
174
|
+
const handleTouchMove = (e) => {
|
|
175
|
+
if (!touchStartRef.current) return;
|
|
176
|
+
const touch = e.touches[0];
|
|
177
|
+
const dx = touch.clientX - touchStartRef.current.x;
|
|
178
|
+
const dy = touch.clientY - touchStartRef.current.y;
|
|
179
|
+
if (Math.abs(dx) > 10 || Math.abs(dy) > 10) cancelLongPress();
|
|
180
|
+
};
|
|
149
181
|
const handleResizeStart = (e) => {
|
|
150
182
|
e.preventDefault();
|
|
151
183
|
e.stopPropagation();
|
|
@@ -195,6 +227,10 @@ var DraggableHeader = React.memo(
|
|
|
195
227
|
style: headerStyle,
|
|
196
228
|
className: `${column.className ?? ""} ${classNames?.header ?? ""} ${isPinned ? classNames?.pinnedHeader ?? "" : ""}`,
|
|
197
229
|
onContextMenu: handleContextMenu,
|
|
230
|
+
onTouchStart: handleTouchStart,
|
|
231
|
+
onTouchMove: handleTouchMove,
|
|
232
|
+
onTouchEnd: cancelLongPress,
|
|
233
|
+
onTouchCancel: cancelLongPress,
|
|
198
234
|
children: [
|
|
199
235
|
/* @__PURE__ */ jsxs2(
|
|
200
236
|
"div",
|
|
@@ -1076,6 +1112,8 @@ var TableBody = ({
|
|
|
1076
1112
|
"div",
|
|
1077
1113
|
{
|
|
1078
1114
|
"data-row-key": rowKey,
|
|
1115
|
+
"data-column-key": col.key,
|
|
1116
|
+
"data-bt-cell": "",
|
|
1079
1117
|
"data-selected": isSelected || void 0,
|
|
1080
1118
|
style: {
|
|
1081
1119
|
position: "absolute",
|
|
@@ -1190,85 +1228,100 @@ var TableBody = ({
|
|
|
1190
1228
|
style: {
|
|
1191
1229
|
gridColumn: "1 / -1",
|
|
1192
1230
|
gridRow: 2,
|
|
1193
|
-
|
|
1194
|
-
|
|
1231
|
+
height: `${totalSize}px`,
|
|
1232
|
+
position: "relative",
|
|
1195
1233
|
zIndex: 20,
|
|
1196
|
-
|
|
1234
|
+
pointerEvents: "none"
|
|
1197
1235
|
},
|
|
1198
|
-
children:
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
backgroundColor: pinnedRowBg,
|
|
1232
|
-
...isPinned && styles?.pinnedCell ? styles.pinnedCell : {}
|
|
1233
|
-
},
|
|
1234
|
-
children: /* @__PURE__ */ jsx4(
|
|
1236
|
+
children: /* @__PURE__ */ jsx4(
|
|
1237
|
+
"div",
|
|
1238
|
+
{
|
|
1239
|
+
style: {
|
|
1240
|
+
position: "sticky",
|
|
1241
|
+
top: headerHeight,
|
|
1242
|
+
pointerEvents: "auto",
|
|
1243
|
+
boxShadow: "0 2px 6px -1px rgba(0,0,0,0.08)"
|
|
1244
|
+
},
|
|
1245
|
+
children: pinnedTopData.map((row, rowIdx) => {
|
|
1246
|
+
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1247
|
+
const isSelected = selectedKeySet.has(rk);
|
|
1248
|
+
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1249
|
+
return /* @__PURE__ */ jsx4(
|
|
1250
|
+
"div",
|
|
1251
|
+
{
|
|
1252
|
+
className: classNames?.pinnedRow ?? "",
|
|
1253
|
+
style: {
|
|
1254
|
+
display: "grid",
|
|
1255
|
+
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1256
|
+
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1257
|
+
...styles?.pinnedRow
|
|
1258
|
+
},
|
|
1259
|
+
children: orderedColumns.map((col) => {
|
|
1260
|
+
const cellValue = row[col.dataIndex];
|
|
1261
|
+
const stickyOffset = columnOffsets.get(col.key);
|
|
1262
|
+
const isPinned = Boolean(col.pinned);
|
|
1263
|
+
let zIndex = 0;
|
|
1264
|
+
if (col.key === "__select__" || col.key === "__expand__")
|
|
1265
|
+
zIndex = 11;
|
|
1266
|
+
else if (isPinned) zIndex = 2;
|
|
1267
|
+
const recordFingerprint = col.render ? JSON.stringify(row) : void 0;
|
|
1268
|
+
return /* @__PURE__ */ jsx4(
|
|
1235
1269
|
"div",
|
|
1236
1270
|
{
|
|
1271
|
+
"data-row-key": rk,
|
|
1272
|
+
"data-column-key": col.key,
|
|
1273
|
+
"data-bt-cell": "",
|
|
1274
|
+
"data-selected": isSelected || void 0,
|
|
1237
1275
|
style: {
|
|
1238
|
-
|
|
1239
|
-
|
|
1276
|
+
position: isPinned ? "sticky" : "relative",
|
|
1277
|
+
...col.pinned === "left" && stickyOffset !== void 0 ? { left: `${stickyOffset}px` } : {},
|
|
1278
|
+
...col.pinned === "right" && stickyOffset !== void 0 ? { right: `${stickyOffset}px` } : {},
|
|
1279
|
+
zIndex,
|
|
1280
|
+
backgroundColor: pinnedRowBg,
|
|
1281
|
+
backdropFilter: "blur(12px)",
|
|
1282
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
1283
|
+
...isPinned && styles?.pinnedCell ? styles.pinnedCell : {}
|
|
1240
1284
|
},
|
|
1241
1285
|
children: /* @__PURE__ */ jsx4(
|
|
1242
|
-
|
|
1286
|
+
"div",
|
|
1243
1287
|
{
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1288
|
+
style: {
|
|
1289
|
+
height: `${rowHeight}px`,
|
|
1290
|
+
position: "relative"
|
|
1291
|
+
},
|
|
1292
|
+
children: /* @__PURE__ */ jsx4(
|
|
1293
|
+
Cell,
|
|
1294
|
+
{
|
|
1295
|
+
value: cellValue,
|
|
1296
|
+
record: row,
|
|
1297
|
+
column: col,
|
|
1298
|
+
rowIndex: rowIdx,
|
|
1299
|
+
classNames,
|
|
1300
|
+
styles,
|
|
1301
|
+
isSelected,
|
|
1302
|
+
isExpanded,
|
|
1303
|
+
rowSelection,
|
|
1304
|
+
normalizedSelectedKeys,
|
|
1305
|
+
rowKey: rk,
|
|
1306
|
+
allData: allDataForSelection,
|
|
1307
|
+
getRowKey,
|
|
1308
|
+
accentColor,
|
|
1309
|
+
isLoading: false,
|
|
1310
|
+
recordFingerprint
|
|
1311
|
+
}
|
|
1312
|
+
)
|
|
1260
1313
|
}
|
|
1261
1314
|
)
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1315
|
+
},
|
|
1316
|
+
col.key
|
|
1317
|
+
);
|
|
1318
|
+
})
|
|
1319
|
+
},
|
|
1320
|
+
`pinned-top-${rk}`
|
|
1321
|
+
);
|
|
1322
|
+
})
|
|
1323
|
+
}
|
|
1324
|
+
)
|
|
1272
1325
|
}
|
|
1273
1326
|
),
|
|
1274
1327
|
pinnedBottomData.length > 0 && /* @__PURE__ */ jsx4(
|
|
@@ -1277,86 +1330,103 @@ var TableBody = ({
|
|
|
1277
1330
|
style: {
|
|
1278
1331
|
gridColumn: "1 / -1",
|
|
1279
1332
|
gridRow: 2,
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
alignSelf: "end",
|
|
1333
|
+
height: `${totalSize}px`,
|
|
1334
|
+
position: "relative",
|
|
1283
1335
|
zIndex: 20,
|
|
1284
|
-
|
|
1336
|
+
pointerEvents: "none",
|
|
1337
|
+
display: "flex",
|
|
1338
|
+
flexDirection: "column"
|
|
1285
1339
|
},
|
|
1286
|
-
children:
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
...isPinned && styles?.pinnedCell ? styles.pinnedCell : {}
|
|
1321
|
-
},
|
|
1322
|
-
children: /* @__PURE__ */ jsx4(
|
|
1340
|
+
children: /* @__PURE__ */ jsx4(
|
|
1341
|
+
"div",
|
|
1342
|
+
{
|
|
1343
|
+
style: {
|
|
1344
|
+
marginTop: "auto",
|
|
1345
|
+
position: "sticky",
|
|
1346
|
+
bottom: 0,
|
|
1347
|
+
pointerEvents: "auto",
|
|
1348
|
+
boxShadow: "0 -2px 6px -1px rgba(0,0,0,0.08)"
|
|
1349
|
+
},
|
|
1350
|
+
children: pinnedBottomData.map((row, rowIdx) => {
|
|
1351
|
+
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1352
|
+
const isSelected = selectedKeySet.has(rk);
|
|
1353
|
+
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1354
|
+
return /* @__PURE__ */ jsx4(
|
|
1355
|
+
"div",
|
|
1356
|
+
{
|
|
1357
|
+
className: classNames?.pinnedRow ?? "",
|
|
1358
|
+
style: {
|
|
1359
|
+
display: "grid",
|
|
1360
|
+
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1361
|
+
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1362
|
+
...styles?.pinnedRow
|
|
1363
|
+
},
|
|
1364
|
+
children: orderedColumns.map((col) => {
|
|
1365
|
+
const cellValue = row[col.dataIndex];
|
|
1366
|
+
const stickyOffset = columnOffsets.get(col.key);
|
|
1367
|
+
const isPinned = Boolean(col.pinned);
|
|
1368
|
+
let zIndex = 0;
|
|
1369
|
+
if (col.key === "__select__" || col.key === "__expand__")
|
|
1370
|
+
zIndex = 11;
|
|
1371
|
+
else if (isPinned) zIndex = 2;
|
|
1372
|
+
const recordFingerprint = col.render ? JSON.stringify(row) : void 0;
|
|
1373
|
+
return /* @__PURE__ */ jsx4(
|
|
1323
1374
|
"div",
|
|
1324
1375
|
{
|
|
1376
|
+
"data-row-key": rk,
|
|
1377
|
+
"data-column-key": col.key,
|
|
1378
|
+
"data-bt-cell": "",
|
|
1379
|
+
"data-selected": isSelected || void 0,
|
|
1325
1380
|
style: {
|
|
1326
|
-
|
|
1327
|
-
|
|
1381
|
+
position: isPinned ? "sticky" : "relative",
|
|
1382
|
+
...col.pinned === "left" && stickyOffset !== void 0 ? { left: `${stickyOffset}px` } : {},
|
|
1383
|
+
...col.pinned === "right" && stickyOffset !== void 0 ? { right: `${stickyOffset}px` } : {},
|
|
1384
|
+
zIndex,
|
|
1385
|
+
backgroundColor: pinnedRowBg,
|
|
1386
|
+
backdropFilter: "blur(12px)",
|
|
1387
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
1388
|
+
...isPinned && styles?.pinnedCell ? styles.pinnedCell : {}
|
|
1328
1389
|
},
|
|
1329
1390
|
children: /* @__PURE__ */ jsx4(
|
|
1330
|
-
|
|
1391
|
+
"div",
|
|
1331
1392
|
{
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1393
|
+
style: {
|
|
1394
|
+
height: `${rowHeight}px`,
|
|
1395
|
+
position: "relative"
|
|
1396
|
+
},
|
|
1397
|
+
children: /* @__PURE__ */ jsx4(
|
|
1398
|
+
Cell,
|
|
1399
|
+
{
|
|
1400
|
+
value: cellValue,
|
|
1401
|
+
record: row,
|
|
1402
|
+
column: col,
|
|
1403
|
+
rowIndex: rowIdx,
|
|
1404
|
+
classNames,
|
|
1405
|
+
styles,
|
|
1406
|
+
isSelected,
|
|
1407
|
+
isExpanded,
|
|
1408
|
+
rowSelection,
|
|
1409
|
+
normalizedSelectedKeys,
|
|
1410
|
+
rowKey: rk,
|
|
1411
|
+
allData: allDataForSelection,
|
|
1412
|
+
getRowKey,
|
|
1413
|
+
accentColor,
|
|
1414
|
+
isLoading: false,
|
|
1415
|
+
recordFingerprint
|
|
1416
|
+
}
|
|
1417
|
+
)
|
|
1348
1418
|
}
|
|
1349
1419
|
)
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1420
|
+
},
|
|
1421
|
+
col.key
|
|
1422
|
+
);
|
|
1423
|
+
})
|
|
1424
|
+
},
|
|
1425
|
+
`pinned-bottom-${rk}`
|
|
1426
|
+
);
|
|
1427
|
+
})
|
|
1428
|
+
}
|
|
1429
|
+
)
|
|
1360
1430
|
}
|
|
1361
1431
|
)
|
|
1362
1432
|
] });
|
|
@@ -1394,6 +1464,7 @@ function BoltTable({
|
|
|
1394
1464
|
onColumnHide,
|
|
1395
1465
|
rowSelection,
|
|
1396
1466
|
rowPinning,
|
|
1467
|
+
onRowPin,
|
|
1397
1468
|
expandable,
|
|
1398
1469
|
rowKey = "id",
|
|
1399
1470
|
onEndReached,
|
|
@@ -1963,6 +2034,44 @@ function BoltTable({
|
|
|
1963
2034
|
}, [processedData, rowPinning, getRowKey]);
|
|
1964
2035
|
const pinnedTopHeight = pinnedTopRows.length * rowHeight;
|
|
1965
2036
|
const pinnedBottomHeight = pinnedBottomRows.length * rowHeight;
|
|
2037
|
+
const pinnedTopKeySet = useMemo2(
|
|
2038
|
+
() => new Set((rowPinning?.top ?? []).map(String)),
|
|
2039
|
+
[rowPinning?.top]
|
|
2040
|
+
);
|
|
2041
|
+
const pinnedBottomKeySet = useMemo2(
|
|
2042
|
+
() => new Set((rowPinning?.bottom ?? []).map(String)),
|
|
2043
|
+
[rowPinning?.bottom]
|
|
2044
|
+
);
|
|
2045
|
+
const [cellContextMenu, setCellContextMenu] = useState2(null);
|
|
2046
|
+
const cellMenuRef = useRef4(null);
|
|
2047
|
+
const cellLongPressTimer = useRef4(
|
|
2048
|
+
null
|
|
2049
|
+
);
|
|
2050
|
+
const cellTouchStart = useRef4(null);
|
|
2051
|
+
const cancelCellLongPress = useCallback(() => {
|
|
2052
|
+
if (cellLongPressTimer.current) {
|
|
2053
|
+
clearTimeout(cellLongPressTimer.current);
|
|
2054
|
+
cellLongPressTimer.current = null;
|
|
2055
|
+
}
|
|
2056
|
+
cellTouchStart.current = null;
|
|
2057
|
+
}, []);
|
|
2058
|
+
React4.useEffect(() => {
|
|
2059
|
+
if (!cellContextMenu) return;
|
|
2060
|
+
const close = (e) => {
|
|
2061
|
+
if (cellMenuRef.current && cellMenuRef.current.contains(e.target))
|
|
2062
|
+
return;
|
|
2063
|
+
setCellContextMenu(null);
|
|
2064
|
+
};
|
|
2065
|
+
const onKey = (e) => {
|
|
2066
|
+
if (e.key === "Escape") setCellContextMenu(null);
|
|
2067
|
+
};
|
|
2068
|
+
document.addEventListener("mousedown", close);
|
|
2069
|
+
document.addEventListener("keydown", onKey);
|
|
2070
|
+
return () => {
|
|
2071
|
+
document.removeEventListener("mousedown", close);
|
|
2072
|
+
document.removeEventListener("keydown", onKey);
|
|
2073
|
+
};
|
|
2074
|
+
}, [cellContextMenu]);
|
|
1966
2075
|
const columnFiltersKey = Object.keys(columnFilters).sort().map((k) => `${k}:${columnFilters[k]}`).join("|");
|
|
1967
2076
|
React4.useEffect(() => {
|
|
1968
2077
|
tableAreaRef.current?.scrollTo({ top: 0 });
|
|
@@ -2324,6 +2433,64 @@ function BoltTable({
|
|
|
2324
2433
|
position: "relative",
|
|
2325
2434
|
...isEmpty ? { height: "100%" } : {}
|
|
2326
2435
|
},
|
|
2436
|
+
onContextMenu: (e) => {
|
|
2437
|
+
const cell = e.target.closest("[data-bt-cell]");
|
|
2438
|
+
if (!cell) return;
|
|
2439
|
+
const rk = cell.dataset.rowKey;
|
|
2440
|
+
const ck = cell.dataset.columnKey;
|
|
2441
|
+
if (!rk || !ck) return;
|
|
2442
|
+
const col = freshOrderedColumns.find(
|
|
2443
|
+
(c) => c.key === ck
|
|
2444
|
+
);
|
|
2445
|
+
const hasCopy = col?.copy;
|
|
2446
|
+
const hasRowPin = !!onRowPin;
|
|
2447
|
+
if (!hasCopy && !hasRowPin) return;
|
|
2448
|
+
e.preventDefault();
|
|
2449
|
+
setCellContextMenu({
|
|
2450
|
+
x: Math.min(e.clientX, window.innerWidth - 200),
|
|
2451
|
+
y: Math.min(e.clientY, window.innerHeight - 200),
|
|
2452
|
+
rowKey: rk,
|
|
2453
|
+
columnKey: ck
|
|
2454
|
+
});
|
|
2455
|
+
},
|
|
2456
|
+
onTouchStart: (e) => {
|
|
2457
|
+
cancelCellLongPress();
|
|
2458
|
+
const cell = e.target.closest("[data-bt-cell]");
|
|
2459
|
+
if (!cell) return;
|
|
2460
|
+
const touch = e.touches[0];
|
|
2461
|
+
cellTouchStart.current = {
|
|
2462
|
+
x: touch.clientX,
|
|
2463
|
+
y: touch.clientY
|
|
2464
|
+
};
|
|
2465
|
+
const rk = cell.dataset.rowKey;
|
|
2466
|
+
const ck = cell.dataset.columnKey;
|
|
2467
|
+
cellLongPressTimer.current = setTimeout(() => {
|
|
2468
|
+
cellLongPressTimer.current = null;
|
|
2469
|
+
if (!rk || !ck) return;
|
|
2470
|
+
const col = freshOrderedColumns.find(
|
|
2471
|
+
(c) => c.key === ck
|
|
2472
|
+
);
|
|
2473
|
+
const hasCopy = col?.copy;
|
|
2474
|
+
const hasRowPin = !!onRowPin;
|
|
2475
|
+
if (!hasCopy && !hasRowPin) return;
|
|
2476
|
+
setCellContextMenu({
|
|
2477
|
+
x: Math.min(touch.clientX, window.innerWidth - 200),
|
|
2478
|
+
y: Math.min(touch.clientY, window.innerHeight - 200),
|
|
2479
|
+
rowKey: rk,
|
|
2480
|
+
columnKey: ck
|
|
2481
|
+
});
|
|
2482
|
+
}, 500);
|
|
2483
|
+
},
|
|
2484
|
+
onTouchMove: (e) => {
|
|
2485
|
+
if (!cellTouchStart.current) return;
|
|
2486
|
+
const touch = e.touches[0];
|
|
2487
|
+
const dx = touch.clientX - cellTouchStart.current.x;
|
|
2488
|
+
const dy = touch.clientY - cellTouchStart.current.y;
|
|
2489
|
+
if (Math.abs(dx) > 10 || Math.abs(dy) > 10)
|
|
2490
|
+
cancelCellLongPress();
|
|
2491
|
+
},
|
|
2492
|
+
onTouchEnd: cancelCellLongPress,
|
|
2493
|
+
onTouchCancel: cancelCellLongPress,
|
|
2327
2494
|
children: [
|
|
2328
2495
|
orderedColumns.map((column, visualIndex) => {
|
|
2329
2496
|
if (column.key === "__select__" && rowSelection) {
|
|
@@ -2822,7 +2989,166 @@ function BoltTable({
|
|
|
2822
2989
|
}
|
|
2823
2990
|
),
|
|
2824
2991
|
document.body
|
|
2825
|
-
)
|
|
2992
|
+
),
|
|
2993
|
+
cellContextMenu && typeof document !== "undefined" && (() => {
|
|
2994
|
+
const menuCol = freshOrderedColumns.find(
|
|
2995
|
+
(c) => c.key === cellContextMenu.columnKey
|
|
2996
|
+
);
|
|
2997
|
+
const isPinnedTop = pinnedTopKeySet.has(cellContextMenu.rowKey);
|
|
2998
|
+
const isPinnedBottom = pinnedBottomKeySet.has(
|
|
2999
|
+
cellContextMenu.rowKey
|
|
3000
|
+
);
|
|
3001
|
+
const hasCopy = menuCol?.copy;
|
|
3002
|
+
const hasRowPin = !!onRowPin;
|
|
3003
|
+
let menuRecord;
|
|
3004
|
+
let menuRowIndex = 0;
|
|
3005
|
+
const allRows = [
|
|
3006
|
+
...pinnedTopRows,
|
|
3007
|
+
...displayData,
|
|
3008
|
+
...pinnedBottomRows
|
|
3009
|
+
];
|
|
3010
|
+
for (let i = 0; i < allRows.length; i++) {
|
|
3011
|
+
const rk = getRowKey(allRows[i], i);
|
|
3012
|
+
if (rk === cellContextMenu.rowKey) {
|
|
3013
|
+
menuRecord = allRows[i];
|
|
3014
|
+
menuRowIndex = i;
|
|
3015
|
+
break;
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
const menuValue = menuRecord && menuCol ? menuRecord[menuCol.dataIndex] : void 0;
|
|
3019
|
+
const btnStyle = {
|
|
3020
|
+
display: "flex",
|
|
3021
|
+
width: "100%",
|
|
3022
|
+
alignItems: "center",
|
|
3023
|
+
gap: 8,
|
|
3024
|
+
background: "none",
|
|
3025
|
+
border: "none",
|
|
3026
|
+
padding: "6px 12px",
|
|
3027
|
+
fontSize: 12,
|
|
3028
|
+
cursor: "pointer",
|
|
3029
|
+
color: "inherit",
|
|
3030
|
+
whiteSpace: "nowrap"
|
|
3031
|
+
};
|
|
3032
|
+
return createPortal2(
|
|
3033
|
+
/* @__PURE__ */ jsxs5(
|
|
3034
|
+
"div",
|
|
3035
|
+
{
|
|
3036
|
+
ref: cellMenuRef,
|
|
3037
|
+
style: {
|
|
3038
|
+
position: "fixed",
|
|
3039
|
+
top: cellContextMenu.y,
|
|
3040
|
+
left: cellContextMenu.x,
|
|
3041
|
+
zIndex: 99999,
|
|
3042
|
+
minWidth: 170,
|
|
3043
|
+
borderRadius: 8,
|
|
3044
|
+
border: "1px solid rgba(128,128,128,0.2)",
|
|
3045
|
+
boxShadow: "0 4px 24px rgba(0,0,0,0.12)",
|
|
3046
|
+
backdropFilter: "blur(16px)",
|
|
3047
|
+
WebkitBackdropFilter: "blur(16px)",
|
|
3048
|
+
backgroundColor: "rgba(128,128,128,0.08)",
|
|
3049
|
+
padding: "4px 0",
|
|
3050
|
+
fontSize: 10
|
|
3051
|
+
},
|
|
3052
|
+
children: [
|
|
3053
|
+
hasRowPin && /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
3054
|
+
/* @__PURE__ */ jsxs5(
|
|
3055
|
+
"button",
|
|
3056
|
+
{
|
|
3057
|
+
"data-bt-ctx-item": true,
|
|
3058
|
+
style: btnStyle,
|
|
3059
|
+
onClick: () => {
|
|
3060
|
+
onRowPin(
|
|
3061
|
+
cellContextMenu.rowKey,
|
|
3062
|
+
isPinnedTop ? false : "top"
|
|
3063
|
+
);
|
|
3064
|
+
setCellContextMenu(null);
|
|
3065
|
+
},
|
|
3066
|
+
children: [
|
|
3067
|
+
isPinnedTop ? icons?.pinOff ?? /* @__PURE__ */ jsx5(
|
|
3068
|
+
PinOffIcon,
|
|
3069
|
+
{
|
|
3070
|
+
style: { width: 14, height: 14, flexShrink: 0 }
|
|
3071
|
+
}
|
|
3072
|
+
) : icons?.pin ?? /* @__PURE__ */ jsx5(
|
|
3073
|
+
PinIcon,
|
|
3074
|
+
{
|
|
3075
|
+
style: { width: 14, height: 14, flexShrink: 0 }
|
|
3076
|
+
}
|
|
3077
|
+
),
|
|
3078
|
+
isPinnedTop ? "Unpin Row from Top" : "Pin Row to Top"
|
|
3079
|
+
]
|
|
3080
|
+
}
|
|
3081
|
+
),
|
|
3082
|
+
/* @__PURE__ */ jsxs5(
|
|
3083
|
+
"button",
|
|
3084
|
+
{
|
|
3085
|
+
"data-bt-ctx-item": true,
|
|
3086
|
+
style: btnStyle,
|
|
3087
|
+
onClick: () => {
|
|
3088
|
+
onRowPin(
|
|
3089
|
+
cellContextMenu.rowKey,
|
|
3090
|
+
isPinnedBottom ? false : "bottom"
|
|
3091
|
+
);
|
|
3092
|
+
setCellContextMenu(null);
|
|
3093
|
+
},
|
|
3094
|
+
children: [
|
|
3095
|
+
isPinnedBottom ? icons?.pinOff ?? /* @__PURE__ */ jsx5(
|
|
3096
|
+
PinOffIcon,
|
|
3097
|
+
{
|
|
3098
|
+
style: { width: 14, height: 14, flexShrink: 0 }
|
|
3099
|
+
}
|
|
3100
|
+
) : icons?.pin ?? /* @__PURE__ */ jsx5(
|
|
3101
|
+
PinIcon,
|
|
3102
|
+
{
|
|
3103
|
+
style: {
|
|
3104
|
+
width: 14,
|
|
3105
|
+
height: 14,
|
|
3106
|
+
flexShrink: 0,
|
|
3107
|
+
transform: "rotate(180deg)"
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
),
|
|
3111
|
+
isPinnedBottom ? "Unpin Row from Bottom" : "Pin Row to Bottom"
|
|
3112
|
+
]
|
|
3113
|
+
}
|
|
3114
|
+
)
|
|
3115
|
+
] }),
|
|
3116
|
+
hasRowPin && hasCopy && /* @__PURE__ */ jsx5(
|
|
3117
|
+
"div",
|
|
3118
|
+
{
|
|
3119
|
+
style: {
|
|
3120
|
+
borderTop: "1px solid rgba(128,128,128,0.2)",
|
|
3121
|
+
margin: "4px 0"
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
),
|
|
3125
|
+
hasCopy && menuRecord && menuCol && /* @__PURE__ */ jsxs5(
|
|
3126
|
+
"button",
|
|
3127
|
+
{
|
|
3128
|
+
"data-bt-ctx-item": true,
|
|
3129
|
+
style: btnStyle,
|
|
3130
|
+
onClick: () => {
|
|
3131
|
+
const text = typeof menuCol.copy === "function" ? menuCol.copy(menuValue, menuRecord, menuRowIndex) : String(menuValue ?? "");
|
|
3132
|
+
navigator.clipboard?.writeText(text);
|
|
3133
|
+
setCellContextMenu(null);
|
|
3134
|
+
},
|
|
3135
|
+
children: [
|
|
3136
|
+
icons?.copy ?? /* @__PURE__ */ jsx5(
|
|
3137
|
+
CopyIcon,
|
|
3138
|
+
{
|
|
3139
|
+
style: { width: 14, height: 14, flexShrink: 0 }
|
|
3140
|
+
}
|
|
3141
|
+
),
|
|
3142
|
+
"Copy"
|
|
3143
|
+
]
|
|
3144
|
+
}
|
|
3145
|
+
)
|
|
3146
|
+
]
|
|
3147
|
+
}
|
|
3148
|
+
),
|
|
3149
|
+
document.body
|
|
3150
|
+
);
|
|
3151
|
+
})()
|
|
2826
3152
|
] });
|
|
2827
3153
|
}
|
|
2828
3154
|
export {
|