react-pagination-thami 1.0.0

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/README.md ADDED
File without changes
@@ -0,0 +1,3 @@
1
+ import { PaginationProps } from "./pagination.types";
2
+ import "./pagination.css";
3
+ export default function Pagination({ total, pageSize, currentPage, onChange, siblingCount, }: PaginationProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,7 @@
1
+ export type PaginationProps = {
2
+ total: number;
3
+ pageSize: number;
4
+ currentPage: number;
5
+ onChange: (page: number) => void;
6
+ siblingCount?: number;
7
+ };
@@ -0,0 +1,2 @@
1
+ export declare const DOTS = "...";
2
+ export declare function range(start: number, end: number): number[];
@@ -0,0 +1,2 @@
1
+ import { PaginationProps } from "./pagination.types";
2
+ export declare function usePagination({ total, pageSize, currentPage, siblingCount, }: PaginationProps): (string | number)[];
@@ -0,0 +1 @@
1
+ export default function App(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.css ADDED
@@ -0,0 +1,28 @@
1
+ /* src/components/Pagination/pagination.css */
2
+ .pagination {
3
+ display: flex;
4
+ gap: 6px;
5
+ list-style: none;
6
+ padding: 0;
7
+ align-items: center;
8
+ flex-wrap: wrap;
9
+ }
10
+ .pagination button {
11
+ padding: 6px 10px;
12
+ border: 1px solid #ddd;
13
+ background: white;
14
+ border-radius: 6px;
15
+ cursor: pointer;
16
+ }
17
+ .pagination button.active {
18
+ background: black;
19
+ color: white;
20
+ }
21
+ .pagination button:disabled {
22
+ opacity: 0.4;
23
+ cursor: not-allowed;
24
+ }
25
+ .dots {
26
+ padding: 6px 10px;
27
+ }
28
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Pagination/pagination.css"],"sourcesContent":[".pagination {\r\n display: flex;\r\n gap: 6px;\r\n list-style: none;\r\n padding: 0;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.pagination button {\r\n padding: 6px 10px;\r\n border: 1px solid #ddd;\r\n background: white;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n}\r\n\r\n.pagination button.active {\r\n background: black;\r\n color: white;\r\n}\r\n\r\n.pagination button:disabled {\r\n opacity: 0.4;\r\n cursor: not-allowed;\r\n}\r\n\r\n.dots {\r\n padding: 6px 10px;\r\n}"],"mappings":";AAAA,CAAC;AACC,WAAS;AACT,OAAK;AACL,cAAY;AACZ,WAAS;AACT,eAAa;AACb,aAAW;AACb;AAEA,CATC,WASW;AACV,WAAS,IAAI;AACb,UAAQ,IAAI,MAAM;AAClB,cAAY;AACZ,iBAAe;AACf,UAAQ;AACV;AAEA,CAjBC,WAiBW,MAAM,CAAC;AACjB,cAAY;AACZ,SAAO;AACT;AAEA,CAtBC,WAsBW,MAAM;AAChB,WAAS;AACT,UAAQ;AACV;AAEA,CAAC;AACC,WAAS,IAAI;AACf;","names":[]}
@@ -0,0 +1 @@
1
+ export { default as Pagination } from "./components/Pagination/Pagination";
package/dist/index.js ADDED
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Pagination: () => Pagination
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/components/Pagination/usePagination.ts
28
+ var import_react = require("react");
29
+
30
+ // src/components/Pagination/pagination.utils.ts
31
+ var DOTS = "...";
32
+ function range(start, end) {
33
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
34
+ }
35
+
36
+ // src/components/Pagination/usePagination.ts
37
+ function usePagination({
38
+ total,
39
+ pageSize,
40
+ currentPage,
41
+ siblingCount = 1
42
+ }) {
43
+ return (0, import_react.useMemo)(() => {
44
+ const totalPages = Math.ceil(total / pageSize);
45
+ const totalPageNumbers = siblingCount + 5;
46
+ if (totalPageNumbers >= totalPages) {
47
+ return range(1, totalPages);
48
+ }
49
+ const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
50
+ const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages);
51
+ const showLeftDots = leftSiblingIndex > 2;
52
+ const showRightDots = rightSiblingIndex < totalPages - 2;
53
+ if (!showLeftDots && showRightDots) {
54
+ return [
55
+ ...range(1, 3 + 2 * siblingCount),
56
+ DOTS,
57
+ totalPages
58
+ ];
59
+ }
60
+ if (showLeftDots && !showRightDots) {
61
+ return [
62
+ 1,
63
+ DOTS,
64
+ ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages)
65
+ ];
66
+ }
67
+ if (showLeftDots && showRightDots) {
68
+ return [
69
+ 1,
70
+ DOTS,
71
+ ...range(leftSiblingIndex, rightSiblingIndex),
72
+ DOTS,
73
+ totalPages
74
+ ];
75
+ }
76
+ return [];
77
+ }, [total, pageSize, currentPage, siblingCount]);
78
+ }
79
+
80
+ // src/components/Pagination/Pagination.tsx
81
+ var import_jsx_runtime = require("react/jsx-runtime");
82
+ function Pagination({
83
+ total,
84
+ pageSize,
85
+ currentPage,
86
+ onChange,
87
+ siblingCount = 1
88
+ }) {
89
+ const totalPages = Math.ceil(total / pageSize);
90
+ const paginationRange = usePagination({
91
+ total,
92
+ pageSize,
93
+ currentPage,
94
+ onChange,
95
+ siblingCount
96
+ });
97
+ if (totalPages <= 1 || !paginationRange) return null;
98
+ const handleKeyDown = (e, page) => {
99
+ if (page === DOTS) return;
100
+ if (e.key === "Enter" || e.key === " ") {
101
+ e.preventDefault();
102
+ onChange(Number(page));
103
+ }
104
+ };
105
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { "aria-label": "Pagination", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", { className: "pagination", children: [
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
107
+ "button",
108
+ {
109
+ type: "button",
110
+ onClick: () => onChange(currentPage - 1),
111
+ disabled: currentPage === 1,
112
+ "aria-label": "Previous page",
113
+ children: "Prev"
114
+ }
115
+ ) }),
116
+ paginationRange.map((page, idx) => {
117
+ if (page === DOTS) {
118
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { className: "dots", children: "..." }, `dots-${idx}`);
119
+ }
120
+ const pageNumber = Number(page);
121
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
122
+ "button",
123
+ {
124
+ type: "button",
125
+ className: currentPage === pageNumber ? "active" : "",
126
+ onClick: () => onChange(pageNumber),
127
+ onKeyDown: (e) => handleKeyDown(e, page),
128
+ "aria-current": currentPage === pageNumber ? "page" : void 0,
129
+ children: pageNumber
130
+ }
131
+ ) }, pageNumber);
132
+ }),
133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
134
+ "button",
135
+ {
136
+ type: "button",
137
+ onClick: () => onChange(currentPage + 1),
138
+ disabled: currentPage === totalPages,
139
+ "aria-label": "Next page",
140
+ children: "Next"
141
+ }
142
+ ) })
143
+ ] }) });
144
+ }
145
+ // Annotate the CommonJS export names for ESM import in node:
146
+ 0 && (module.exports = {
147
+ Pagination
148
+ });
149
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/components/Pagination/usePagination.ts","../src/components/Pagination/pagination.utils.ts","../src/components/Pagination/Pagination.tsx"],"sourcesContent":["export { default as Pagination } from \"./components/Pagination/Pagination\";","import { useMemo } from \"react\";\r\nimport { DOTS, range } from \"./pagination.utils\";\r\nimport { PaginationProps } from \"./pagination.types\";\r\n\r\nexport function usePagination({\r\n total,\r\n pageSize,\r\n currentPage,\r\n siblingCount = 1,\r\n}: PaginationProps) {\r\n return useMemo(() => {\r\n const totalPages = Math.ceil(total / pageSize);\r\n\r\n const totalPageNumbers = siblingCount + 5;\r\n\r\n if (totalPageNumbers >= totalPages) {\r\n return range(1, totalPages);\r\n }\r\n\r\n const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);\r\n const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages);\r\n\r\n const showLeftDots = leftSiblingIndex > 2;\r\n const showRightDots = rightSiblingIndex < totalPages - 2;\r\n\r\n if (!showLeftDots && showRightDots) {\r\n return [\r\n ...range(1, 3 + 2 * siblingCount),\r\n DOTS,\r\n totalPages,\r\n ];\r\n }\r\n\r\n if (showLeftDots && !showRightDots) {\r\n return [\r\n 1,\r\n DOTS,\r\n ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages),\r\n ];\r\n }\r\n\r\n if (showLeftDots && showRightDots) {\r\n return [\r\n 1,\r\n DOTS,\r\n ...range(leftSiblingIndex, rightSiblingIndex),\r\n DOTS,\r\n totalPages,\r\n ];\r\n }\r\n\r\n return [];\r\n }, [total, pageSize, currentPage, siblingCount]);\r\n}","export const DOTS = \"...\";\r\n\r\nexport function range(start: number, end: number) {\r\n return Array.from({ length: end - start + 1 }, (_, i) => start + i);\r\n}","import React from \"react\";\r\nimport { usePagination } from \"./usePagination\";\r\nimport { PaginationProps } from \"./pagination.types\";\r\nimport { DOTS } from \"./pagination.utils\";\r\nimport \"./pagination.css\";\r\n\r\nexport default function Pagination({\r\n total,\r\n pageSize,\r\n currentPage,\r\n onChange,\r\n siblingCount = 1,\r\n}: PaginationProps) {\r\n const totalPages = Math.ceil(total / pageSize);\r\n\r\n const paginationRange = usePagination({\r\n total,\r\n pageSize,\r\n currentPage,\r\n onChange,\r\n siblingCount,\r\n });\r\n\r\n if (totalPages <= 1 || !paginationRange) return null;\r\n\r\n const handleKeyDown = (\r\n e: React.KeyboardEvent<HTMLButtonElement>,\r\n page: string | number\r\n ) => {\r\n if (page === DOTS) return;\r\n\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n onChange(Number(page));\r\n }\r\n };\r\n\r\n return (\r\n <nav aria-label=\"Pagination\">\r\n <ul className=\"pagination\">\r\n {/* Prev */}\r\n <li>\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(currentPage - 1)}\r\n disabled={currentPage === 1}\r\n aria-label=\"Previous page\"\r\n >\r\n Prev\r\n </button>\r\n </li>\r\n\r\n {/* Pages */}\r\n {paginationRange.map((page: string | number, idx: number) => {\r\n if (page === DOTS) {\r\n return (\r\n <li key={`dots-${idx}`} className=\"dots\">\r\n ...\r\n </li>\r\n );\r\n }\r\n\r\n const pageNumber = Number(page);\r\n\r\n return (\r\n <li key={pageNumber}>\r\n <button\r\n type=\"button\"\r\n className={currentPage === pageNumber ? \"active\" : \"\"}\r\n onClick={() => onChange(pageNumber)}\r\n onKeyDown={(e) => handleKeyDown(e, page)}\r\n aria-current={currentPage === pageNumber ? \"page\" : undefined}\r\n >\r\n {pageNumber}\r\n </button>\r\n </li>\r\n );\r\n })}\r\n\r\n {/* Next */}\r\n <li>\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(currentPage + 1)}\r\n disabled={currentPage === totalPages}\r\n aria-label=\"Next page\"\r\n >\r\n Next\r\n </button>\r\n </li>\r\n </ul>\r\n </nav>\r\n );\r\n}"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,122 @@
1
+ // src/components/Pagination/usePagination.ts
2
+ import { useMemo } from "react";
3
+
4
+ // src/components/Pagination/pagination.utils.ts
5
+ var DOTS = "...";
6
+ function range(start, end) {
7
+ return Array.from({ length: end - start + 1 }, (_, i) => start + i);
8
+ }
9
+
10
+ // src/components/Pagination/usePagination.ts
11
+ function usePagination({
12
+ total,
13
+ pageSize,
14
+ currentPage,
15
+ siblingCount = 1
16
+ }) {
17
+ return useMemo(() => {
18
+ const totalPages = Math.ceil(total / pageSize);
19
+ const totalPageNumbers = siblingCount + 5;
20
+ if (totalPageNumbers >= totalPages) {
21
+ return range(1, totalPages);
22
+ }
23
+ const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
24
+ const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages);
25
+ const showLeftDots = leftSiblingIndex > 2;
26
+ const showRightDots = rightSiblingIndex < totalPages - 2;
27
+ if (!showLeftDots && showRightDots) {
28
+ return [
29
+ ...range(1, 3 + 2 * siblingCount),
30
+ DOTS,
31
+ totalPages
32
+ ];
33
+ }
34
+ if (showLeftDots && !showRightDots) {
35
+ return [
36
+ 1,
37
+ DOTS,
38
+ ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages)
39
+ ];
40
+ }
41
+ if (showLeftDots && showRightDots) {
42
+ return [
43
+ 1,
44
+ DOTS,
45
+ ...range(leftSiblingIndex, rightSiblingIndex),
46
+ DOTS,
47
+ totalPages
48
+ ];
49
+ }
50
+ return [];
51
+ }, [total, pageSize, currentPage, siblingCount]);
52
+ }
53
+
54
+ // src/components/Pagination/Pagination.tsx
55
+ import { jsx, jsxs } from "react/jsx-runtime";
56
+ function Pagination({
57
+ total,
58
+ pageSize,
59
+ currentPage,
60
+ onChange,
61
+ siblingCount = 1
62
+ }) {
63
+ const totalPages = Math.ceil(total / pageSize);
64
+ const paginationRange = usePagination({
65
+ total,
66
+ pageSize,
67
+ currentPage,
68
+ onChange,
69
+ siblingCount
70
+ });
71
+ if (totalPages <= 1 || !paginationRange) return null;
72
+ const handleKeyDown = (e, page) => {
73
+ if (page === DOTS) return;
74
+ if (e.key === "Enter" || e.key === " ") {
75
+ e.preventDefault();
76
+ onChange(Number(page));
77
+ }
78
+ };
79
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Pagination", children: /* @__PURE__ */ jsxs("ul", { className: "pagination", children: [
80
+ /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
81
+ "button",
82
+ {
83
+ type: "button",
84
+ onClick: () => onChange(currentPage - 1),
85
+ disabled: currentPage === 1,
86
+ "aria-label": "Previous page",
87
+ children: "Prev"
88
+ }
89
+ ) }),
90
+ paginationRange.map((page, idx) => {
91
+ if (page === DOTS) {
92
+ return /* @__PURE__ */ jsx("li", { className: "dots", children: "..." }, `dots-${idx}`);
93
+ }
94
+ const pageNumber = Number(page);
95
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
96
+ "button",
97
+ {
98
+ type: "button",
99
+ className: currentPage === pageNumber ? "active" : "",
100
+ onClick: () => onChange(pageNumber),
101
+ onKeyDown: (e) => handleKeyDown(e, page),
102
+ "aria-current": currentPage === pageNumber ? "page" : void 0,
103
+ children: pageNumber
104
+ }
105
+ ) }, pageNumber);
106
+ }),
107
+ /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
108
+ "button",
109
+ {
110
+ type: "button",
111
+ onClick: () => onChange(currentPage + 1),
112
+ disabled: currentPage === totalPages,
113
+ "aria-label": "Next page",
114
+ children: "Next"
115
+ }
116
+ ) })
117
+ ] }) });
118
+ }
119
+ export {
120
+ Pagination
121
+ };
122
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Pagination/usePagination.ts","../src/components/Pagination/pagination.utils.ts","../src/components/Pagination/Pagination.tsx"],"sourcesContent":["import { useMemo } from \"react\";\r\nimport { DOTS, range } from \"./pagination.utils\";\r\nimport { PaginationProps } from \"./pagination.types\";\r\n\r\nexport function usePagination({\r\n total,\r\n pageSize,\r\n currentPage,\r\n siblingCount = 1,\r\n}: PaginationProps) {\r\n return useMemo(() => {\r\n const totalPages = Math.ceil(total / pageSize);\r\n\r\n const totalPageNumbers = siblingCount + 5;\r\n\r\n if (totalPageNumbers >= totalPages) {\r\n return range(1, totalPages);\r\n }\r\n\r\n const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);\r\n const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages);\r\n\r\n const showLeftDots = leftSiblingIndex > 2;\r\n const showRightDots = rightSiblingIndex < totalPages - 2;\r\n\r\n if (!showLeftDots && showRightDots) {\r\n return [\r\n ...range(1, 3 + 2 * siblingCount),\r\n DOTS,\r\n totalPages,\r\n ];\r\n }\r\n\r\n if (showLeftDots && !showRightDots) {\r\n return [\r\n 1,\r\n DOTS,\r\n ...range(totalPages - (3 + 2 * siblingCount) + 1, totalPages),\r\n ];\r\n }\r\n\r\n if (showLeftDots && showRightDots) {\r\n return [\r\n 1,\r\n DOTS,\r\n ...range(leftSiblingIndex, rightSiblingIndex),\r\n DOTS,\r\n totalPages,\r\n ];\r\n }\r\n\r\n return [];\r\n }, [total, pageSize, currentPage, siblingCount]);\r\n}","export const DOTS = \"...\";\r\n\r\nexport function range(start: number, end: number) {\r\n return Array.from({ length: end - start + 1 }, (_, i) => start + i);\r\n}","import React from \"react\";\r\nimport { usePagination } from \"./usePagination\";\r\nimport { PaginationProps } from \"./pagination.types\";\r\nimport { DOTS } from \"./pagination.utils\";\r\nimport \"./pagination.css\";\r\n\r\nexport default function Pagination({\r\n total,\r\n pageSize,\r\n currentPage,\r\n onChange,\r\n siblingCount = 1,\r\n}: PaginationProps) {\r\n const totalPages = Math.ceil(total / pageSize);\r\n\r\n const paginationRange = usePagination({\r\n total,\r\n pageSize,\r\n currentPage,\r\n onChange,\r\n siblingCount,\r\n });\r\n\r\n if (totalPages <= 1 || !paginationRange) return null;\r\n\r\n const handleKeyDown = (\r\n e: React.KeyboardEvent<HTMLButtonElement>,\r\n page: string | number\r\n ) => {\r\n if (page === DOTS) return;\r\n\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n onChange(Number(page));\r\n }\r\n };\r\n\r\n return (\r\n <nav aria-label=\"Pagination\">\r\n <ul className=\"pagination\">\r\n {/* Prev */}\r\n <li>\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(currentPage - 1)}\r\n disabled={currentPage === 1}\r\n aria-label=\"Previous page\"\r\n >\r\n Prev\r\n </button>\r\n </li>\r\n\r\n {/* Pages */}\r\n {paginationRange.map((page: string | number, idx: number) => {\r\n if (page === DOTS) {\r\n return (\r\n <li key={`dots-${idx}`} className=\"dots\">\r\n ...\r\n </li>\r\n );\r\n }\r\n\r\n const pageNumber = Number(page);\r\n\r\n return (\r\n <li key={pageNumber}>\r\n <button\r\n type=\"button\"\r\n className={currentPage === pageNumber ? \"active\" : \"\"}\r\n onClick={() => onChange(pageNumber)}\r\n onKeyDown={(e) => handleKeyDown(e, page)}\r\n aria-current={currentPage === pageNumber ? \"page\" : undefined}\r\n >\r\n {pageNumber}\r\n </button>\r\n </li>\r\n );\r\n })}\r\n\r\n {/* Next */}\r\n <li>\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(currentPage + 1)}\r\n disabled={currentPage === totalPages}\r\n aria-label=\"Next page\"\r\n >\r\n Next\r\n </button>\r\n </li>\r\n </ul>\r\n </nav>\r\n );\r\n}"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "react-pagination-thami",
3
+ "version": "1.0.0",
4
+ "description": "Reusable React pagination component",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "npm run build:js && npm run build:types",
13
+ "build:js": "tsup src/index.ts",
14
+ "build:types": "tsc --declaration --emitDeclarationOnly --outDir dist",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "react",
19
+ "pagination",
20
+ "component",
21
+ "ui"
22
+ ],
23
+ "author": "thami",
24
+ "license": "MIT",
25
+ "peerDependencies": {
26
+ "react": ">=17",
27
+ "react-dom": ">=17"
28
+ },
29
+ "devDependencies": {
30
+ "typescript": "^5.0.0",
31
+ "tsup": "^8.0.0",
32
+ "@types/react": "^18.0.0",
33
+ "@types/react-dom": "^18.0.0"
34
+ }
35
+ }