bolt-table 0.1.34 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -84,31 +84,52 @@ interface ColumnType<T = unknown> {
84
84
  interface CellContextMenuItem<T = unknown> {
85
85
  /** Unique identifier for this menu item, used as the React `key`. */
86
86
  key: string;
87
- /** The label shown in the menu. Can be a string or React node. */
88
- label: React.ReactNode;
89
- /** Optional icon shown to the left of the label. */
90
- icon?: React.ReactNode;
87
+ /**
88
+ * The label shown in the menu. Can be a string, React node, or a function
89
+ * `(columnKey, record, rowIndex) => ReactNode` that returns a custom node
90
+ * derived from the row being clicked.
91
+ */
92
+ label: React.ReactNode | ((columnKey: string, record: T, rowIndex: number) => React.ReactNode);
93
+ /**
94
+ * Optional icon shown to the left of the label. Can be a React node or a
95
+ * function `(columnKey, record, rowIndex) => ReactNode` for row-aware icons.
96
+ */
97
+ icon?: React.ReactNode | ((columnKey: string, record: T, rowIndex: number) => React.ReactNode);
91
98
  /** When `true`, the label renders in red to indicate a destructive action. */
92
99
  danger?: boolean;
93
100
  /** When `true`, the item is grayed out and click handler is not called. */
94
101
  disabled?: boolean;
95
- /** Called when the user clicks this menu item. Receives the column key, row record, and row index. */
96
- onClick: (columnKey: string, record: T, rowIndex: number) => void;
102
+ /**
103
+ * Called when the user clicks this menu item. Receives the column key, row
104
+ * record, and row index. Optional — omit if the item's label renders its
105
+ * own interactive content (e.g. a custom React node that handles clicks).
106
+ */
107
+ onClick?: (columnKey: string, record: T, rowIndex: number) => void;
97
108
  }
98
109
  /** A single item in the column header right-click context menu. */
99
110
  interface ColumnContextMenuItem {
100
111
  /** Unique identifier for this menu item, used as the React `key`. */
101
112
  key: string;
102
- /** The label shown in the menu. Can be a string or React node. */
103
- label: React.ReactNode;
104
- /** Optional icon shown to the left of the label. */
105
- icon?: React.ReactNode;
113
+ /**
114
+ * The label shown in the menu. Can be a string, React node, or a function
115
+ * `(columnKey) => ReactNode` that returns a custom node derived from the
116
+ * column being clicked.
117
+ */
118
+ label: React.ReactNode | ((columnKey: string) => React.ReactNode);
119
+ /**
120
+ * Optional icon shown to the left of the label. Can be a React node or a
121
+ * function `(columnKey) => ReactNode` for column-aware icons.
122
+ */
123
+ icon?: React.ReactNode | ((columnKey: string) => React.ReactNode);
106
124
  /** When `true`, the label renders in red to indicate a destructive action. */
107
125
  danger?: boolean;
108
126
  /** When `true`, the item is grayed out and click handler is not called. */
109
127
  disabled?: boolean;
110
- /** Called when the user clicks this menu item. Receives the column `key`. */
111
- onClick: (columnKey: string) => void;
128
+ /**
129
+ * Called when the user clicks this menu item. Receives the column `key`.
130
+ * Optional — omit if the item's label renders its own interactive content.
131
+ */
132
+ onClick?: (columnKey: string) => void;
112
133
  }
113
134
  /** How the row selection was triggered: `'all'`, `'single'`, or `'multiple'`. */
114
135
  type RowSelectMethod = "all" | "single" | "multiple";
package/dist/index.d.ts CHANGED
@@ -84,31 +84,52 @@ interface ColumnType<T = unknown> {
84
84
  interface CellContextMenuItem<T = unknown> {
85
85
  /** Unique identifier for this menu item, used as the React `key`. */
86
86
  key: string;
87
- /** The label shown in the menu. Can be a string or React node. */
88
- label: React.ReactNode;
89
- /** Optional icon shown to the left of the label. */
90
- icon?: React.ReactNode;
87
+ /**
88
+ * The label shown in the menu. Can be a string, React node, or a function
89
+ * `(columnKey, record, rowIndex) => ReactNode` that returns a custom node
90
+ * derived from the row being clicked.
91
+ */
92
+ label: React.ReactNode | ((columnKey: string, record: T, rowIndex: number) => React.ReactNode);
93
+ /**
94
+ * Optional icon shown to the left of the label. Can be a React node or a
95
+ * function `(columnKey, record, rowIndex) => ReactNode` for row-aware icons.
96
+ */
97
+ icon?: React.ReactNode | ((columnKey: string, record: T, rowIndex: number) => React.ReactNode);
91
98
  /** When `true`, the label renders in red to indicate a destructive action. */
92
99
  danger?: boolean;
93
100
  /** When `true`, the item is grayed out and click handler is not called. */
94
101
  disabled?: boolean;
95
- /** Called when the user clicks this menu item. Receives the column key, row record, and row index. */
96
- onClick: (columnKey: string, record: T, rowIndex: number) => void;
102
+ /**
103
+ * Called when the user clicks this menu item. Receives the column key, row
104
+ * record, and row index. Optional — omit if the item's label renders its
105
+ * own interactive content (e.g. a custom React node that handles clicks).
106
+ */
107
+ onClick?: (columnKey: string, record: T, rowIndex: number) => void;
97
108
  }
98
109
  /** A single item in the column header right-click context menu. */
99
110
  interface ColumnContextMenuItem {
100
111
  /** Unique identifier for this menu item, used as the React `key`. */
101
112
  key: string;
102
- /** The label shown in the menu. Can be a string or React node. */
103
- label: React.ReactNode;
104
- /** Optional icon shown to the left of the label. */
105
- icon?: React.ReactNode;
113
+ /**
114
+ * The label shown in the menu. Can be a string, React node, or a function
115
+ * `(columnKey) => ReactNode` that returns a custom node derived from the
116
+ * column being clicked.
117
+ */
118
+ label: React.ReactNode | ((columnKey: string) => React.ReactNode);
119
+ /**
120
+ * Optional icon shown to the left of the label. Can be a React node or a
121
+ * function `(columnKey) => ReactNode` for column-aware icons.
122
+ */
123
+ icon?: React.ReactNode | ((columnKey: string) => React.ReactNode);
106
124
  /** When `true`, the label renders in red to indicate a destructive action. */
107
125
  danger?: boolean;
108
126
  /** When `true`, the item is grayed out and click handler is not called. */
109
127
  disabled?: boolean;
110
- /** Called when the user clicks this menu item. Receives the column `key`. */
111
- onClick: (columnKey: string) => void;
128
+ /**
129
+ * Called when the user clicks this menu item. Receives the column `key`.
130
+ * Optional — omit if the item's label renders its own interactive content.
131
+ */
132
+ onClick?: (columnKey: string) => void;
112
133
  }
113
134
  /** How the row selection was triggered: `'all'`, `'single'`, or `'multiple'`. */
114
135
  type RowSelectMethod = "all" | "single" | "multiple";
package/dist/index.js CHANGED
@@ -243,7 +243,7 @@ var DraggableHeader = import_react.default.memo(
243
243
  const widthPx = `${columnWidth}px`;
244
244
  const isPinned = Boolean(column.pinned);
245
245
  const zIndex = isPinned ? 12 : 10;
246
- const HEADER_SEP = "1px solid rgba(128,128,128,0.3)";
246
+ const HEADER_SEP = "1px solid rgba(128,128,128,0.2)";
247
247
  const headerStyle = {
248
248
  position: "sticky",
249
249
  top: stickyTop,
@@ -260,15 +260,16 @@ var DraggableHeader = import_react.default.memo(
260
260
  textOverflow: "ellipsis",
261
261
  whiteSpace: "nowrap",
262
262
  boxSizing: "border-box",
263
- borderTop: "none",
264
- borderLeft: "none",
265
- borderBottom: HEADER_SEP,
266
- borderRight: isLastColumn ? "none" : HEADER_SEP,
267
263
  ...column.pinned === "left" && stickyOffset !== void 0 ? { left: `${stickyOffset}px` } : {},
268
264
  ...column.pinned === "right" && stickyOffset !== void 0 ? { right: `${stickyOffset}px` } : {},
269
265
  ...column.style,
270
266
  ...isPinned ? styles?.pinnedHeader : {},
271
- ...styles?.header
267
+ ...styles?.header,
268
+ // Borders after spreads so styles.header cannot override them
269
+ borderTop: "none",
270
+ borderLeft: "none",
271
+ borderBottom: HEADER_SEP,
272
+ borderRight: isLastColumn ? "none" : HEADER_SEP
272
273
  };
273
274
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
274
275
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
@@ -622,40 +623,44 @@ var DraggableHeader = import_react.default.memo(
622
623
  ] }),
623
624
  customContextMenuItems && customContextMenuItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
624
625
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { marginTop: 4, marginBottom: 4, borderTop: "1px solid rgba(128,128,128,0.2)" } }),
625
- customContextMenuItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
626
- "button",
627
- {
628
- type: "button",
629
- "data-bt-ctx-item": "",
630
- disabled: item.disabled,
631
- style: {
632
- display: "flex",
633
- width: "100%",
634
- alignItems: "center",
635
- gap: 8,
636
- paddingLeft: 12,
637
- paddingRight: 12,
638
- paddingTop: 6,
639
- paddingBottom: 6,
640
- textAlign: "left",
641
- background: "none",
642
- border: "none",
643
- fontSize: "inherit",
644
- cursor: item.disabled ? "not-allowed" : "pointer",
645
- opacity: item.disabled ? 0.5 : 1,
646
- color: item.danger ? "#ef4444" : "inherit"
647
- },
648
- onClick: () => {
649
- item.onClick(column.key);
650
- setContextMenu(null);
626
+ customContextMenuItems.map((item) => {
627
+ const resolvedIcon = typeof item.icon === "function" ? item.icon(column.key) : item.icon;
628
+ const resolvedLabel = typeof item.label === "function" ? item.label(column.key) : item.label;
629
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
630
+ "button",
631
+ {
632
+ type: "button",
633
+ "data-bt-ctx-item": "",
634
+ disabled: item.disabled,
635
+ style: {
636
+ display: "flex",
637
+ width: "100%",
638
+ alignItems: "center",
639
+ gap: 8,
640
+ paddingLeft: 12,
641
+ paddingRight: 12,
642
+ paddingTop: 6,
643
+ paddingBottom: 6,
644
+ textAlign: "left",
645
+ background: "none",
646
+ border: "none",
647
+ fontSize: "inherit",
648
+ cursor: item.disabled ? "not-allowed" : "pointer",
649
+ opacity: item.disabled ? 0.5 : 1,
650
+ color: item.danger ? "#ef4444" : "inherit"
651
+ },
652
+ onClick: () => {
653
+ item.onClick?.(column.key);
654
+ setContextMenu(null);
655
+ },
656
+ children: [
657
+ resolvedIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { display: "flex", width: 12, height: 12, alignItems: "center", justifyContent: "center" }, children: resolvedIcon }),
658
+ resolvedLabel
659
+ ]
651
660
  },
652
- children: [
653
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { display: "flex", width: 12, height: 12, alignItems: "center", justifyContent: "center" }, children: item.icon }),
654
- item.label
655
- ]
656
- },
657
- item.key
658
- ))
661
+ item.key
662
+ );
663
+ })
659
664
  ] })
660
665
  ] });
661
666
  })()
@@ -2973,7 +2978,7 @@ function BoltTable({
2973
2978
  background-color: rgba(128, 128, 128, 0.15);
2974
2979
  }
2975
2980
  [data-bt-header][data-dragging] {
2976
- opacity: 0.3 !important;
2981
+ opacity: 0.2 !important;
2977
2982
  }
2978
2983
  [data-bt-header][data-drag-over] {
2979
2984
  border: 1px dashed ${accentColor} !important;
@@ -3433,14 +3438,14 @@ function BoltTable({
3433
3438
  textOverflow: "ellipsis",
3434
3439
  whiteSpace: "nowrap",
3435
3440
  boxSizing: "border-box",
3436
- borderTop: "none",
3437
- borderLeft: "none",
3438
- borderBottom: "1px solid rgba(128,128,128,0.3)",
3439
- borderRight: groupEndsAtLastCol ? "none" : "1px solid rgba(128,128,128,0.3)",
3440
3441
  fontWeight: 500,
3441
3442
  userSelect: "none",
3442
3443
  ...group.style,
3443
- ...styles.header
3444
+ ...styles.header,
3445
+ borderTop: "none",
3446
+ borderLeft: "none",
3447
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
3448
+ borderRight: groupEndsAtLastCol ? "none" : "1px solid rgba(128,128,128,0.2)"
3444
3449
  },
3445
3450
  children: group.title
3446
3451
  },
@@ -3472,10 +3477,6 @@ function BoltTable({
3472
3477
  textOverflow: "ellipsis",
3473
3478
  whiteSpace: "nowrap",
3474
3479
  boxSizing: "border-box",
3475
- borderTop: "none",
3476
- borderLeft: "none",
3477
- borderBottom: "1px solid rgba(128,128,128,0.3)",
3478
- borderRight: "1px solid rgba(128,128,128,0.3)",
3479
3480
  position: "sticky",
3480
3481
  left: columnOffsets.get("__select__") ?? 0,
3481
3482
  top: 0,
@@ -3483,7 +3484,11 @@ function BoltTable({
3483
3484
  width: "48px",
3484
3485
  gridRow: leafGridRow,
3485
3486
  ...styles.header,
3486
- ...styles.pinnedHeader
3487
+ ...styles.pinnedHeader,
3488
+ borderTop: "none",
3489
+ borderLeft: "none",
3490
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
3491
+ borderRight: "1px solid rgba(128,128,128,0.2)"
3487
3492
  },
3488
3493
  children: rowSelection.type !== "radio" && !rowSelection.hideSelectAll && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3489
3494
  "input",
@@ -3542,10 +3547,6 @@ function BoltTable({
3542
3547
  textOverflow: "ellipsis",
3543
3548
  whiteSpace: "nowrap",
3544
3549
  boxSizing: "border-box",
3545
- borderTop: "none",
3546
- borderLeft: "none",
3547
- borderBottom: "1px solid rgba(128,128,128,0.3)",
3548
- borderRight: "1px solid rgba(128,128,128,0.3)",
3549
3550
  position: "sticky",
3550
3551
  left: columnOffsets.get("__expand__") ?? 0,
3551
3552
  top: 0,
@@ -3554,7 +3555,11 @@ function BoltTable({
3554
3555
  backgroundColor: styles.pinnedBg,
3555
3556
  gridRow: leafGridRow,
3556
3557
  ...styles.header,
3557
- ...styles.pinnedHeader
3558
+ ...styles.pinnedHeader,
3559
+ borderTop: "none",
3560
+ borderLeft: "none",
3561
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
3562
+ borderRight: "1px solid rgba(128,128,128,0.2)"
3558
3563
  }
3559
3564
  },
3560
3565
  "__expand__"
@@ -3772,7 +3777,7 @@ function BoltTable({
3772
3777
  alignItems: "center",
3773
3778
  justifyContent: "center",
3774
3779
  fontSize: 12,
3775
- opacity: currentPage === 1 ? 0.3 : 1,
3780
+ opacity: currentPage === 1 ? 0.2 : 1,
3776
3781
  background: "none",
3777
3782
  border: "none",
3778
3783
  padding: 0,
@@ -3798,7 +3803,7 @@ function BoltTable({
3798
3803
  alignItems: "center",
3799
3804
  justifyContent: "center",
3800
3805
  fontSize: 12,
3801
- opacity: currentPage === 1 ? 0.3 : 1,
3806
+ opacity: currentPage === 1 ? 0.2 : 1,
3802
3807
  background: "none",
3803
3808
  border: "none",
3804
3809
  padding: 0,
@@ -3870,7 +3875,7 @@ function BoltTable({
3870
3875
  alignItems: "center",
3871
3876
  justifyContent: "center",
3872
3877
  fontSize: 12,
3873
- opacity: currentPage === totalPages ? 0.3 : 1,
3878
+ opacity: currentPage === totalPages ? 0.2 : 1,
3874
3879
  background: "none",
3875
3880
  border: "none",
3876
3881
  padding: 0,
@@ -3896,7 +3901,7 @@ function BoltTable({
3896
3901
  alignItems: "center",
3897
3902
  justifyContent: "center",
3898
3903
  fontSize: 12,
3899
- opacity: currentPage === totalPages ? 0.3 : 1,
3904
+ opacity: currentPage === totalPages ? 0.2 : 1,
3900
3905
  background: "none",
3901
3906
  border: "none",
3902
3907
  padding: 0,
@@ -3971,7 +3976,7 @@ function BoltTable({
3971
3976
  textOverflow: "ellipsis",
3972
3977
  whiteSpace: "nowrap",
3973
3978
  borderRadius: 6,
3974
- border: "1px dashed rgba(128,128,128,0.3)",
3979
+ border: "1px dashed rgba(128,128,128,0.2)",
3975
3980
  boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
3976
3981
  backdropFilter: "blur(16px)",
3977
3982
  WebkitBackdropFilter: "blur(16px)",
@@ -4224,44 +4229,60 @@ function BoltTable({
4224
4229
  }
4225
4230
  }
4226
4231
  ),
4227
- menuCol.columnCellContextMenuItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4228
- "button",
4229
- {
4230
- type: "button",
4231
- "data-bt-ctx-item": "",
4232
- disabled: item.disabled,
4233
- style: {
4234
- ...btnStyle,
4235
- cursor: item.disabled ? "not-allowed" : "pointer",
4236
- opacity: item.disabled ? 0.5 : 1,
4237
- color: item.danger ? "#ef4444" : "inherit"
4238
- },
4239
- onClick: () => {
4240
- if (menuRecord) {
4241
- item.onClick(menuCol.key, menuRecord, menuRowIndex);
4242
- }
4243
- setCellContextMenu(null);
4244
- },
4245
- children: [
4246
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4247
- "span",
4248
- {
4249
- style: {
4250
- display: "flex",
4251
- width: 14,
4252
- height: 14,
4253
- alignItems: "center",
4254
- justifyContent: "center",
4255
- flexShrink: 0
4256
- },
4257
- children: item.icon
4232
+ menuCol.columnCellContextMenuItems.map((item) => {
4233
+ const resolvedIcon = typeof item.icon === "function" ? menuRecord ? item.icon(
4234
+ menuCol.key,
4235
+ menuRecord,
4236
+ menuRowIndex
4237
+ ) : null : item.icon;
4238
+ const resolvedLabel = typeof item.label === "function" ? menuRecord ? item.label(
4239
+ menuCol.key,
4240
+ menuRecord,
4241
+ menuRowIndex
4242
+ ) : null : item.label;
4243
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4244
+ "button",
4245
+ {
4246
+ type: "button",
4247
+ "data-bt-ctx-item": "",
4248
+ disabled: item.disabled,
4249
+ style: {
4250
+ ...btnStyle,
4251
+ cursor: item.disabled ? "not-allowed" : "pointer",
4252
+ opacity: item.disabled ? 0.5 : 1,
4253
+ color: item.danger ? "#ef4444" : "inherit"
4254
+ },
4255
+ onClick: () => {
4256
+ if (menuRecord && item.onClick) {
4257
+ item.onClick(
4258
+ menuCol.key,
4259
+ menuRecord,
4260
+ menuRowIndex
4261
+ );
4258
4262
  }
4259
- ),
4260
- item.label
4261
- ]
4262
- },
4263
- item.key
4264
- ))
4263
+ setCellContextMenu(null);
4264
+ },
4265
+ children: [
4266
+ resolvedIcon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4267
+ "span",
4268
+ {
4269
+ style: {
4270
+ display: "flex",
4271
+ width: 14,
4272
+ height: 14,
4273
+ alignItems: "center",
4274
+ justifyContent: "center",
4275
+ flexShrink: 0
4276
+ },
4277
+ children: resolvedIcon
4278
+ }
4279
+ ),
4280
+ resolvedLabel
4281
+ ]
4282
+ },
4283
+ item.key
4284
+ );
4285
+ })
4265
4286
  ] })
4266
4287
  ]
4267
4288
  }
package/dist/index.mjs CHANGED
@@ -209,7 +209,7 @@ var DraggableHeader = React.memo(
209
209
  const widthPx = `${columnWidth}px`;
210
210
  const isPinned = Boolean(column.pinned);
211
211
  const zIndex = isPinned ? 12 : 10;
212
- const HEADER_SEP = "1px solid rgba(128,128,128,0.3)";
212
+ const HEADER_SEP = "1px solid rgba(128,128,128,0.2)";
213
213
  const headerStyle = {
214
214
  position: "sticky",
215
215
  top: stickyTop,
@@ -226,15 +226,16 @@ var DraggableHeader = React.memo(
226
226
  textOverflow: "ellipsis",
227
227
  whiteSpace: "nowrap",
228
228
  boxSizing: "border-box",
229
- borderTop: "none",
230
- borderLeft: "none",
231
- borderBottom: HEADER_SEP,
232
- borderRight: isLastColumn ? "none" : HEADER_SEP,
233
229
  ...column.pinned === "left" && stickyOffset !== void 0 ? { left: `${stickyOffset}px` } : {},
234
230
  ...column.pinned === "right" && stickyOffset !== void 0 ? { right: `${stickyOffset}px` } : {},
235
231
  ...column.style,
236
232
  ...isPinned ? styles?.pinnedHeader : {},
237
- ...styles?.header
233
+ ...styles?.header,
234
+ // Borders after spreads so styles.header cannot override them
235
+ borderTop: "none",
236
+ borderLeft: "none",
237
+ borderBottom: HEADER_SEP,
238
+ borderRight: isLastColumn ? "none" : HEADER_SEP
238
239
  };
239
240
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
240
241
  /* @__PURE__ */ jsxs2(
@@ -588,40 +589,44 @@ var DraggableHeader = React.memo(
588
589
  ] }),
589
590
  customContextMenuItems && customContextMenuItems.length > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
590
591
  /* @__PURE__ */ jsx2("div", { style: { marginTop: 4, marginBottom: 4, borderTop: "1px solid rgba(128,128,128,0.2)" } }),
591
- customContextMenuItems.map((item) => /* @__PURE__ */ jsxs2(
592
- "button",
593
- {
594
- type: "button",
595
- "data-bt-ctx-item": "",
596
- disabled: item.disabled,
597
- style: {
598
- display: "flex",
599
- width: "100%",
600
- alignItems: "center",
601
- gap: 8,
602
- paddingLeft: 12,
603
- paddingRight: 12,
604
- paddingTop: 6,
605
- paddingBottom: 6,
606
- textAlign: "left",
607
- background: "none",
608
- border: "none",
609
- fontSize: "inherit",
610
- cursor: item.disabled ? "not-allowed" : "pointer",
611
- opacity: item.disabled ? 0.5 : 1,
612
- color: item.danger ? "#ef4444" : "inherit"
613
- },
614
- onClick: () => {
615
- item.onClick(column.key);
616
- setContextMenu(null);
592
+ customContextMenuItems.map((item) => {
593
+ const resolvedIcon = typeof item.icon === "function" ? item.icon(column.key) : item.icon;
594
+ const resolvedLabel = typeof item.label === "function" ? item.label(column.key) : item.label;
595
+ return /* @__PURE__ */ jsxs2(
596
+ "button",
597
+ {
598
+ type: "button",
599
+ "data-bt-ctx-item": "",
600
+ disabled: item.disabled,
601
+ style: {
602
+ display: "flex",
603
+ width: "100%",
604
+ alignItems: "center",
605
+ gap: 8,
606
+ paddingLeft: 12,
607
+ paddingRight: 12,
608
+ paddingTop: 6,
609
+ paddingBottom: 6,
610
+ textAlign: "left",
611
+ background: "none",
612
+ border: "none",
613
+ fontSize: "inherit",
614
+ cursor: item.disabled ? "not-allowed" : "pointer",
615
+ opacity: item.disabled ? 0.5 : 1,
616
+ color: item.danger ? "#ef4444" : "inherit"
617
+ },
618
+ onClick: () => {
619
+ item.onClick?.(column.key);
620
+ setContextMenu(null);
621
+ },
622
+ children: [
623
+ resolvedIcon && /* @__PURE__ */ jsx2("span", { style: { display: "flex", width: 12, height: 12, alignItems: "center", justifyContent: "center" }, children: resolvedIcon }),
624
+ resolvedLabel
625
+ ]
617
626
  },
618
- children: [
619
- item.icon && /* @__PURE__ */ jsx2("span", { style: { display: "flex", width: 12, height: 12, alignItems: "center", justifyContent: "center" }, children: item.icon }),
620
- item.label
621
- ]
622
- },
623
- item.key
624
- ))
627
+ item.key
628
+ );
629
+ })
625
630
  ] })
626
631
  ] });
627
632
  })()
@@ -2945,7 +2950,7 @@ function BoltTable({
2945
2950
  background-color: rgba(128, 128, 128, 0.15);
2946
2951
  }
2947
2952
  [data-bt-header][data-dragging] {
2948
- opacity: 0.3 !important;
2953
+ opacity: 0.2 !important;
2949
2954
  }
2950
2955
  [data-bt-header][data-drag-over] {
2951
2956
  border: 1px dashed ${accentColor} !important;
@@ -3405,14 +3410,14 @@ function BoltTable({
3405
3410
  textOverflow: "ellipsis",
3406
3411
  whiteSpace: "nowrap",
3407
3412
  boxSizing: "border-box",
3408
- borderTop: "none",
3409
- borderLeft: "none",
3410
- borderBottom: "1px solid rgba(128,128,128,0.3)",
3411
- borderRight: groupEndsAtLastCol ? "none" : "1px solid rgba(128,128,128,0.3)",
3412
3413
  fontWeight: 500,
3413
3414
  userSelect: "none",
3414
3415
  ...group.style,
3415
- ...styles.header
3416
+ ...styles.header,
3417
+ borderTop: "none",
3418
+ borderLeft: "none",
3419
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
3420
+ borderRight: groupEndsAtLastCol ? "none" : "1px solid rgba(128,128,128,0.2)"
3416
3421
  },
3417
3422
  children: group.title
3418
3423
  },
@@ -3444,10 +3449,6 @@ function BoltTable({
3444
3449
  textOverflow: "ellipsis",
3445
3450
  whiteSpace: "nowrap",
3446
3451
  boxSizing: "border-box",
3447
- borderTop: "none",
3448
- borderLeft: "none",
3449
- borderBottom: "1px solid rgba(128,128,128,0.3)",
3450
- borderRight: "1px solid rgba(128,128,128,0.3)",
3451
3452
  position: "sticky",
3452
3453
  left: columnOffsets.get("__select__") ?? 0,
3453
3454
  top: 0,
@@ -3455,7 +3456,11 @@ function BoltTable({
3455
3456
  width: "48px",
3456
3457
  gridRow: leafGridRow,
3457
3458
  ...styles.header,
3458
- ...styles.pinnedHeader
3459
+ ...styles.pinnedHeader,
3460
+ borderTop: "none",
3461
+ borderLeft: "none",
3462
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
3463
+ borderRight: "1px solid rgba(128,128,128,0.2)"
3459
3464
  },
3460
3465
  children: rowSelection.type !== "radio" && !rowSelection.hideSelectAll && /* @__PURE__ */ jsx5(
3461
3466
  "input",
@@ -3514,10 +3519,6 @@ function BoltTable({
3514
3519
  textOverflow: "ellipsis",
3515
3520
  whiteSpace: "nowrap",
3516
3521
  boxSizing: "border-box",
3517
- borderTop: "none",
3518
- borderLeft: "none",
3519
- borderBottom: "1px solid rgba(128,128,128,0.3)",
3520
- borderRight: "1px solid rgba(128,128,128,0.3)",
3521
3522
  position: "sticky",
3522
3523
  left: columnOffsets.get("__expand__") ?? 0,
3523
3524
  top: 0,
@@ -3526,7 +3527,11 @@ function BoltTable({
3526
3527
  backgroundColor: styles.pinnedBg,
3527
3528
  gridRow: leafGridRow,
3528
3529
  ...styles.header,
3529
- ...styles.pinnedHeader
3530
+ ...styles.pinnedHeader,
3531
+ borderTop: "none",
3532
+ borderLeft: "none",
3533
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
3534
+ borderRight: "1px solid rgba(128,128,128,0.2)"
3530
3535
  }
3531
3536
  },
3532
3537
  "__expand__"
@@ -3744,7 +3749,7 @@ function BoltTable({
3744
3749
  alignItems: "center",
3745
3750
  justifyContent: "center",
3746
3751
  fontSize: 12,
3747
- opacity: currentPage === 1 ? 0.3 : 1,
3752
+ opacity: currentPage === 1 ? 0.2 : 1,
3748
3753
  background: "none",
3749
3754
  border: "none",
3750
3755
  padding: 0,
@@ -3770,7 +3775,7 @@ function BoltTable({
3770
3775
  alignItems: "center",
3771
3776
  justifyContent: "center",
3772
3777
  fontSize: 12,
3773
- opacity: currentPage === 1 ? 0.3 : 1,
3778
+ opacity: currentPage === 1 ? 0.2 : 1,
3774
3779
  background: "none",
3775
3780
  border: "none",
3776
3781
  padding: 0,
@@ -3842,7 +3847,7 @@ function BoltTable({
3842
3847
  alignItems: "center",
3843
3848
  justifyContent: "center",
3844
3849
  fontSize: 12,
3845
- opacity: currentPage === totalPages ? 0.3 : 1,
3850
+ opacity: currentPage === totalPages ? 0.2 : 1,
3846
3851
  background: "none",
3847
3852
  border: "none",
3848
3853
  padding: 0,
@@ -3868,7 +3873,7 @@ function BoltTable({
3868
3873
  alignItems: "center",
3869
3874
  justifyContent: "center",
3870
3875
  fontSize: 12,
3871
- opacity: currentPage === totalPages ? 0.3 : 1,
3876
+ opacity: currentPage === totalPages ? 0.2 : 1,
3872
3877
  background: "none",
3873
3878
  border: "none",
3874
3879
  padding: 0,
@@ -3943,7 +3948,7 @@ function BoltTable({
3943
3948
  textOverflow: "ellipsis",
3944
3949
  whiteSpace: "nowrap",
3945
3950
  borderRadius: 6,
3946
- border: "1px dashed rgba(128,128,128,0.3)",
3951
+ border: "1px dashed rgba(128,128,128,0.2)",
3947
3952
  boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
3948
3953
  backdropFilter: "blur(16px)",
3949
3954
  WebkitBackdropFilter: "blur(16px)",
@@ -4196,44 +4201,60 @@ function BoltTable({
4196
4201
  }
4197
4202
  }
4198
4203
  ),
4199
- menuCol.columnCellContextMenuItems.map((item) => /* @__PURE__ */ jsxs5(
4200
- "button",
4201
- {
4202
- type: "button",
4203
- "data-bt-ctx-item": "",
4204
- disabled: item.disabled,
4205
- style: {
4206
- ...btnStyle,
4207
- cursor: item.disabled ? "not-allowed" : "pointer",
4208
- opacity: item.disabled ? 0.5 : 1,
4209
- color: item.danger ? "#ef4444" : "inherit"
4210
- },
4211
- onClick: () => {
4212
- if (menuRecord) {
4213
- item.onClick(menuCol.key, menuRecord, menuRowIndex);
4214
- }
4215
- setCellContextMenu(null);
4216
- },
4217
- children: [
4218
- item.icon && /* @__PURE__ */ jsx5(
4219
- "span",
4220
- {
4221
- style: {
4222
- display: "flex",
4223
- width: 14,
4224
- height: 14,
4225
- alignItems: "center",
4226
- justifyContent: "center",
4227
- flexShrink: 0
4228
- },
4229
- children: item.icon
4204
+ menuCol.columnCellContextMenuItems.map((item) => {
4205
+ const resolvedIcon = typeof item.icon === "function" ? menuRecord ? item.icon(
4206
+ menuCol.key,
4207
+ menuRecord,
4208
+ menuRowIndex
4209
+ ) : null : item.icon;
4210
+ const resolvedLabel = typeof item.label === "function" ? menuRecord ? item.label(
4211
+ menuCol.key,
4212
+ menuRecord,
4213
+ menuRowIndex
4214
+ ) : null : item.label;
4215
+ return /* @__PURE__ */ jsxs5(
4216
+ "button",
4217
+ {
4218
+ type: "button",
4219
+ "data-bt-ctx-item": "",
4220
+ disabled: item.disabled,
4221
+ style: {
4222
+ ...btnStyle,
4223
+ cursor: item.disabled ? "not-allowed" : "pointer",
4224
+ opacity: item.disabled ? 0.5 : 1,
4225
+ color: item.danger ? "#ef4444" : "inherit"
4226
+ },
4227
+ onClick: () => {
4228
+ if (menuRecord && item.onClick) {
4229
+ item.onClick(
4230
+ menuCol.key,
4231
+ menuRecord,
4232
+ menuRowIndex
4233
+ );
4230
4234
  }
4231
- ),
4232
- item.label
4233
- ]
4234
- },
4235
- item.key
4236
- ))
4235
+ setCellContextMenu(null);
4236
+ },
4237
+ children: [
4238
+ resolvedIcon && /* @__PURE__ */ jsx5(
4239
+ "span",
4240
+ {
4241
+ style: {
4242
+ display: "flex",
4243
+ width: 14,
4244
+ height: 14,
4245
+ alignItems: "center",
4246
+ justifyContent: "center",
4247
+ flexShrink: 0
4248
+ },
4249
+ children: resolvedIcon
4250
+ }
4251
+ ),
4252
+ resolvedLabel
4253
+ ]
4254
+ },
4255
+ item.key
4256
+ );
4257
+ })
4237
4258
  ] })
4238
4259
  ]
4239
4260
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bolt-table",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "Virtualized React table with column drag & drop, pinning, resizing, sorting, filtering, and pagination.",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",