@dreamtree-org/twreact-ui 1.0.76 → 1.0.78

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
@@ -276,26 +276,6 @@ const ChevronUp = createLucideIcon$1("ChevronUp", [
276
276
  */
277
277
 
278
278
 
279
- const ChevronsLeft = createLucideIcon$1("ChevronsLeft", [
280
- ["path", { d: "m11 17-5-5 5-5", key: "13zhaf" }],
281
- ["path", { d: "m18 17-5-5 5-5", key: "h8a8et" }]
282
- ]);
283
-
284
- /**
285
- * lucide-react v0.0.1 - ISC
286
- */
287
-
288
-
289
- const ChevronsRight = createLucideIcon$1("ChevronsRight", [
290
- ["path", { d: "m6 17 5-5-5-5", key: "xnjwq" }],
291
- ["path", { d: "m13 17 5-5-5-5", key: "17xmmf" }]
292
- ]);
293
-
294
- /**
295
- * lucide-react v0.0.1 - ISC
296
- */
297
-
298
-
299
279
  const EyeOff = createLucideIcon$1("EyeOff", [
300
280
  ["path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24", key: "1jxqfv" }],
301
281
  [
@@ -3903,16 +3883,16 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
3903
3883
  }, error));
3904
3884
  });
3905
3885
 
3906
- var _excluded$k = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "stripedColors", "responsiveBreakpoint", "serverSide", "totalRecords", "pageNumber", "onPageChange"];
3886
+ var _excluded$k = ["data", "columns", "sortable", "filterable", "selectable", "pagination", "pageSize", "onSort", "onFilter", "onFetch", "onFilterChange", "onSelectionChange", "onRowClick", "hasDetails", "DetailsComponent", "className", "withAction", "onAction", "actions", "showSerial", "cellClass", "rowClass", "globalSearch", "limitOptions", "showLimitSelector", "onLimitChange", "showReloadButton", "renderReloadButton", "onReload", "stripedRows", "stripedColors", "responsiveBreakpoint", "serverSide", "totalRecords", "pageNumber"];
3907
3887
  function ownKeys$9(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3908
3888
  function _objectSpread$9(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$9(Object(t), true).forEach(function (r) { _defineProperty$4(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$9(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3909
3889
 
3910
- // Constants moved outside component
3890
+ // Move static default actions outside component to prevent recreation
3911
3891
  var DEFAULT_ACTIONS = [{
3912
3892
  name: "edit",
3913
3893
  label: "Edit",
3914
3894
  onClick: function onClick() {
3915
- console.log("Edit action clicked");
3895
+ return console.log("Edit action clicked");
3916
3896
  },
3917
3897
  icon: /*#__PURE__*/React.createElement(PenSquare, {
3918
3898
  size: 16
@@ -3921,7 +3901,7 @@ var DEFAULT_ACTIONS = [{
3921
3901
  name: "delete",
3922
3902
  label: "Delete",
3923
3903
  onClick: function onClick() {
3924
- console.log("Delete action clicked");
3904
+ return console.log("Delete action clicked");
3925
3905
  },
3926
3906
  icon: /*#__PURE__*/React.createElement(Trash, {
3927
3907
  size: 16
@@ -3930,344 +3910,345 @@ var DEFAULT_ACTIONS = [{
3930
3910
  name: "view",
3931
3911
  label: "View",
3932
3912
  onClick: function onClick() {
3933
- console.log("View action clicked");
3913
+ return console.log("View action clicked");
3934
3914
  },
3935
3915
  icon: /*#__PURE__*/React.createElement(Eye, {
3936
3916
  size: 16
3937
3917
  })
3938
3918
  }];
3939
- var RESIZE_DEBOUNCE_MS = 150;
3940
- var MENU_PLACEMENT_THRESHOLD = 160;
3941
-
3942
- // Helper functions
3943
- var getRowKey = function getRowKey(row, globalIndex) {
3944
- if ((row === null || row === void 0 ? void 0 : row.id) != null) return String(row.id);
3945
- if ((row === null || row === void 0 ? void 0 : row._id) != null) return String(row._id);
3946
- return String(globalIndex);
3947
- };
3948
-
3949
- // Calculate pagination numbers
3950
- var getPaginationNumbers = function getPaginationNumbers(currentPage, totalPages) {
3951
- var maxVisible = 5;
3952
- if (totalPages <= maxVisible) {
3953
- return Array.from({
3954
- length: totalPages
3955
- }, function (_, i) {
3956
- return i + 1;
3957
- });
3958
- }
3959
- if (currentPage <= 3) {
3960
- return Array.from({
3961
- length: maxVisible
3962
- }, function (_, i) {
3963
- return i + 1;
3964
- });
3965
- }
3966
- if (currentPage >= totalPages - 2) {
3967
- return Array.from({
3968
- length: maxVisible
3969
- }, function (_, i) {
3970
- return totalPages - 4 + i;
3971
- });
3972
- }
3973
- return Array.from({
3974
- length: maxVisible
3975
- }, function (_, i) {
3976
- return currentPage - 2 + i;
3977
- });
3978
- };
3979
3919
 
3980
- // Empty and Loading state components
3981
- var EmptyState = function EmptyState() {
3982
- return /*#__PURE__*/React.createElement("div", {
3983
- className: "flex flex-col items-center gap-2"
3984
- }, /*#__PURE__*/React.createElement("div", {
3985
- className: "text-gray-400"
3986
- }, /*#__PURE__*/React.createElement(List, {
3987
- className: "h-8 w-8"
3988
- })), /*#__PURE__*/React.createElement("span", {
3989
- className: "text-sm text-gray-500"
3990
- }, "No results found."));
3991
- };
3992
- var LoadingState = function LoadingState() {
3993
- return /*#__PURE__*/React.createElement("div", {
3994
- className: "flex flex-col items-center gap-2"
3995
- }, /*#__PURE__*/React.createElement("div", {
3996
- className: "h-6 w-6 animate-spin rounded-full border-2 border-primary-600 border-t-transparent"
3997
- }), /*#__PURE__*/React.createElement("span", {
3998
- className: "text-sm text-gray-500"
3999
- }, "Loading..."));
4000
- };
4001
- var Table = function Table(_ref) {
4002
- var _ref$data = _ref.data,
4003
- data = _ref$data === void 0 ? [] : _ref$data,
4004
- _ref$columns = _ref.columns,
4005
- columns = _ref$columns === void 0 ? [] : _ref$columns,
4006
- _ref$sortable = _ref.sortable,
4007
- sortable = _ref$sortable === void 0 ? true : _ref$sortable,
4008
- _ref$filterable = _ref.filterable,
4009
- filterable = _ref$filterable === void 0 ? false : _ref$filterable,
4010
- _ref$selectable = _ref.selectable,
4011
- selectable = _ref$selectable === void 0 ? false : _ref$selectable,
4012
- _ref$pagination = _ref.pagination,
4013
- pagination = _ref$pagination === void 0 ? false : _ref$pagination,
4014
- _ref$pageSize = _ref.pageSize,
4015
- pageSize = _ref$pageSize === void 0 ? 25 : _ref$pageSize,
4016
- onSort = _ref.onSort,
4017
- onFilter = _ref.onFilter,
4018
- onFetch = _ref.onFetch,
4019
- onFilterChange = _ref.onFilterChange,
4020
- onSelectionChange = _ref.onSelectionChange,
4021
- onRowClick = _ref.onRowClick,
4022
- _ref$hasDetails = _ref.hasDetails,
4023
- hasDetails = _ref$hasDetails === void 0 ? false : _ref$hasDetails,
4024
- _ref$DetailsComponent = _ref.DetailsComponent,
4025
- DetailsComponent = _ref$DetailsComponent === void 0 ? null : _ref$DetailsComponent,
4026
- className = _ref.className,
4027
- _ref$withAction = _ref.withAction,
4028
- withAction = _ref$withAction === void 0 ? true : _ref$withAction,
3920
+ // Memoized ActionMenuPortal to prevent unnecessary re-renders
3921
+ var ActionMenuPortal = /*#__PURE__*/React.memo(function ActionMenuPortal(_ref) {
3922
+ var anchorElem = _ref.anchorElem,
3923
+ _ref$actions = _ref.actions,
3924
+ actions = _ref$actions === void 0 ? [] : _ref$actions,
3925
+ anchorRow = _ref.anchorRow,
4029
3926
  onAction = _ref.onAction,
4030
- actions = _ref.actions,
4031
- _ref$showSerial = _ref.showSerial,
4032
- showSerial = _ref$showSerial === void 0 ? true : _ref$showSerial,
4033
- cellClass = _ref.cellClass,
4034
- rowClass = _ref.rowClass,
4035
- _ref$globalSearch = _ref.globalSearch,
4036
- globalSearch = _ref$globalSearch === void 0 ? false : _ref$globalSearch,
4037
- _ref$limitOptions = _ref.limitOptions,
4038
- limitOptions = _ref$limitOptions === void 0 ? [10, 25, 50, 100] : _ref$limitOptions,
4039
- _ref$showLimitSelecto = _ref.showLimitSelector,
4040
- showLimitSelector = _ref$showLimitSelecto === void 0 ? true : _ref$showLimitSelecto,
4041
- onLimitChange = _ref.onLimitChange,
4042
- _ref$showReloadButton = _ref.showReloadButton,
4043
- showReloadButton = _ref$showReloadButton === void 0 ? true : _ref$showReloadButton,
4044
- renderReloadButton = _ref.renderReloadButton,
4045
- onReload = _ref.onReload,
4046
- _ref$stripedRows = _ref.stripedRows,
4047
- stripedRows = _ref$stripedRows === void 0 ? true : _ref$stripedRows,
4048
- _ref$stripedColors = _ref.stripedColors,
4049
- stripedColors = _ref$stripedColors === void 0 ? ["#ffffff", "#f7fafc"] : _ref$stripedColors,
4050
- _ref$responsiveBreakp = _ref.responsiveBreakpoint,
4051
- responsiveBreakpoint = _ref$responsiveBreakp === void 0 ? 768 : _ref$responsiveBreakp,
4052
- _ref$serverSide = _ref.serverSide,
4053
- serverSide = _ref$serverSide === void 0 ? false : _ref$serverSide,
4054
- _ref$totalRecords = _ref.totalRecords,
4055
- totalRecords = _ref$totalRecords === void 0 ? 0 : _ref$totalRecords,
4056
- pageNumber = _ref.pageNumber,
4057
- onPageChange = _ref.onPageChange,
4058
- props = _objectWithoutProperties$1(_ref, _excluded$k);
4059
- // State for responsive view
4060
- var _useState = React.useState(false),
3927
+ menuRef = _ref.menuRef;
3928
+ var _useState = React.useState({
3929
+ left: 0,
3930
+ top: 0,
3931
+ transformOrigin: "top right",
3932
+ maxHeight: 300,
3933
+ width: 180,
3934
+ opacity: 0
3935
+ }),
4061
3936
  _useState2 = _slicedToArray(_useState, 2),
4062
- isMobileView = _useState2[0],
4063
- setIsMobileView = _useState2[1];
3937
+ style = _useState2[0],
3938
+ setStyle = _useState2[1];
3939
+ var menuWidth = 180;
3940
+ var maxMenuHeight = 320;
3941
+ var margin = 8;
3942
+ var minMenuHeight = 80;
3943
+ React.useLayoutEffect(function () {
3944
+ if (!anchorElem) return;
3945
+ var computePosition = function computePosition() {
3946
+ var rect = anchorElem.getBoundingClientRect();
3947
+ var scrollY = window.scrollY || window.pageYOffset;
3948
+ var scrollX = window.scrollX || window.pageXOffset;
3949
+ var spaceBelow = window.innerHeight - rect.bottom;
3950
+ var spaceAbove = rect.top;
3951
+ var placement = "bottom";
3952
+ var allowedMaxHeight;
3953
+ if (spaceBelow < 160 && spaceAbove > spaceBelow) {
3954
+ placement = "top";
3955
+ allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, spaceAbove - margin));
3956
+ } else {
3957
+ allowedMaxHeight = Math.min(maxMenuHeight, Math.max(minMenuHeight, spaceBelow - margin));
3958
+ }
3959
+ var measuredMenuHeight = allowedMaxHeight;
3960
+ var menuEl = menuRef === null || menuRef === void 0 ? void 0 : menuRef.current;
3961
+ if (menuEl) {
3962
+ var contentHeight = menuEl.scrollHeight || menuEl.offsetHeight || allowedMaxHeight;
3963
+ measuredMenuHeight = Math.min(contentHeight, allowedMaxHeight);
3964
+ }
3965
+ var top = placement === "top" ? rect.top + scrollY - measuredMenuHeight - margin : rect.bottom + scrollY + margin;
3966
+ var minTop = margin + scrollY;
3967
+ var maxTop = window.innerHeight + scrollY - measuredMenuHeight - margin;
3968
+ top = Math.max(minTop, Math.min(top, maxTop));
3969
+ var left = rect.right + scrollX - menuWidth;
3970
+ left = Math.max(margin, Math.min(left, window.innerWidth - menuWidth - margin));
3971
+ setStyle({
3972
+ left: left,
3973
+ top: top,
3974
+ transformOrigin: placement === "bottom" ? "top right" : "bottom right",
3975
+ maxHeight: allowedMaxHeight,
3976
+ width: menuWidth,
3977
+ opacity: 1
3978
+ });
3979
+ };
3980
+ computePosition();
3981
+ var onScrollOrResize = function onScrollOrResize() {
3982
+ window.requestAnimationFrame(computePosition);
3983
+ };
3984
+ window.addEventListener("resize", onScrollOrResize);
3985
+ window.addEventListener("scroll", onScrollOrResize, true);
3986
+ return function () {
3987
+ window.removeEventListener("resize", onScrollOrResize);
3988
+ window.removeEventListener("scroll", onScrollOrResize, true);
3989
+ };
3990
+ }, [anchorElem, menuRef]);
3991
+ return /*#__PURE__*/React.createElement("div", {
3992
+ ref: menuRef,
3993
+ style: {
3994
+ position: "absolute",
3995
+ top: style.top,
3996
+ left: style.left,
3997
+ width: style.width,
3998
+ maxHeight: style.maxHeight,
3999
+ transformOrigin: style.transformOrigin,
4000
+ opacity: style.opacity
4001
+ },
4002
+ className: "absolute z-50 bg-white rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 overflow-y-auto transition-opacity duration-150 ease-out",
4003
+ onClick: function onClick(e) {
4004
+ return e.stopPropagation();
4005
+ }
4006
+ }, /*#__PURE__*/React.createElement("div", {
4007
+ className: "p-1"
4008
+ }, actions.length === 0 ? /*#__PURE__*/React.createElement("div", {
4009
+ className: "px-3 py-2 text-sm text-gray-500"
4010
+ }, "No actions") : actions.map(function (action) {
4011
+ return /*#__PURE__*/React.createElement("div", {
4012
+ key: action.name,
4013
+ className: "px-1"
4014
+ }, /*#__PURE__*/React.createElement("button", {
4015
+ className: "w-full text-left px-3 py-2 text-sm hover:bg-gray-100 flex items-center gap-2 rounded-md",
4016
+ onClick: function onClick(e) {
4017
+ e.stopPropagation();
4018
+ onAction === null || onAction === void 0 || onAction(action, anchorRow);
4019
+ }
4020
+ }, action.render ? action.render(anchorRow) : /*#__PURE__*/React.createElement(React.Fragment, null, action.icon && /*#__PURE__*/React.createElement("span", {
4021
+ className: "inline-flex"
4022
+ }, action.icon), /*#__PURE__*/React.createElement("span", null, action.label))));
4023
+ })));
4024
+ });
4064
4025
 
4065
- // Keep original table data / loading
4066
- var _useState3 = React.useState(function () {
4026
+ // Custom hook for click-outside detection (consolidates 3 handlers into 1)
4027
+ function useClickOutside(refs, isActive, onClickOutside) {
4028
+ React.useEffect(function () {
4029
+ if (!isActive) return;
4030
+ var handler = function handler(e) {
4031
+ var isOutside = refs.every(function (ref) {
4032
+ return !ref.current || !ref.current.contains(e.target);
4033
+ });
4034
+ if (isOutside) onClickOutside();
4035
+ };
4036
+ document.addEventListener("click", handler);
4037
+ return function () {
4038
+ return document.removeEventListener("click", handler);
4039
+ };
4040
+ }, [refs, isActive, onClickOutside]);
4041
+ }
4042
+
4043
+ // Helper to get row key - stable function
4044
+ var getRowKey = function getRowKey(row, globalIndex) {
4045
+ if (row == null) return String(globalIndex);
4046
+ if (row.id !== undefined && row.id !== null) return String(row.id);
4047
+ if (row._id !== undefined && row._id !== null) return String(row._id);
4048
+ return String(globalIndex);
4049
+ };
4050
+ var Table = function Table(_ref2) {
4051
+ var _ref2$data = _ref2.data,
4052
+ data = _ref2$data === void 0 ? [] : _ref2$data,
4053
+ _ref2$columns = _ref2.columns,
4054
+ columns = _ref2$columns === void 0 ? [] : _ref2$columns,
4055
+ _ref2$sortable = _ref2.sortable,
4056
+ sortable = _ref2$sortable === void 0 ? true : _ref2$sortable,
4057
+ _ref2$filterable = _ref2.filterable,
4058
+ filterable = _ref2$filterable === void 0 ? false : _ref2$filterable,
4059
+ _ref2$selectable = _ref2.selectable,
4060
+ selectable = _ref2$selectable === void 0 ? false : _ref2$selectable,
4061
+ _ref2$pagination = _ref2.pagination,
4062
+ pagination = _ref2$pagination === void 0 ? false : _ref2$pagination,
4063
+ _ref2$pageSize = _ref2.pageSize,
4064
+ pageSize = _ref2$pageSize === void 0 ? 25 : _ref2$pageSize,
4065
+ onSort = _ref2.onSort,
4066
+ onFilter = _ref2.onFilter,
4067
+ onFetch = _ref2.onFetch,
4068
+ onFilterChange = _ref2.onFilterChange,
4069
+ onSelectionChange = _ref2.onSelectionChange,
4070
+ onRowClick = _ref2.onRowClick,
4071
+ _ref2$hasDetails = _ref2.hasDetails,
4072
+ hasDetails = _ref2$hasDetails === void 0 ? false : _ref2$hasDetails,
4073
+ _ref2$DetailsComponen = _ref2.DetailsComponent,
4074
+ DetailsComponent = _ref2$DetailsComponen === void 0 ? null : _ref2$DetailsComponen,
4075
+ className = _ref2.className,
4076
+ _ref2$withAction = _ref2.withAction,
4077
+ withAction = _ref2$withAction === void 0 ? true : _ref2$withAction,
4078
+ onAction = _ref2.onAction,
4079
+ actions = _ref2.actions,
4080
+ _ref2$showSerial = _ref2.showSerial,
4081
+ showSerial = _ref2$showSerial === void 0 ? true : _ref2$showSerial,
4082
+ cellClass = _ref2.cellClass,
4083
+ rowClass = _ref2.rowClass,
4084
+ _ref2$globalSearch = _ref2.globalSearch,
4085
+ globalSearch = _ref2$globalSearch === void 0 ? false : _ref2$globalSearch,
4086
+ _ref2$limitOptions = _ref2.limitOptions,
4087
+ limitOptions = _ref2$limitOptions === void 0 ? [10, 25, 50, 100] : _ref2$limitOptions,
4088
+ _ref2$showLimitSelect = _ref2.showLimitSelector,
4089
+ showLimitSelector = _ref2$showLimitSelect === void 0 ? true : _ref2$showLimitSelect,
4090
+ onLimitChange = _ref2.onLimitChange,
4091
+ _ref2$showReloadButto = _ref2.showReloadButton,
4092
+ showReloadButton = _ref2$showReloadButto === void 0 ? true : _ref2$showReloadButto,
4093
+ renderReloadButton = _ref2.renderReloadButton,
4094
+ onReload = _ref2.onReload,
4095
+ _ref2$stripedRows = _ref2.stripedRows,
4096
+ stripedRows = _ref2$stripedRows === void 0 ? true : _ref2$stripedRows,
4097
+ _ref2$stripedColors = _ref2.stripedColors,
4098
+ stripedColors = _ref2$stripedColors === void 0 ? ["#ffffff", "#f7fafc"] : _ref2$stripedColors,
4099
+ _ref2$responsiveBreak = _ref2.responsiveBreakpoint,
4100
+ responsiveBreakpoint = _ref2$responsiveBreak === void 0 ? 768 : _ref2$responsiveBreak,
4101
+ _ref2$serverSide = _ref2.serverSide,
4102
+ serverSide = _ref2$serverSide === void 0 ? false : _ref2$serverSide,
4103
+ _ref2$totalRecords = _ref2.totalRecords,
4104
+ totalRecords = _ref2$totalRecords === void 0 ? 0 : _ref2$totalRecords,
4105
+ pageNumber = _ref2.pageNumber,
4106
+ props = _objectWithoutProperties$1(_ref2, _excluded$k);
4107
+ // Core state
4108
+ var _useState3 = React.useState(false),
4109
+ _useState4 = _slicedToArray(_useState3, 2),
4110
+ isMobileView = _useState4[0],
4111
+ setIsMobileView = _useState4[1];
4112
+ var _useState5 = React.useState(function () {
4067
4113
  return Array.isArray(data) ? data : [];
4068
4114
  }),
4069
- _useState4 = _slicedToArray(_useState3, 2),
4070
- tableData = _useState4[0],
4071
- setTableData = _useState4[1];
4072
- var _useState5 = React.useState(false),
4073
4115
  _useState6 = _slicedToArray(_useState5, 2),
4074
- loading = _useState6[0],
4075
- _setLoading = _useState6[1];
4116
+ tableData = _useState6[0],
4117
+ setTableData = _useState6[1];
4118
+ var _useState7 = React.useState(false),
4119
+ _useState8 = _slicedToArray(_useState7, 2),
4120
+ loading = _useState8[0],
4121
+ setLoading = _useState8[1];
4122
+ var _useState9 = React.useState(pageSize),
4123
+ _useState0 = _slicedToArray(_useState9, 2),
4124
+ limit = _useState0[0],
4125
+ setLimit = _useState0[1];
4126
+ var _useState1 = React.useState(function () {
4127
+ return typeof pageNumber === "number" ? pageNumber : 1;
4128
+ }),
4129
+ _useState10 = _slicedToArray(_useState1, 2),
4130
+ currentPage = _useState10[0],
4131
+ setCurrentPage = _useState10[1];
4076
4132
 
4077
- // Column visibility state
4078
- var _useState7 = React.useState(function () {
4133
+ // Column state
4134
+ var _useState11 = React.useState(function () {
4079
4135
  return Array.isArray(columns) ? columns.map(function (c) {
4080
4136
  return _objectSpread$9({}, c);
4081
4137
  }) : [];
4082
4138
  }),
4083
- _useState8 = _slicedToArray(_useState7, 2),
4084
- columnsState = _useState8[0],
4085
- setColumnsState = _useState8[1];
4086
- React.useEffect(function () {
4087
- // Sync when prop changes - only update if columns actually changed
4088
- if (Array.isArray(columns)) {
4089
- setColumnsState(function (prev) {
4090
- var prevKeys = new Set(prev.map(function (c) {
4091
- return c.key;
4092
- }));
4093
- var newKeys = new Set(columns.map(function (c) {
4094
- return c.key;
4095
- }));
4096
- var keysChanged = prevKeys.size !== newKeys.size || _toConsumableArray$1(prevKeys).some(function (k) {
4097
- return !newKeys.has(k);
4098
- });
4099
- if (keysChanged) {
4100
- return columns.map(function (c) {
4101
- return _objectSpread$9({}, c);
4102
- });
4103
- }
4104
- return prev;
4105
- });
4106
- }
4107
- }, [columns]);
4108
-
4109
- // Popover state for column toggler
4110
- var _useState9 = React.useState(false),
4111
- _useState0 = _slicedToArray(_useState9, 2),
4112
- showColumnMenu = _useState0[0],
4113
- setShowColumnMenu = _useState0[1];
4114
- var columnMenuRef = React.useRef(null);
4115
- var columnToggleBtnRef = React.useRef(null);
4116
- var _useState1 = React.useState(pageSize),
4117
- _useState10 = _slicedToArray(_useState1, 2),
4118
- limit = _useState10[0],
4119
- setLimit = _useState10[1];
4139
+ _useState12 = _slicedToArray(_useState11, 2),
4140
+ columnsState = _useState12[0],
4141
+ setColumnsState = _useState12[1];
4142
+ var _useState13 = React.useState(false),
4143
+ _useState14 = _slicedToArray(_useState13, 2),
4144
+ showColumnMenu = _useState14[0],
4145
+ setShowColumnMenu = _useState14[1];
4120
4146
 
4121
- // Other states
4122
- var _useState11 = React.useState({
4147
+ // Sorting/filtering state
4148
+ var _useState15 = React.useState({
4123
4149
  key: null,
4124
4150
  direction: "asc"
4125
4151
  }),
4126
- _useState12 = _slicedToArray(_useState11, 2),
4127
- sortConfig = _useState12[0],
4128
- setSortConfig = _useState12[1];
4129
- var _useState13 = React.useState(new Set()),
4130
- _useState14 = _slicedToArray(_useState13, 2),
4131
- selectedRows = _useState14[0],
4132
- setSelectedRows = _useState14[1];
4133
- var _useState15 = React.useState(new Set()),
4134
4152
  _useState16 = _slicedToArray(_useState15, 2),
4135
- expandedRows = _useState16[0],
4136
- setExpandedRows = _useState16[1];
4137
- var _useState17 = React.useState(typeof pageNumber === "number" ? pageNumber : 1),
4153
+ sortConfig = _useState16[0],
4154
+ setSortConfig = _useState16[1];
4155
+ var _useState17 = React.useState({}),
4138
4156
  _useState18 = _slicedToArray(_useState17, 2),
4139
- currentPage = _useState18[0],
4140
- setCurrentPage = _useState18[1];
4141
- var _useState19 = React.useState({}),
4157
+ filters = _useState18[0],
4158
+ setFilters = _useState18[1];
4159
+ var _useState19 = React.useState(""),
4142
4160
  _useState20 = _slicedToArray(_useState19, 2),
4143
- filters = _useState20[0],
4144
- setFilters = _useState20[1];
4145
- var _useState21 = React.useState(filters.global || ""),
4161
+ searchInput = _useState20[0],
4162
+ setSearchInput = _useState20[1];
4163
+
4164
+ // Selection/expansion state
4165
+ var _useState21 = React.useState(function () {
4166
+ return new Set();
4167
+ }),
4146
4168
  _useState22 = _slicedToArray(_useState21, 2),
4147
- searchInput = _useState22[0],
4148
- setSearchInput = _useState22[1];
4149
- var _useState23 = React.useState(false),
4169
+ selectedRows = _useState22[0],
4170
+ setSelectedRows = _useState22[1];
4171
+ var _useState23 = React.useState(function () {
4172
+ return new Set();
4173
+ }),
4150
4174
  _useState24 = _slicedToArray(_useState23, 2),
4151
- showMobileFilters = _useState24[0],
4152
- setShowMobileFilters = _useState24[1];
4175
+ expandedRows = _useState24[0],
4176
+ setExpandedRows = _useState24[1];
4153
4177
 
4154
- // Popover per-row
4178
+ // Action menu state
4155
4179
  var _useState25 = React.useState(null),
4156
4180
  _useState26 = _slicedToArray(_useState25, 2),
4157
4181
  actionAnchor = _useState26[0],
4158
4182
  setActionAnchor = _useState26[1];
4183
+ var _useState27 = React.useState(false),
4184
+ _useState28 = _slicedToArray(_useState27, 2),
4185
+ showMobileFilters = _useState28[0],
4186
+ setShowMobileFilters = _useState28[1];
4187
+
4188
+ // Refs
4189
+ var columnMenuRef = React.useRef(null);
4190
+ var columnToggleBtnRef = React.useRef(null);
4159
4191
  var actionMenuRef = React.useRef(null);
4160
4192
 
4161
- // Per-row action menu open key
4162
- var _useState27 = React.useState(null),
4163
- _useState28 = _slicedToArray(_useState27, 2),
4164
- openActionKey = _useState28[0],
4165
- setOpenActionKey = _useState28[1];
4193
+ // Actions to use (memoized)
4194
+ var actionsToUse = React.useMemo(function () {
4195
+ return actions !== undefined ? actions : DEFAULT_ACTIONS;
4196
+ }, [actions]);
4197
+
4198
+ // Sync external props
4166
4199
  React.useEffect(function () {
4167
4200
  if (typeof pageNumber === "number" && pageNumber !== currentPage) {
4168
4201
  setCurrentPage(pageNumber);
4169
- // Note: onPageChange is intentionally not called here to avoid loops
4170
- // Parent should handle page changes via controlled component pattern
4171
4202
  }
4172
- }, [pageNumber, currentPage]);
4203
+ }, [pageNumber]); // eslint-disable-line react-hooks/exhaustive-deps
4204
+
4173
4205
  React.useEffect(function () {
4174
4206
  setLimit(pageSize);
4175
4207
  }, [pageSize]);
4208
+ React.useEffect(function () {
4209
+ setColumnsState(Array.isArray(columns) ? columns.map(function (c) {
4210
+ return _objectSpread$9({}, c);
4211
+ }) : []);
4212
+ }, [columns]);
4213
+
4214
+ // Single effect for data sync (consolidated from 3 effects)
4215
+ React.useEffect(function () {
4216
+ if (serverSide || onFetch) return;
4217
+ if (Array.isArray(data)) {
4218
+ setTableData(data);
4219
+ }
4220
+ }, [data, serverSide, onFetch]);
4176
4221
 
4177
- // Check if mobile view with debouncing
4222
+ // Mobile view detection
4178
4223
  React.useEffect(function () {
4179
- var timeoutId;
4180
4224
  var checkMobile = function checkMobile() {
4181
- setIsMobileView(window.innerWidth < responsiveBreakpoint);
4225
+ return setIsMobileView(window.innerWidth < responsiveBreakpoint);
4182
4226
  };
4183
- var debouncedCheck = function debouncedCheck() {
4184
- clearTimeout(timeoutId);
4185
- timeoutId = setTimeout(checkMobile, RESIZE_DEBOUNCE_MS);
4186
- };
4187
-
4188
- // Initial check
4189
4227
  checkMobile();
4190
-
4191
- // Add event listener with debouncing
4192
- window.addEventListener("resize", debouncedCheck);
4228
+ window.addEventListener("resize", checkMobile);
4193
4229
  return function () {
4194
- clearTimeout(timeoutId);
4195
- window.removeEventListener("resize", debouncedCheck);
4230
+ return window.removeEventListener("resize", checkMobile);
4196
4231
  };
4197
4232
  }, [responsiveBreakpoint]);
4198
4233
 
4199
- // Close column menu when clicking outside
4200
- React.useEffect(function () {
4201
- if (!showColumnMenu) return;
4202
- var onDocClick = function onDocClick(e) {
4203
- if (columnMenuRef.current && !columnMenuRef.current.contains(e.target) && columnToggleBtnRef.current && !columnToggleBtnRef.current.contains(e.target)) {
4204
- setShowColumnMenu(false);
4205
- }
4206
- };
4207
- document.addEventListener("click", onDocClick);
4208
- return function () {
4209
- return document.removeEventListener("click", onDocClick);
4210
- };
4211
- }, [showColumnMenu]);
4234
+ // Click-outside handlers (using consolidated hook)
4235
+ var closeColumnMenu = React.useCallback(function () {
4236
+ return setShowColumnMenu(false);
4237
+ }, []);
4238
+ var closeActionMenu = React.useCallback(function () {
4239
+ return setActionAnchor(null);
4240
+ }, []);
4241
+ useClickOutside([columnMenuRef, columnToggleBtnRef], showColumnMenu, closeColumnMenu);
4242
+ useClickOutside([actionMenuRef], !!actionAnchor, closeActionMenu);
4212
4243
 
4213
- // Visible columns derived from columnsState
4244
+ // Visible columns (memoized)
4214
4245
  var visibleColumns = React.useMemo(function () {
4215
4246
  return columnsState.filter(function (col) {
4216
4247
  return col.isVisible !== false;
4217
4248
  });
4218
4249
  }, [columnsState]);
4219
4250
 
4220
- // Memoize actions
4221
- var actionsToUse = React.useMemo(function () {
4222
- return actions !== null && actions !== void 0 ? actions : DEFAULT_ACTIONS;
4223
- }, [actions]);
4224
-
4225
- // Memoize visible count
4226
- var visibleCount = React.useMemo(function () {
4227
- return (showSerial ? 1 : 0) + visibleColumns.length + (selectable ? 1 : 0) + (hasDetails ? 1 : 0) + (withAction ? 1 : 0);
4228
- }, [showSerial, visibleColumns.length, selectable, hasDetails, withAction]);
4229
-
4230
- // Memoize key-to-row mapping for selection
4231
- var keyToRowMap = React.useMemo(function () {
4232
- var map = new Map();
4233
- filteredData.forEach(function (row, i) {
4234
- map.set(getRowKey(row, i), row);
4235
- });
4236
- return map;
4237
- }, [filteredData]);
4238
-
4239
- // Wrapper for setCurrentPage that also calls onPageChange
4240
- var handlePageChange = React.useCallback(function (newPage) {
4241
- setCurrentPage(newPage);
4242
- onPageChange === null || onPageChange === void 0 || onPageChange(newPage);
4243
- }, [onPageChange]);
4244
- var toggleColumnVisibility = React.useCallback(function (key) {
4245
- setColumnsState(function (prev) {
4246
- return prev.map(function (c) {
4247
- return c.key === key ? _objectSpread$9(_objectSpread$9({}, c), {}, {
4248
- isVisible: !(c.isVisible !== false)
4249
- }) : c;
4250
- });
4251
- });
4252
- handlePageChange(1);
4253
- }, [handlePageChange]);
4254
-
4255
- // Handle actions
4256
- var handleOnAction = React.useCallback(function (action, row) {
4257
- var _action$onClick;
4258
- (_action$onClick = action.onClick) === null || _action$onClick === void 0 || _action$onClick.call(action, {
4259
- action: action,
4260
- row: row
4261
- });
4262
- onAction === null || onAction === void 0 || onAction({
4263
- action: action,
4264
- row: row
4265
- });
4266
- setOpenActionKey(null);
4267
- setActionAnchor(null);
4268
- }, [onAction]);
4269
-
4270
- // Sorting
4251
+ // Sorted data (memoized)
4271
4252
  var sortedData = React.useMemo(function () {
4272
4253
  if (serverSide || !sortConfig.key) return tableData;
4273
4254
  var key = sortConfig.key,
@@ -4276,265 +4257,173 @@ var Table = function Table(_ref) {
4276
4257
  var av = a === null || a === void 0 ? void 0 : a[key];
4277
4258
  var bv = b === null || b === void 0 ? void 0 : b[key];
4278
4259
  if (av == null || bv == null) return 0;
4279
- if (typeof av === "number") return direction === "asc" ? av - bv : bv - av;
4260
+ if (typeof av === "number") {
4261
+ return direction === "asc" ? av - bv : bv - av;
4262
+ }
4280
4263
  return direction === "asc" ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av));
4281
4264
  });
4282
4265
  }, [tableData, sortConfig, serverSide]);
4283
4266
 
4284
- // Filtering
4267
+ // Filtered data (memoized)
4285
4268
  var filteredData = React.useMemo(function () {
4286
4269
  if (serverSide || !filterable || !Object.keys(filters).length) return sortedData;
4270
+ var q = (filters.global || "").toLowerCase();
4287
4271
  return sortedData.filter(function (row) {
4288
- // Apply global search filter if present
4289
- if (filters.global) {
4290
- var q = filters.global.toLowerCase();
4291
- var matchesGlobal = Object.values(row || {}).some(function (v) {
4292
- return String(v).toLowerCase().includes(q);
4293
- });
4294
- if (!matchesGlobal) return false;
4295
- }
4296
-
4297
- // Apply column-specific filters
4298
- return visibleColumns.every(function (column) {
4299
- var columnFilter = filters[column.key];
4300
- if (!columnFilter) return true; // No filter for this column
4301
-
4302
- var cellValue = row === null || row === void 0 ? void 0 : row[column.key];
4303
- return String(cellValue || "").toLowerCase().includes(columnFilter.toLowerCase());
4272
+ return Object.values(row || {}).some(function (v) {
4273
+ return String(v).toLowerCase().includes(q);
4304
4274
  });
4305
4275
  });
4306
- }, [sortedData, filters, filterable, serverSide, visibleColumns]);
4276
+ }, [sortedData, filters, filterable, serverSide]);
4307
4277
 
4308
- // Pagination indices - memoized
4278
+ // Pagination calculations (memoized)
4309
4279
  var _useMemo = React.useMemo(function () {
4310
4280
  var start = pagination ? (currentPage - 1) * limit : 0;
4311
4281
  var end = pagination ? start + limit : filteredData.length;
4282
+ var paginated = !pagination || serverSide ? filteredData : filteredData.slice(start, start + limit);
4283
+ var pages = !pagination ? 1 : serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(filteredData.length / limit));
4312
4284
  return {
4313
4285
  startIndex: start,
4314
- endIndex: end
4286
+ endIndex: end,
4287
+ paginatedData: paginated,
4288
+ totalPages: pages
4315
4289
  };
4316
- }, [pagination, currentPage, limit, filteredData.length]),
4290
+ }, [filteredData, pagination, serverSide, currentPage, limit, totalRecords]),
4317
4291
  startIndex = _useMemo.startIndex,
4318
- endIndex = _useMemo.endIndex;
4319
-
4320
- // Paginated view
4321
- var paginatedData = React.useMemo(function () {
4322
- if (!pagination || serverSide) return filteredData;
4323
- var start = (currentPage - 1) * limit;
4324
- return filteredData.slice(start, start + limit);
4325
- }, [filteredData, pagination, serverSide, currentPage, limit]);
4326
- var totalPages = React.useMemo(function () {
4327
- if (!pagination) return 1;
4328
- return serverSide ? Math.max(1, Math.ceil((totalRecords || 0) / limit)) : Math.max(1, Math.ceil(filteredData.length / limit));
4329
- }, [pagination, serverSide, totalRecords, filteredData.length, limit]);
4330
-
4331
- // Sorting handler
4292
+ endIndex = _useMemo.endIndex,
4293
+ paginatedData = _useMemo.paginatedData,
4294
+ totalPages = _useMemo.totalPages;
4295
+
4296
+ // Column count for colspan (memoized)
4297
+ var visibleCount = React.useMemo(function () {
4298
+ return (showSerial ? 1 : 0) + visibleColumns.length + (selectable ? 1 : 0) + (hasDetails ? 1 : 0) + (withAction ? 1 : 0) + 1;
4299
+ },
4300
+ // column toggler
4301
+ [showSerial, visibleColumns.length, selectable, hasDetails, withAction]);
4302
+
4303
+ // Row key map for selection (memoized per filtered data)
4304
+ var rowKeyMap = React.useMemo(function () {
4305
+ return new Map(filteredData.map(function (r, i) {
4306
+ return [getRowKey(r, i), r];
4307
+ }));
4308
+ }, [filteredData]);
4309
+
4310
+ // Callbacks (memoized to prevent child re-renders)
4311
+ var toggleColumnVisibility = React.useCallback(function (key) {
4312
+ setColumnsState(function (prev) {
4313
+ return prev.map(function (c) {
4314
+ return c.key === key ? _objectSpread$9(_objectSpread$9({}, c), {}, {
4315
+ isVisible: !(c.isVisible !== false)
4316
+ }) : c;
4317
+ });
4318
+ });
4319
+ }, []);
4332
4320
  var handleSort = React.useCallback(function (key) {
4333
4321
  if (!sortable) return;
4334
- var direction = sortConfig.key === key && sortConfig.direction === "asc" ? "desc" : "asc";
4335
- setSortConfig({
4336
- key: key,
4337
- direction: direction
4338
- });
4339
- onSort === null || onSort === void 0 || onSort(key, direction);
4340
- }, [sortable, sortConfig, onSort]);
4341
-
4342
- // Selection handlers - optimized with memoized keyToRowMap
4343
- var handleSelectAll = React.useCallback(function () {
4344
- var newSelection = new Set(selectedRows);
4345
- var pageRowKeys = paginatedData.map(function (r, i) {
4346
- return getRowKey(r, startIndex + i);
4322
+ setSortConfig(function (prev) {
4323
+ var direction = prev.key === key && prev.direction === "asc" ? "desc" : "asc";
4324
+ onSort === null || onSort === void 0 || onSort(key, direction);
4325
+ return {
4326
+ key: key,
4327
+ direction: direction
4328
+ };
4347
4329
  });
4348
- var allSelected = pageRowKeys.every(function (k) {
4349
- return newSelection.has(k);
4330
+ }, [sortable, onSort]);
4331
+ var handleFilter = React.useCallback(function (key, value) {
4332
+ setFilters(function (prev) {
4333
+ var newFilters = _objectSpread$9(_objectSpread$9({}, prev), {}, _defineProperty$4({}, key, value));
4334
+ onFilter === null || onFilter === void 0 || onFilter(newFilters);
4335
+ onFilterChange === null || onFilterChange === void 0 || onFilterChange(newFilters);
4336
+ return newFilters;
4350
4337
  });
4351
- if (allSelected) {
4352
- pageRowKeys.forEach(function (k) {
4353
- return newSelection["delete"](k);
4338
+ setCurrentPage(1);
4339
+ }, [onFilter, onFilterChange]);
4340
+ var handleSelectAll = React.useCallback(function () {
4341
+ setSelectedRows(function (prev) {
4342
+ var newSelection = new Set(prev);
4343
+ var pageRowKeys = paginatedData.map(function (r, i) {
4344
+ return getRowKey(r, startIndex + i);
4354
4345
  });
4355
- } else {
4356
- pageRowKeys.forEach(function (k) {
4357
- return newSelection.add(k);
4346
+ var allSelected = pageRowKeys.every(function (k) {
4347
+ return newSelection.has(k);
4358
4348
  });
4359
- }
4360
- setSelectedRows(newSelection);
4361
- var selectedData = Array.from(newSelection).map(function (k) {
4362
- return keyToRowMap.get(k);
4363
- }).filter(Boolean);
4364
- onSelectionChange === null || onSelectionChange === void 0 || onSelectionChange(selectedData);
4365
- }, [selectedRows, paginatedData, startIndex, keyToRowMap, onSelectionChange]);
4349
+ if (allSelected) {
4350
+ pageRowKeys.forEach(function (k) {
4351
+ return newSelection["delete"](k);
4352
+ });
4353
+ } else {
4354
+ pageRowKeys.forEach(function (k) {
4355
+ return newSelection.add(k);
4356
+ });
4357
+ }
4358
+
4359
+ // Notify parent
4360
+ var selectedData = Array.from(newSelection).map(function (k) {
4361
+ return rowKeyMap.get(k);
4362
+ }).filter(Boolean);
4363
+ onSelectionChange === null || onSelectionChange === void 0 || onSelectionChange(selectedData);
4364
+ return newSelection;
4365
+ });
4366
+ }, [paginatedData, startIndex, rowKeyMap, onSelectionChange]);
4366
4367
  var handleSelectRow = React.useCallback(function (row, rowIndexInPage) {
4367
4368
  var globalIndex = startIndex + rowIndexInPage;
4368
4369
  var key = getRowKey(row, globalIndex);
4369
- var newSelection = new Set(selectedRows);
4370
- if (newSelection.has(key)) newSelection["delete"](key);else newSelection.add(key);
4371
- setSelectedRows(newSelection);
4372
- var selectedData = Array.from(newSelection).map(function (k) {
4373
- return keyToRowMap.get(k);
4374
- }).filter(Boolean);
4375
- onSelectionChange === null || onSelectionChange === void 0 || onSelectionChange(selectedData);
4376
- }, [startIndex, selectedRows, keyToRowMap, onSelectionChange]);
4370
+ setSelectedRows(function (prev) {
4371
+ var newSelection = new Set(prev);
4372
+ if (newSelection.has(key)) {
4373
+ newSelection["delete"](key);
4374
+ } else {
4375
+ newSelection.add(key);
4376
+ }
4377
+ var selectedData = Array.from(newSelection).map(function (k) {
4378
+ return rowKeyMap.get(k);
4379
+ }).filter(Boolean);
4380
+ onSelectionChange === null || onSelectionChange === void 0 || onSelectionChange(selectedData);
4381
+ return newSelection;
4382
+ });
4383
+ }, [startIndex, rowKeyMap, onSelectionChange]);
4377
4384
  var toggleExpandRow = React.useCallback(function (row, rowIndexInPage) {
4378
4385
  var globalIndex = startIndex + rowIndexInPage;
4379
4386
  var key = getRowKey(row, globalIndex);
4380
4387
  setExpandedRows(function (prev) {
4381
4388
  var newExpanded = new Set(prev);
4382
- if (newExpanded.has(key)) newExpanded["delete"](key);else newExpanded.add(key);
4389
+ if (newExpanded.has(key)) {
4390
+ newExpanded["delete"](key);
4391
+ } else {
4392
+ newExpanded.add(key);
4393
+ }
4383
4394
  return newExpanded;
4384
4395
  });
4385
4396
  }, [startIndex]);
4386
- var handleFilter = React.useCallback(function (key, value) {
4387
- setFilters(function (prev) {
4388
- var newFilters = _objectSpread$9(_objectSpread$9({}, prev), {}, _defineProperty$4({}, key, value));
4389
- onFilter === null || onFilter === void 0 || onFilter(newFilters);
4390
- onFilterChange === null || onFilterChange === void 0 || onFilterChange(newFilters);
4391
- return newFilters;
4392
- });
4393
- handlePageChange(1);
4394
- }, [onFilter, onFilterChange, handlePageChange]);
4395
- var renderCell = React.useCallback(function (column, row, globalIndex) {
4396
- if (column.render) return column.render(row, globalIndex);
4397
- return row === null || row === void 0 ? void 0 : row[column.key];
4398
- }, []);
4399
4397
  var toggleActions = React.useCallback(function (e, actionCellKey, row) {
4400
4398
  e.stopPropagation();
4401
- if (actionAnchor && actionAnchor.key === actionCellKey) {
4402
- setOpenActionKey(null);
4403
- setActionAnchor(null);
4404
- } else {
4405
- setOpenActionKey(actionCellKey);
4406
- setActionAnchor({
4399
+ setActionAnchor(function (prev) {
4400
+ if (prev && prev.key === actionCellKey) return null;
4401
+ return {
4407
4402
  elem: e.currentTarget,
4408
4403
  key: actionCellKey,
4409
4404
  row: row
4410
- });
4411
- }
4412
- }, [actionAnchor]);
4413
- React.useEffect(function () {
4414
- if (!actionAnchor) return;
4415
- var onDocClick = function onDocClick(ev) {
4416
- if (actionMenuRef.current && (actionMenuRef.current.contains(ev.target) || actionAnchor.elem && actionAnchor.elem.contains(ev.target))) {
4417
- return;
4418
- }
4419
- setOpenActionKey(null);
4420
- setActionAnchor(null);
4421
- };
4422
- var onScrollResize = function onScrollResize() {
4423
- // Close menu on scroll/resize to prevent positioning issues
4424
- setOpenActionKey(null);
4425
- setActionAnchor(null);
4426
- };
4427
- window.addEventListener("click", onDocClick);
4428
- window.addEventListener("scroll", onScrollResize, true);
4429
- window.addEventListener("resize", onScrollResize);
4430
- return function () {
4431
- window.removeEventListener("click", onDocClick);
4432
- window.removeEventListener("scroll", onScrollResize, true);
4433
- window.removeEventListener("resize", onScrollResize);
4434
- };
4435
- }, [actionAnchor]);
4436
-
4437
- // Track previous fetch params to prevent unnecessary calls
4438
- var prevFetchParamsRef = React.useRef(null);
4439
- var isFetchingRef = React.useRef(false);
4440
- var isMountedRef = React.useRef(true);
4441
- var onFetchRef = React.useRef(onFetch);
4442
- var activeFetchIdRef = React.useRef(0);
4443
-
4444
- // Keep ref in sync with onFetch
4445
- React.useEffect(function () {
4446
- onFetchRef.current = onFetch;
4447
- }, [onFetch]);
4448
-
4449
- // Track mount status
4450
- React.useEffect(function () {
4451
- isMountedRef.current = true;
4452
- return function () {
4453
- isMountedRef.current = false;
4454
- isFetchingRef.current = false;
4455
- };
4405
+ };
4406
+ });
4456
4407
  }, []);
4457
-
4458
- // Serialize fetch params for comparison - serialize filters to avoid object reference issues
4459
- var fetchParams = React.useMemo(function () {
4460
- return {
4461
- filters: filters,
4462
- page: currentPage,
4463
- limit: limit,
4464
- sortKey: sortConfig.key,
4465
- sortDirection: sortConfig.direction
4466
- };
4467
- }, [filters, currentPage, limit, sortConfig.key, sortConfig.direction]);
4468
- var fetchParamsString = React.useMemo(function () {
4469
- return JSON.stringify(fetchParams);
4470
- }, [fetchParams]);
4471
-
4472
- // Consolidated data sync effect
4473
- React.useEffect(function () {
4474
- var currentOnFetch = onFetchRef.current;
4475
- if (currentOnFetch) {
4476
- // Only fetch if params actually changed and not already fetching
4477
- if (!isFetchingRef.current && prevFetchParamsRef.current !== fetchParamsString) {
4478
- prevFetchParamsRef.current = fetchParamsString;
4479
- isFetchingRef.current = true;
4480
-
4481
- // Track fetch ID to prevent race conditions
4482
- var fetchId = Date.now();
4483
- activeFetchIdRef.current = fetchId;
4484
- try {
4485
- var result = currentOnFetch({
4486
- setData: function setData(rows) {
4487
- // Only update if component is still mounted and this is the active fetch
4488
- if (isMountedRef.current && activeFetchIdRef.current === fetchId) {
4489
- setTableData(Array.isArray(rows) ? rows : []);
4490
- // Don't set isFetchingRef to false here - let setLoading handle it
4491
- }
4492
- },
4493
- setLoading: function setLoading(loading) {
4494
- // Only update if component is still mounted and this is the active fetch
4495
- if (isMountedRef.current && activeFetchIdRef.current === fetchId) {
4496
- _setLoading(loading);
4497
- if (!loading) {
4498
- isFetchingRef.current = false;
4499
- }
4500
- }
4501
- },
4502
- filters: fetchParams.filters,
4503
- page: fetchParams.page,
4504
- limit: fetchParams.limit,
4505
- sort: {
4506
- key: fetchParams.sortKey,
4507
- direction: fetchParams.sortDirection
4508
- }
4509
- });
4510
-
4511
- // Handle promise if onFetch returns one
4512
- if (result && typeof result.then === "function") {
4513
- result["catch"](function (error) {
4514
- console.error("Table onFetch error:", error);
4515
- if (isMountedRef.current && activeFetchIdRef.current === fetchId) {
4516
- _setLoading(false);
4517
- isFetchingRef.current = false;
4518
- }
4519
- });
4520
- }
4521
- } catch (error) {
4522
- console.error("Table onFetch error:", error);
4523
- if (isMountedRef.current && activeFetchIdRef.current === fetchId) {
4524
- _setLoading(false);
4525
- isFetchingRef.current = false;
4526
- }
4527
- }
4528
- }
4529
- } else if (!serverSide && Array.isArray(data)) {
4530
- setTableData(data);
4531
- }
4532
- }, [serverSide, data, fetchParamsString]);
4533
-
4534
- // Global search
4535
- React.useEffect(function () {
4536
- setSearchInput(filters.global || "");
4537
- }, [filters.global]);
4408
+ var handleOnAction = React.useCallback(function (action, row) {
4409
+ var _action$onClick;
4410
+ (_action$onClick = action.onClick) === null || _action$onClick === void 0 || _action$onClick.call(action, {
4411
+ action: action,
4412
+ row: row
4413
+ });
4414
+ onAction === null || onAction === void 0 || onAction({
4415
+ action: action,
4416
+ row: row
4417
+ });
4418
+ setActionAnchor(null);
4419
+ }, [onAction]);
4420
+ var handleLimitChange = React.useCallback(function (nextLimit) {
4421
+ var parsed = Number(nextLimit);
4422
+ if (!Number.isFinite(parsed) || parsed <= 0) return;
4423
+ setLimit(parsed);
4424
+ setCurrentPage(1);
4425
+ onLimitChange === null || onLimitChange === void 0 || onLimitChange(parsed);
4426
+ }, [onLimitChange]);
4538
4427
  var applyGlobalSearch = React.useCallback(function () {
4539
4428
  handleFilter("global", searchInput);
4540
4429
  }, [handleFilter, searchInput]);
@@ -4544,52 +4433,49 @@ var Table = function Table(_ref) {
4544
4433
  applyGlobalSearch();
4545
4434
  }
4546
4435
  }, [applyGlobalSearch]);
4547
- var handleLimitChange = React.useCallback(function (nextLimit) {
4548
- var parsed = Number(nextLimit);
4549
- if (!Number.isFinite(parsed) || parsed <= 0) return;
4550
- setLimit(parsed);
4551
- handlePageChange(1);
4552
- onLimitChange === null || onLimitChange === void 0 || onLimitChange(parsed);
4553
- }, [onLimitChange, handlePageChange]);
4436
+ var handlePageChange = React.useCallback(function (newPage) {
4437
+ setCurrentPage(newPage);
4438
+ }, []);
4554
4439
 
4555
- // Memoize limit options
4556
- var limitOptionsMemo = React.useMemo(function () {
4557
- var opts = Array.isArray(limitOptions) && limitOptions.length > 0 ? limitOptions : [25, 50, 100];
4558
- return opts.map(function (opt) {
4559
- return {
4560
- label: String(opt),
4561
- value: opt
4562
- };
4440
+ // Data fetching effect
4441
+ React.useEffect(function () {
4442
+ if (!onFetch) return;
4443
+ onFetch({
4444
+ setData: function setData(rows) {
4445
+ return setTableData(Array.isArray(rows) ? rows : []);
4446
+ },
4447
+ setLoading: setLoading,
4448
+ filters: filters,
4449
+ page: currentPage,
4450
+ limit: limit,
4451
+ sort: sortConfig
4563
4452
  });
4564
- }, [limitOptions]);
4453
+ }, [onFetch, filters, currentPage, limit, sortConfig]);
4454
+
4455
+ // Sync searchInput with filters.global
4456
+ React.useEffect(function () {
4457
+ setSearchInput(filters.global || "");
4458
+ }, [filters.global]);
4565
4459
 
4566
- // Extract row metadata computation
4567
- var getRowMetadata = React.useCallback(function (row, rowIndexInPage) {
4460
+ // Render cell helper
4461
+ var renderCell = React.useCallback(function (column, row, globalIndex) {
4462
+ if (column.render) return column.render(row, globalIndex);
4463
+ return row === null || row === void 0 ? void 0 : row[column.key];
4464
+ }, []);
4465
+
4466
+ // Render mobile card
4467
+ var renderMobileCard = React.useCallback(function (row, rowIndexInPage) {
4568
4468
  var globalIndex = startIndex + rowIndexInPage;
4569
4469
  var key = getRowKey(row, globalIndex);
4570
4470
  var actionCellKey = "actions-".concat(key);
4571
- var extraRowClass = typeof rowClass === "function" ? (rowClass({
4471
+ var isSelected = selectedRows.has(key);
4472
+ var isExpanded = expandedRows.has(key);
4473
+ var extraRowClass = typeof rowClass === "function" ? rowClass({
4572
4474
  row: row,
4573
4475
  rowIndex: globalIndex
4574
- }) || "").trim() : "";
4575
- var stripeBg = stripedRows && !selectedRows.has(key) ? stripedColors[globalIndex % stripedColors.length] : undefined;
4576
- return {
4577
- globalIndex: globalIndex,
4578
- key: key,
4579
- actionCellKey: actionCellKey,
4580
- extraRowClass: extraRowClass,
4581
- stripeBg: stripeBg
4582
- };
4583
- }, [startIndex, rowClass, stripedRows, selectedRows, stripedColors]);
4584
-
4585
- // Render mobile card
4586
- var renderMobileCard = React.useCallback(function (row, rowIndexInPage) {
4587
- var _getRowMetadata = getRowMetadata(row, rowIndexInPage),
4588
- globalIndex = _getRowMetadata.globalIndex,
4589
- key = _getRowMetadata.key,
4590
- actionCellKey = _getRowMetadata.actionCellKey,
4591
- extraRowClass = _getRowMetadata.extraRowClass,
4592
- stripeBg = _getRowMetadata.stripeBg;
4476
+ }) : "";
4477
+ var safeExtraRowClass = typeof extraRowClass === "string" ? extraRowClass.trim() : "";
4478
+ var stripeBg = stripedRows && !isSelected ? stripedColors[globalIndex % stripedColors.length] : undefined;
4593
4479
  return /*#__PURE__*/React.createElement("div", {
4594
4480
  key: key,
4595
4481
  style: stripeBg ? {
@@ -4597,9 +4483,9 @@ var Table = function Table(_ref) {
4597
4483
  } : undefined,
4598
4484
  className: cn$1("border rounded-lg mb-3 shadow-sm overflow-hidden transition-all duration-200", {
4599
4485
  "cursor-pointer": !!onRowClick,
4600
- "bg-primary-50 border-primary-200": selectedRows.has(key),
4601
- "hover:shadow-md": !selectedRows.has(key)
4602
- }, extraRowClass),
4486
+ "bg-primary-50 border-primary-200": isSelected,
4487
+ "hover:shadow-md": !isSelected
4488
+ }, safeExtraRowClass),
4603
4489
  onClick: function onClick() {
4604
4490
  return onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row, globalIndex);
4605
4491
  }
@@ -4612,12 +4498,12 @@ var Table = function Table(_ref) {
4612
4498
  e.stopPropagation();
4613
4499
  toggleExpandRow(row, rowIndexInPage);
4614
4500
  },
4615
- "aria-expanded": expandedRows.has(key),
4501
+ "aria-expanded": isExpanded,
4616
4502
  className: "p-1 rounded hover:bg-gray-200"
4617
- }, expandedRows.has(key) ? "▾" : "▸"), selectable && /*#__PURE__*/React.createElement("input", {
4503
+ }, isExpanded ? "▾" : "▸"), selectable && /*#__PURE__*/React.createElement("input", {
4618
4504
  type: "checkbox",
4619
4505
  className: "rounded border-gray-300 h-4 w-4",
4620
- checked: selectedRows.has(key),
4506
+ checked: isSelected,
4621
4507
  onChange: function onChange(e) {
4622
4508
  e.stopPropagation();
4623
4509
  handleSelectRow(row, rowIndexInPage);
@@ -4631,52 +4517,46 @@ var Table = function Table(_ref) {
4631
4517
  className: "relative"
4632
4518
  }, /*#__PURE__*/React.createElement("button", {
4633
4519
  onClick: function onClick(e) {
4634
- e.stopPropagation();
4635
- toggleActions(e, actionCellKey, row);
4520
+ return toggleActions(e, actionCellKey, row);
4636
4521
  },
4637
- "aria-expanded": openActionKey === actionCellKey,
4522
+ "aria-expanded": (actionAnchor === null || actionAnchor === void 0 ? void 0 : actionAnchor.key) === actionCellKey,
4638
4523
  className: "p-1.5 rounded hover:bg-gray-200",
4639
4524
  title: "Actions"
4640
4525
  }, /*#__PURE__*/React.createElement(MoreVertical, {
4641
4526
  className: "h-4 w-4"
4642
- })), actionAnchor && actionAnchor.key === actionCellKey && /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(ActionMenuPortal, {
4527
+ })), (actionAnchor === null || actionAnchor === void 0 ? void 0 : actionAnchor.key) === actionCellKey && /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(ActionMenuPortal, {
4643
4528
  anchorElem: actionAnchor.elem,
4644
4529
  anchorRow: actionAnchor.row,
4645
4530
  actions: actionsToUse,
4646
- onClose: function onClose() {
4647
- setOpenActionKey(null);
4648
- setActionAnchor(null);
4649
- },
4650
4531
  onAction: function onAction(action) {
4651
- handleOnAction(action, row);
4652
- setOpenActionKey(null);
4653
- setActionAnchor(null);
4532
+ return handleOnAction(action, row);
4654
4533
  },
4655
4534
  menuRef: actionMenuRef
4656
4535
  }), document.body))), /*#__PURE__*/React.createElement("div", {
4657
4536
  className: "p-4"
4658
4537
  }, visibleColumns.map(function (column, colIndex) {
4659
- var extraCellClass = typeof cellClass === "function" ? (cellClass({
4538
+ var extraCellClass = typeof cellClass === "function" ? cellClass({
4660
4539
  row: row,
4661
4540
  rowIndex: globalIndex,
4662
4541
  column: column,
4663
4542
  columnIndex: colIndex
4664
- }) || "").trim() : "";
4543
+ }) : "";
4544
+ var safeExtraCellClass = typeof extraCellClass === "string" ? extraCellClass.trim() : "";
4665
4545
  return /*#__PURE__*/React.createElement("div", {
4666
4546
  key: column.key,
4667
- className: cn$1("flex justify-between items-center flex-row py-2 border-b last:border-b-0", extraCellClass)
4547
+ className: cn$1("flex justify-between items-center flex-row py-2 border-b last:border-b-0", safeExtraCellClass)
4668
4548
  }, /*#__PURE__*/React.createElement("div", {
4669
4549
  className: "text-xs font-medium text-gray-500 uppercase tracking-wide mb-1 sm:mb-0 sm:w-1/3 sm:pr-2"
4670
4550
  }, column.label), /*#__PURE__*/React.createElement("div", {
4671
4551
  className: "text-sm text-gray-900 sm:w-2/3 sm:pl-2 break-words"
4672
4552
  }, renderCell(column, row, globalIndex)));
4673
- })), hasDetails && expandedRows.has(key) && DetailsComponent && /*#__PURE__*/React.createElement("div", {
4553
+ })), hasDetails && isExpanded && DetailsComponent && /*#__PURE__*/React.createElement("div", {
4674
4554
  className: "border-t bg-gray-50 p-4"
4675
4555
  }, /*#__PURE__*/React.createElement(DetailsComponent, {
4676
4556
  row: row,
4677
4557
  index: globalIndex
4678
4558
  })));
4679
- }, [getRowMetadata, hasDetails, selectable, showSerial, withAction, expandedRows, selectedRows, onRowClick, visibleColumns, renderCell, cellClass, DetailsComponent, actionsToUse, actionAnchor, openActionKey, handleOnAction, actionMenuRef, toggleActions, toggleExpandRow, handleSelectRow]);
4559
+ }, [startIndex, selectedRows, expandedRows, rowClass, stripedRows, stripedColors, onRowClick, hasDetails, selectable, showSerial, withAction, visibleColumns, cellClass, DetailsComponent, actionsToUse, actionAnchor, toggleExpandRow, handleSelectRow, toggleActions, handleOnAction, renderCell]);
4680
4560
 
4681
4561
  // Render mobile filters
4682
4562
  var renderMobileFilters = React.useCallback(function () {
@@ -4688,12 +4568,14 @@ var Table = function Table(_ref) {
4688
4568
  className: "text-sm font-medium text-gray-700"
4689
4569
  }, "Filters"), /*#__PURE__*/React.createElement("button", {
4690
4570
  onClick: function onClick() {
4691
- return setShowMobileFilters(!showMobileFilters);
4571
+ return setShowMobileFilters(function (s) {
4572
+ return !s;
4573
+ });
4692
4574
  },
4693
4575
  className: "text-xs text-gray-500 hover:text-gray-700"
4694
4576
  }, showMobileFilters ? "Hide" : "Show")), showMobileFilters && /*#__PURE__*/React.createElement("div", {
4695
4577
  className: "space-y-3"
4696
- }, globalSearch && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
4578
+ }, globalSearch && /*#__PURE__*/React.createElement("div", {
4697
4579
  className: "relative"
4698
4580
  }, /*#__PURE__*/React.createElement("input", {
4699
4581
  type: "text",
@@ -4706,7 +4588,7 @@ var Table = function Table(_ref) {
4706
4588
  onKeyDown: onGlobalKeyDown
4707
4589
  }), /*#__PURE__*/React.createElement(Search, {
4708
4590
  className: "absolute right-3 top-2.5 h-4 w-4 text-gray-400"
4709
- }))), filterable && visibleColumns.map(function (column) {
4591
+ })), filterable && visibleColumns.map(function (column) {
4710
4592
  return /*#__PURE__*/React.createElement("div", {
4711
4593
  key: column.key
4712
4594
  }, /*#__PURE__*/React.createElement("label", {
@@ -4721,9 +4603,26 @@ var Table = function Table(_ref) {
4721
4603
  }
4722
4604
  }));
4723
4605
  })));
4724
- }, [showMobileFilters, globalSearch, searchInput, onGlobalKeyDown, filterable, visibleColumns, filters, handleFilter, setShowMobileFilters, setSearchInput]);
4606
+ }, [showMobileFilters, globalSearch, searchInput, onGlobalKeyDown, filterable, visibleColumns, filters, handleFilter]);
4607
+
4608
+ // Check if all page rows are selected
4609
+ var allPageSelected = React.useMemo(function () {
4610
+ if (paginatedData.length === 0) return false;
4611
+ return paginatedData.every(function (r, i) {
4612
+ return selectedRows.has(getRowKey(r, startIndex + i));
4613
+ });
4614
+ }, [paginatedData, selectedRows, startIndex]);
4725
4615
 
4726
- // Render
4616
+ // Limit options for selector
4617
+ var limitOptionsForSelect = React.useMemo(function () {
4618
+ var opts = Array.isArray(limitOptions) && limitOptions.length > 0 ? limitOptions : [25, 50, 100];
4619
+ return opts.map(function (opt) {
4620
+ return {
4621
+ label: String(opt),
4622
+ value: opt
4623
+ };
4624
+ });
4625
+ }, [limitOptions]);
4727
4626
  return /*#__PURE__*/React.createElement("div", {
4728
4627
  className: "w-full border rounded-lg md:rounded-md bg-white"
4729
4628
  }, /*#__PURE__*/React.createElement("div", {
@@ -4744,7 +4643,7 @@ var Table = function Table(_ref) {
4744
4643
  htmlFor: "pagination-limit",
4745
4644
  className: "text-sm text-gray-600 whitespace-nowrap"
4746
4645
  }, "Show"), /*#__PURE__*/React.createElement(Select, {
4747
- options: limitOptionsMemo,
4646
+ options: limitOptionsForSelect,
4748
4647
  value: limit,
4749
4648
  allowClear: false,
4750
4649
  placeholder: "",
@@ -4756,28 +4655,15 @@ var Table = function Table(_ref) {
4756
4655
  className: "flex flex-col sm:flex-row items-start sm:items-center gap-3 w-full md:w-auto"
4757
4656
  }, /*#__PURE__*/React.createElement("div", {
4758
4657
  className: "text-sm text-gray-700 whitespace-nowrap"
4759
- }, filteredData.length === 0 ? 0 : startIndex + 1, " -", " ", Math.min(endIndex, filteredData.length), " of ", filteredData.length, " ", "results"), pagination && /*#__PURE__*/React.createElement("div", {
4658
+ }, filteredData.length === 0 ? 0 : startIndex + 1, " -", " ", Math.min(endIndex, filteredData.length), " of ", filteredData.length, " results"), pagination && /*#__PURE__*/React.createElement("div", {
4760
4659
  className: "flex items-center gap-1"
4761
- }, /*#__PURE__*/React.createElement("div", {
4762
- className: "flex gap-1"
4763
4660
  }, /*#__PURE__*/React.createElement("button", {
4764
- className: "rounded-lg md:rounded-md border border-gray-300 p-2 disabled:opacity-50 hover:bg-gray-50",
4765
- disabled: currentPage === 1,
4766
- onClick: function onClick() {
4767
- return handlePageChange(1);
4768
- },
4769
- "aria-label": "First page",
4770
- title: "First page"
4771
- }, /*#__PURE__*/React.createElement(ChevronsLeft, {
4772
- className: "size-4 md:size-5 text-gray-800"
4773
- })), /*#__PURE__*/React.createElement("button", {
4774
4661
  className: "rounded-lg md:rounded-md border border-gray-300 p-2 disabled:opacity-50 hover:bg-gray-50",
4775
4662
  disabled: currentPage === 1,
4776
4663
  onClick: function onClick() {
4777
4664
  return handlePageChange(Math.max(1, currentPage - 1));
4778
4665
  },
4779
- "aria-label": "Previous page",
4780
- title: "Previous page"
4666
+ "aria-label": "Previous page"
4781
4667
  }, /*#__PURE__*/React.createElement(ChevronLeft, {
4782
4668
  className: "size-4 md:size-5 text-gray-800"
4783
4669
  })), /*#__PURE__*/React.createElement("button", {
@@ -4786,21 +4672,10 @@ var Table = function Table(_ref) {
4786
4672
  onClick: function onClick() {
4787
4673
  return handlePageChange(Math.min(totalPages, currentPage + 1));
4788
4674
  },
4789
- "aria-label": "Next page",
4790
- title: "Next page"
4675
+ "aria-label": "Next page"
4791
4676
  }, /*#__PURE__*/React.createElement(ChevronRight, {
4792
4677
  className: "size-4 md:size-5 text-gray-800"
4793
- })), /*#__PURE__*/React.createElement("button", {
4794
- className: "rounded-lg md:rounded-md border border-gray-300 p-2 disabled:opacity-50 hover:bg-gray-50",
4795
- disabled: currentPage === totalPages,
4796
- onClick: function onClick() {
4797
- return handlePageChange(totalPages);
4798
- },
4799
- "aria-label": "Last page",
4800
- title: "Last page"
4801
- }, /*#__PURE__*/React.createElement(ChevronsRight, {
4802
- className: "size-4 md:size-5 text-gray-800"
4803
- })))))), globalSearch && /*#__PURE__*/React.createElement("div", {
4678
+ }))))), globalSearch && /*#__PURE__*/React.createElement("div", {
4804
4679
  className: "p-4 border-b"
4805
4680
  }, /*#__PURE__*/React.createElement("div", {
4806
4681
  className: "flex flex-col sm:flex-row items-start sm:items-center gap-2"
@@ -4866,9 +4741,7 @@ var Table = function Table(_ref) {
4866
4741
  }, /*#__PURE__*/React.createElement("input", {
4867
4742
  type: "checkbox",
4868
4743
  className: "rounded border-gray-300",
4869
- checked: paginatedData.length > 0 && paginatedData.every(function (r, i) {
4870
- return selectedRows.has(getRowKey(r, startIndex + i));
4871
- }),
4744
+ checked: allPageSelected,
4872
4745
  onChange: handleSelectAll
4873
4746
  })), visibleColumns.map(function (column) {
4874
4747
  return /*#__PURE__*/React.createElement("th", {
@@ -4938,16 +4811,35 @@ var Table = function Table(_ref) {
4938
4811
  }, loading ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
4939
4812
  colSpan: visibleCount,
4940
4813
  className: "px-6 py-8 text-center"
4941
- }, /*#__PURE__*/React.createElement(LoadingState, null))) : paginatedData.length === 0 ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
4814
+ }, /*#__PURE__*/React.createElement("div", {
4815
+ className: "flex flex-col items-center gap-2"
4816
+ }, /*#__PURE__*/React.createElement("div", {
4817
+ className: "h-6 w-6 animate-spin rounded-full border-2 border-primary-600 border-t-transparent"
4818
+ }), /*#__PURE__*/React.createElement("span", {
4819
+ className: "text-sm text-gray-500"
4820
+ }, "Loading...")))) : paginatedData.length === 0 ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
4942
4821
  colSpan: visibleCount,
4943
4822
  className: "px-6 py-8 text-center"
4944
- }, /*#__PURE__*/React.createElement(EmptyState, null))) : paginatedData.map(function (row, rowIndexInPage) {
4945
- var _getRowMetadata2 = getRowMetadata(row, rowIndexInPage),
4946
- globalIndex = _getRowMetadata2.globalIndex,
4947
- key = _getRowMetadata2.key,
4948
- actionCellKey = _getRowMetadata2.actionCellKey,
4949
- extraRowClass = _getRowMetadata2.extraRowClass,
4950
- stripeBg = _getRowMetadata2.stripeBg;
4823
+ }, /*#__PURE__*/React.createElement("div", {
4824
+ className: "flex flex-col items-center gap-2"
4825
+ }, /*#__PURE__*/React.createElement("div", {
4826
+ className: "text-gray-400"
4827
+ }, /*#__PURE__*/React.createElement(List, {
4828
+ className: "h-8 w-8"
4829
+ })), /*#__PURE__*/React.createElement("span", {
4830
+ className: "text-sm text-gray-500"
4831
+ }, "No results found.")))) : paginatedData.map(function (row, rowIndexInPage) {
4832
+ var globalIndex = startIndex + rowIndexInPage;
4833
+ var key = getRowKey(row, globalIndex);
4834
+ var actionCellKey = "actions-".concat(key);
4835
+ var isSelected = selectedRows.has(key);
4836
+ var isExpanded = expandedRows.has(key);
4837
+ var extraRowClass = typeof rowClass === "function" ? rowClass({
4838
+ row: row,
4839
+ rowIndex: globalIndex
4840
+ }) : "";
4841
+ var safeExtraRowClass = typeof extraRowClass === "string" ? extraRowClass.trim() : "";
4842
+ var stripeBg = stripedRows && !isSelected ? stripedColors[globalIndex % stripedColors.length] : undefined;
4951
4843
  return /*#__PURE__*/React.createElement(React.Fragment, {
4952
4844
  key: key
4953
4845
  }, /*#__PURE__*/React.createElement("tr", {
@@ -4956,8 +4848,8 @@ var Table = function Table(_ref) {
4956
4848
  } : undefined,
4957
4849
  className: cn$1("hover:bg-gray-50", {
4958
4850
  "cursor-pointer": !!onRowClick,
4959
- "bg-primary-50": selectedRows.has(key)
4960
- }, extraRowClass),
4851
+ "bg-primary-50": isSelected
4852
+ }, safeExtraRowClass),
4961
4853
  onClick: function onClick() {
4962
4854
  return onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row, globalIndex);
4963
4855
  }
@@ -4968,33 +4860,36 @@ var Table = function Table(_ref) {
4968
4860
  e.stopPropagation();
4969
4861
  toggleExpandRow(row, rowIndexInPage);
4970
4862
  },
4971
- "aria-expanded": expandedRows.has(key),
4863
+ "aria-expanded": isExpanded,
4972
4864
  className: "p-1 rounded hover:bg-gray-100"
4973
- }, expandedRows.has(key) ? "▾" : "▸")), showSerial && /*#__PURE__*/React.createElement("td", {
4865
+ }, isExpanded ? "▾" : "▸")), showSerial && /*#__PURE__*/React.createElement("td", {
4974
4866
  className: "px-4 py-4 whitespace-nowrap text-sm text-gray-900"
4975
4867
  }, globalIndex + 1), selectable && /*#__PURE__*/React.createElement("td", {
4976
4868
  className: "px-6 py-4",
4977
4869
  onClick: function onClick(e) {
4978
- e.stopPropagation();
4870
+ return e.stopPropagation();
4979
4871
  }
4980
4872
  }, /*#__PURE__*/React.createElement("input", {
4981
4873
  type: "checkbox",
4982
4874
  className: "rounded border-gray-300",
4983
- checked: selectedRows.has(key),
4875
+ checked: isSelected,
4984
4876
  onChange: function onChange() {
4985
4877
  return handleSelectRow(row, rowIndexInPage);
4986
4878
  }
4987
4879
  })), visibleColumns.map(function (column, columnIndex) {
4988
- var extraCellClass = typeof cellClass === "function" ? (cellClass({
4880
+ var extraCellClass = typeof cellClass === "function" ? cellClass({
4989
4881
  row: row,
4990
4882
  rowIndex: globalIndex,
4991
4883
  column: column,
4992
4884
  columnIndex: columnIndex
4993
- }) || "").trim() : "";
4885
+ }) : "";
4886
+ var safeExtraCellClass = typeof extraCellClass === "string" ? extraCellClass.trim() : "";
4994
4887
  return /*#__PURE__*/React.createElement("td", {
4995
4888
  key: column.key,
4996
- className: cn$1("px-6 py-4 whitespace-nowrap text-sm text-gray-900", extraCellClass)
4889
+ className: cn$1("px-6 py-4 whitespace-nowrap text-sm text-gray-900", safeExtraCellClass)
4997
4890
  }, renderCell(column, row, globalIndex));
4891
+ }), /*#__PURE__*/React.createElement("td", {
4892
+ className: "px-4 py-4"
4998
4893
  }), withAction && /*#__PURE__*/React.createElement("td", {
4999
4894
  className: "px-4 py-4 text-sm text-right",
5000
4895
  onClick: function onClick(e) {
@@ -5006,39 +4901,47 @@ var Table = function Table(_ref) {
5006
4901
  onClick: function onClick(e) {
5007
4902
  return toggleActions(e, actionCellKey, row);
5008
4903
  },
5009
- "aria-expanded": openActionKey === actionCellKey,
4904
+ "aria-expanded": (actionAnchor === null || actionAnchor === void 0 ? void 0 : actionAnchor.key) === actionCellKey,
5010
4905
  className: "p-1 rounded hover:bg-gray-100",
5011
4906
  title: "Actions"
5012
4907
  }, /*#__PURE__*/React.createElement(MoreVertical, {
5013
4908
  className: "h-4 w-4"
5014
- }))), actionAnchor && actionAnchor.key === actionCellKey && /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(ActionMenuPortal, {
4909
+ }))), (actionAnchor === null || actionAnchor === void 0 ? void 0 : actionAnchor.key) === actionCellKey && /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(ActionMenuPortal, {
5015
4910
  anchorElem: actionAnchor.elem,
5016
4911
  anchorRow: actionAnchor.row,
5017
4912
  actions: actionsToUse,
5018
- onClose: function onClose() {
5019
- setOpenActionKey(null);
5020
- setActionAnchor(null);
5021
- },
5022
4913
  onAction: function onAction(action) {
5023
- handleOnAction(action, row);
5024
- setOpenActionKey(null);
5025
- setActionAnchor(null);
4914
+ return handleOnAction(action, row);
5026
4915
  },
5027
4916
  menuRef: actionMenuRef
5028
- }), document.body))), hasDetails && expandedRows.has(key) && DetailsComponent && /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
4917
+ }), document.body))), hasDetails && isExpanded && DetailsComponent && /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
5029
4918
  colSpan: visibleCount,
5030
4919
  className: "px-6 py-4 bg-gray-50"
5031
- }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(DetailsComponent, {
4920
+ }, /*#__PURE__*/React.createElement(DetailsComponent, {
5032
4921
  row: row,
5033
4922
  index: globalIndex
5034
- })))));
4923
+ }))));
5035
4924
  })))), isMobileView && /*#__PURE__*/React.createElement("div", {
5036
4925
  className: "p-4"
5037
4926
  }, loading ? /*#__PURE__*/React.createElement("div", {
5038
4927
  className: "py-8 text-center"
5039
- }, /*#__PURE__*/React.createElement(LoadingState, null)) : paginatedData.length === 0 ? /*#__PURE__*/React.createElement("div", {
4928
+ }, /*#__PURE__*/React.createElement("div", {
4929
+ className: "flex flex-col items-center gap-2"
4930
+ }, /*#__PURE__*/React.createElement("div", {
4931
+ className: "h-6 w-6 animate-spin rounded-full border-2 border-primary-600 border-t-transparent"
4932
+ }), /*#__PURE__*/React.createElement("span", {
4933
+ className: "text-sm text-gray-500"
4934
+ }, "Loading..."))) : paginatedData.length === 0 ? /*#__PURE__*/React.createElement("div", {
5040
4935
  className: "py-8 text-center"
5041
- }, /*#__PURE__*/React.createElement(EmptyState, null)) : paginatedData.map(function (row, rowIndexInPage) {
4936
+ }, /*#__PURE__*/React.createElement("div", {
4937
+ className: "flex flex-col items-center gap-2"
4938
+ }, /*#__PURE__*/React.createElement("div", {
4939
+ className: "text-gray-400"
4940
+ }, /*#__PURE__*/React.createElement(List, {
4941
+ className: "h-8 w-8"
4942
+ })), /*#__PURE__*/React.createElement("span", {
4943
+ className: "text-sm text-gray-500"
4944
+ }, "No results found."))) : paginatedData.map(function (row, rowIndexInPage) {
5042
4945
  return renderMobileCard(row, rowIndexInPage);
5043
4946
  })), pagination && /*#__PURE__*/React.createElement("div", {
5044
4947
  className: "p-4 border-t"
@@ -5049,17 +4952,6 @@ var Table = function Table(_ref) {
5049
4952
  }, "Page ", currentPage, " of ", totalPages), /*#__PURE__*/React.createElement("div", {
5050
4953
  className: "flex items-center gap-2"
5051
4954
  }, /*#__PURE__*/React.createElement("button", {
5052
- className: "rounded-lg md:rounded-md border border-gray-300 px-3 py-2 text-sm disabled:opacity-50 hover:bg-gray-50 flex items-center gap-1",
5053
- disabled: currentPage === 1,
5054
- onClick: function onClick() {
5055
- return handlePageChange(1);
5056
- },
5057
- title: "First page"
5058
- }, /*#__PURE__*/React.createElement(ChevronsLeft, {
5059
- className: "size-4"
5060
- }), /*#__PURE__*/React.createElement("span", {
5061
- className: "hidden sm:inline"
5062
- }, "First")), /*#__PURE__*/React.createElement("button", {
5063
4955
  className: "rounded-lg md:rounded-md border border-gray-300 px-4 py-2 text-sm disabled:opacity-50 hover:bg-gray-50",
5064
4956
  disabled: currentPage === 1,
5065
4957
  onClick: function onClick() {
@@ -5067,7 +4959,19 @@ var Table = function Table(_ref) {
5067
4959
  }
5068
4960
  }, "Previous"), /*#__PURE__*/React.createElement("div", {
5069
4961
  className: "flex items-center gap-1"
5070
- }, getPaginationNumbers(currentPage, totalPages).map(function (pageNum) {
4962
+ }, Array.from({
4963
+ length: Math.min(5, totalPages)
4964
+ }, function (_, i) {
4965
+ var pageNum;
4966
+ if (totalPages <= 5) {
4967
+ pageNum = i + 1;
4968
+ } else if (currentPage <= 3) {
4969
+ pageNum = i + 1;
4970
+ } else if (currentPage >= totalPages - 2) {
4971
+ pageNum = totalPages - 4 + i;
4972
+ } else {
4973
+ pageNum = currentPage - 2 + i;
4974
+ }
5071
4975
  return /*#__PURE__*/React.createElement("button", {
5072
4976
  key: pageNum,
5073
4977
  className: cn$1("h-8 w-8 rounded-lg md:rounded-md text-sm", {
@@ -5084,174 +4988,9 @@ var Table = function Table(_ref) {
5084
4988
  onClick: function onClick() {
5085
4989
  return handlePageChange(Math.min(totalPages, currentPage + 1));
5086
4990
  }
5087
- }, "Next"), /*#__PURE__*/React.createElement("button", {
5088
- className: "rounded-lg md:rounded-md border border-gray-300 px-3 py-2 text-sm disabled:opacity-50 hover:bg-gray-50 flex items-center gap-1",
5089
- disabled: currentPage === totalPages,
5090
- onClick: function onClick() {
5091
- return handlePageChange(totalPages);
5092
- },
5093
- title: "Last page"
5094
- }, /*#__PURE__*/React.createElement("span", {
5095
- className: "hidden sm:inline"
5096
- }, "Last"), /*#__PURE__*/React.createElement(ChevronsRight, {
5097
- className: "size-4"
5098
- }))))));
4991
+ }, "Next")))));
5099
4992
  };
5100
4993
 
5101
- // ActionMenuPortal constants
5102
- var MENU_WIDTH = 180;
5103
- var MAX_MENU_HEIGHT = 320;
5104
- var MENU_MARGIN = 8;
5105
- var MIN_MENU_HEIGHT = 80;
5106
- function ActionMenuPortal(_ref2) {
5107
- var anchorElem = _ref2.anchorElem,
5108
- anchorRow = _ref2.anchorRow,
5109
- _ref2$actions = _ref2.actions,
5110
- actions = _ref2$actions === void 0 ? [] : _ref2$actions;
5111
- _ref2.onClose;
5112
- var onAction = _ref2.onAction,
5113
- menuRef = _ref2.menuRef;
5114
- var _useState29 = React.useState({
5115
- left: 0,
5116
- top: 0,
5117
- transformOrigin: "top right",
5118
- maxHeight: 300,
5119
- width: MENU_WIDTH,
5120
- opacity: 0
5121
- }),
5122
- _useState30 = _slicedToArray(_useState29, 2),
5123
- style = _useState30[0],
5124
- setStyle = _useState30[1];
5125
-
5126
- // compute position using actual menu height (if available) and layout measurements
5127
- var computePosition = function computePosition() {
5128
- if (!anchorElem) return;
5129
- var rect = anchorElem.getBoundingClientRect();
5130
- var scrollY = window.scrollY || window.pageYOffset;
5131
- var scrollX = window.scrollX || window.pageXOffset;
5132
- var spaceBelow = window.innerHeight - rect.bottom;
5133
- var spaceAbove = rect.top;
5134
-
5135
- // allowed max height based on available space
5136
- var allowedMaxHeight = Math.min(MAX_MENU_HEIGHT, Math.max(MIN_MENU_HEIGHT, Math.max(spaceBelow - MENU_MARGIN, spaceAbove - MENU_MARGIN)));
5137
-
5138
- // choose placement by comparing actual available spaces
5139
- var placement = "bottom";
5140
- if (spaceBelow < MENU_PLACEMENT_THRESHOLD && spaceAbove > spaceBelow) {
5141
- placement = "top";
5142
- // when placing on top we should cap allowedMaxHeight by spaceAbove
5143
- allowedMaxHeight = Math.min(MAX_MENU_HEIGHT, Math.max(MIN_MENU_HEIGHT, spaceAbove - MENU_MARGIN));
5144
- } else {
5145
- // placing bottom: cap by spaceBelow
5146
- allowedMaxHeight = Math.min(MAX_MENU_HEIGHT, Math.max(MIN_MENU_HEIGHT, spaceBelow - MENU_MARGIN));
5147
- }
5148
-
5149
- // measure the menu's content height if we can, and compute the actual menu height we'll use.
5150
- var measuredMenuHeight = allowedMaxHeight;
5151
- var menuEl = menuRef === null || menuRef === void 0 ? void 0 : menuRef.current;
5152
- if (menuEl) {
5153
- // scrollHeight is the content height; offsetHeight may reflect current rendered height.
5154
- var contentHeight = menuEl.scrollHeight || menuEl.offsetHeight || allowedMaxHeight;
5155
- // actual height will be min(contentHeight, allowedMaxHeight)
5156
- measuredMenuHeight = Math.min(contentHeight, allowedMaxHeight);
5157
- }
5158
-
5159
- // compute top according to placement and measuredMenuHeight
5160
- var top;
5161
- if (placement === "top") {
5162
- // place menu so its bottom sits just above the anchor (rect.top - margin)
5163
- top = rect.top + scrollY - measuredMenuHeight - MENU_MARGIN;
5164
- } else {
5165
- // place menu just below the anchor (rect.bottom + margin)
5166
- top = rect.bottom + scrollY + MENU_MARGIN;
5167
- }
5168
-
5169
- // clamp top to viewport (so it never goes off-screen)
5170
- var minTop = MENU_MARGIN + scrollY;
5171
- var maxTop = window.innerHeight + scrollY - measuredMenuHeight - MENU_MARGIN;
5172
- if (top < minTop) top = minTop;
5173
- if (top > maxTop) top = maxTop;
5174
-
5175
- // compute left and clamp horizontally
5176
- var left = rect.right + scrollX - MENU_WIDTH;
5177
- if (left < MENU_MARGIN) left = MENU_MARGIN;
5178
- if (left + MENU_WIDTH > window.innerWidth - MENU_MARGIN) {
5179
- left = Math.max(MENU_MARGIN, window.innerWidth - MENU_WIDTH - MENU_MARGIN);
5180
- }
5181
- var transformOrigin = placement === "bottom" ? "top right" : "bottom right";
5182
-
5183
- // set style (opacity 1 to fade-in)
5184
- setStyle({
5185
- left: left,
5186
- top: top,
5187
- transformOrigin: transformOrigin,
5188
- maxHeight: allowedMaxHeight,
5189
- width: MENU_WIDTH,
5190
- opacity: 1
5191
- });
5192
- };
5193
-
5194
- // useLayoutEffect so the position is measured & applied before paint
5195
- React.useLayoutEffect(function () {
5196
- // compute once after mount
5197
- computePosition();
5198
- var onScrollOrResize = function onScrollOrResize() {
5199
- // using requestAnimationFrame to avoid layout thrash on fast scroll/resize
5200
- window.requestAnimationFrame(function () {
5201
- return computePosition();
5202
- });
5203
- };
5204
- window.addEventListener("resize", onScrollOrResize);
5205
- // capture scrolls (true) so position updates even when scrolling ancestor elements
5206
- window.addEventListener("scroll", onScrollOrResize, true);
5207
- return function () {
5208
- window.removeEventListener("resize", onScrollOrResize);
5209
- window.removeEventListener("scroll", onScrollOrResize, true);
5210
- };
5211
- // Recompute when anchor element changes or actions change (content height may change).
5212
- // Note: menuRef is a ref object and never changes, so it's safe to include
5213
- }, [anchorElem, actions]);
5214
- return /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div", {
5215
- ref: menuRef,
5216
- style: {
5217
- position: "absolute",
5218
- top: style.top,
5219
- left: style.left,
5220
- width: style.width,
5221
- maxHeight: style.maxHeight,
5222
- transformOrigin: style.transformOrigin,
5223
- opacity: style.opacity
5224
- },
5225
- className: "absolute z-50 bg-white rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 overflow-y-auto transition-opacity duration-150 ease-out",
5226
- onClick: function onClick(e) {
5227
- return e.stopPropagation();
5228
- }
5229
- }, /*#__PURE__*/React.createElement("div", {
5230
- className: "p-1"
5231
- }, actions.length === 0 ? /*#__PURE__*/React.createElement("div", {
5232
- className: "px-3 py-2 text-sm text-gray-500"
5233
- }, "No actions") : actions.map(function (action) {
5234
- return /*#__PURE__*/React.createElement("div", {
5235
- key: action.name,
5236
- className: "px-1"
5237
- }, action.render ? /*#__PURE__*/React.createElement("button", {
5238
- className: "w-full text-left px-3 py-2 text-sm hover:bg-gray-100 flex items-center gap-2 rounded-md",
5239
- onClick: function onClick(e) {
5240
- e.stopPropagation();
5241
- onAction === null || onAction === void 0 || onAction(action, anchorRow);
5242
- }
5243
- }, action.render(anchorRow)) : /*#__PURE__*/React.createElement("button", {
5244
- className: "w-full text-left px-3 py-2 text-sm hover:bg-gray-100 flex items-center gap-2 rounded-md",
5245
- onClick: function onClick(e) {
5246
- e.stopPropagation();
5247
- onAction === null || onAction === void 0 || onAction(action, anchorRow);
5248
- }
5249
- }, action.icon && /*#__PURE__*/React.createElement("span", {
5250
- className: "inline-flex"
5251
- }, action.icon), /*#__PURE__*/React.createElement("span", null, action.label)));
5252
- }))), document.body);
5253
- }
5254
-
5255
4994
  var isCheckBoxInput = (element) => element.type === 'checkbox';
5256
4995
 
5257
4996
  var isDateObject = (value) => value instanceof Date;