@neukoio/react-table 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/.babelrc ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "presets": ["@babel/preset-env", "@babel/preset-react"],
3
+ "plugins": ["@babel/plugin-transform-runtime"]
4
+ }
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/Button.js ADDED
@@ -0,0 +1,215 @@
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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
14
+ var _react = _interopRequireWildcard(require("react"));
15
+ require("./styles.css");
16
+ var _solid = require("@heroicons/react/20/solid");
17
+ var _useWindowSize = _interopRequireDefault(require("./useWindowSize"));
18
+ 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); }
19
+ 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; }
20
+ function ownKeys(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; }
21
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
22
+ var Button = function Button(_ref) {
23
+ var data = _ref.data,
24
+ columnDefs = _ref.columnDefs,
25
+ isMoreData = _ref.isMoreData,
26
+ onLoadMore = _ref.onLoadMore;
27
+ var width = (0, _useWindowSize["default"])();
28
+ var _useState = (0, _react.useState)(columnDefs),
29
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
30
+ mergedColumnDefs = _useState2[0],
31
+ setMergedColumnDefs = _useState2[1];
32
+ var _useState3 = (0, _react.useState)(data),
33
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
34
+ mergedData = _useState4[0],
35
+ setMergedData = _useState4[1];
36
+
37
+ // Merge columns and data based on the screen width
38
+ (0, _react.useEffect)(function () {
39
+ if (width >= 640 && width < 768) {
40
+ // sm screen
41
+ var removedColumns = columnDefs.slice(1, 3);
42
+ var combinedColumnName = removedColumns.join(' and ');
43
+ var updatedColumnDefs = columnDefs.filter(function (_, index) {
44
+ return index !== 1 && index !== 2;
45
+ }).concat(combinedColumnName);
46
+ var updatedData = data.map(function (item) {
47
+ return _objectSpread(_objectSpread({}, item), {}, (0, _defineProperty2["default"])({}, combinedColumnName, "".concat(item.Priority, " - ").concat(item.Description)));
48
+ });
49
+ setMergedColumnDefs(updatedColumnDefs);
50
+ setMergedData(updatedData);
51
+ } else {
52
+ setMergedColumnDefs(columnDefs);
53
+ setMergedData(data);
54
+ }
55
+ }, [width, data, columnDefs]);
56
+
57
+ // Pagination state
58
+ var _useState5 = (0, _react.useState)(1),
59
+ _useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
60
+ currentPage = _useState6[0],
61
+ setCurrentPage = _useState6[1];
62
+ var _useState7 = (0, _react.useState)(10),
63
+ _useState8 = (0, _slicedToArray2["default"])(_useState7, 2),
64
+ itemsPerPage = _useState8[0],
65
+ setItemsPerPage = _useState8[1]; // State for results per page
66
+ var _useState9 = (0, _react.useState)(false),
67
+ _useState10 = (0, _slicedToArray2["default"])(_useState9, 2),
68
+ userTriggeredAction = _useState10[0],
69
+ setUserTriggeredAction = _useState10[1];
70
+ var handleResultsPerPageChange = function handleResultsPerPageChange(value) {
71
+ setItemsPerPage(value);
72
+ setCurrentPage(1); // Reset to the first page when items per page changes
73
+ setUserTriggeredAction(true);
74
+ };
75
+
76
+ // Get the data for the current page
77
+ var startIndex = (currentPage - 1) * itemsPerPage;
78
+ var currentData = mergedData.slice(startIndex, startIndex + itemsPerPage);
79
+ var totalPages = Math.ceil(mergedData.length / itemsPerPage);
80
+ var handleNextPage = /*#__PURE__*/function () {
81
+ var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
82
+ return _regenerator["default"].wrap(function _callee$(_context) {
83
+ while (1) switch (_context.prev = _context.next) {
84
+ case 0:
85
+ if (!(currentPage === totalPages && isMoreData)) {
86
+ _context.next = 3;
87
+ break;
88
+ }
89
+ _context.next = 3;
90
+ return onLoadMore();
91
+ case 3:
92
+ setCurrentPage(function (prevPage) {
93
+ return Math.min(prevPage + 1, totalPages + (isMoreData ? 1 : 0));
94
+ });
95
+ setUserTriggeredAction(true);
96
+ case 5:
97
+ case "end":
98
+ return _context.stop();
99
+ }
100
+ }, _callee);
101
+ }));
102
+ return function handleNextPage() {
103
+ return _ref2.apply(this, arguments);
104
+ };
105
+ }();
106
+ var handlePreviousPage = function handlePreviousPage() {
107
+ setCurrentPage(function (prevPage) {
108
+ return Math.max(prevPage - 1, 1);
109
+ });
110
+ setUserTriggeredAction(true); // Mark user triggered action
111
+ };
112
+
113
+ // Run the effect only when user triggers the action (next page or results per page change)
114
+ (0, _react.useEffect)(function () {
115
+ if (userTriggeredAction && mergedData.length < currentPage * itemsPerPage) {
116
+ onLoadMore(); // Load more data if the current page exceeds the available data
117
+ setUserTriggeredAction(false); // Reset after loading more data
118
+ }
119
+ }, [currentPage, itemsPerPage, mergedData, onLoadMore, userTriggeredAction]);
120
+ return /*#__PURE__*/_react["default"].createElement("div", {
121
+ className: "px-4 sm:px-6 lg:px-8"
122
+ }, /*#__PURE__*/_react["default"].createElement("div", {
123
+ className: "mt-8 flow-root"
124
+ }, /*#__PURE__*/_react["default"].createElement("div", {
125
+ className: "-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"
126
+ }, /*#__PURE__*/_react["default"].createElement("div", {
127
+ className: "inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"
128
+ }, /*#__PURE__*/_react["default"].createElement("div", {
129
+ className: "overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg"
130
+ }, /*#__PURE__*/_react["default"].createElement("table", {
131
+ className: "min-w-full divide-y divide-gray-300"
132
+ }, /*#__PURE__*/_react["default"].createElement("thead", {
133
+ className: "bg-gray-50"
134
+ }, /*#__PURE__*/_react["default"].createElement("tr", null, mergedColumnDefs.map(function (columnDef, index) {
135
+ return /*#__PURE__*/_react["default"].createElement("th", {
136
+ key: columnDef,
137
+ scope: "col",
138
+ className: "".concat(index === 0 ? 'py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:text-base' : 'px-3 py-3.5 text-left text-sm font-semibold text-gray-900 md:text-sm lg:text-base')
139
+ }, columnDef);
140
+ }), /*#__PURE__*/_react["default"].createElement("th", {
141
+ scope: "col",
142
+ className: "relative py-3.5 pl-3 pr-4 sm:pr-6"
143
+ }, /*#__PURE__*/_react["default"].createElement("span", {
144
+ className: "sr-only"
145
+ }, "Edit")))), /*#__PURE__*/_react["default"].createElement("tbody", {
146
+ className: "divide-y divide-gray-200 bg-white"
147
+ }, currentData.map(function (item, index) {
148
+ return /*#__PURE__*/_react["default"].createElement("tr", {
149
+ key: index
150
+ }, mergedColumnDefs.map(function (columnDef, index) {
151
+ return /*#__PURE__*/_react["default"].createElement("td", {
152
+ key: columnDef,
153
+ className: "".concat(index === 0 ? 'whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 md:text-sm lg:text-base' : 'whitespace-nowrap px-3 py-4 text-sm text-gray-500 md:text-sm lg:text-base')
154
+ }, item[columnDef]);
155
+ }), /*#__PURE__*/_react["default"].createElement("td", {
156
+ className: "relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6"
157
+ }, /*#__PURE__*/_react["default"].createElement("a", {
158
+ href: "#",
159
+ className: "text-indigo-600 hover:text-indigo-900"
160
+ }, "Edit", /*#__PURE__*/_react["default"].createElement("span", {
161
+ className: "sr-only"
162
+ }, ", ", item['Group Name']))));
163
+ }))))))), /*#__PURE__*/_react["default"].createElement("div", {
164
+ className: "flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6"
165
+ }, /*#__PURE__*/_react["default"].createElement("div", {
166
+ className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between"
167
+ }, /*#__PURE__*/_react["default"].createElement("div", {
168
+ className: "flex items-center"
169
+ }, /*#__PURE__*/_react["default"].createElement("label", {
170
+ htmlFor: "results-per-page",
171
+ className: "mr-3 text-sm text-gray-700"
172
+ }, "Results per page:"), /*#__PURE__*/_react["default"].createElement("select", {
173
+ id: "results-per-page",
174
+ name: "results-per-page",
175
+ value: itemsPerPage,
176
+ onChange: function onChange(e) {
177
+ return handleResultsPerPageChange(Number(e.target.value));
178
+ },
179
+ 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"
180
+ }, /*#__PURE__*/_react["default"].createElement("option", {
181
+ value: "10"
182
+ }, "10"), /*#__PURE__*/_react["default"].createElement("option", {
183
+ value: "20"
184
+ }, "20"), /*#__PURE__*/_react["default"].createElement("option", {
185
+ value: "50"
186
+ }, "50"), /*#__PURE__*/_react["default"].createElement("option", {
187
+ value: "100"
188
+ }, "100"))), /*#__PURE__*/_react["default"].createElement("nav", {
189
+ "aria-label": "Pagination",
190
+ className: "isolate inline-flex -space-x-px rounded-md shadow-sm"
191
+ }, /*#__PURE__*/_react["default"].createElement("button", {
192
+ onClick: handlePreviousPage,
193
+ 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'),
194
+ disabled: currentPage === 1
195
+ }, /*#__PURE__*/_react["default"].createElement(_solid.ChevronLeftIcon, {
196
+ "aria-hidden": "true",
197
+ className: "w-5 h-5"
198
+ })), (0, _toConsumableArray2["default"])(Array(totalPages)).map(function (_, index) {
199
+ return /*#__PURE__*/_react["default"].createElement("button", {
200
+ key: index,
201
+ onClick: function onClick() {
202
+ return setCurrentPage(index + 1);
203
+ },
204
+ 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')
205
+ }, index + 1);
206
+ }), /*#__PURE__*/_react["default"].createElement("button", {
207
+ onClick: handleNextPage,
208
+ 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'),
209
+ disabled: currentPage === totalPages && !isMoreData
210
+ }, /*#__PURE__*/_react["default"].createElement(_solid.ChevronRightIcon, {
211
+ "aria-hidden": "true",
212
+ className: "w-5 h-5"
213
+ }))))));
214
+ };
215
+ var _default = exports["default"] = Button;
package/dist/Table.js ADDED
@@ -0,0 +1,214 @@
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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
14
+ var _react = _interopRequireWildcard(require("react"));
15
+ require("./styles.css");
16
+ var _solid = require("@heroicons/react/20/solid");
17
+ var _useWindowSize = _interopRequireDefault(require("./useWindowSize"));
18
+ 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); }
19
+ 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; }
20
+ function ownKeys(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; }
21
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
22
+ var Table = function Table(_ref) {
23
+ var data = _ref.data,
24
+ columnDefs = _ref.columnDefs,
25
+ isMoreData = _ref.isMoreData,
26
+ onLoadMore = _ref.onLoadMore;
27
+ var width = (0, _useWindowSize["default"])();
28
+ var _useState = (0, _react.useState)(columnDefs),
29
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
30
+ mergedColumnDefs = _useState2[0],
31
+ setMergedColumnDefs = _useState2[1];
32
+ var _useState3 = (0, _react.useState)(data),
33
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
34
+ mergedData = _useState4[0],
35
+ setMergedData = _useState4[1];
36
+
37
+ // Merge columns and data based on the screen width
38
+ (0, _react.useEffect)(function () {
39
+ if (width >= 640 && width < 768) {
40
+ // sm screen
41
+ var removedColumns = columnDefs.slice(1, 3);
42
+ var combinedColumnName = removedColumns.join(' and ');
43
+ var updatedColumnDefs = columnDefs.filter(function (_, index) {
44
+ return index !== 1 && index !== 2;
45
+ }).concat(combinedColumnName);
46
+ var updatedData = data.map(function (item) {
47
+ return _objectSpread(_objectSpread({}, item), {}, (0, _defineProperty2["default"])({}, combinedColumnName, "".concat(item.Priority, " - ").concat(item.Description)));
48
+ });
49
+ setMergedColumnDefs(updatedColumnDefs);
50
+ setMergedData(updatedData);
51
+ } else {
52
+ setMergedColumnDefs(columnDefs);
53
+ setMergedData(data);
54
+ }
55
+ }, [width, data, columnDefs]);
56
+
57
+ // Pagination state
58
+ var _useState5 = (0, _react.useState)(1),
59
+ _useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
60
+ currentPage = _useState6[0],
61
+ setCurrentPage = _useState6[1];
62
+ var _useState7 = (0, _react.useState)(10),
63
+ _useState8 = (0, _slicedToArray2["default"])(_useState7, 2),
64
+ itemsPerPage = _useState8[0],
65
+ setItemsPerPage = _useState8[1]; // State for results per page
66
+ var _useState9 = (0, _react.useState)(false),
67
+ _useState10 = (0, _slicedToArray2["default"])(_useState9, 2),
68
+ userTriggeredAction = _useState10[0],
69
+ setUserTriggeredAction = _useState10[1];
70
+ var handleResultsPerPageChange = function handleResultsPerPageChange(value) {
71
+ setItemsPerPage(value);
72
+ setCurrentPage(1); // Reset to the first page when items per page changes
73
+ setUserTriggeredAction(true);
74
+ };
75
+
76
+ // Get the data for the current page
77
+ var startIndex = (currentPage - 1) * itemsPerPage;
78
+ var currentData = mergedData.slice(startIndex, startIndex + itemsPerPage);
79
+ var totalPages = Math.ceil(mergedData.length / itemsPerPage);
80
+ var handleNextPage = /*#__PURE__*/function () {
81
+ var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
82
+ return _regenerator["default"].wrap(function _callee$(_context) {
83
+ while (1) switch (_context.prev = _context.next) {
84
+ case 0:
85
+ if (!(currentPage === totalPages && isMoreData)) {
86
+ _context.next = 3;
87
+ break;
88
+ }
89
+ _context.next = 3;
90
+ return onLoadMore();
91
+ case 3:
92
+ setCurrentPage(function (prevPage) {
93
+ return Math.min(prevPage + 1, totalPages + (isMoreData ? 1 : 0));
94
+ });
95
+ setUserTriggeredAction(true);
96
+ case 5:
97
+ case "end":
98
+ return _context.stop();
99
+ }
100
+ }, _callee);
101
+ }));
102
+ return function handleNextPage() {
103
+ return _ref2.apply(this, arguments);
104
+ };
105
+ }();
106
+ var handlePreviousPage = function handlePreviousPage() {
107
+ setCurrentPage(function (prevPage) {
108
+ return Math.max(prevPage - 1, 1);
109
+ });
110
+ };
111
+
112
+ // Run the effect only when user triggers the action (next page or results per page change)
113
+ (0, _react.useEffect)(function () {
114
+ if (userTriggeredAction && mergedData.length < currentPage * itemsPerPage) {
115
+ onLoadMore(); // Load more data if the current page exceeds the available data
116
+ setUserTriggeredAction(false); // Reset after loading more data
117
+ }
118
+ }, [currentPage, itemsPerPage, mergedData, onLoadMore, userTriggeredAction]);
119
+ return /*#__PURE__*/_react["default"].createElement("div", {
120
+ className: "px-4 sm:px-6 lg:px-8"
121
+ }, /*#__PURE__*/_react["default"].createElement("div", {
122
+ className: "mt-8 flow-root"
123
+ }, /*#__PURE__*/_react["default"].createElement("div", {
124
+ className: "-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"
125
+ }, /*#__PURE__*/_react["default"].createElement("div", {
126
+ className: "inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8"
127
+ }, /*#__PURE__*/_react["default"].createElement("div", {
128
+ className: "overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg"
129
+ }, /*#__PURE__*/_react["default"].createElement("table", {
130
+ className: "min-w-full divide-y divide-gray-300"
131
+ }, /*#__PURE__*/_react["default"].createElement("thead", {
132
+ className: "bg-gray-50"
133
+ }, /*#__PURE__*/_react["default"].createElement("tr", null, mergedColumnDefs.map(function (columnDef, index) {
134
+ return /*#__PURE__*/_react["default"].createElement("th", {
135
+ key: columnDef,
136
+ scope: "col",
137
+ className: "".concat(index === 0 ? 'py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:text-base' : 'px-3 py-3.5 text-left text-sm font-semibold text-gray-900 md:text-sm lg:text-base')
138
+ }, columnDef);
139
+ }), /*#__PURE__*/_react["default"].createElement("th", {
140
+ scope: "col",
141
+ className: "relative py-3.5 pl-3 pr-4 sm:pr-6"
142
+ }, /*#__PURE__*/_react["default"].createElement("span", {
143
+ className: "sr-only"
144
+ }, "Edit")))), /*#__PURE__*/_react["default"].createElement("tbody", {
145
+ className: "divide-y divide-gray-200 bg-white"
146
+ }, currentData.map(function (item, index) {
147
+ return /*#__PURE__*/_react["default"].createElement("tr", {
148
+ key: index
149
+ }, mergedColumnDefs.map(function (columnDef, index) {
150
+ return /*#__PURE__*/_react["default"].createElement("td", {
151
+ key: columnDef,
152
+ className: "".concat(index === 0 ? 'whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 md:text-sm lg:text-base' : 'whitespace-nowrap px-3 py-4 text-sm text-gray-500 md:text-sm lg:text-base')
153
+ }, item[columnDef]);
154
+ }), /*#__PURE__*/_react["default"].createElement("td", {
155
+ className: "relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6"
156
+ }, /*#__PURE__*/_react["default"].createElement("a", {
157
+ href: "#",
158
+ className: "text-indigo-600 hover:text-indigo-900"
159
+ }, "Edit", /*#__PURE__*/_react["default"].createElement("span", {
160
+ className: "sr-only"
161
+ }, ", ", item['Group Name']))));
162
+ }))))))), /*#__PURE__*/_react["default"].createElement("div", {
163
+ className: "flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6"
164
+ }, /*#__PURE__*/_react["default"].createElement("div", {
165
+ className: "hidden sm:flex sm:flex-1 sm:items-center sm:justify-between"
166
+ }, /*#__PURE__*/_react["default"].createElement("div", {
167
+ className: "flex items-center"
168
+ }, /*#__PURE__*/_react["default"].createElement("label", {
169
+ htmlFor: "results-per-page",
170
+ className: "mr-3 text-sm text-gray-700"
171
+ }, "Results per page:"), /*#__PURE__*/_react["default"].createElement("select", {
172
+ id: "results-per-page",
173
+ name: "results-per-page",
174
+ value: itemsPerPage,
175
+ onChange: function onChange(e) {
176
+ return handleResultsPerPageChange(Number(e.target.value));
177
+ },
178
+ 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"
179
+ }, /*#__PURE__*/_react["default"].createElement("option", {
180
+ value: "10"
181
+ }, "10"), /*#__PURE__*/_react["default"].createElement("option", {
182
+ value: "20"
183
+ }, "20"), /*#__PURE__*/_react["default"].createElement("option", {
184
+ value: "50"
185
+ }, "50"), /*#__PURE__*/_react["default"].createElement("option", {
186
+ value: "100"
187
+ }, "100"))), /*#__PURE__*/_react["default"].createElement("nav", {
188
+ "aria-label": "Pagination",
189
+ className: "isolate inline-flex -space-x-px rounded-md shadow-sm"
190
+ }, /*#__PURE__*/_react["default"].createElement("button", {
191
+ onClick: handlePreviousPage,
192
+ 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'),
193
+ disabled: currentPage === 1
194
+ }, /*#__PURE__*/_react["default"].createElement(_solid.ChevronLeftIcon, {
195
+ "aria-hidden": "true",
196
+ className: "w-5 h-5"
197
+ })), (0, _toConsumableArray2["default"])(Array(totalPages)).map(function (_, index) {
198
+ return /*#__PURE__*/_react["default"].createElement("button", {
199
+ key: index,
200
+ onClick: function onClick() {
201
+ return setCurrentPage(index + 1);
202
+ },
203
+ 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')
204
+ }, index + 1);
205
+ }), /*#__PURE__*/_react["default"].createElement("button", {
206
+ onClick: handleNextPage,
207
+ 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'),
208
+ disabled: currentPage === totalPages && !isMoreData
209
+ }, /*#__PURE__*/_react["default"].createElement(_solid.ChevronRightIcon, {
210
+ "aria-hidden": "true",
211
+ className: "w-5 h-5"
212
+ }))))));
213
+ };
214
+ 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"));
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -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,30 @@
1
+ {
2
+ "name": "@neukoio/react-table",
3
+ "version": "0.0.1",
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
+ "@tailwindcss/aspect-ratio": "^0.4.2",
16
+ "@tailwindcss/forms": "^0.5.9",
17
+ "@tailwindcss/typography": "^0.5.15",
18
+ "react": "^18.3.1",
19
+ "react-dom": "^18.3.1",
20
+ "tailwindcss-animate": "^1.0.7"
21
+ },
22
+ "devDependencies": {
23
+ "@babel/cli": "^7.25.9",
24
+ "@babel/core": "^7.26.0",
25
+ "@babel/plugin-transform-runtime": "^7.21.0",
26
+ "@babel/preset-env": "^7.26.0",
27
+ "@babel/preset-react": "^7.25.9",
28
+ "tailwindcss": "^3.2.4"
29
+ }
30
+ }
package/src/Table.js ADDED
@@ -0,0 +1,189 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import './styles.css';
3
+ import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/20/solid';
4
+ import useWindowSize from './useWindowSize';
5
+
6
+ const Table = ({ data, columnDefs, isMoreData, onLoadMore }) => {
7
+ const width = useWindowSize();
8
+
9
+ const [mergedColumnDefs, setMergedColumnDefs] = useState(columnDefs);
10
+ const [mergedData, setMergedData] = useState(data);
11
+
12
+
13
+ // Merge columns and data based on the screen width
14
+ useEffect(() => {
15
+ if (width >= 640 && width < 768) { // sm screen
16
+ const removedColumns = columnDefs.slice(1, 3);
17
+ const combinedColumnName = removedColumns.join(' and ');
18
+
19
+ const updatedColumnDefs = columnDefs
20
+ .filter((_, index) => index !== 1 && index !== 2)
21
+ .concat(combinedColumnName);
22
+
23
+ const updatedData = data.map((item) => ({
24
+ ...item,
25
+ [combinedColumnName]: `${item.Priority} - ${item.Description}`,
26
+ }));
27
+
28
+ setMergedColumnDefs(updatedColumnDefs);
29
+ setMergedData(updatedData);
30
+ } else {
31
+ setMergedColumnDefs(columnDefs);
32
+ setMergedData(data);
33
+ }
34
+ }, [width, data, columnDefs]);
35
+
36
+ // Pagination state
37
+ const [currentPage, setCurrentPage] = useState(1);
38
+ const [itemsPerPage, setItemsPerPage] = useState(10); // State for results per page
39
+ const [userTriggeredAction, setUserTriggeredAction] = useState(false);
40
+
41
+
42
+ const handleResultsPerPageChange = (value) => {
43
+ setItemsPerPage(value);
44
+ setCurrentPage(1); // Reset to the first page when items per page changes
45
+ setUserTriggeredAction(true);
46
+ };
47
+
48
+ // Get the data for the current page
49
+ const startIndex = (currentPage - 1) * itemsPerPage;
50
+ const currentData = mergedData.slice(startIndex, startIndex + itemsPerPage);
51
+
52
+ const totalPages = Math.ceil(mergedData.length / itemsPerPage);
53
+
54
+
55
+ const handleNextPage = async () => {
56
+ if (currentPage === totalPages && isMoreData) await onLoadMore();
57
+ setCurrentPage((prevPage) => Math.min(prevPage + 1, totalPages + (isMoreData ? 1 : 0)));
58
+ setUserTriggeredAction(true);
59
+ };
60
+
61
+ const handlePreviousPage = () => {
62
+ setCurrentPage((prevPage) => Math.max(prevPage - 1, 1));
63
+ };
64
+
65
+ // Run the effect only when user triggers the action (next page or results per page change)
66
+ useEffect(() => {
67
+ if (userTriggeredAction && mergedData.length < currentPage * itemsPerPage) {
68
+ onLoadMore(); // Load more data if the current page exceeds the available data
69
+ setUserTriggeredAction(false); // Reset after loading more data
70
+ }
71
+ }, [currentPage, itemsPerPage, mergedData, onLoadMore, userTriggeredAction]);
72
+
73
+ return (
74
+ <div className="px-4 sm:px-6 lg:px-8">
75
+ <div className="mt-8 flow-root">
76
+ <div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
77
+ <div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
78
+ <div className="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg">
79
+ <table className="min-w-full divide-y divide-gray-300">
80
+ <thead className="bg-gray-50">
81
+ <tr>
82
+ {mergedColumnDefs.map((columnDef, index) => (
83
+ <th
84
+ key={columnDef}
85
+ scope="col"
86
+ className={`${index === 0
87
+ ? 'py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:text-base'
88
+ : 'px-3 py-3.5 text-left text-sm font-semibold text-gray-900 md:text-sm lg:text-base'
89
+ }`}
90
+ >
91
+ {columnDef}
92
+ </th>
93
+ ))}
94
+ <th scope="col" className="relative py-3.5 pl-3 pr-4 sm:pr-6">
95
+ <span className="sr-only">Edit</span>
96
+ </th>
97
+ </tr>
98
+ </thead>
99
+ <tbody className="divide-y divide-gray-200 bg-white">
100
+ {currentData.map((item, index) => (
101
+ <tr key={index}>
102
+ {mergedColumnDefs.map((columnDef, index) => (
103
+ <td
104
+ key={columnDef}
105
+ className={`${index === 0
106
+ ? 'whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 md:text-sm lg:text-base'
107
+ : 'whitespace-nowrap px-3 py-4 text-sm text-gray-500 md:text-sm lg:text-base'
108
+ }`}
109
+ >
110
+ {item[columnDef]}
111
+ </td>
112
+ ))}
113
+ <td className="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
114
+ <a href="#" className="text-indigo-600 hover:text-indigo-900">
115
+ Edit<span className="sr-only">, {item['Group Name']}</span>
116
+ </a>
117
+ </td>
118
+ </tr>
119
+ ))}
120
+ </tbody>
121
+ </table>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+
127
+ {/* Pagination Section */}
128
+ <div className="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6">
129
+ <div className="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
130
+ <div className="flex items-center">
131
+ <label htmlFor="results-per-page" className="mr-3 text-sm text-gray-700">
132
+ Results per page:
133
+ </label>
134
+ <select
135
+ id="results-per-page"
136
+ name="results-per-page"
137
+ value={itemsPerPage}
138
+ onChange={(e) => handleResultsPerPageChange(Number(e.target.value))}
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
+ >
141
+ <option value="10">10</option>
142
+ <option value="20">20</option>
143
+ <option value="50">50</option>
144
+ <option value="100">100</option>
145
+ </select>
146
+ </div>
147
+ <nav aria-label="Pagination" className="isolate inline-flex -space-x-px rounded-md shadow-sm">
148
+ <button
149
+ onClick={handlePreviousPage}
150
+ className={`relative inline-flex items-center rounded-l-md px-3 py-2 text-sm font-medium ${currentPage === 1
151
+ ? 'text-gray-300 bg-gray-50 cursor-not-allowed'
152
+ : 'text-gray-700 bg-white hover:bg-gray-100'
153
+ }`}
154
+ disabled={currentPage === 1}
155
+ >
156
+ <ChevronLeftIcon aria-hidden="true" className="w-5 h-5" />
157
+ </button>
158
+
159
+ {[...Array(totalPages)].map((_, index) => (
160
+ <button
161
+ key={index}
162
+ onClick={() => setCurrentPage(index + 1)}
163
+ className={`relative inline-flex items-center px-4 py-2 text-sm font-medium ${currentPage === index + 1
164
+ ? 'bg-indigo-600 text-white'
165
+ : 'text-gray-700 bg-white hover:bg-gray-100'
166
+ }`}
167
+ >
168
+ {index + 1}
169
+ </button>
170
+ ))}
171
+
172
+ <button
173
+ onClick={handleNextPage}
174
+ className={`relative inline-flex items-center rounded-r-md px-3 py-2 text-sm font-medium ${currentPage === totalPages && !isMoreData
175
+ ? 'text-gray-300 bg-gray-50 cursor-not-allowed'
176
+ : 'text-gray-700 bg-white hover:bg-gray-100'
177
+ }`}
178
+ disabled={currentPage === totalPages && !isMoreData}
179
+ >
180
+ <ChevronRightIcon aria-hidden="true" className="w-5 h-5" />
181
+ </button>
182
+ </nav>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ );
187
+ };
188
+
189
+ export default Table;
package/src/index.js ADDED
@@ -0,0 +1,2 @@
1
+ // index.js
2
+ export { default as Table } from './Table';
package/src/styles.css ADDED
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -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;