@neukoio/react-table 0.0.2
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/.babelrc +4 -0
- package/README.md +52 -0
- package/dist/Table.js +175 -0
- package/dist/index.js +13 -0
- package/dist/styles.css +3 -0
- package/dist/useWindowSize.js +27 -0
- package/package.json +26 -0
- package/src/Table.js +150 -0
- package/src/index.js +2 -0
- package/src/styles.css +3 -0
- package/src/useWindowSize.js +16 -0
package/.babelrc
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# My React Table Package
|
|
2
|
+
|
|
3
|
+
**`react-table-neuko-io`** is a lightweight, customizable, and reusable table component designed for React applications. Built with React and styled using Tailwind CSS, this package simplifies the creation of interactive and visually appealing tables.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- π¦ **Reusable Components**: Comes with a `Table` and `Button` component out of the box.
|
|
10
|
+
- π¨ **Tailwind CSS Styling**: Fully styled and customizable using Tailwind CSS.
|
|
11
|
+
- π **Ease of Use**: Simple API for quick integration.
|
|
12
|
+
- β‘ **Responsive Design**: Adapts to all screen sizes seamlessly.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Install the package via npm:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install react-table-neuko-io
|
|
22
|
+
```
|
|
23
|
+
---
|
|
24
|
+
## File Structure
|
|
25
|
+
|
|
26
|
+
Hereβs the structure of the package:
|
|
27
|
+
|
|
28
|
+
react-table-neuko-io/
|
|
29
|
+
βββ src/
|
|
30
|
+
β βββ index.js # Entry point for the components
|
|
31
|
+
β βββ Table.js # Table component
|
|
32
|
+
β βββ Button.js # Button component
|
|
33
|
+
β βββ styles.css # Tailwind CSS styles
|
|
34
|
+
β βββ useWindowSize.js # Custom hook for handling responsive design
|
|
35
|
+
βββ dist/ # Transpiled output
|
|
36
|
+
βββ package.json # Package configuration
|
|
37
|
+
βββ .babelrc # Babel configuration
|
|
38
|
+
βββ tailwind.config.js # Tailwind configuration
|
|
39
|
+
βββ postcss.config.js # PostCSS configuration
|
|
40
|
+
βββ README.md # Documentation
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
## Development
|
|
45
|
+
If you'd like to contribute or make changes to the package, follow these steps:
|
|
46
|
+
|
|
47
|
+
Clone the repository:
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
## License
|
|
51
|
+
This project is licensed under the MIT License. See the LICENSE file for more details.
|
|
52
|
+
|
package/dist/Table.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports["default"] = void 0;
|
|
9
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
10
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
11
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
12
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
13
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
14
|
+
require("./styles.css");
|
|
15
|
+
var _useWindowSize = _interopRequireDefault(require("./useWindowSize"));
|
|
16
|
+
var _solid = require("@heroicons/react/20/solid");
|
|
17
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
18
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
|
|
19
|
+
var Table = function Table(_ref) {
|
|
20
|
+
var data = _ref.data,
|
|
21
|
+
columnDefs = _ref.columnDefs,
|
|
22
|
+
_ref$isMoreData = _ref.isMoreData,
|
|
23
|
+
isMoreData = _ref$isMoreData === void 0 ? false : _ref$isMoreData,
|
|
24
|
+
_ref$onLoadMore = _ref.onLoadMore,
|
|
25
|
+
onLoadMore = _ref$onLoadMore === void 0 ? function () {} : _ref$onLoadMore;
|
|
26
|
+
var width = (0, _useWindowSize["default"])();
|
|
27
|
+
|
|
28
|
+
// Get the appropriate column definitions based on the screen size
|
|
29
|
+
var getColumnDefs = function getColumnDefs() {
|
|
30
|
+
if (width >= 640 && width <= 768) return columnDefs.sm || columnDefs["default"];
|
|
31
|
+
if (width >= 769 && width <= 1024) return columnDefs.md || columnDefs["default"];
|
|
32
|
+
if (width >= 1025 && width <= 1280) return columnDefs.lg || columnDefs["default"];
|
|
33
|
+
if (width >= 1281 && width <= 1536) return columnDefs.xl || columnDefs["default"];
|
|
34
|
+
if (width >= 1537) return columnDefs.xxl || columnDefs["default"];
|
|
35
|
+
return columnDefs["default"];
|
|
36
|
+
};
|
|
37
|
+
var currentColumnDefs = getColumnDefs();
|
|
38
|
+
|
|
39
|
+
// Pagination state
|
|
40
|
+
var _useState = (0, _react.useState)(1),
|
|
41
|
+
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
|
|
42
|
+
currentPage = _useState2[0],
|
|
43
|
+
setCurrentPage = _useState2[1];
|
|
44
|
+
var _useState3 = (0, _react.useState)(10),
|
|
45
|
+
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
|
|
46
|
+
itemsPerPage = _useState4[0],
|
|
47
|
+
setItemsPerPage = _useState4[1]; // State for results per page
|
|
48
|
+
|
|
49
|
+
var handleResultsPerPageChange = function handleResultsPerPageChange(value) {
|
|
50
|
+
setItemsPerPage(value);
|
|
51
|
+
setCurrentPage(1); // Reset to the first page when items per page changes
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Get the data for the current page
|
|
55
|
+
var startIndex = (currentPage - 1) * itemsPerPage;
|
|
56
|
+
var currentData = data.slice(startIndex, startIndex + itemsPerPage);
|
|
57
|
+
var totalPages = Math.ceil(data.length / itemsPerPage);
|
|
58
|
+
|
|
59
|
+
// Handle next page logic
|
|
60
|
+
var handleNextPage = /*#__PURE__*/function () {
|
|
61
|
+
var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
|
|
62
|
+
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
63
|
+
while (1) switch (_context.prev = _context.next) {
|
|
64
|
+
case 0:
|
|
65
|
+
if (!(currentPage === totalPages && isMoreData)) {
|
|
66
|
+
_context.next = 3;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
_context.next = 3;
|
|
70
|
+
return onLoadMore();
|
|
71
|
+
case 3:
|
|
72
|
+
// Increase page number after data is loaded (or if data was already loaded)
|
|
73
|
+
setCurrentPage(function (prevPage) {
|
|
74
|
+
return Math.min(prevPage + 1, totalPages + (isMoreData ? 1 : 0));
|
|
75
|
+
});
|
|
76
|
+
case 4:
|
|
77
|
+
case "end":
|
|
78
|
+
return _context.stop();
|
|
79
|
+
}
|
|
80
|
+
}, _callee);
|
|
81
|
+
}));
|
|
82
|
+
return function handleNextPage() {
|
|
83
|
+
return _ref2.apply(this, arguments);
|
|
84
|
+
};
|
|
85
|
+
}();
|
|
86
|
+
|
|
87
|
+
// Handle previous page logic
|
|
88
|
+
var handlePreviousPage = function handlePreviousPage() {
|
|
89
|
+
setCurrentPage(function (prevPage) {
|
|
90
|
+
return Math.max(prevPage - 1, 1);
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
return /*#__PURE__*/_react["default"].createElement("div", {
|
|
94
|
+
className: "px-4 sm:px-6 lg:px-8"
|
|
95
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
96
|
+
className: "mt-8 flow-root"
|
|
97
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
98
|
+
className: "-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"
|
|
99
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
100
|
+
className: "inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"
|
|
101
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
102
|
+
className: "overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg"
|
|
103
|
+
}, /*#__PURE__*/_react["default"].createElement("table", {
|
|
104
|
+
className: "min-w-full divide-y divide-gray-300"
|
|
105
|
+
}, /*#__PURE__*/_react["default"].createElement("thead", {
|
|
106
|
+
className: "bg-gray-50"
|
|
107
|
+
}, /*#__PURE__*/_react["default"].createElement("tr", null, currentColumnDefs.map(function (col, index) {
|
|
108
|
+
return /*#__PURE__*/_react["default"].createElement("th", {
|
|
109
|
+
key: index,
|
|
110
|
+
className: "".concat(col.style)
|
|
111
|
+
}, col.name);
|
|
112
|
+
}))), /*#__PURE__*/_react["default"].createElement("tbody", {
|
|
113
|
+
className: "divide-y divide-gray-200 bg-white"
|
|
114
|
+
}, currentData.map(function (row, rowIndex) {
|
|
115
|
+
return /*#__PURE__*/_react["default"].createElement("tr", {
|
|
116
|
+
key: rowIndex
|
|
117
|
+
}, currentColumnDefs.map(function (column, colIndex) {
|
|
118
|
+
return /*#__PURE__*/_react["default"].createElement("td", {
|
|
119
|
+
key: "cell-".concat(rowIndex, "-").concat(colIndex),
|
|
120
|
+
className: "px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"
|
|
121
|
+
}, column.row ? column.row(row) : row[column.accessorKey]);
|
|
122
|
+
}));
|
|
123
|
+
}))))))), /*#__PURE__*/_react["default"].createElement("div", {
|
|
124
|
+
className: "flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6"
|
|
125
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
126
|
+
className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between"
|
|
127
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
128
|
+
className: "flex items-center"
|
|
129
|
+
}, /*#__PURE__*/_react["default"].createElement("label", {
|
|
130
|
+
htmlFor: "results-per-page",
|
|
131
|
+
className: "mr-3 text-sm text-gray-700"
|
|
132
|
+
}, "Results per page:"), /*#__PURE__*/_react["default"].createElement("select", {
|
|
133
|
+
id: "results-per-page",
|
|
134
|
+
name: "results-per-page",
|
|
135
|
+
value: itemsPerPage,
|
|
136
|
+
onChange: function onChange(e) {
|
|
137
|
+
return handleResultsPerPageChange(Number(e.target.value));
|
|
138
|
+
},
|
|
139
|
+
className: "block w-24 rounded-md border-gray-300 bg-white py-2 pl-3 pr-10 text-gray-900 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
|
140
|
+
}, /*#__PURE__*/_react["default"].createElement("option", {
|
|
141
|
+
value: "10"
|
|
142
|
+
}, "10"), /*#__PURE__*/_react["default"].createElement("option", {
|
|
143
|
+
value: "20"
|
|
144
|
+
}, "20"), /*#__PURE__*/_react["default"].createElement("option", {
|
|
145
|
+
value: "50"
|
|
146
|
+
}, "50"), /*#__PURE__*/_react["default"].createElement("option", {
|
|
147
|
+
value: "100"
|
|
148
|
+
}, "100"))), /*#__PURE__*/_react["default"].createElement("nav", {
|
|
149
|
+
"aria-label": "Pagination",
|
|
150
|
+
className: "isolate inline-flex -space-x-px rounded-md shadow-sm"
|
|
151
|
+
}, /*#__PURE__*/_react["default"].createElement("button", {
|
|
152
|
+
onClick: handlePreviousPage,
|
|
153
|
+
className: "relative inline-flex items-center rounded-l-md px-3 py-2 text-sm font-medium ".concat(currentPage === 1 ? 'text-gray-300 bg-gray-50 cursor-not-allowed' : 'text-gray-700 bg-white hover:bg-gray-100'),
|
|
154
|
+
disabled: currentPage === 1
|
|
155
|
+
}, /*#__PURE__*/_react["default"].createElement(_solid.ChevronLeftIcon, {
|
|
156
|
+
"aria-hidden": "true",
|
|
157
|
+
className: "w-5 h-5"
|
|
158
|
+
})), (0, _toConsumableArray2["default"])(Array(totalPages)).map(function (_, index) {
|
|
159
|
+
return /*#__PURE__*/_react["default"].createElement("button", {
|
|
160
|
+
key: index,
|
|
161
|
+
onClick: function onClick() {
|
|
162
|
+
return setCurrentPage(index + 1);
|
|
163
|
+
},
|
|
164
|
+
className: "relative inline-flex items-center px-4 py-2 text-sm font-medium ".concat(currentPage === index + 1 ? 'bg-indigo-600 text-white' : 'text-gray-700 bg-white hover:bg-gray-100')
|
|
165
|
+
}, index + 1);
|
|
166
|
+
}), /*#__PURE__*/_react["default"].createElement("button", {
|
|
167
|
+
onClick: handleNextPage,
|
|
168
|
+
className: "relative inline-flex items-center rounded-r-md px-3 py-2 text-sm font-medium ".concat(currentPage === totalPages && !isMoreData ? 'text-gray-300 bg-gray-50 cursor-not-allowed' : 'text-gray-700 bg-white hover:bg-gray-100'),
|
|
169
|
+
disabled: currentPage === totalPages && !isMoreData
|
|
170
|
+
}, /*#__PURE__*/_react["default"].createElement(_solid.ChevronRightIcon, {
|
|
171
|
+
"aria-hidden": "true",
|
|
172
|
+
className: "w-5 h-5"
|
|
173
|
+
}))))));
|
|
174
|
+
};
|
|
175
|
+
var _default = exports["default"] = Table;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
Object.defineProperty(exports, "Table", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function get() {
|
|
10
|
+
return _Table["default"];
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
var _Table = _interopRequireDefault(require("./Table"));
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports["default"] = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _react = require("react");
|
|
10
|
+
var useWindowSize = function useWindowSize() {
|
|
11
|
+
var _useState = (0, _react.useState)(window.innerWidth),
|
|
12
|
+
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
|
|
13
|
+
width = _useState2[0],
|
|
14
|
+
setWidth = _useState2[1]; // Initial value is window.innerWidth
|
|
15
|
+
|
|
16
|
+
(0, _react.useEffect)(function () {
|
|
17
|
+
var handleResize = function handleResize() {
|
|
18
|
+
return setWidth(window.innerWidth);
|
|
19
|
+
};
|
|
20
|
+
window.addEventListener('resize', handleResize);
|
|
21
|
+
return function () {
|
|
22
|
+
return window.removeEventListener('resize', handleResize);
|
|
23
|
+
};
|
|
24
|
+
}, []);
|
|
25
|
+
return width; // Return width directly
|
|
26
|
+
};
|
|
27
|
+
var _default = exports["default"] = useWindowSize;
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@neukoio/react-table",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
7
|
+
"build": "babel src --out-dir dist --copy-files"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"description": "",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@heroicons/react": "^2.1.5",
|
|
15
|
+
"react": "^18.3.1",
|
|
16
|
+
"react-dom": "^18.3.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@babel/cli": "^7.25.9",
|
|
20
|
+
"@babel/core": "^7.26.0",
|
|
21
|
+
"@babel/plugin-transform-runtime": "^7.21.0",
|
|
22
|
+
"@babel/preset-env": "^7.26.0",
|
|
23
|
+
"@babel/preset-react": "^7.25.9",
|
|
24
|
+
"tailwindcss": "^3.2.4"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/Table.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import './styles.css';
|
|
3
|
+
import useWindowSize from './useWindowSize';
|
|
4
|
+
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/20/solid';
|
|
5
|
+
|
|
6
|
+
const Table = ({ data, columnDefs, isMoreData = false, onLoadMore = () => {} }) => {
|
|
7
|
+
const width = useWindowSize();
|
|
8
|
+
|
|
9
|
+
// Get the appropriate column definitions based on the screen size
|
|
10
|
+
const getColumnDefs = () => {
|
|
11
|
+
if (width >= 640 && width <= 768) return columnDefs.sm || columnDefs.default;
|
|
12
|
+
if (width >= 769 && width <= 1024) return columnDefs.md || columnDefs.default;
|
|
13
|
+
if (width >= 1025 && width <= 1280) return columnDefs.lg || columnDefs.default;
|
|
14
|
+
if (width >= 1281 && width <= 1536) return columnDefs.xl || columnDefs.default;
|
|
15
|
+
if (width >= 1537) return columnDefs.xxl || columnDefs.default;
|
|
16
|
+
return columnDefs.default;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const currentColumnDefs = getColumnDefs();
|
|
20
|
+
|
|
21
|
+
// Pagination state
|
|
22
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
23
|
+
const [itemsPerPage, setItemsPerPage] = useState(10); // State for results per page
|
|
24
|
+
|
|
25
|
+
const handleResultsPerPageChange = (value) => {
|
|
26
|
+
setItemsPerPage(value);
|
|
27
|
+
setCurrentPage(1); // Reset to the first page when items per page changes
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Get the data for the current page
|
|
31
|
+
const startIndex = (currentPage - 1) * itemsPerPage;
|
|
32
|
+
const currentData = data.slice(startIndex, startIndex + itemsPerPage);
|
|
33
|
+
|
|
34
|
+
const totalPages = Math.ceil(data.length / itemsPerPage);
|
|
35
|
+
|
|
36
|
+
// Handle next page logic
|
|
37
|
+
const handleNextPage = async () => {
|
|
38
|
+
if (currentPage === totalPages && isMoreData) {
|
|
39
|
+
// Fetch more data when on the last page
|
|
40
|
+
await onLoadMore(); // Fetch more data
|
|
41
|
+
}
|
|
42
|
+
// Increase page number after data is loaded (or if data was already loaded)
|
|
43
|
+
setCurrentPage((prevPage) => Math.min(prevPage + 1, totalPages + (isMoreData ? 1 : 0)));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Handle previous page logic
|
|
47
|
+
const handlePreviousPage = () => {
|
|
48
|
+
setCurrentPage((prevPage) => Math.max(prevPage - 1, 1));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className="px-4 sm:px-6 lg:px-8">
|
|
53
|
+
<div className="mt-8 flow-root">
|
|
54
|
+
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
|
55
|
+
<div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
|
56
|
+
<div className="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg">
|
|
57
|
+
<table className="min-w-full divide-y divide-gray-300">
|
|
58
|
+
<thead className="bg-gray-50">
|
|
59
|
+
<tr>
|
|
60
|
+
{currentColumnDefs.map((col, index) => (
|
|
61
|
+
<th key={index} className={`${col.style}`}>
|
|
62
|
+
{col.name}
|
|
63
|
+
</th>
|
|
64
|
+
))}
|
|
65
|
+
</tr>
|
|
66
|
+
</thead>
|
|
67
|
+
<tbody className="divide-y divide-gray-200 bg-white">
|
|
68
|
+
{currentData.map((row, rowIndex) => (
|
|
69
|
+
<tr key={rowIndex}>
|
|
70
|
+
{currentColumnDefs.map((column, colIndex) => (
|
|
71
|
+
<td
|
|
72
|
+
key={`cell-${rowIndex}-${colIndex}`}
|
|
73
|
+
className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"
|
|
74
|
+
>
|
|
75
|
+
{column.row ? column.row(row) : row[column.accessorKey]}
|
|
76
|
+
</td>
|
|
77
|
+
))}
|
|
78
|
+
</tr>
|
|
79
|
+
))}
|
|
80
|
+
</tbody>
|
|
81
|
+
</table>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
{/* Pagination Section */}
|
|
88
|
+
<div className="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6">
|
|
89
|
+
<div className="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
|
|
90
|
+
<div className="flex items-center">
|
|
91
|
+
<label htmlFor="results-per-page" className="mr-3 text-sm text-gray-700">
|
|
92
|
+
Results per page:
|
|
93
|
+
</label>
|
|
94
|
+
<select
|
|
95
|
+
id="results-per-page"
|
|
96
|
+
name="results-per-page"
|
|
97
|
+
value={itemsPerPage}
|
|
98
|
+
onChange={(e) => handleResultsPerPageChange(Number(e.target.value))}
|
|
99
|
+
className="block w-24 rounded-md border-gray-300 bg-white py-2 pl-3 pr-10 text-gray-900 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
|
100
|
+
>
|
|
101
|
+
<option value="10">10</option>
|
|
102
|
+
<option value="20">20</option>
|
|
103
|
+
<option value="50">50</option>
|
|
104
|
+
<option value="100">100</option>
|
|
105
|
+
</select>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<nav aria-label="Pagination" className="isolate inline-flex -space-x-px rounded-md shadow-sm">
|
|
109
|
+
<button
|
|
110
|
+
onClick={handlePreviousPage}
|
|
111
|
+
className={`relative inline-flex items-center rounded-l-md px-3 py-2 text-sm font-medium ${currentPage === 1
|
|
112
|
+
? 'text-gray-300 bg-gray-50 cursor-not-allowed'
|
|
113
|
+
: 'text-gray-700 bg-white hover:bg-gray-100'
|
|
114
|
+
}`}
|
|
115
|
+
disabled={currentPage === 1}
|
|
116
|
+
>
|
|
117
|
+
<ChevronLeftIcon aria-hidden="true" className="w-5 h-5" />
|
|
118
|
+
</button>
|
|
119
|
+
|
|
120
|
+
{[...Array(totalPages)].map((_, index) => (
|
|
121
|
+
<button
|
|
122
|
+
key={index}
|
|
123
|
+
onClick={() => setCurrentPage(index + 1)}
|
|
124
|
+
className={`relative inline-flex items-center px-4 py-2 text-sm font-medium ${currentPage === index + 1
|
|
125
|
+
? 'bg-indigo-600 text-white'
|
|
126
|
+
: 'text-gray-700 bg-white hover:bg-gray-100'
|
|
127
|
+
}`}
|
|
128
|
+
>
|
|
129
|
+
{index + 1}
|
|
130
|
+
</button>
|
|
131
|
+
))}
|
|
132
|
+
|
|
133
|
+
<button
|
|
134
|
+
onClick={handleNextPage}
|
|
135
|
+
className={`relative inline-flex items-center rounded-r-md px-3 py-2 text-sm font-medium ${currentPage === totalPages && !isMoreData
|
|
136
|
+
? 'text-gray-300 bg-gray-50 cursor-not-allowed'
|
|
137
|
+
: 'text-gray-700 bg-white hover:bg-gray-100'
|
|
138
|
+
}`}
|
|
139
|
+
disabled={currentPage === totalPages && !isMoreData}
|
|
140
|
+
>
|
|
141
|
+
<ChevronRightIcon aria-hidden="true" className="w-5 h-5" />
|
|
142
|
+
</button>
|
|
143
|
+
</nav>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export default Table;
|
package/src/index.js
ADDED
package/src/styles.css
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
const useWindowSize = () => {
|
|
4
|
+
const [width, setWidth] = useState(window.innerWidth); // Initial value is window.innerWidth
|
|
5
|
+
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const handleResize = () => setWidth(window.innerWidth);
|
|
8
|
+
|
|
9
|
+
window.addEventListener('resize', handleResize);
|
|
10
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
11
|
+
}, []);
|
|
12
|
+
|
|
13
|
+
return width; // Return width directly
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default useWindowSize;
|