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