@cwellt_software/cwellt-reactjs-lib 1.2.5 → 1.2.7

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.cjs.js CHANGED
@@ -1555,12 +1555,12 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
1555
1555
  *
1556
1556
  * @returns React component
1557
1557
  */
1558
- function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, rowSelection }) {
1558
+ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, rowSelection, }) {
1559
1559
  const [currentPage, setCurrentPage] = React.useState(1);
1560
1560
  const [expandedRowKey, setExpandedRowKey] = React.useState(null);
1561
1561
  const [sortConfig, setSortConfig] = React.useState({
1562
1562
  key: null,
1563
- direction: "asc"
1563
+ direction: "asc",
1564
1564
  });
1565
1565
  const [localItemsPerPage, setLocalItemsPerPage] = React.useState(pageSizeOptions[0]);
1566
1566
  const [columnWidths, setColumnWidths] = React.useState(() => columns.reduce((acc, col) => {
@@ -1585,7 +1585,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1585
1585
  onExpand?.(item);
1586
1586
  }, [rowKey, onExpand]);
1587
1587
  const handleSort = React.useCallback((columnKey) => {
1588
- setSortConfig(prev => {
1588
+ setSortConfig((prev) => {
1589
1589
  if (prev.key !== columnKey)
1590
1590
  return { key: columnKey, direction: "asc" };
1591
1591
  if (prev.direction === "asc")
@@ -1612,7 +1612,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1612
1612
  if (typeof aVal === "string" && typeof bVal === "string") {
1613
1613
  const comparison = aVal.localeCompare(bVal, undefined, {
1614
1614
  sensitivity: "base",
1615
- numeric: true
1615
+ numeric: true,
1616
1616
  });
1617
1617
  return comparison * (sortConfig.direction === "asc" ? 1 : -1);
1618
1618
  }
@@ -1628,7 +1628,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1628
1628
  return;
1629
1629
  }
1630
1630
  const itemKey = item[rowKey];
1631
- setSelectedKeys(prev => {
1631
+ setSelectedKeys((prev) => {
1632
1632
  const newSet = new Set(prev);
1633
1633
  if (rowSelection?.type === "single") {
1634
1634
  // Single mode: only one row selected
@@ -1649,7 +1649,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1649
1649
  newSet.add(itemKey);
1650
1650
  }
1651
1651
  }
1652
- const selectedRows = sortedData.filter(item => newSet.has(item[rowKey]));
1652
+ const selectedRows = sortedData.filter((item) => newSet.has(item[rowKey]));
1653
1653
  // Run after render to avoid "Cannot update a component while rendering another component"
1654
1654
  setTimeout(() => {
1655
1655
  rowSelection?.onChange?.(Array.from(newSet), selectedRows);
@@ -1678,7 +1678,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1678
1678
  const startWidth = e.target.parentElement?.offsetWidth || 0;
1679
1679
  const onMouseMove = (moveEvent) => {
1680
1680
  const newWidth = Math.max(startWidth + moveEvent.clientX - startX, 50); // min 50px
1681
- setColumnWidths(prev => ({ ...prev, [key]: newWidth }));
1681
+ setColumnWidths((prev) => ({ ...prev, [key]: newWidth }));
1682
1682
  };
1683
1683
  const onMouseUp = () => {
1684
1684
  window.removeEventListener("mousemove", onMouseMove);
@@ -1691,7 +1691,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1691
1691
  if (stickyHeader || scrollHeight) {
1692
1692
  return {
1693
1693
  maxHeight: scrollHeight ?? 300,
1694
- overflowY: "auto"
1694
+ overflowY: "auto",
1695
1695
  };
1696
1696
  }
1697
1697
  return {}; // no height or scroll
@@ -1707,34 +1707,26 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1707
1707
  if (!paginatedData || paginatedData.length === 0) {
1708
1708
  return (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { colSpan: getColSpan(), className: "cw-table-cell-empty", style: { textAlign: "center" }, children: textNoData }) }));
1709
1709
  }
1710
- return paginatedData.map(item => {
1710
+ return paginatedData.map((item) => {
1711
1711
  const itemKey = item[rowKey];
1712
1712
  if (!itemKey)
1713
1713
  console.warn("Missing row key for item", item);
1714
1714
  const isSelected = selectedKeys.has(itemKey);
1715
- const dynamicClassName = typeof classNameRow === "function"
1716
- ? classNameRow(item)
1717
- : classNameRow ?? "";
1715
+ const dynamicClassName = typeof classNameRow === "function" ? classNameRow(item) : (classNameRow ?? "");
1718
1716
  return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsxs("tr", { className: `${dynamicClassName} ${hasClassNameRow(item) ? item.classNameRow : ""} ${isSelected ? "cw-table-row-selected" : ""}`, onClick: (e) => rowSelection && handleRowClick(item, e), style: {
1719
1717
  cursor: rowSelection ? "pointer" : "default",
1720
1718
  backgroundColor: isSelected ? "var(--cw-color-info-container)" : undefined,
1721
1719
  transition: "background-color 0.2s ease",
1722
- }, children: [expandedRowRender && (jsxRuntime.jsx("td", { className: "cw-table-col-action cw-table-col-expand", children: jsxRuntime.jsx("button", { onClick: () => handleRowExpand(item), className: `cw-button-icon ${expandedRowKey === itemKey
1723
- ? "cwi-chevron-down"
1724
- : "cwi-chevron-right"}` }) })), columns.map(col => (jsxRuntime.jsx("td", { className: col.className ?? "", children: col.render ? col.render(item) : col.dataIndex ? String(item[col.dataIndex]) : "" }, `${itemKey}_${col.key}`)))] }), expandedRowRender && expandedRowKey === itemKey && (jsxRuntime.jsx("tr", { className: "cw-table-row-expanded", children: jsxRuntime.jsx("td", { colSpan: getColSpan(), children: expandedRowRender(item) }) }))] }, String(itemKey)));
1720
+ }, children: [expandedRowRender && (jsxRuntime.jsx("td", { className: "cw-table-col-action cw-table-col-expand", children: jsxRuntime.jsx("button", { onClick: () => handleRowExpand(item), className: `cw-button-icon ${expandedRowKey === itemKey ? "cwi-chevron-down" : "cwi-chevron-right"}` }) })), columns.map((col) => (jsxRuntime.jsx("td", { className: col.className ?? "", children: col.render ? col.render(item) : col.dataIndex ? String(item[col.dataIndex]) : "" }, `${itemKey}_${col.key}`)))] }), expandedRowRender && expandedRowKey === itemKey && (jsxRuntime.jsx("tr", { className: "cw-table-row-expanded", children: jsxRuntime.jsx("td", { colSpan: getColSpan(), children: expandedRowRender(item) }) }))] }, String(itemKey)));
1725
1721
  });
1726
1722
  };
1727
- return (jsxRuntime.jsxs("div", { id: id, className: `cw-table-container ${classNameContainer ?? ""}`, style: style, children: [jsxRuntime.jsx("div", { style: scrollContainerStyle, children: jsxRuntime.jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { style: stickyHeader
1728
- ? { position: "sticky", top: 0, background: "white", zIndex: 2 }
1729
- : undefined, children: jsxRuntime.jsxs("tr", { children: [expandedRowRender && jsxRuntime.jsx("th", {}), columns.map(col => (jsxRuntime.jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${sortConfig.key === col.dataIndex
1730
- ? sortConfig.direction
1731
- : ""}`.trim(), style: {
1723
+ return (jsxRuntime.jsxs("div", { id: id, className: `cw-table-container ${classNameContainer ?? ""}`, style: style, children: [jsxRuntime.jsx("div", { style: scrollContainerStyle, children: jsxRuntime.jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { style: stickyHeader ? { position: "sticky", top: 0, background: "white", zIndex: 2 } : undefined, children: jsxRuntime.jsxs("tr", { children: [expandedRowRender && jsxRuntime.jsx("th", {}), columns.map((col) => (jsxRuntime.jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${sortConfig.key === col.dataIndex ? sortConfig.direction : ""}`.trim(), style: {
1732
1724
  cursor: col.sortable ? "pointer" : "default",
1733
1725
  userSelect: "none",
1734
1726
  width: columnWidths[col.key] ?? col.width,
1735
1727
  ...((col.width || columnWidths[col.key]) && {
1736
1728
  minWidth: 50,
1737
- maxWidth: columnWidths[col.key] ?? col.width
1729
+ maxWidth: columnWidths[col.key] ?? col.width,
1738
1730
  }),
1739
1731
  }, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsxRuntime.jsx("span", { children: col.title }), col.sortable && col.dataIndex && (jsxRuntime.jsx(CwIcon, { size: "large", iconId: sortConfig.key !== col.dataIndex
1740
1732
  ? "sortable"
@@ -1749,7 +1741,214 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
1749
1741
  if (isNaN(value) || value < 1 || value > totalPages) {
1750
1742
  handlePageChange(1);
1751
1743
  }
1752
- }, min: 1, max: totalPages }), jsxRuntime.jsxs("span", { children: ["of ", totalPages] }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right", title: "Next" }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right-double", title: "Last" }), jsxRuntime.jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, children: pageSizeOptions.map(size => (jsxRuntime.jsxs("option", { value: size, children: [size, " / page"] }, size))) })] }))] }));
1744
+ }, min: 1, max: totalPages }), jsxRuntime.jsxs("span", { children: ["of ", totalPages] }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right", title: "Next" }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right-double", title: "Last" }), jsxRuntime.jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, children: pageSizeOptions.map((size) => (jsxRuntime.jsxs("option", { value: size, children: [size, " / page"] }, size))) })] }))] }));
1745
+ }
1746
+
1747
+ /**
1748
+ * A reusable and customizable table component (server-side pagination and sorting).
1749
+ *
1750
+ * @param props - Component props to configure columns, data, styles, pagination, expanded rows, and more.
1751
+ *
1752
+ * @example
1753
+ * // --- Componente padre ---
1754
+ * const columns: Column<User>[] = [
1755
+ * { title: "Name", dataIndex: "name", key: "name", sortable: true },
1756
+ * { title: "Age", dataIndex: "age", key: "age", sortable: true },
1757
+ * { title: "Address", dataIndex: "address", key: "address" }
1758
+ * ];
1759
+ *
1760
+ * // Estado para datos, total y paginación/ordenación
1761
+ * const [tableState, setTableState] = useState<ServerSideTableState<User>>({
1762
+ * page: 1,
1763
+ * pageSize: 5,
1764
+ * sortKey: null,
1765
+ * sortDirection: null
1766
+ * });
1767
+ * const [data, setData] = useState<User[]>([]);
1768
+ * const [totalItems, setTotalItems] = useState(0);
1769
+ * const [loading, setLoading] = useState(false);
1770
+ *
1771
+ * // Simulación de fetch al servidor
1772
+ * useEffect(() => {
1773
+ * setLoading(true);
1774
+ * fetch(`/api/users?page=${tableState.page}&pageSize=${tableState.pageSize}` +
1775
+ * (tableState.sortKey ? `&sortKey=${tableState.sortKey}&sortDirection=${tableState.sortDirection}` : "")
1776
+ * )
1777
+ * .then(res => res.json())
1778
+ * .then(({ items, total }) => {
1779
+ * setData(items);
1780
+ * setTotalItems(total);
1781
+ * })
1782
+ * .finally(() => setLoading(false));
1783
+ * }, [tableState]);
1784
+ *
1785
+ * <CwTableServerSide<User>
1786
+ * columns={columns}
1787
+ * data={data}
1788
+ * totalItems={totalItems}
1789
+ * pagination={true}
1790
+ * pageSizeOptions={[5, 10, 20]}
1791
+ * loading={loading}
1792
+ * serverState={tableState}
1793
+ * onChange={setTableState}
1794
+ * rowKey="id"
1795
+ * textNoData="No data available"
1796
+ * />
1797
+ *
1798
+ * @returns React component
1799
+ */
1800
+ function CwTableServerSide({ columns, data, totalItems, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, rowSelection, onChange, serverState, }) {
1801
+ const [internalState, setInternalState] = React.useState({
1802
+ page: 1,
1803
+ pageSize: pageSizeOptions[0],
1804
+ sortKey: null,
1805
+ sortDirection: null,
1806
+ });
1807
+ const [expandedRowKey, setExpandedRowKey] = React.useState(null);
1808
+ const [columnWidths, setColumnWidths] = React.useState(() => columns.reduce((acc, col) => {
1809
+ if (col.width)
1810
+ acc[col.key] = col.width;
1811
+ return acc;
1812
+ }, {}));
1813
+ const [selectedKeys, setSelectedKeys] = React.useState(new Set(rowSelection?.selectedRowKeys || []));
1814
+ React.useEffect(() => {
1815
+ setSelectedKeys(new Set(rowSelection?.selectedRowKeys || []));
1816
+ }, [rowSelection?.selectedRowKeys]);
1817
+ // Usar estado controlado o interno
1818
+ const state = serverState ?? internalState;
1819
+ // Notificar cambios al padre
1820
+ const triggerChange = React.useCallback((next) => {
1821
+ const newState = { ...state, ...next };
1822
+ if (!serverState)
1823
+ setInternalState(newState);
1824
+ onChange?.(newState);
1825
+ }, [state, serverState, onChange]);
1826
+ const handleItemsPerPageChange = React.useCallback((e) => {
1827
+ triggerChange({ pageSize: parseInt(e.target.value, 10), page: 1 });
1828
+ }, [triggerChange]);
1829
+ const handleRowExpand = React.useCallback((item) => {
1830
+ const itemKey = item[rowKey];
1831
+ setExpandedRowKey((prev) => (prev === itemKey ? null : itemKey));
1832
+ onExpand?.(item);
1833
+ }, [rowKey, onExpand]);
1834
+ const handleSort = React.useCallback((columnKey) => {
1835
+ let nextSortKey = columnKey;
1836
+ let nextSortDirection = "asc";
1837
+ if (state.sortKey === columnKey) {
1838
+ nextSortDirection = state.sortDirection === "asc" ? "desc" : state.sortDirection === "desc" ? null : "asc";
1839
+ if (nextSortDirection === null)
1840
+ nextSortKey = null;
1841
+ }
1842
+ triggerChange({ sortKey: nextSortKey, sortDirection: nextSortDirection, page: 1 });
1843
+ }, [state, triggerChange]);
1844
+ const handleRowClick = React.useCallback((item, e) => {
1845
+ if (e.target.closest(".cw-table-col-expand")) {
1846
+ return;
1847
+ }
1848
+ const itemKey = item[rowKey];
1849
+ setSelectedKeys((prev) => {
1850
+ const newSet = new Set(prev);
1851
+ if (rowSelection?.type === "single") {
1852
+ if (newSet.has(itemKey)) {
1853
+ newSet.clear();
1854
+ }
1855
+ else {
1856
+ newSet.clear();
1857
+ newSet.add(itemKey);
1858
+ }
1859
+ }
1860
+ else {
1861
+ if (newSet.has(itemKey)) {
1862
+ newSet.delete(itemKey);
1863
+ }
1864
+ else {
1865
+ newSet.add(itemKey);
1866
+ }
1867
+ }
1868
+ const selectedRows = data.filter((item) => newSet.has(item[rowKey]));
1869
+ setTimeout(() => {
1870
+ rowSelection?.onChange?.(Array.from(newSet), selectedRows);
1871
+ }, 0);
1872
+ return newSet;
1873
+ });
1874
+ }, [rowSelection, rowKey, data]);
1875
+ const totalPages = React.useMemo(() => {
1876
+ return pagination ? Math.ceil(totalItems / state.pageSize) : 1;
1877
+ }, [totalItems, state.pageSize, pagination]);
1878
+ const handlePageChange = (page) => {
1879
+ if (page >= 1 && page <= totalPages)
1880
+ triggerChange({ page });
1881
+ };
1882
+ const startResize = (e, key) => {
1883
+ e.preventDefault();
1884
+ const startX = e.clientX;
1885
+ const startWidth = e.target.parentElement?.offsetWidth || 0;
1886
+ const onMouseMove = (moveEvent) => {
1887
+ const newWidth = Math.max(startWidth + moveEvent.clientX - startX, 50);
1888
+ setColumnWidths((prev) => ({ ...prev, [key]: newWidth }));
1889
+ };
1890
+ const onMouseUp = () => {
1891
+ window.removeEventListener("mousemove", onMouseMove);
1892
+ window.removeEventListener("mouseup", onMouseUp);
1893
+ };
1894
+ window.addEventListener("mousemove", onMouseMove);
1895
+ window.addEventListener("mouseup", onMouseUp);
1896
+ };
1897
+ const scrollContainerStyle = React.useMemo(() => {
1898
+ if (stickyHeader || scrollHeight) {
1899
+ return {
1900
+ maxHeight: scrollHeight ?? 300,
1901
+ overflowY: "auto",
1902
+ };
1903
+ }
1904
+ return {};
1905
+ }, [stickyHeader, scrollHeight]);
1906
+ const getColSpan = () => columns.length + (expandedRowRender ? 1 : 0);
1907
+ const hasClassNameRow = (item) => {
1908
+ return typeof item === "object" && item !== null && "classNameRow" in item;
1909
+ };
1910
+ const renderTableBody = () => {
1911
+ if (loading) {
1912
+ return (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { colSpan: getColSpan(), children: jsxRuntime.jsx("div", { children: "Loading data..." }) }) }));
1913
+ }
1914
+ if (!data || data.length === 0) {
1915
+ return (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { colSpan: getColSpan(), className: "cw-table-cell-empty", style: { textAlign: "center" }, children: textNoData }) }));
1916
+ }
1917
+ return data.map((item) => {
1918
+ const itemKey = item[rowKey];
1919
+ if (!itemKey)
1920
+ console.warn("Missing row key for item", item);
1921
+ const isSelected = selectedKeys.has(itemKey);
1922
+ const dynamicClassName = typeof classNameRow === "function" ? classNameRow(item) : (classNameRow ?? "");
1923
+ return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsxs("tr", { className: `${dynamicClassName} ${hasClassNameRow(item) ? item.classNameRow : ""} ${isSelected ? "cw-table-row-selected" : ""}`, onClick: (e) => rowSelection && handleRowClick(item, e), style: {
1924
+ cursor: rowSelection ? "pointer" : "default",
1925
+ backgroundColor: isSelected ? "var(--cw-color-info-container)" : undefined,
1926
+ transition: "background-color 0.2s ease",
1927
+ }, children: [expandedRowRender && (jsxRuntime.jsx("td", { className: "cw-table-col-action cw-table-col-expand", children: jsxRuntime.jsx("button", { onClick: () => handleRowExpand(item), className: `cw-button-icon ${expandedRowKey === itemKey ? "cwi-chevron-down" : "cwi-chevron-right"}` }) })), columns.map((col) => (jsxRuntime.jsx("td", { className: col.className ?? "", children: col.render ? col.render(item) : col.dataIndex ? String(item[col.dataIndex]) : "" }, `${itemKey}_${col.key}`)))] }), expandedRowRender && expandedRowKey === itemKey && (jsxRuntime.jsx("tr", { className: "cw-table-row-expanded", children: jsxRuntime.jsx("td", { colSpan: getColSpan(), children: expandedRowRender(item) }) }))] }, String(itemKey)));
1928
+ });
1929
+ };
1930
+ return (jsxRuntime.jsxs("div", { id: id, className: `cw-table-container ${classNameContainer ?? ""}`, style: style, children: [jsxRuntime.jsx("div", { style: scrollContainerStyle, children: jsxRuntime.jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { style: stickyHeader ? { position: "sticky", top: 0, background: "white", zIndex: 2 } : undefined, children: jsxRuntime.jsxs("tr", { children: [expandedRowRender && jsxRuntime.jsx("th", {}), columns.map((col) => (jsxRuntime.jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${state.sortKey === col.dataIndex ? state.sortDirection : ""}`.trim(), style: {
1931
+ cursor: col.sortable ? "pointer" : "default",
1932
+ userSelect: "none",
1933
+ width: columnWidths[col.key] ?? col.width,
1934
+ ...((col.width || columnWidths[col.key]) && {
1935
+ minWidth: 50,
1936
+ maxWidth: columnWidths[col.key] ?? col.width,
1937
+ }),
1938
+ }, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsxRuntime.jsx("span", { children: col.title }), col.sortable && col.dataIndex && (jsxRuntime.jsx(CwIcon, { size: "large", iconId: state.sortKey !== col.dataIndex
1939
+ ? "sortable"
1940
+ : state.sortDirection === "asc"
1941
+ ? "sortable-asc"
1942
+ : "sortable-desc" }))] }), jsxRuntime.jsx("span", { onMouseDown: (e) => startResize(e, col.key), className: "th-column-resizer" })] }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderTableBody() })] }) }), pagination && totalPages > 1 && (jsxRuntime.jsxs("footer", { className: "cw-table-pagination", children: [jsxRuntime.jsx("button", { onClick: () => handlePageChange(1), disabled: state.page === 1 || totalPages === 1, className: "cw-button-icon cwi-chevron-left-double", title: "First" }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(state.page - 1), disabled: state.page === 1 || totalPages === 1, className: "cw-button-icon cwi-chevron-left", title: "Previous" }), jsxRuntime.jsx("input", { type: "text", inputMode: "numeric", value: state.page, onChange: (e) => {
1943
+ const value = parseInt(e.target.value, 10);
1944
+ if (!isNaN(value))
1945
+ handlePageChange(value);
1946
+ }, onBlur: (e) => {
1947
+ const value = parseInt(e.target.value, 10);
1948
+ if (isNaN(value) || value < 1 || value > totalPages) {
1949
+ handlePageChange(1);
1950
+ }
1951
+ }, min: 1, max: totalPages }), jsxRuntime.jsxs("span", { children: ["of ", totalPages] }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right", title: "Next" }), jsxRuntime.jsx("button", { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages === 1, className: "cw-button-icon cwi-chevron-right-double", title: "Last" }), jsxRuntime.jsx("select", { value: state.pageSize, onChange: handleItemsPerPageChange, children: pageSizeOptions.map((size) => (jsxRuntime.jsxs("option", { value: size, children: [size, " / page"] }, size))) })] }))] }));
1753
1952
  }
1754
1953
 
1755
1954
  var styles$e = {"cw-tabs":"cw-tabs-module_cw-tabs__1pmji","badge":"cw-tabs-module_badge__AmVxW","cw-tabs-content":"cw-tabs-module_cw-tabs-content__HTp8d"};
@@ -9331,6 +9530,7 @@ exports.CwSortableList = CwSortableList;
9331
9530
  exports.CwSuperScheduler = CwSuperScheduler;
9332
9531
  exports.CwTable = CwTable;
9333
9532
  exports.CwTableGrouped = CwTableGrouped;
9533
+ exports.CwTableServerSide = CwTableServerSide;
9334
9534
  exports.CwTabs = CwTabs;
9335
9535
  exports.CwTextArea = CwTextArea;
9336
9536
  exports.CwTime = CwTime;