bolt-table 0.1.38 → 0.1.40

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
@@ -184,7 +184,8 @@ var DraggableHeader = import_react.default.memo(
184
184
  headerGridRow = 1,
185
185
  headerHeight = 36,
186
186
  stickyTop = 0,
187
- isFirstColumn = false
187
+ isFirstColumn = false,
188
+ onAutoFitColumn
188
189
  }) => {
189
190
  const effectivelySortable = isColumnSortable(column);
190
191
  const effectivelyFilterable = !disabledFilters && isColumnFilterable(column);
@@ -252,6 +253,12 @@ var DraggableHeader = import_react.default.memo(
252
253
  if (column.pinned) return;
253
254
  onResizeStart?.(column.key, e);
254
255
  };
256
+ const handleResizeDoubleClick = (e) => {
257
+ e.preventDefault();
258
+ e.stopPropagation();
259
+ if (column.pinned) return;
260
+ onAutoFitColumn?.(column.key);
261
+ };
255
262
  const columnWidth = column.width ?? 150;
256
263
  const widthPx = `${columnWidth}px`;
257
264
  const isPinned = Boolean(column.pinned);
@@ -399,7 +406,8 @@ var DraggableHeader = import_react.default.memo(
399
406
  padding: 0
400
407
  },
401
408
  onMouseDown: handleResizeStart,
402
- "aria-label": `Resize ${column.key} column`,
409
+ onDoubleClick: handleResizeDoubleClick,
410
+ "aria-label": `Resize ${column.key} column (double-click to auto-fit)`,
403
411
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
404
412
  "div",
405
413
  {
@@ -1490,7 +1498,8 @@ var TableBody = ({
1490
1498
  enableDynamicRowHeight = false,
1491
1499
  onRowHeightChange,
1492
1500
  columnGridIndexMap,
1493
- cellStyleFn
1501
+ cellStyleFn,
1502
+ onRowDragStart
1494
1503
  }) => {
1495
1504
  const virtualItems = rowVirtualizer.getVirtualItems();
1496
1505
  const totalSize = rowVirtualizer.getTotalSize();
@@ -1572,6 +1581,7 @@ var TableBody = ({
1572
1581
  "div",
1573
1582
  {
1574
1583
  "data-row-key": rowKey,
1584
+ "data-row-index": virtualRow.index,
1575
1585
  "data-column-key": col.key,
1576
1586
  "data-bt-cell": "",
1577
1587
  "data-selected": isSelected || void 0,
@@ -1584,7 +1594,45 @@ var TableBody = ({
1584
1594
  height: enableDynamicRowHeight ? void 0 : `${virtualRow.size}px`,
1585
1595
  minHeight: enableDynamicRowHeight ? `${rowHeight}px` : void 0
1586
1596
  },
1587
- children: enableDynamicRowHeight && onRowHeightChange && colIndex === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1597
+ children: col.key === "__drag__" && onRowDragStart ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1598
+ "div",
1599
+ {
1600
+ style: {
1601
+ height: `${rowHeight}px`,
1602
+ display: "flex",
1603
+ alignItems: "center",
1604
+ justifyContent: "center",
1605
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
1606
+ ...rowSty
1607
+ },
1608
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1609
+ "span",
1610
+ {
1611
+ "data-bt-row-grip": "",
1612
+ onPointerDown: (e) => {
1613
+ if (e.button !== 0) return;
1614
+ onRowDragStart(virtualRow.index, e);
1615
+ },
1616
+ style: {
1617
+ display: "flex",
1618
+ alignItems: "center",
1619
+ justifyContent: "center",
1620
+ touchAction: "none",
1621
+ width: "100%",
1622
+ height: "100%"
1623
+ },
1624
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1625
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "5", r: "1" }),
1626
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "12", r: "1" }),
1627
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "19", r: "1" }),
1628
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "5", r: "1" }),
1629
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "12", r: "1" }),
1630
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "19", r: "1" })
1631
+ ] })
1632
+ }
1633
+ )
1634
+ }
1635
+ ) : enableDynamicRowHeight && onRowHeightChange && colIndex === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1588
1636
  DynamicRowMeasurer,
1589
1637
  {
1590
1638
  index: virtualRow.index,
@@ -2079,7 +2127,9 @@ function BoltTable({
2079
2127
  onAIQuery,
2080
2128
  onAIResponse,
2081
2129
  aiPlaceholder = "Ask AI anything about your data...",
2082
- aiButtonLabel
2130
+ aiButtonLabel,
2131
+ rowDragEnabled = false,
2132
+ onRowReorder
2083
2133
  }) {
2084
2134
  const data = (0, import_react4.useMemo)(() => {
2085
2135
  if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
@@ -2276,6 +2326,7 @@ function BoltTable({
2276
2326
  }
2277
2327
  });
2278
2328
  const [showSavedFilters, setShowSavedFilters] = (0, import_react4.useState)(false);
2329
+ const [justSavedFilter, setJustSavedFilter] = (0, import_react4.useState)(false);
2279
2330
  const savedFiltersRef = (0, import_react4.useRef)(null);
2280
2331
  import_react4.default.useEffect(() => {
2281
2332
  if (!showSavedFilters) return;
@@ -2297,6 +2348,8 @@ function BoltTable({
2297
2348
  localStorage.setItem(aiFiltersStorageKey, JSON.stringify(next));
2298
2349
  } catch {
2299
2350
  }
2351
+ setJustSavedFilter(true);
2352
+ setTimeout(() => setJustSavedFilter(false), 1500);
2300
2353
  }, [aiResult, aiQuery, savedAIFilters, aiFiltersStorageKey]);
2301
2354
  const removeSavedFilter = (0, import_react4.useCallback)((index) => {
2302
2355
  const next = savedAIFilters.filter((_, i) => i !== index);
@@ -2510,17 +2563,29 @@ function BoltTable({
2510
2563
  }, []);
2511
2564
  const getRowKey = (0, import_react4.useCallback)(
2512
2565
  (record, index) => {
2513
- if (record == null) return String(index);
2566
+ if (record == null) return `__row_${index}`;
2514
2567
  try {
2515
- if (typeof rowKey === "function") return String(rowKey(record));
2568
+ if (typeof rowKey === "function") {
2569
+ const result = rowKey(record);
2570
+ const str = String(result);
2571
+ if (str === "undefined" || str === "null" || str === "NaN" || str === "") {
2572
+ return `__row_${index}`;
2573
+ }
2574
+ return str;
2575
+ }
2516
2576
  if (typeof rowKey === "string") {
2517
2577
  const val = record[rowKey];
2518
- return val != null ? String(val) : String(index);
2578
+ if (val == null) return `__row_${index}`;
2579
+ const str = String(val);
2580
+ if (str === "undefined" || str === "null" || str === "NaN" || str === "") {
2581
+ return `__row_${index}`;
2582
+ }
2583
+ return str;
2519
2584
  }
2520
2585
  } catch {
2521
- return String(index);
2586
+ return `__row_${index}`;
2522
2587
  }
2523
- return String(index);
2588
+ return `__row_${index}`;
2524
2589
  },
2525
2590
  [rowKey]
2526
2591
  );
@@ -2554,11 +2619,20 @@ function BoltTable({
2554
2619
  (record, index) => {
2555
2620
  if (record == null) return index;
2556
2621
  try {
2557
- if (typeof rowKey === "function") return rowKey(record);
2622
+ if (typeof rowKey === "function") {
2623
+ const result = rowKey(record);
2624
+ if (result == null || typeof result === "number" && Number.isNaN(result)) return index;
2625
+ const str = String(result);
2626
+ if (str === "undefined" || str === "null" || str === "NaN" || str === "") return index;
2627
+ return result;
2628
+ }
2558
2629
  if (typeof rowKey === "string") {
2559
2630
  const val = record[rowKey];
2631
+ if (val == null || typeof val === "number" && Number.isNaN(val)) return index;
2632
+ const str = String(val);
2633
+ if (str === "undefined" || str === "null" || str === "NaN" || str === "") return index;
2560
2634
  if (typeof val === "number" || typeof val === "string") return val;
2561
- return val != null ? String(val) : index;
2635
+ return str;
2562
2636
  }
2563
2637
  } catch {
2564
2638
  return index;
@@ -2645,6 +2719,19 @@ function BoltTable({
2645
2719
  };
2646
2720
  return [selectionColumn, ...columnsWithExpand];
2647
2721
  }, [rowSelection, columnsWithExpand]);
2722
+ const columnsWithDrag = (0, import_react4.useMemo)(() => {
2723
+ if (!rowDragEnabled || !onRowReorder) return columnsWithSelection;
2724
+ const dragColumn = {
2725
+ key: "__drag__",
2726
+ dataIndex: "__drag__",
2727
+ title: "",
2728
+ width: 36,
2729
+ pinned: "left",
2730
+ hidden: false,
2731
+ render: () => null
2732
+ };
2733
+ return [dragColumn, ...columnsWithSelection];
2734
+ }, [rowDragEnabled, onRowReorder, columnsWithSelection]);
2648
2735
  const resizeOverlayRef = (0, import_react4.useRef)(null);
2649
2736
  const tableAreaRef = (0, import_react4.useRef)(null);
2650
2737
  const [scrollAreaWidth, setScrollAreaWidth] = (0, import_react4.useState)(0);
@@ -2727,7 +2814,7 @@ function BoltTable({
2727
2814
  onColumnOrderChangeRef.current = onColumnOrderChange;
2728
2815
  const handleColumnDragStart = (0, import_react4.useCallback)(
2729
2816
  (columnKey, e) => {
2730
- if (columnKey === "__select__" || columnKey === "__expand__") return;
2817
+ if (columnKey === "__select__" || columnKey === "__expand__" || columnKey === "__drag__") return;
2731
2818
  const headerEl = e.currentTarget.closest(
2732
2819
  "[data-column-key]"
2733
2820
  );
@@ -2762,7 +2849,7 @@ function BoltTable({
2762
2849
  let newOverId = null;
2763
2850
  headers.forEach((h) => {
2764
2851
  const key = h.dataset.columnKey;
2765
- if (!key || key === "__select__" || key === "__expand__" || key === columnKey) {
2852
+ if (!key || key === "__select__" || key === "__expand__" || key === "__drag__" || key === columnKey) {
2766
2853
  h.removeAttribute("data-drag-over");
2767
2854
  return;
2768
2855
  }
@@ -2814,16 +2901,97 @@ function BoltTable({
2814
2901
  },
2815
2902
  []
2816
2903
  );
2904
+ const rowDragGhostRef = (0, import_react4.useRef)(null);
2905
+ const rowDragFromRef = (0, import_react4.useRef)(null);
2906
+ const rowDragOverRef = (0, import_react4.useRef)(null);
2907
+ const onRowReorderRef = (0, import_react4.useRef)(onRowReorder);
2908
+ onRowReorderRef.current = onRowReorder;
2909
+ const handleRowDragStart = (0, import_react4.useCallback)(
2910
+ (rowIndex, e) => {
2911
+ if (!onRowReorderRef.current) return;
2912
+ e.preventDefault();
2913
+ rowDragFromRef.current = rowIndex;
2914
+ rowDragOverRef.current = null;
2915
+ const target = e.currentTarget.closest("[data-row-key]");
2916
+ const rowHeight2 = target?.offsetHeight ?? 40;
2917
+ const ghost = rowDragGhostRef.current;
2918
+ if (ghost) {
2919
+ ghost.textContent = `Row ${rowIndex + 1}`;
2920
+ ghost.style.display = "flex";
2921
+ ghost.style.left = `${e.clientX + 12}px`;
2922
+ ghost.style.top = `${e.clientY - 12}px`;
2923
+ ghost.style.height = `${Math.min(rowHeight2, 36)}px`;
2924
+ }
2925
+ const grabStyle = document.createElement("style");
2926
+ grabStyle.textContent = "* { cursor: grabbing !important; }";
2927
+ document.head.appendChild(grabStyle);
2928
+ const scrollEl = tableAreaRef.current;
2929
+ const onMove = (ev) => {
2930
+ if (ghost) {
2931
+ ghost.style.left = `${ev.clientX + 12}px`;
2932
+ ghost.style.top = `${ev.clientY - 12}px`;
2933
+ }
2934
+ if (!scrollEl) return;
2935
+ const cells = scrollEl.querySelectorAll("[data-bt-cell][data-row-key]");
2936
+ let closestIdx = null;
2937
+ let closestDist = Infinity;
2938
+ cells.forEach((cell) => {
2939
+ const rk = cell.dataset.rowKey;
2940
+ if (!rk) return;
2941
+ const rect = cell.getBoundingClientRect();
2942
+ const midY = rect.top + rect.height / 2;
2943
+ const dist = Math.abs(ev.clientY - midY);
2944
+ if (dist < closestDist) {
2945
+ closestDist = dist;
2946
+ const idxAttr = cell.dataset.rowIndex;
2947
+ if (idxAttr != null) closestIdx = Number(idxAttr);
2948
+ }
2949
+ });
2950
+ scrollEl.querySelectorAll("[data-row-drag-over]").forEach(
2951
+ (el) => el.removeAttribute("data-row-drag-over")
2952
+ );
2953
+ if (closestIdx != null && closestIdx !== rowDragFromRef.current) {
2954
+ rowDragOverRef.current = closestIdx;
2955
+ scrollEl.querySelectorAll(
2956
+ `[data-bt-cell][data-row-index="${closestIdx}"]`
2957
+ ).forEach((el) => el.setAttribute("data-row-drag-over", ""));
2958
+ } else {
2959
+ rowDragOverRef.current = null;
2960
+ }
2961
+ };
2962
+ const onUp = () => {
2963
+ document.removeEventListener("pointermove", onMove);
2964
+ document.removeEventListener("pointerup", onUp);
2965
+ grabStyle.remove();
2966
+ if (ghost) ghost.style.display = "none";
2967
+ if (scrollEl) {
2968
+ scrollEl.querySelectorAll("[data-row-drag-over]").forEach(
2969
+ (el) => el.removeAttribute("data-row-drag-over")
2970
+ );
2971
+ }
2972
+ const from = rowDragFromRef.current;
2973
+ const to = rowDragOverRef.current;
2974
+ if (from != null && to != null && from !== to) {
2975
+ onRowReorderRef.current?.(from, to);
2976
+ }
2977
+ rowDragFromRef.current = null;
2978
+ rowDragOverRef.current = null;
2979
+ };
2980
+ document.addEventListener("pointermove", onMove);
2981
+ document.addEventListener("pointerup", onUp);
2982
+ },
2983
+ []
2984
+ );
2817
2985
  const handleResizeStart = (columnKey, e) => {
2818
2986
  e.preventDefault();
2819
2987
  e.stopPropagation();
2820
- if (columnKey === "__select__" || columnKey === "__expand__") return;
2821
- const columnIndex = columnsWithSelection.findIndex(
2988
+ if (columnKey === "__select__" || columnKey === "__expand__" || columnKey === "__drag__") return;
2989
+ const columnIndex = columnsWithDrag.findIndex(
2822
2990
  (col) => col.key === columnKey
2823
2991
  );
2824
2992
  if (columnIndex === -1) return;
2825
- if (columnsWithSelection[columnIndex].pinned) return;
2826
- const column = columnsWithSelection[columnIndex];
2993
+ if (columnsWithDrag[columnIndex].pinned) return;
2994
+ const column = columnsWithDrag[columnIndex];
2827
2995
  const startWidth = column.width ?? 150;
2828
2996
  resizeStateRef.current = {
2829
2997
  columnKey,
@@ -2880,9 +3048,50 @@ function BoltTable({
2880
3048
  });
2881
3049
  onColumnResize?.(columnKey, finalWidth);
2882
3050
  }, [onColumnResize]);
3051
+ const handleAutoFitColumn = (0, import_react4.useCallback)((columnKey) => {
3052
+ const scrollEl = tableAreaRef.current;
3053
+ if (!scrollEl) return;
3054
+ const col = columnsWithDrag.find((c) => c.key === columnKey);
3055
+ if (!col) return;
3056
+ const headerEl = scrollEl.querySelector(
3057
+ `[data-column-key="${columnKey}"] [data-bt-grip]`
3058
+ )?.parentElement ?? scrollEl.querySelector(`[data-column-key="${columnKey}"]`);
3059
+ let maxWidth = 0;
3060
+ if (headerEl) {
3061
+ const title = typeof col.title === "string" ? col.title : col.key;
3062
+ const canvas = document.createElement("canvas");
3063
+ const ctx = canvas.getContext("2d");
3064
+ if (ctx) {
3065
+ const computedStyle = window.getComputedStyle(headerEl);
3066
+ ctx.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;
3067
+ maxWidth = ctx.measureText(title).width + 60;
3068
+ }
3069
+ }
3070
+ const cells = scrollEl.querySelectorAll(
3071
+ `[data-bt-cell][data-column-key="${columnKey}"]`
3072
+ );
3073
+ cells.forEach((cell) => {
3074
+ const inner = cell.querySelector("div > div");
3075
+ if (inner) {
3076
+ const scrollW = inner.scrollWidth;
3077
+ if (scrollW > maxWidth) maxWidth = scrollW;
3078
+ }
3079
+ });
3080
+ const finalWidth = Math.max(60, Math.min(Math.ceil(maxWidth) + 24, 800));
3081
+ manuallyResizedRef.current.add(columnKey);
3082
+ import_react4.default.startTransition(() => {
3083
+ setColumnWidths((prev) => {
3084
+ const next = new Map(prev);
3085
+ next.set(columnKey, finalWidth);
3086
+ return next;
3087
+ });
3088
+ });
3089
+ onColumnResize?.(columnKey, finalWidth);
3090
+ }, [columnsWithDrag, onColumnResize]);
2883
3091
  const { leftPinned, unpinned, rightPinned } = (0, import_react4.useMemo)(() => {
2884
- const columnMap = new Map(columnsWithSelection.map((c) => [c.key, c]));
3092
+ const columnMap = new Map(columnsWithDrag.map((c) => [c.key, c]));
2885
3093
  const systemKeys = [
3094
+ ...rowDragEnabled && onRowReorder ? ["__drag__"] : [],
2886
3095
  ...rowSelection ? ["__select__"] : [],
2887
3096
  ...expandable ? ["__expand__"] : []
2888
3097
  ];
@@ -2894,7 +3103,7 @@ function BoltTable({
2894
3103
  else center.push(col);
2895
3104
  });
2896
3105
  return { leftPinned: left, unpinned: center, rightPinned: right };
2897
- }, [columnOrder, columnsWithSelection, rowSelection, expandable]);
3106
+ }, [columnOrder, columnsWithDrag, rowSelection, expandable, rowDragEnabled, onRowReorder]);
2898
3107
  const orderedColumns = (0, import_react4.useMemo)(
2899
3108
  () => [...leftPinned, ...unpinned, ...rightPinned],
2900
3109
  [leftPinned, unpinned, rightPinned]
@@ -2902,7 +3111,7 @@ function BoltTable({
2902
3111
  const freshOrderedColumns = (0, import_react4.useMemo)(() => {
2903
3112
  const latestMap = new Map(initialColumnsRef.current.map((c) => [c.key, c]));
2904
3113
  return orderedColumns.map((col) => {
2905
- if (col.key === "__select__" || col.key === "__expand__") return col;
3114
+ if (col.key === "__select__" || col.key === "__expand__" || col.key === "__drag__") return col;
2906
3115
  const latest = latestMap.get(col.key);
2907
3116
  if (!latest) return col;
2908
3117
  return {
@@ -3395,7 +3604,7 @@ function BoltTable({
3395
3604
  return freshOrderedColumns;
3396
3605
  return freshOrderedColumns.filter((col, idx) => {
3397
3606
  if (col.pinned) return true;
3398
- if (col.key === "__select__" || col.key === "__expand__") return true;
3607
+ if (col.key === "__select__" || col.key === "__expand__" || col.key === "__drag__") return true;
3399
3608
  return idx >= visibleColumnRange.start && idx <= visibleColumnRange.end;
3400
3609
  });
3401
3610
  }, [enableColumnVirtualization, visibleColumnRange, freshOrderedColumns]);
@@ -3542,8 +3751,11 @@ function BoltTable({
3542
3751
  [data-bt-resize]:hover [data-bt-resize-line] {
3543
3752
  opacity: 1 !important;
3544
3753
  }
3754
+ [data-bt-ctx-item] {
3755
+ transition: background-color 0.15s ease;
3756
+ }
3545
3757
  [data-bt-ctx-item]:not(:disabled):hover {
3546
- background-color: rgba(128, 128, 128, 0.15);
3758
+ background-color: rgba(128, 128, 128, 0.15) !important;
3547
3759
  }
3548
3760
  [data-bt-header][data-dragging] {
3549
3761
  opacity: 0.2 !important;
@@ -3552,6 +3764,17 @@ function BoltTable({
3552
3764
  border: 1px dashed ${accentColor} !important;
3553
3765
  }
3554
3766
  ${onRowClick ? "[data-bt-cell] { cursor: pointer; }" : ""}
3767
+ [data-row-drag-over] {
3768
+ box-shadow: 0 -2px 0 0 ${accentColor} inset;
3769
+ }
3770
+ [data-bt-row-grip] {
3771
+ cursor: grab;
3772
+ opacity: 0.3;
3773
+ transition: opacity 0.15s;
3774
+ }
3775
+ [data-bt-row-grip]:hover {
3776
+ opacity: 0.8;
3777
+ }
3555
3778
  @keyframes bt-spin { to { transform: rotate(360deg); } }
3556
3779
  @keyframes bt-ai-shimmer {
3557
3780
  0% { background-position: -200% 0; }
@@ -3707,7 +3930,7 @@ function BoltTable({
3707
3930
  marginTop: 4
3708
3931
  },
3709
3932
  children: initialColumns.filter(
3710
- (c) => c.key !== "__select__" && c.key !== "__expand__"
3933
+ (c) => c.key !== "__select__" && c.key !== "__expand__" && c.key !== "__drag__"
3711
3934
  ).map((col) => {
3712
3935
  const current = columns.find(
3713
3936
  (c) => c.key === col.key
@@ -4036,14 +4259,15 @@ function BoltTable({
4036
4259
  {
4037
4260
  type: "button",
4038
4261
  onClick: saveCurrentAIFilter,
4262
+ disabled: justSavedFilter,
4039
4263
  style: {
4040
4264
  display: "flex",
4041
4265
  alignItems: "center",
4042
4266
  gap: 4,
4043
- background: `${accentColor}12`,
4044
- border: `1px solid ${accentColor}30`,
4267
+ background: justSavedFilter ? `${accentColor}25` : `${accentColor}12`,
4268
+ border: `1px solid ${justSavedFilter ? accentColor : `${accentColor}30`}`,
4045
4269
  borderRadius: 4,
4046
- cursor: "pointer",
4270
+ cursor: justSavedFilter ? "default" : "pointer",
4047
4271
  padding: "2px 8px",
4048
4272
  color: accentColor,
4049
4273
  fontSize: 11,
@@ -4051,14 +4275,14 @@ function BoltTable({
4051
4275
  fontWeight: 500,
4052
4276
  transition: "all 0.2s ease"
4053
4277
  },
4054
- title: "Save this filter for quick access later",
4278
+ title: justSavedFilter ? "Filter saved!" : "Save this filter for quick access later",
4055
4279
  children: [
4056
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4280
+ justSavedFilter ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4057
4281
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
4058
4282
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "17 21 17 13 7 13 7 21" }),
4059
4283
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "7 3 7 8 15 8" })
4060
4284
  ] }),
4061
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Save Filter" })
4285
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: justSavedFilter ? "Saved" : "Save Filter" })
4062
4286
  ]
4063
4287
  }
4064
4288
  ),
@@ -4165,7 +4389,7 @@ function BoltTable({
4165
4389
  orderedColumns.map((column) => {
4166
4390
  const isPinned = !!column.pinned;
4167
4391
  const offset = columnOffsets.get(column.key);
4168
- const isSystem = column.key === "__select__" || column.key === "__expand__";
4392
+ const isSystem = column.key === "__select__" || column.key === "__expand__" || column.key === "__drag__";
4169
4393
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4170
4394
  "div",
4171
4395
  {
@@ -4204,7 +4428,7 @@ function BoltTable({
4204
4428
  children: orderedColumns.map((column, colIndex) => {
4205
4429
  const isPinned = !!column.pinned;
4206
4430
  const offset = columnOffsets.get(column.key);
4207
- const isSystem = column.key === "__select__" || column.key === "__expand__";
4431
+ const isSystem = column.key === "__select__" || column.key === "__expand__" || column.key === "__drag__";
4208
4432
  const widthPercent = SHIMMER_WIDTHS2[(rowIndex * 7 + colIndex) % SHIMMER_WIDTHS2.length];
4209
4433
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4210
4434
  "div",
@@ -4414,7 +4638,7 @@ function BoltTable({
4414
4638
  }),
4415
4639
  (() => {
4416
4640
  const firstDataColIndex = orderedColumns.findIndex(
4417
- (c) => c.key !== "__select__" && c.key !== "__expand__"
4641
+ (c) => c.key !== "__select__" && c.key !== "__expand__" && c.key !== "__drag__"
4418
4642
  );
4419
4643
  return orderedColumns.map((column, visualIndex) => {
4420
4644
  const isInGroup = groupedColumnKeySet?.has(column.key) ?? false;
@@ -4491,6 +4715,39 @@ function BoltTable({
4491
4715
  "__select__"
4492
4716
  );
4493
4717
  }
4718
+ if (column.key === "__drag__") {
4719
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4720
+ "div",
4721
+ {
4722
+ "data-bt-header": "",
4723
+ "data-bt-pinned": "",
4724
+ className: `${classNames.header ?? ""} ${classNames.pinnedHeader ?? ""}`,
4725
+ style: {
4726
+ display: "flex",
4727
+ height: leafHeight,
4728
+ alignItems: "center",
4729
+ justifyContent: "center",
4730
+ overflow: "hidden",
4731
+ whiteSpace: "nowrap",
4732
+ boxSizing: "border-box",
4733
+ position: "sticky",
4734
+ left: columnOffsets.get("__drag__") ?? 0,
4735
+ top: 0,
4736
+ zIndex: 13,
4737
+ width: "36px",
4738
+ gridRow: leafGridRow,
4739
+ ...styles.header,
4740
+ ...styles.pinnedHeader,
4741
+ borderTop: "none",
4742
+ borderLeft: "none",
4743
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
4744
+ borderRight: "1px solid rgba(128,128,128,0.2)"
4745
+ },
4746
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GripVerticalIcon, { style: { width: 12, height: 12, opacity: 0.4 } })
4747
+ },
4748
+ "__drag__"
4749
+ );
4750
+ }
4494
4751
  if (column.key === "__expand__") {
4495
4752
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4496
4753
  "div",
@@ -4555,7 +4812,8 @@ function BoltTable({
4555
4812
  disabledFilters,
4556
4813
  headerGridRow: leafGridRow,
4557
4814
  headerHeight: leafHeight,
4558
- stickyTop: leafStickyTop
4815
+ stickyTop: leafStickyTop,
4816
+ onAutoFitColumn: handleAutoFitColumn
4559
4817
  },
4560
4818
  column.key
4561
4819
  );
@@ -4640,7 +4898,8 @@ function BoltTable({
4640
4898
  enableDynamicRowHeight,
4641
4899
  onRowHeightChange: handleRowHeightChange,
4642
4900
  columnGridIndexMap,
4643
- cellStyleFn: aiCellStyleOps.length > 0 ? (record, columnKey) => getAICellStyleForRecord(record, columnKey) : void 0
4901
+ cellStyleFn: aiCellStyleOps.length > 0 ? (record, columnKey) => getAICellStyleForRecord(record, columnKey) : void 0,
4902
+ onRowDragStart: rowDragEnabled && onRowReorder ? handleRowDragStart : void 0
4644
4903
  }
4645
4904
  )
4646
4905
  ]
@@ -4994,6 +5253,35 @@ function BoltTable({
4994
5253
  ),
4995
5254
  document.body
4996
5255
  ),
5256
+ mounted && rowDragEnabled && onRowReorder && (0, import_react_dom2.createPortal)(
5257
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5258
+ "div",
5259
+ {
5260
+ ref: rowDragGhostRef,
5261
+ style: {
5262
+ display: "none",
5263
+ position: "fixed",
5264
+ zIndex: 99999,
5265
+ height: 32,
5266
+ fontSize: 11,
5267
+ alignItems: "center",
5268
+ justifyContent: "center",
5269
+ padding: "0 12px",
5270
+ borderRadius: 6,
5271
+ border: `1px dashed ${accentColor}60`,
5272
+ boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
5273
+ backdropFilter: "blur(16px)",
5274
+ WebkitBackdropFilter: "blur(16px)",
5275
+ backgroundColor: "rgba(128,128,128,0.12)",
5276
+ cursor: "grabbing",
5277
+ pointerEvents: "none",
5278
+ fontWeight: 500,
5279
+ color: accentColor
5280
+ }
5281
+ }
5282
+ ),
5283
+ document.body
5284
+ ),
4997
5285
  cellContextMenu && mounted && (() => {
4998
5286
  const menuCol = freshOrderedColumns.find(
4999
5287
  (c) => c.key === cellContextMenu.columnKey