bolt-table 0.1.23 → 0.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -114,6 +114,10 @@ var CopyIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.
114
114
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }),
115
115
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
116
116
  ] });
117
+ var PencilIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgBase, style, className, children: [
118
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" }),
119
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m15 5 4 4" })
120
+ ] });
117
121
  var EyeOffIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgBase, style, className, children: [
118
122
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }),
119
123
  /* @__PURE__ */ (0, import_jsx_runtime.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" }),
@@ -151,7 +155,11 @@ var DraggableHeader = import_react.default.memo(
151
155
  customContextMenuItems,
152
156
  icons,
153
157
  onColumnDragStart,
154
- disabledFilters
158
+ disabledFilters,
159
+ headerGridRow = 1,
160
+ headerHeight = 36,
161
+ stickyTop = 0,
162
+ isFirstColumn = false
155
163
  }) => {
156
164
  const effectivelySortable = isColumnSortable(column);
157
165
  const effectivelyFilterable = !disabledFilters && isColumnFilterable(column);
@@ -225,23 +233,23 @@ var DraggableHeader = import_react.default.memo(
225
233
  const zIndex = isPinned ? 12 : 10;
226
234
  const headerStyle = {
227
235
  position: "sticky",
228
- top: 0,
236
+ top: stickyTop,
229
237
  zIndex,
230
238
  width: isLastColumn ? "100%" : widthPx,
231
239
  minWidth: widthPx,
232
240
  ...isLastColumn ? {} : { maxWidth: widthPx },
233
241
  gridColumn: visualIndex + 1,
234
- gridRow: 1,
242
+ gridRow: headerGridRow,
235
243
  display: "flex",
236
- height: 36,
244
+ height: headerHeight,
237
245
  alignItems: "center",
238
246
  overflow: "hidden",
239
247
  textOverflow: "ellipsis",
240
248
  whiteSpace: "nowrap",
241
249
  borderTop: "none",
242
- borderRight: "none",
250
+ borderRight: "0.5px solid rgba(128,128,128,0.2)",
243
251
  borderBottom: "1px solid rgba(128,128,128,0.2)",
244
- borderLeft: "none",
252
+ borderLeft: isFirstColumn ? "none" : "0.5px solid rgba(128,128,128,0.2)",
245
253
  ...column.pinned === "left" && stickyOffset !== void 0 ? { left: `${stickyOffset}px` } : {},
246
254
  ...column.pinned === "right" && stickyOffset !== void 0 ? { right: `${stickyOffset}px` } : {},
247
255
  ...column.style,
@@ -288,7 +296,7 @@ var DraggableHeader = import_react.default.memo(
288
296
  whiteSpace: "nowrap",
289
297
  paddingLeft: 8,
290
298
  paddingRight: 8,
291
- borderLeft: "1px solid rgba(128,128,128,0.2)",
299
+ borderLeft: isFirstColumn ? "none" : "1px solid rgba(128,128,128,0.2)",
292
300
  fontWeight: 500,
293
301
  cursor: isPinned ? "default" : "grab"
294
302
  },
@@ -323,6 +331,7 @@ var DraggableHeader = import_react.default.memo(
323
331
  isPinned && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
324
332
  "button",
325
333
  {
334
+ type: "button",
326
335
  style: {
327
336
  position: "relative",
328
337
  height: "100%",
@@ -350,6 +359,7 @@ var DraggableHeader = import_react.default.memo(
350
359
  !isPinned && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
351
360
  "button",
352
361
  {
362
+ type: "button",
353
363
  "data-bt-resize": "",
354
364
  style: {
355
365
  position: "relative",
@@ -428,6 +438,7 @@ var DraggableHeader = import_react.default.memo(
428
438
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
429
439
  "button",
430
440
  {
441
+ type: "button",
431
442
  "data-bt-ctx-item": "",
432
443
  style: {
433
444
  ...ctxItemBase,
@@ -447,6 +458,7 @@ var DraggableHeader = import_react.default.memo(
447
458
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
448
459
  "button",
449
460
  {
461
+ type: "button",
450
462
  "data-bt-ctx-item": "",
451
463
  style: {
452
464
  ...ctxItemBase,
@@ -504,6 +516,7 @@ var DraggableHeader = import_react.default.memo(
504
516
  ) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
505
517
  "button",
506
518
  {
519
+ type: "button",
507
520
  "data-bt-ctx-item": "",
508
521
  style: ctxItemBase,
509
522
  onClick: () => {
@@ -518,6 +531,7 @@ var DraggableHeader = import_react.default.memo(
518
531
  filterValue && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
519
532
  "button",
520
533
  {
534
+ type: "button",
521
535
  "data-bt-ctx-item": "",
522
536
  style: {
523
537
  ...ctxItemBase,
@@ -539,6 +553,7 @@ var DraggableHeader = import_react.default.memo(
539
553
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
540
554
  "button",
541
555
  {
556
+ type: "button",
542
557
  "data-bt-ctx-item": "",
543
558
  style: ctxItemBase,
544
559
  onClick: () => {
@@ -557,6 +572,7 @@ var DraggableHeader = import_react.default.memo(
557
572
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
558
573
  "button",
559
574
  {
575
+ type: "button",
560
576
  "data-bt-ctx-item": "",
561
577
  style: ctxItemBase,
562
578
  onClick: () => {
@@ -577,6 +593,7 @@ var DraggableHeader = import_react.default.memo(
577
593
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
578
594
  "button",
579
595
  {
596
+ type: "button",
580
597
  "data-bt-ctx-item": "",
581
598
  style: ctxItemBase,
582
599
  onClick: () => {
@@ -595,6 +612,7 @@ var DraggableHeader = import_react.default.memo(
595
612
  customContextMenuItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
596
613
  "button",
597
614
  {
615
+ type: "button",
598
616
  "data-bt-ctx-item": "",
599
617
  disabled: item.disabled,
600
618
  style: {
@@ -635,7 +653,7 @@ var DraggableHeader = import_react.default.memo(
635
653
  ] });
636
654
  },
637
655
  (prevProps, nextProps) => {
638
- return prevProps.column.width === nextProps.column.width && prevProps.column.key === nextProps.column.key && prevProps.column.pinned === nextProps.column.pinned && prevProps.column.sortable === nextProps.column.sortable && prevProps.column.filterable === nextProps.column.filterable && prevProps.column.sorter === nextProps.column.sorter && prevProps.column.filterFn === nextProps.column.filterFn && prevProps.visualIndex === nextProps.visualIndex && prevProps.stickyOffset === nextProps.stickyOffset && prevProps.isLastColumn === nextProps.isLastColumn && prevProps.sortDirection === nextProps.sortDirection && prevProps.filterValue === nextProps.filterValue && prevProps.classNames === nextProps.classNames && prevProps.styles === nextProps.styles && prevProps.customContextMenuItems === nextProps.customContextMenuItems && prevProps.disabledFilters === nextProps.disabledFilters;
656
+ return prevProps.column.width === nextProps.column.width && prevProps.column.key === nextProps.column.key && prevProps.column.pinned === nextProps.column.pinned && prevProps.column.sortable === nextProps.column.sortable && prevProps.column.filterable === nextProps.column.filterable && prevProps.column.sorter === nextProps.column.sorter && prevProps.column.filterFn === nextProps.column.filterFn && prevProps.visualIndex === nextProps.visualIndex && prevProps.stickyOffset === nextProps.stickyOffset && prevProps.isLastColumn === nextProps.isLastColumn && prevProps.sortDirection === nextProps.sortDirection && prevProps.filterValue === nextProps.filterValue && prevProps.classNames === nextProps.classNames && prevProps.styles === nextProps.styles && prevProps.customContextMenuItems === nextProps.customContextMenuItems && prevProps.disabledFilters === nextProps.disabledFilters && prevProps.headerGridRow === nextProps.headerGridRow && prevProps.headerHeight === nextProps.headerHeight && prevProps.stickyTop === nextProps.stickyTop && prevProps.isFirstColumn === nextProps.isFirstColumn;
639
657
  }
640
658
  );
641
659
  DraggableHeader.displayName = "DraggableHeader";
@@ -781,6 +799,61 @@ var ResizeOverlay_default = ResizeOverlay;
781
799
  var import_react3 = __toESM(require("react"));
782
800
  var import_jsx_runtime4 = require("react/jsx-runtime");
783
801
  var SHIMMER_WIDTHS = [55, 70, 45, 80, 60, 50, 75, 65];
802
+ var EditableCell = ({
803
+ value,
804
+ record,
805
+ column,
806
+ rowIndex,
807
+ onEdit,
808
+ onEditComplete
809
+ }) => {
810
+ const [draft, setDraft] = (0, import_react3.useState)(String(value ?? ""));
811
+ const inputRef = (0, import_react3.useRef)(null);
812
+ (0, import_react3.useEffect)(() => {
813
+ setDraft(String(value ?? ""));
814
+ requestAnimationFrame(() => {
815
+ inputRef.current?.focus();
816
+ inputRef.current?.select();
817
+ });
818
+ }, [value]);
819
+ const commit = (0, import_react3.useCallback)(() => {
820
+ const raw = String(value ?? "");
821
+ if (draft !== raw && column.dataIndex) {
822
+ const coerced = typeof value === "number" && !Number.isNaN(Number(draft)) ? Number(draft) : draft;
823
+ onEdit(coerced, record, column.dataIndex, rowIndex);
824
+ }
825
+ onEditComplete();
826
+ }, [draft, value, column.dataIndex, record, rowIndex, onEdit, onEditComplete]);
827
+ const cancel = (0, import_react3.useCallback)(() => {
828
+ onEditComplete();
829
+ }, [onEditComplete]);
830
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
831
+ "input",
832
+ {
833
+ ref: inputRef,
834
+ value: draft,
835
+ onChange: (e) => setDraft(e.target.value),
836
+ onBlur: commit,
837
+ onKeyDown: (e) => {
838
+ if (e.key === "Enter") commit();
839
+ if (e.key === "Escape") cancel();
840
+ },
841
+ style: {
842
+ width: "100%",
843
+ height: "100%",
844
+ border: "none",
845
+ outline: "none",
846
+ background: "transparent",
847
+ font: "inherit",
848
+ color: "inherit",
849
+ padding: 0,
850
+ margin: 0,
851
+ boxSizing: "border-box"
852
+ }
853
+ }
854
+ );
855
+ };
856
+ EditableCell.displayName = "EditableCell";
784
857
  var Cell = import_react3.default.memo(
785
858
  ({
786
859
  value,
@@ -796,7 +869,10 @@ var Cell = import_react3.default.memo(
796
869
  getRowKey,
797
870
  getRawRowKey,
798
871
  accentColor,
799
- isLoading
872
+ isLoading,
873
+ onEdit,
874
+ isEditing,
875
+ onEditComplete
800
876
  }) => {
801
877
  const isPinned = Boolean(column.pinned);
802
878
  if (isLoading && column.key !== "__select__" && column.key !== "__expand__") {
@@ -875,7 +951,7 @@ var Cell = import_react3.default.memo(
875
951
  type: "multiple"
876
952
  });
877
953
  },
878
- style: { cursor: "pointer", accentColor }
954
+ style: { cursor: "pointer", accentColor, colorScheme: "light dark" }
879
955
  }
880
956
  );
881
957
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -900,8 +976,22 @@ var Cell = import_react3.default.memo(
900
976
  }
901
977
  );
902
978
  }
979
+ const isEditable = !!column.editable && !column.render && !!onEdit;
980
+ const showEditor = isEditable && isEditing && onEditComplete;
903
981
  let content;
904
- if (column.render) {
982
+ if (showEditor) {
983
+ content = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
984
+ EditableCell,
985
+ {
986
+ value,
987
+ record,
988
+ column,
989
+ rowIndex,
990
+ onEdit,
991
+ onEditComplete
992
+ }
993
+ );
994
+ } else if (column.render) {
905
995
  try {
906
996
  content = column.render(value, record, rowIndex);
907
997
  } catch {
@@ -930,7 +1020,7 @@ var Cell = import_react3.default.memo(
930
1020
  ...isPinned ? styles?.pinnedCell : void 0,
931
1021
  ...styles?.cell
932
1022
  },
933
- children: isSystem ? content : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1023
+ children: isSystem ? content : showEditor ? content : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
934
1024
  "div",
935
1025
  {
936
1026
  style: {
@@ -951,6 +1041,10 @@ var Cell = import_react3.default.memo(
951
1041
  if (prev.column.pinned !== next.column.pinned) return false;
952
1042
  if (prev.classNames !== next.classNames) return false;
953
1043
  if (prev.styles !== next.styles) return false;
1044
+ if (prev.column.editable !== next.column.editable) return false;
1045
+ if (prev.onEdit !== next.onEdit) return false;
1046
+ if (prev.isEditing !== next.isEditing) return false;
1047
+ if (prev.onEditComplete !== next.onEditComplete) return false;
954
1048
  if (prev.column.key === "__select__") {
955
1049
  return prev.isSelected === next.isSelected && prev.normalizedSelectedKeys === next.normalizedSelectedKeys;
956
1050
  }
@@ -1018,7 +1112,11 @@ var TableBody = ({
1018
1112
  gridTemplateColumns,
1019
1113
  headerHeight = 36,
1020
1114
  rowClassName,
1021
- rowStyle
1115
+ rowStyle,
1116
+ bodyGridRow = 2,
1117
+ onEdit,
1118
+ editingCell,
1119
+ onEditComplete
1022
1120
  }) => {
1023
1121
  const virtualItems = rowVirtualizer.getVirtualItems();
1024
1122
  const totalSize = rowVirtualizer.getTotalSize();
@@ -1040,7 +1138,7 @@ var TableBody = ({
1040
1138
  else if (isPinned) zIndex = 2;
1041
1139
  const style = {
1042
1140
  gridColumn: colIndex + 1,
1043
- gridRow: 2,
1141
+ gridRow: bodyGridRow,
1044
1142
  height: `${totalSize}px`,
1045
1143
  position: isPinned ? "sticky" : "relative",
1046
1144
  zIndex
@@ -1054,7 +1152,7 @@ var TableBody = ({
1054
1152
  }
1055
1153
  return { key: col.key, style, isPinned };
1056
1154
  });
1057
- }, [safeColumns, columnOffsets, totalSize, styles]);
1155
+ }, [safeColumns, columnOffsets, totalSize, styles, bodyGridRow]);
1058
1156
  if (safeData.length === 0 || safeColumns.length === 0) return null;
1059
1157
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1060
1158
  columnStyles.map((colStyle, colIndex) => {
@@ -1072,7 +1170,7 @@ var TableBody = ({
1072
1170
  const rowKey = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
1073
1171
  const isSelected = selectedKeySet.has(rowKey);
1074
1172
  const isExpanded = resolvedExpandedKeys?.has(rowKey) ?? false;
1075
- const cellValue = row[col.dataIndex];
1173
+ const cellValue = col.dataIndex != null ? row[col.dataIndex] : void 0;
1076
1174
  const isRowShimmer = isLoading || rowKey.startsWith("__shimmer_");
1077
1175
  let recordFingerprint;
1078
1176
  if (hasRender && !isRowShimmer) {
@@ -1134,7 +1232,10 @@ var TableBody = ({
1134
1232
  getRawRowKey,
1135
1233
  accentColor,
1136
1234
  isLoading: isRowShimmer,
1137
- recordFingerprint
1235
+ recordFingerprint,
1236
+ onEdit,
1237
+ isEditing: editingCell?.rowKey === rowKey && editingCell?.columnKey === col.key,
1238
+ onEditComplete
1138
1239
  }
1139
1240
  )
1140
1241
  }
@@ -1152,7 +1253,7 @@ var TableBody = ({
1152
1253
  {
1153
1254
  style: {
1154
1255
  gridColumn: "1 / -1",
1155
- gridRow: 2,
1256
+ gridRow: bodyGridRow,
1156
1257
  height: `${totalSize}px`,
1157
1258
  position: "relative",
1158
1259
  zIndex: 15,
@@ -1216,7 +1317,7 @@ var TableBody = ({
1216
1317
  {
1217
1318
  style: {
1218
1319
  gridColumn: "1 / -1",
1219
- gridRow: 2,
1320
+ gridRow: bodyGridRow,
1220
1321
  height: `${totalSize}px`,
1221
1322
  position: "relative",
1222
1323
  zIndex: 20,
@@ -1258,7 +1359,7 @@ var TableBody = ({
1258
1359
  ...rowSty
1259
1360
  },
1260
1361
  children: safeColumns.map((col) => {
1261
- const cellValue = row[col.dataIndex];
1362
+ const cellValue = col.dataIndex != null ? row[col.dataIndex] : void 0;
1262
1363
  const stickyOffset = columnOffsets.get(col.key);
1263
1364
  const isPinned = Boolean(col.pinned);
1264
1365
  let zIndex = 0;
@@ -1316,7 +1417,10 @@ var TableBody = ({
1316
1417
  getRawRowKey,
1317
1418
  accentColor,
1318
1419
  isLoading: false,
1319
- recordFingerprint
1420
+ recordFingerprint,
1421
+ onEdit,
1422
+ isEditing: editingCell?.rowKey === rk && editingCell?.columnKey === col.key,
1423
+ onEditComplete
1320
1424
  }
1321
1425
  )
1322
1426
  }
@@ -1338,7 +1442,7 @@ var TableBody = ({
1338
1442
  {
1339
1443
  style: {
1340
1444
  gridColumn: "1 / -1",
1341
- gridRow: 2,
1445
+ gridRow: bodyGridRow,
1342
1446
  height: `${totalSize}px`,
1343
1447
  position: "relative",
1344
1448
  zIndex: 20,
@@ -1383,7 +1487,7 @@ var TableBody = ({
1383
1487
  ...rowSty
1384
1488
  },
1385
1489
  children: safeColumns.map((col) => {
1386
- const cellValue = row[col.dataIndex];
1490
+ const cellValue = col.dataIndex != null ? row[col.dataIndex] : void 0;
1387
1491
  const stickyOffset = columnOffsets.get(col.key);
1388
1492
  const isPinned = Boolean(col.pinned);
1389
1493
  let zIndex = 0;
@@ -1441,7 +1545,10 @@ var TableBody = ({
1441
1545
  getRawRowKey,
1442
1546
  accentColor,
1443
1547
  isLoading: false,
1444
- recordFingerprint
1548
+ recordFingerprint,
1549
+ onEdit,
1550
+ isEditing: editingCell?.rowKey === rk && editingCell?.columnKey === col.key,
1551
+ onEditComplete
1445
1552
  }
1446
1553
  )
1447
1554
  }
@@ -1471,6 +1578,18 @@ function arrayMove(arr, from, to) {
1471
1578
  result.splice(to, 0, item);
1472
1579
  return result;
1473
1580
  }
1581
+ function flattenColumns(columns) {
1582
+ const result = [];
1583
+ for (const col of columns) {
1584
+ if (col == null) continue;
1585
+ if (col.children && col.children.length > 0) {
1586
+ result.push(...flattenColumns(col.children));
1587
+ } else {
1588
+ result.push(col);
1589
+ }
1590
+ }
1591
+ return result;
1592
+ }
1474
1593
  var SHIMMER_WIDTHS2 = [55, 70, 45, 80, 60, 50, 75, 65, 40, 72];
1475
1594
  var EMPTY_CLASSNAMES = {};
1476
1595
  var EMPTY_STYLES = {};
@@ -1513,7 +1632,9 @@ function BoltTable({
1513
1632
  rowStyle,
1514
1633
  disabledFilters,
1515
1634
  onCopy,
1516
- keepPinnedRowsAcrossPages
1635
+ keepPinnedRowsAcrossPages,
1636
+ onEdit,
1637
+ onRowClick
1517
1638
  }) {
1518
1639
  const data = (0, import_react4.useMemo)(() => {
1519
1640
  if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
@@ -1522,11 +1643,43 @@ function BoltTable({
1522
1643
  }, [rawData]);
1523
1644
  const initialColumns = (0, import_react4.useMemo)(() => {
1524
1645
  if (!Array.isArray(rawInitialColumns)) return STABLE_EMPTY_COLS;
1525
- const filtered = rawInitialColumns.filter(
1646
+ const safe = rawInitialColumns.filter(
1647
+ (col) => col != null && typeof col.key === "string"
1648
+ );
1649
+ const flattened = flattenColumns(safe);
1650
+ const validated = flattened.filter(
1526
1651
  (col) => col != null && typeof col.key === "string"
1527
1652
  );
1528
- return filtered.length > 0 ? filtered : STABLE_EMPTY_COLS;
1653
+ return validated.length > 0 ? validated : STABLE_EMPTY_COLS;
1529
1654
  }, [rawInitialColumns]);
1655
+ const headerGroups = (0, import_react4.useMemo)(() => {
1656
+ if (!Array.isArray(rawInitialColumns)) return [];
1657
+ const groups = [];
1658
+ for (const col of rawInitialColumns) {
1659
+ if (col != null && typeof col.key === "string" && col.children && col.children.length > 0) {
1660
+ const leafKeys = flattenColumns([col]).filter((c) => c != null && typeof c.key === "string").map((c) => c.key);
1661
+ if (leafKeys.length > 0) {
1662
+ groups.push({
1663
+ key: col.key,
1664
+ title: col.title,
1665
+ childKeys: leafKeys,
1666
+ style: col.style,
1667
+ className: col.className
1668
+ });
1669
+ }
1670
+ }
1671
+ }
1672
+ return groups;
1673
+ }, [rawInitialColumns]);
1674
+ const hasColumnGroups = headerGroups.length > 0;
1675
+ const groupedColumnKeySet = (0, import_react4.useMemo)(() => {
1676
+ if (!hasColumnGroups) return null;
1677
+ const keys = /* @__PURE__ */ new Set();
1678
+ for (const g of headerGroups) {
1679
+ for (const k of g.childKeys) keys.add(k);
1680
+ }
1681
+ return keys;
1682
+ }, [headerGroups, hasColumnGroups]);
1530
1683
  const [columns, setColumns] = (0, import_react4.useState)(initialColumns);
1531
1684
  const [columnOrder, setColumnOrder] = (0, import_react4.useState)(
1532
1685
  () => initialColumns.map((c) => c.key)
@@ -1680,6 +1833,7 @@ function BoltTable({
1680
1833
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1681
1834
  "button",
1682
1835
  {
1836
+ type: "button",
1683
1837
  onClick: (e) => {
1684
1838
  e.stopPropagation();
1685
1839
  toggleExpandRef.current(key);
@@ -1779,6 +1933,17 @@ function BoltTable({
1779
1933
  };
1780
1934
  }, []);
1781
1935
  const resizeStateRef = (0, import_react4.useRef)(null);
1936
+ const columnGroupMapRef = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
1937
+ (0, import_react4.useMemo)(() => {
1938
+ const map = /* @__PURE__ */ new Map();
1939
+ for (const g of headerGroups) {
1940
+ for (const k of g.childKeys) map.set(k, g.key);
1941
+ }
1942
+ for (const col of initialColumns) {
1943
+ if (!map.has(col.key)) map.set(col.key, null);
1944
+ }
1945
+ columnGroupMapRef.current = map;
1946
+ }, [headerGroups, initialColumns]);
1782
1947
  const overIdRef = (0, import_react4.useRef)(null);
1783
1948
  const dragActiveIdRef = (0, import_react4.useRef)(null);
1784
1949
  const ghostRef = (0, import_react4.useRef)(null);
@@ -1807,6 +1972,7 @@ function BoltTable({
1807
1972
  const grabStyle = document.createElement("style");
1808
1973
  grabStyle.textContent = "* { cursor: grabbing !important; }";
1809
1974
  document.head.appendChild(grabStyle);
1975
+ const draggedGroup = columnGroupMapRef.current.get(columnKey);
1810
1976
  const onMove = (ev) => {
1811
1977
  if (ghost) {
1812
1978
  ghost.style.left = `${ev.clientX - offsetX}px`;
@@ -1822,6 +1988,11 @@ function BoltTable({
1822
1988
  h.removeAttribute("data-drag-over");
1823
1989
  return;
1824
1990
  }
1991
+ const targetGroup = columnGroupMapRef.current.get(key);
1992
+ if (draggedGroup !== targetGroup) {
1993
+ h.removeAttribute("data-drag-over");
1994
+ return;
1995
+ }
1825
1996
  const r = h.getBoundingClientRect();
1826
1997
  if (ev.clientX >= r.left && ev.clientX <= r.right && ev.clientY >= r.top - 20 && ev.clientY <= r.bottom + 20) {
1827
1998
  newOverId = key;
@@ -1844,7 +2015,7 @@ function BoltTable({
1844
2015
  if (ghost) ghost.style.display = "none";
1845
2016
  const currentOverId = overIdRef.current;
1846
2017
  const currentActiveId = dragActiveIdRef.current;
1847
- if (currentOverId && currentActiveId && currentOverId !== currentActiveId) {
2018
+ if (currentOverId && currentActiveId && currentOverId !== currentActiveId && columnGroupMapRef.current.get(currentActiveId) === columnGroupMapRef.current.get(currentOverId)) {
1848
2019
  import_react4.default.startTransition(() => {
1849
2020
  setColumnOrder((items) => {
1850
2021
  const oldIndex = items.indexOf(currentActiveId);
@@ -2084,7 +2255,7 @@ function BoltTable({
2084
2255
  try {
2085
2256
  const col = columnsLookupRef.current.find((c) => c.key === key);
2086
2257
  if (typeof col?.filterFn === "function") {
2087
- return col.filterFn(columnFilters[key], row, col.dataIndex);
2258
+ return col.filterFn(columnFilters[key], row, col.dataIndex ?? key);
2088
2259
  }
2089
2260
  const cellVal = String(row[key] ?? "").toLowerCase();
2090
2261
  return cellVal.includes(columnFilters[key].toLowerCase());
@@ -2190,6 +2361,10 @@ function BoltTable({
2190
2361
  () => new Set((resolvedRowPinning?.bottom ?? []).map(String)),
2191
2362
  [resolvedRowPinning?.bottom]
2192
2363
  );
2364
+ const [editingCell, setEditingCell] = (0, import_react4.useState)(null);
2365
+ const handleEditComplete = (0, import_react4.useCallback)(() => {
2366
+ setEditingCell(null);
2367
+ }, []);
2193
2368
  const [cellContextMenu, setCellContextMenu] = (0, import_react4.useState)(null);
2194
2369
  const cellMenuRef = (0, import_react4.useRef)(null);
2195
2370
  const cellLongPressTimer = (0, import_react4.useRef)(
@@ -2400,7 +2575,7 @@ function BoltTable({
2400
2575
  totalPages
2401
2576
  ];
2402
2577
  };
2403
- const HEADER_HEIGHT = 36;
2578
+ const HEADER_HEIGHT = hasColumnGroups ? 72 : 36;
2404
2579
  const MAX_AUTO_ROWS = 10;
2405
2580
  const virtualTotalSize = rowVirtualizer.getTotalSize();
2406
2581
  const naturalContentHeight = virtualTotalSize + HEADER_HEIGHT;
@@ -2457,6 +2632,7 @@ function BoltTable({
2457
2632
  [data-bt-header][data-drag-over] {
2458
2633
  border: 1px dashed ${accentColor} !important;
2459
2634
  }
2635
+ ${onRowClick ? "[data-bt-cell] { cursor: pointer; }" : ""}
2460
2636
  ` }),
2461
2637
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2462
2638
  "div",
@@ -2595,7 +2771,7 @@ function BoltTable({
2595
2771
  style: {
2596
2772
  display: "grid",
2597
2773
  gridTemplateColumns,
2598
- gridTemplateRows: isEmpty ? "36px 1fr" : `36px ${virtualTotalSize}px`,
2774
+ gridTemplateRows: isEmpty ? hasColumnGroups ? "36px 36px 1fr" : "36px 1fr" : hasColumnGroups ? `36px 36px ${virtualTotalSize}px` : `36px ${virtualTotalSize}px`,
2599
2775
  minWidth: `${totalTableWidth}px`,
2600
2776
  width: "100%",
2601
2777
  position: "relative",
@@ -2613,7 +2789,8 @@ function BoltTable({
2613
2789
  const hasCopy = !!col?.copy;
2614
2790
  const hasRowPin = !!rowPinning;
2615
2791
  const hasCellItems = col?.columnCellContextMenuItems && col.columnCellContextMenuItems.length > 0;
2616
- if (!hasCopy && !hasRowPin && !hasCellItems) return;
2792
+ const hasEdit = !!col?.editable && !col?.render && !!onEdit;
2793
+ if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit) return;
2617
2794
  e.preventDefault();
2618
2795
  setCellContextMenu({
2619
2796
  x: Math.min(e.clientX, window.innerWidth - 200),
@@ -2642,7 +2819,8 @@ function BoltTable({
2642
2819
  const hasCopy = !!col?.copy;
2643
2820
  const hasRowPin = !!rowPinning;
2644
2821
  const hasCellItems = col?.columnCellContextMenuItems && col.columnCellContextMenuItems.length > 0;
2645
- if (!hasCopy && !hasRowPin && !hasCellItems) return;
2822
+ const hasEdit = !!col?.editable && !col?.render && !!onEdit;
2823
+ if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit) return;
2646
2824
  setCellContextMenu({
2647
2825
  x: Math.min(touch.clientX, window.innerWidth - 200),
2648
2826
  y: Math.min(touch.clientY, window.innerHeight - 200),
@@ -2661,125 +2839,209 @@ function BoltTable({
2661
2839
  },
2662
2840
  onTouchEnd: cancelCellLongPress,
2663
2841
  onTouchCancel: cancelCellLongPress,
2664
- children: [
2665
- orderedColumns.map((column, visualIndex) => {
2666
- if (column.key === "__select__" && rowSelection) {
2667
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2668
- "div",
2669
- {
2670
- "data-bt-header": "",
2671
- "data-bt-pinned": "",
2672
- className: `${classNames.header ?? ""} ${classNames.pinnedHeader ?? ""}`,
2673
- style: {
2674
- display: "flex",
2675
- height: 36,
2676
- alignItems: "center",
2677
- justifyContent: "center",
2678
- overflow: "hidden",
2679
- textOverflow: "ellipsis",
2680
- whiteSpace: "nowrap",
2681
- borderBottom: "1px solid rgba(128,128,128,0.2)",
2682
- position: "sticky",
2683
- left: columnOffsets.get("__select__") ?? 0,
2684
- top: 0,
2685
- zIndex: 13,
2686
- width: "48px",
2687
- ...styles.header,
2688
- ...styles.pinnedHeader
2689
- },
2690
- children: rowSelection.type !== "radio" && !rowSelection.hideSelectAll && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2691
- "input",
2692
- {
2693
- type: "checkbox",
2694
- checked: dataLength > 0 && normalizedSelectedKeys.length === dataLength,
2695
- ref: (input) => {
2696
- if (input) {
2697
- input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length < dataLength;
2698
- }
2699
- },
2700
- onChange: (e) => {
2701
- if (e.target.checked) {
2702
- const allKeys = data.map(
2703
- (row, idx) => getRawRowKey(row, idx)
2704
- );
2705
- rowSelection.onSelectAll?.(
2706
- true,
2707
- data,
2708
- data
2709
- );
2710
- rowSelection.onChange?.(allKeys, data, {
2711
- type: "all"
2712
- });
2713
- } else {
2714
- rowSelection.onSelectAll?.(false, [], data);
2715
- rowSelection.onChange?.([], [], {
2716
- type: "all"
2717
- });
2718
- }
2719
- },
2720
- style: { cursor: "pointer", accentColor }
2721
- }
2722
- )
2723
- },
2724
- "__select__"
2725
- );
2842
+ onClick: onRowClick ? (e) => {
2843
+ const target = e.target;
2844
+ if (target.closest("input, button, a, select, textarea")) return;
2845
+ const cell = target.closest("[data-bt-cell]");
2846
+ if (!cell) return;
2847
+ const rk = cell.dataset.rowKey;
2848
+ if (!rk) return;
2849
+ for (let i = 0; i < displayData.length; i++) {
2850
+ const row = displayData[i];
2851
+ if (row == null) continue;
2852
+ if (getRowKey(row, i) === rk) {
2853
+ onRowClick(row, i, e);
2854
+ return;
2726
2855
  }
2727
- if (column.key === "__expand__") {
2728
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2729
- "div",
2730
- {
2731
- "data-bt-header": "",
2732
- "data-bt-pinned": "",
2733
- className: `${classNames.header ?? ""} ${classNames.pinnedHeader ?? ""}`,
2734
- style: {
2735
- display: "flex",
2736
- height: 36,
2737
- alignItems: "center",
2738
- justifyContent: "center",
2739
- overflow: "hidden",
2740
- textOverflow: "ellipsis",
2741
- whiteSpace: "nowrap",
2742
- borderBottom: "1px solid rgba(128,128,128,0.2)",
2743
- position: "sticky",
2744
- left: columnOffsets.get("__expand__") ?? 0,
2745
- top: 0,
2746
- zIndex: 13,
2747
- width: "40px",
2748
- ...styles.header,
2749
- ...styles.pinnedHeader
2750
- }
2751
- },
2752
- "__expand__"
2753
- );
2856
+ }
2857
+ for (let i = 0; i < pinnedTopRows.length; i++) {
2858
+ if (pinnedTopRows[i] == null) continue;
2859
+ if (getRowKey(pinnedTopRows[i], i) === rk) {
2860
+ onRowClick(pinnedTopRows[i], i, e);
2861
+ return;
2754
2862
  }
2863
+ }
2864
+ for (let i = 0; i < pinnedBottomRows.length; i++) {
2865
+ if (pinnedBottomRows[i] == null) continue;
2866
+ if (getRowKey(pinnedBottomRows[i], i) === rk) {
2867
+ onRowClick(pinnedBottomRows[i], i, e);
2868
+ return;
2869
+ }
2870
+ }
2871
+ } : void 0,
2872
+ children: [
2873
+ hasColumnGroups && headerGroups.map((group) => {
2874
+ let minIdx = Infinity;
2875
+ let maxIdx = -1;
2876
+ orderedColumns.forEach((col, idx) => {
2877
+ if (group.childKeys.includes(col.key)) {
2878
+ minIdx = Math.min(minIdx, idx);
2879
+ maxIdx = Math.max(maxIdx, idx);
2880
+ }
2881
+ });
2882
+ if (minIdx === Infinity) return null;
2755
2883
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2756
- DraggableHeader_default,
2884
+ "div",
2757
2885
  {
2758
- column,
2759
- accentColor,
2760
- visualIndex,
2761
- onResizeStart: handleResizeStart,
2762
- onColumnDragStart: handleColumnDragStart,
2763
- styles,
2764
- classNames,
2765
- gripIcon,
2766
- hideGripIcon,
2767
- icons,
2768
- stickyOffset: columnOffsets.get(column.key),
2769
- onTogglePin: handleTogglePin,
2770
- onToggleHide: handleToggleHide,
2771
- isLastColumn: visualIndex === orderedColumns.length - 1,
2772
- sortDirection: sortState.key === column.key ? sortState.direction : null,
2773
- onSort: handleSort,
2774
- filterValue: columnFilters[column.key] ?? "",
2775
- onFilter: handleColumnFilter,
2776
- onClearFilter: handleClearFilter,
2777
- customContextMenuItems: column.columnHeaderContextMenuItems ? [...columnContextMenuItems ?? [], ...column.columnHeaderContextMenuItems] : columnContextMenuItems,
2778
- disabledFilters
2886
+ "data-bt-header": "",
2887
+ className: `${group.className ?? ""} ${classNames.header ?? ""}`,
2888
+ style: {
2889
+ gridColumn: `${minIdx + 1} / ${maxIdx + 2}`,
2890
+ gridRow: 1,
2891
+ position: "sticky",
2892
+ top: 0,
2893
+ zIndex: 10,
2894
+ display: "flex",
2895
+ height: 36,
2896
+ alignItems: "center",
2897
+ justifyContent: "center",
2898
+ overflow: "hidden",
2899
+ textOverflow: "ellipsis",
2900
+ whiteSpace: "nowrap",
2901
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
2902
+ fontWeight: 500,
2903
+ userSelect: "none",
2904
+ ...group.style,
2905
+ ...styles.header
2906
+ },
2907
+ children: group.title
2779
2908
  },
2780
- column.key
2909
+ `group-${group.key}`
2781
2910
  );
2782
2911
  }),
2912
+ (() => {
2913
+ const firstDataColIndex = orderedColumns.findIndex(
2914
+ (c) => c.key !== "__select__" && c.key !== "__expand__"
2915
+ );
2916
+ return orderedColumns.map((column, visualIndex) => {
2917
+ const isInGroup = groupedColumnKeySet?.has(column.key) ?? false;
2918
+ const leafGridRow = hasColumnGroups ? isInGroup ? 2 : "1 / 3" : 1;
2919
+ const leafHeight = hasColumnGroups && !isInGroup ? 72 : 36;
2920
+ const leafStickyTop = hasColumnGroups && isInGroup ? 36 : 0;
2921
+ if (column.key === "__select__" && rowSelection) {
2922
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2923
+ "div",
2924
+ {
2925
+ "data-bt-header": "",
2926
+ "data-bt-pinned": "",
2927
+ className: `${classNames.header ?? ""} ${classNames.pinnedHeader ?? ""}`,
2928
+ style: {
2929
+ display: "flex",
2930
+ height: leafHeight,
2931
+ alignItems: "center",
2932
+ justifyContent: "center",
2933
+ overflow: "hidden",
2934
+ textOverflow: "ellipsis",
2935
+ whiteSpace: "nowrap",
2936
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
2937
+ position: "sticky",
2938
+ left: columnOffsets.get("__select__") ?? 0,
2939
+ top: 0,
2940
+ zIndex: 13,
2941
+ width: "48px",
2942
+ gridRow: leafGridRow,
2943
+ ...styles.header,
2944
+ ...styles.pinnedHeader
2945
+ },
2946
+ children: rowSelection.type !== "radio" && !rowSelection.hideSelectAll && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2947
+ "input",
2948
+ {
2949
+ type: "checkbox",
2950
+ checked: dataLength > 0 && normalizedSelectedKeys.length === dataLength,
2951
+ ref: (input) => {
2952
+ if (input) {
2953
+ input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length < dataLength;
2954
+ }
2955
+ },
2956
+ onChange: (e) => {
2957
+ if (e.target.checked) {
2958
+ const allKeys = data.map(
2959
+ (row, idx) => getRawRowKey(row, idx)
2960
+ );
2961
+ rowSelection.onSelectAll?.(
2962
+ true,
2963
+ data,
2964
+ data
2965
+ );
2966
+ rowSelection.onChange?.(allKeys, data, {
2967
+ type: "all"
2968
+ });
2969
+ } else {
2970
+ rowSelection.onSelectAll?.(false, [], data);
2971
+ rowSelection.onChange?.([], [], {
2972
+ type: "all"
2973
+ });
2974
+ }
2975
+ },
2976
+ style: { cursor: "pointer", accentColor, colorScheme: "light dark" }
2977
+ }
2978
+ )
2979
+ },
2980
+ "__select__"
2981
+ );
2982
+ }
2983
+ if (column.key === "__expand__") {
2984
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2985
+ "div",
2986
+ {
2987
+ "data-bt-header": "",
2988
+ "data-bt-pinned": "",
2989
+ className: `${classNames.header ?? ""} ${classNames.pinnedHeader ?? ""}`,
2990
+ style: {
2991
+ display: "flex",
2992
+ height: leafHeight,
2993
+ alignItems: "center",
2994
+ justifyContent: "center",
2995
+ overflow: "hidden",
2996
+ textOverflow: "ellipsis",
2997
+ whiteSpace: "nowrap",
2998
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
2999
+ position: "sticky",
3000
+ left: columnOffsets.get("__expand__") ?? 0,
3001
+ top: 0,
3002
+ zIndex: 13,
3003
+ width: "40px",
3004
+ gridRow: leafGridRow,
3005
+ ...styles.header,
3006
+ ...styles.pinnedHeader
3007
+ }
3008
+ },
3009
+ "__expand__"
3010
+ );
3011
+ }
3012
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3013
+ DraggableHeader_default,
3014
+ {
3015
+ column,
3016
+ accentColor,
3017
+ visualIndex,
3018
+ onResizeStart: handleResizeStart,
3019
+ onColumnDragStart: handleColumnDragStart,
3020
+ styles,
3021
+ classNames,
3022
+ gripIcon,
3023
+ hideGripIcon,
3024
+ icons,
3025
+ stickyOffset: columnOffsets.get(column.key),
3026
+ onTogglePin: handleTogglePin,
3027
+ onToggleHide: handleToggleHide,
3028
+ isLastColumn: visualIndex === orderedColumns.length - 1,
3029
+ isFirstColumn: visualIndex === firstDataColIndex,
3030
+ sortDirection: sortState.key === column.key ? sortState.direction : null,
3031
+ onSort: handleSort,
3032
+ filterValue: columnFilters[column.key] ?? "",
3033
+ onFilter: handleColumnFilter,
3034
+ onClearFilter: handleClearFilter,
3035
+ customContextMenuItems: column.columnHeaderContextMenuItems ? [...columnContextMenuItems ?? [], ...column.columnHeaderContextMenuItems] : columnContextMenuItems,
3036
+ disabledFilters,
3037
+ headerGridRow: leafGridRow,
3038
+ headerHeight: leafHeight,
3039
+ stickyTop: leafStickyTop
3040
+ },
3041
+ column.key
3042
+ );
3043
+ });
3044
+ })(),
2783
3045
  isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2784
3046
  "div",
2785
3047
  {
@@ -2846,7 +3108,11 @@ function BoltTable({
2846
3108
  gridTemplateColumns,
2847
3109
  headerHeight: HEADER_HEIGHT,
2848
3110
  rowClassName,
2849
- rowStyle
3111
+ rowStyle,
3112
+ bodyGridRow: hasColumnGroups ? 3 : 2,
3113
+ onEdit,
3114
+ editingCell,
3115
+ onEditComplete: handleEditComplete
2850
3116
  }
2851
3117
  )
2852
3118
  ]
@@ -2860,6 +3126,7 @@ function BoltTable({
2860
3126
  pgEnabled && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2861
3127
  "div",
2862
3128
  {
3129
+ className: classNames.pagination ?? "",
2863
3130
  style: {
2864
3131
  display: "flex",
2865
3132
  height: 36,
@@ -2871,27 +3138,42 @@ function BoltTable({
2871
3138
  fontSize: 12,
2872
3139
  backdropFilter: "blur(8px)",
2873
3140
  backgroundColor: "rgba(128,128,128,0.06)",
2874
- gap: 12
3141
+ gap: 12,
3142
+ ...styles.pagination
2875
3143
  },
2876
3144
  children: [
2877
3145
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", flex: "1 1 0%", alignItems: "center" }, children: (() => {
2878
3146
  const rangeStart = total > 0 ? (currentPage - 1) * pageSize + 1 : 0;
2879
3147
  const rangeEnd = Math.min(currentPage * pageSize, total);
2880
- return typeof pagination === "object" && pagination?.showTotal ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { color: "GrayText", fontSize: 12 }, children: [
2881
- "Showing",
2882
- " ",
2883
- pagination.showTotal(total, [rangeStart, rangeEnd]),
2884
- " of",
2885
- " ",
2886
- total,
2887
- " items"
2888
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { color: "GrayText", fontSize: 12 }, children: [
2889
- rangeStart,
2890
- "\u2013",
2891
- rangeEnd,
2892
- " of ",
2893
- total
2894
- ] });
3148
+ return typeof pagination === "object" && pagination?.showTotal ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3149
+ "span",
3150
+ {
3151
+ className: classNames.paginationInfo ?? "",
3152
+ style: { color: "GrayText", fontSize: 12, ...styles.paginationInfo },
3153
+ children: [
3154
+ "Showing",
3155
+ " ",
3156
+ pagination.showTotal(total, [rangeStart, rangeEnd]),
3157
+ " of",
3158
+ " ",
3159
+ total,
3160
+ " items"
3161
+ ]
3162
+ }
3163
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3164
+ "span",
3165
+ {
3166
+ className: classNames.paginationInfo ?? "",
3167
+ style: { color: "GrayText", fontSize: 12, ...styles.paginationInfo },
3168
+ children: [
3169
+ rangeStart,
3170
+ "\u2013",
3171
+ rangeEnd,
3172
+ " of ",
3173
+ total
3174
+ ]
3175
+ }
3176
+ );
2895
3177
  })() }),
2896
3178
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2897
3179
  "div",
@@ -2907,8 +3189,10 @@ function BoltTable({
2907
3189
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2908
3190
  "button",
2909
3191
  {
3192
+ type: "button",
2910
3193
  onClick: () => handlePageChange(1),
2911
3194
  disabled: currentPage === 1,
3195
+ className: classNames.paginationButton ?? "",
2912
3196
  style: {
2913
3197
  display: "inline-flex",
2914
3198
  height: 24,
@@ -2921,7 +3205,8 @@ function BoltTable({
2921
3205
  background: "none",
2922
3206
  border: "none",
2923
3207
  padding: 0,
2924
- color: "inherit"
3208
+ color: "inherit",
3209
+ ...styles.paginationButton
2925
3210
  },
2926
3211
  title: "First page",
2927
3212
  children: icons?.chevronsLeft ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronsLeftIcon, { style: { width: 12, height: 12 } })
@@ -2930,8 +3215,10 @@ function BoltTable({
2930
3215
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2931
3216
  "button",
2932
3217
  {
3218
+ type: "button",
2933
3219
  onClick: () => handlePageChange(currentPage - 1),
2934
3220
  disabled: currentPage === 1,
3221
+ className: classNames.paginationButton ?? "",
2935
3222
  style: {
2936
3223
  display: "inline-flex",
2937
3224
  height: 24,
@@ -2944,7 +3231,8 @@ function BoltTable({
2944
3231
  background: "none",
2945
3232
  border: "none",
2946
3233
  padding: 0,
2947
- color: "inherit"
3234
+ color: "inherit",
3235
+ ...styles.paginationButton
2948
3236
  },
2949
3237
  title: "Previous page",
2950
3238
  children: icons?.chevronLeft ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronLeftIcon, { style: { width: 12, height: 12 } })
@@ -2967,9 +3255,12 @@ function BoltTable({
2967
3255
  page
2968
3256
  );
2969
3257
  }
3258
+ const isActivePage = page === currentPage;
2970
3259
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2971
3260
  "button",
2972
3261
  {
3262
+ type: "button",
3263
+ className: `${classNames.paginationButton ?? ""} ${isActivePage ? classNames.paginationActiveButton ?? "" : ""}`.trim() || void 0,
2973
3264
  style: {
2974
3265
  display: "inline-flex",
2975
3266
  height: 24,
@@ -2981,9 +3272,11 @@ function BoltTable({
2981
3272
  paddingLeft: 6,
2982
3273
  paddingRight: 6,
2983
3274
  fontSize: 12,
2984
- color: page === currentPage ? accentColor : void 0,
3275
+ color: isActivePage ? accentColor : void 0,
2985
3276
  background: "none",
2986
- border: "none"
3277
+ border: "none",
3278
+ ...styles.paginationButton,
3279
+ ...isActivePage ? styles.paginationActiveButton : void 0
2987
3280
  },
2988
3281
  onClick: () => handlePageChange(page),
2989
3282
  children: page
@@ -2994,8 +3287,10 @@ function BoltTable({
2994
3287
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2995
3288
  "button",
2996
3289
  {
3290
+ type: "button",
2997
3291
  onClick: () => handlePageChange(currentPage + 1),
2998
3292
  disabled: currentPage === totalPages,
3293
+ className: classNames.paginationButton ?? "",
2999
3294
  style: {
3000
3295
  display: "inline-flex",
3001
3296
  height: 24,
@@ -3008,7 +3303,8 @@ function BoltTable({
3008
3303
  background: "none",
3009
3304
  border: "none",
3010
3305
  padding: 0,
3011
- color: "inherit"
3306
+ color: "inherit",
3307
+ ...styles.paginationButton
3012
3308
  },
3013
3309
  title: "Next page",
3014
3310
  children: icons?.chevronRight ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronRightIcon, { style: { width: 12, height: 12 } })
@@ -3017,8 +3313,10 @@ function BoltTable({
3017
3313
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3018
3314
  "button",
3019
3315
  {
3316
+ type: "button",
3020
3317
  onClick: () => handlePageChange(totalPages),
3021
3318
  disabled: currentPage === totalPages,
3319
+ className: classNames.paginationButton ?? "",
3022
3320
  style: {
3023
3321
  display: "inline-flex",
3024
3322
  height: 24,
@@ -3031,7 +3329,8 @@ function BoltTable({
3031
3329
  background: "none",
3032
3330
  border: "none",
3033
3331
  padding: 0,
3034
- color: "inherit"
3332
+ color: "inherit",
3333
+ ...styles.paginationButton
3035
3334
  },
3036
3335
  title: "Last page",
3037
3336
  children: icons?.chevronsRight ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronsRightIcon, { style: { width: 12, height: 12 } })
@@ -3055,6 +3354,7 @@ function BoltTable({
3055
3354
  {
3056
3355
  value: pageSize,
3057
3356
  onChange: (e) => handlePageSizeChange(Number(e.target.value)),
3357
+ className: classNames.paginationSelect ?? "",
3058
3358
  style: {
3059
3359
  cursor: "pointer",
3060
3360
  borderRadius: 4,
@@ -3066,7 +3366,8 @@ function BoltTable({
3066
3366
  fontSize: 12,
3067
3367
  height: 24,
3068
3368
  background: "inherit",
3069
- color: "inherit"
3369
+ color: "inherit",
3370
+ ...styles.paginationSelect
3070
3371
  },
3071
3372
  children: (typeof pagination === "object" && pagination?.pageSizeOptions ? pagination.pageSizeOptions : [10, 15, 20, 25, 50, 100]).map((size) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("option", { value: size, children: [
3072
3373
  size,
@@ -3161,6 +3462,7 @@ function BoltTable({
3161
3462
  );
3162
3463
  const hasCopy = !!menuCol?.copy;
3163
3464
  const hasRowPin = !!rowPinning;
3465
+ const hasEdit = !!menuCol?.editable && !menuCol?.render && !!onEdit;
3164
3466
  let menuRecord;
3165
3467
  let menuRowIndex = 0;
3166
3468
  const allRows = [
@@ -3177,7 +3479,7 @@ function BoltTable({
3177
3479
  break;
3178
3480
  }
3179
3481
  }
3180
- const menuValue = menuRecord && menuCol ? menuRecord[menuCol.dataIndex] : void 0;
3482
+ const menuValue = menuRecord && menuCol?.dataIndex != null ? menuRecord[menuCol.dataIndex] : void 0;
3181
3483
  const btnStyle = {
3182
3484
  display: "flex",
3183
3485
  width: "100%",
@@ -3217,6 +3519,7 @@ function BoltTable({
3217
3519
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3218
3520
  "button",
3219
3521
  {
3522
+ type: "button",
3220
3523
  "data-bt-ctx-item": true,
3221
3524
  style: btnStyle,
3222
3525
  onClick: () => {
@@ -3245,6 +3548,7 @@ function BoltTable({
3245
3548
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3246
3549
  "button",
3247
3550
  {
3551
+ type: "button",
3248
3552
  "data-bt-ctx-item": true,
3249
3553
  style: btnStyle,
3250
3554
  onClick: () => {
@@ -3276,7 +3580,40 @@ function BoltTable({
3276
3580
  }
3277
3581
  )
3278
3582
  ] }),
3279
- hasRowPin && hasCopy && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3583
+ hasRowPin && (hasCopy || hasEdit) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3584
+ "div",
3585
+ {
3586
+ style: {
3587
+ borderTop: "1px solid rgba(128,128,128,0.2)",
3588
+ margin: "4px 0"
3589
+ }
3590
+ }
3591
+ ),
3592
+ hasEdit && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3593
+ "button",
3594
+ {
3595
+ type: "button",
3596
+ "data-bt-ctx-item": true,
3597
+ style: btnStyle,
3598
+ onClick: () => {
3599
+ setEditingCell({
3600
+ rowKey: cellContextMenu.rowKey,
3601
+ columnKey: cellContextMenu.columnKey
3602
+ });
3603
+ setCellContextMenu(null);
3604
+ },
3605
+ children: [
3606
+ icons?.edit ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3607
+ PencilIcon,
3608
+ {
3609
+ style: { width: 14, height: 14, flexShrink: 0 }
3610
+ }
3611
+ ),
3612
+ "Edit"
3613
+ ]
3614
+ }
3615
+ ),
3616
+ (hasEdit || hasRowPin) && hasCopy && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3280
3617
  "div",
3281
3618
  {
3282
3619
  style: {
@@ -3288,6 +3625,7 @@ function BoltTable({
3288
3625
  hasCopy && menuRecord && menuCol && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3289
3626
  "button",
3290
3627
  {
3628
+ type: "button",
3291
3629
  "data-bt-ctx-item": true,
3292
3630
  style: btnStyle,
3293
3631
  onClick: () => {
@@ -3308,7 +3646,7 @@ function BoltTable({
3308
3646
  }
3309
3647
  ),
3310
3648
  menuCol?.columnCellContextMenuItems && menuCol.columnCellContextMenuItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3311
- (hasCopy || hasRowPin) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3649
+ (hasCopy || hasRowPin || hasEdit) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3312
3650
  "div",
3313
3651
  {
3314
3652
  style: {
@@ -3320,6 +3658,7 @@ function BoltTable({
3320
3658
  menuCol.columnCellContextMenuItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3321
3659
  "button",
3322
3660
  {
3661
+ type: "button",
3323
3662
  "data-bt-ctx-item": "",
3324
3663
  disabled: item.disabled,
3325
3664
  style: {