@uktrade/react-component-library 0.22.16 → 0.23.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.
@@ -12,13 +12,13 @@ export type ApiQueryState<T> = {
12
12
  refetch: () => void;
13
13
  };
14
14
  export declare function useApi<T>(key: QueryKey, queryFn: () => Promise<T>): {
15
- query: import("@tanstack/react-query").UseQueryResult<import("@tanstack/query-core").NoInfer<T>, Error>;
15
+ query: import("@tanstack/react-query").UseQueryResult<T, Error>;
16
16
  state: {
17
- data: import("@tanstack/query-core").NoInfer<T> | undefined;
17
+ data: T | undefined;
18
18
  isLoading: boolean;
19
19
  isError: boolean;
20
20
  error: Error | null;
21
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").NoInfer<T>, Error>>;
21
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<T, Error>>;
22
22
  };
23
23
  };
24
24
  export declare function useApiMutation<TData, TVariables = void>(mutationFn: (variables: TVariables) => Promise<TData>): {
@@ -1,6 +1,6 @@
1
1
  .error {
2
- border-color: #d4351c;
3
- background-color: #d4351c;
2
+ border-color: #d4351c !important;
3
+ background-color: #d4351c !important;
4
4
  }
5
5
 
6
6
  .fullWidthContent > p {
@@ -0,0 +1,9 @@
1
+ import type React from "react";
2
+ interface PaginationProps {
3
+ currentPage: number;
4
+ totalPages: number;
5
+ onPageChange: (page: number) => void;
6
+ }
7
+ export declare const Pagination: ({ currentPage, totalPages, onPageChange }: PaginationProps) => React.JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=Pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/components/Pagination/Pagination.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAID,eAAO,MAAM,UAAU,GAAI,2CAA2C,eAAe,KAAG,KAAK,CAAC,GAAG,CAAC,OAsIjG,CAAC"}
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ const MAX_PAGES = 200;
4
+ export const Pagination = ({ currentPage, totalPages, onPageChange }) => {
5
+ const safeTotalPages = Math.min(totalPages, MAX_PAGES);
6
+ const getPageNumbers = () => {
7
+ const pages = [];
8
+ // Always show first page
9
+ pages.push(1);
10
+ const start = Math.max(2, currentPage - 1);
11
+ const end = Math.min(safeTotalPages - 1, currentPage + 1);
12
+ // Ellipsis after first page
13
+ if (start > 2) {
14
+ pages.push("...");
15
+ }
16
+ // Pages around current
17
+ for (let i = start; i <= end; i++) {
18
+ pages.push(i);
19
+ }
20
+ // Ellipsis before last page
21
+ if (end < safeTotalPages - 1) {
22
+ pages.push("...");
23
+ }
24
+ // Always show last page if more than 1
25
+ if (safeTotalPages > 1) {
26
+ pages.push(safeTotalPages);
27
+ }
28
+ return pages;
29
+ };
30
+ const pages = getPageNumbers();
31
+ return (_jsxs("nav", { className: "govuk-pagination", "aria-label": "Pagination", style: { justifyContent: "center" }, "data-testid": "pagination", children: [currentPage > 1 && (_jsx("div", { className: "govuk-pagination__prev", children: _jsxs("a", { className: "govuk-link govuk-pagination__link", href: "#", rel: "prev", onClick: (e) => {
32
+ e.preventDefault();
33
+ onPageChange(currentPage - 1);
34
+ }, children: [_jsx("svg", { className: "govuk-pagination__icon govuk-pagination__icon--prev", xmlns: "http://www.w3.org/2000/svg", height: "13", width: "15", "aria-hidden": "true", focusable: "false", viewBox: "0 0 15 13", children: _jsx("path", { d: "m6.5938-0.0078125-6.7266 6.7266 6.7441 6.4062 1.377-1.449-4.1856-3.9768h12.896v-2h-12.984l4.2931-4.293-1.414-1.414z" }) }), _jsxs("span", { className: "govuk-pagination__link-title", children: ["Previous", _jsx("span", { className: "govuk-visually-hidden", children: " page" })] })] }) })), _jsx("ul", { className: "govuk-pagination__list", children: pages.map((page) => (_jsx("li", { className: `govuk-pagination__item${page === currentPage ? " govuk-pagination__item--current" : ""}`, children: typeof page === "number" ? (_jsx("a", { className: "govuk-link govuk-pagination__link", href: "#", "aria-label": `Page ${page}`, "aria-current": page === currentPage ? "page" : undefined, onClick: (e) => {
35
+ e.preventDefault();
36
+ onPageChange(page);
37
+ }, children: page })) : (_jsx("span", { className: "govuk-pagination__link-title", "aria-hidden": "true", children: page })) }, page))) }), currentPage < safeTotalPages && (_jsx("div", { className: "govuk-pagination__next", children: _jsxs("a", { className: "govuk-link govuk-pagination__link", href: "#", rel: "next", onClick: (e) => {
38
+ e.preventDefault();
39
+ onPageChange(currentPage + 1);
40
+ }, children: [_jsxs("span", { className: "govuk-pagination__link-title", children: ["Next", _jsx("span", { className: "govuk-visually-hidden", children: " page" })] }), _jsx("svg", { className: "govuk-pagination__icon govuk-pagination__icon--next", xmlns: "http://www.w3.org/2000/svg", height: "13", width: "15", "aria-hidden": "true", focusable: "false", viewBox: "0 0 15 13", children: _jsx("path", { d: "m8.107-0.0078125-1.4136 1.414 4.2926 4.293h-12.986v2h12.896l-4.1855 3.9766 1.377 1.4492 6.7441-6.4062-6.7246-6.7266z" }) })] }) }))] }));
41
+ };
@@ -7,7 +7,7 @@ export const Tabs = ({ tabs, title = "Contents", onTabChange, activeTabId, }) =>
7
7
  }
8
8
  // Determine active tab, fallback to first tab
9
9
  const currentActiveId = activeTabId || tabs[0].id;
10
- return (_jsxs("div", { className: "govuk-tabs", "data-module": "govuk-tabs", children: [_jsx("h2", { className: "govuk-tabs__title", children: title }), _jsx("ul", { className: "govuk-tabs__list", children: tabs.map((tab) => (_jsx("li", { className: clsx("govuk-tabs__list-item", tab.id === currentActiveId && "govuk-tabs__list-item--selected"), children: _jsx("a", { className: "govuk-tabs__tab", href: `#${tab.id}`, onClick: (e) => {
10
+ return (_jsxs("div", { className: "govuk-tabs", "data-module": "govuk-tabs", children: [_jsx("h2", { className: "govuk-tabs__title", children: title }), _jsx("ul", { className: "govuk-tabs__list", children: tabs.map((tab) => (_jsx("li", { className: clsx("govuk-tabs__list-item", tab.id === currentActiveId && "govuk-tabs__list-item--selected"), children: _jsx("a", { className: "govuk-tabs__tab", href: `#${tab.id}`, onClick: () => {
11
11
  onTabChange?.(tab.id);
12
12
  }, children: tab.label }) }, tab.id))) }), tabs.map((tab) => (_jsx("div", { id: tab.id, className: clsx("govuk-tabs__panel", tab.id !== currentActiveId && "govuk-tabs__panel--hidden"), children: tab.content }, tab.id)))] }));
13
13
  };
package/dist/index.d.ts CHANGED
@@ -17,4 +17,5 @@ export * from "./components/Details/Details";
17
17
  export * from "./components/Tooltip/Tooltip";
18
18
  export * from "./components/Tabs/Tabs";
19
19
  export * from "./components/Table/Table";
20
+ export * from "./components/Pagination/Pagination";
20
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4CAA4C,CAAC;AAC3D,cAAc,sCAAsC,CAAC;AACrD,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oDAAoD,CAAC;AACnE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,wCAAwC,CAAC;AACvD,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4CAA4C,CAAC;AAC3D,cAAc,sCAAsC,CAAC;AACrD,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oDAAoD,CAAC;AACnE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC"}
package/dist/index.js CHANGED
@@ -17,3 +17,4 @@ export * from "./components/Details/Details";
17
17
  export * from "./components/Tooltip/Tooltip";
18
18
  export * from "./components/Tabs/Tabs";
19
19
  export * from "./components/Table/Table";
20
+ export * from "./components/Pagination/Pagination";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uktrade/react-component-library",
3
- "version": "0.22.16",
3
+ "version": "0.23.0",
4
4
  "description": "A collection of reusable React components following GOV.UK design patterns.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -68,8 +68,8 @@
68
68
  "vitest": "^4.0.18"
69
69
  },
70
70
  "engines": {
71
- "npm": ">=11.6.2",
72
- "node": ">=24.11.1"
71
+ "npm": ">=11.17.0",
72
+ "node": ">=24.19.0"
73
73
  },
74
74
  "dependencies": {
75
75
  "@tanstack/react-query": "^5.90.20",
@@ -1,6 +1,6 @@
1
1
  .error {
2
- border-color: #d4351c;
3
- background-color: #d4351c;
2
+ border-color: #d4351c !important;
3
+ background-color: #d4351c !important;
4
4
  }
5
5
 
6
6
  .fullWidthContent > p {
@@ -0,0 +1,147 @@
1
+ "use client";
2
+
3
+ import type React from "react";
4
+
5
+ interface PaginationProps {
6
+ currentPage: number;
7
+ totalPages: number;
8
+ onPageChange: (page: number) => void;
9
+ }
10
+
11
+ const MAX_PAGES = 200;
12
+
13
+ export const Pagination = ({ currentPage, totalPages, onPageChange }: PaginationProps): React.JSX.Element => {
14
+ const safeTotalPages = Math.min(totalPages, MAX_PAGES);
15
+
16
+ const getPageNumbers = () => {
17
+ const pages: (number | string)[] = [];
18
+
19
+ // Always show first page
20
+ pages.push(1);
21
+
22
+ const start = Math.max(2, currentPage - 1);
23
+ const end = Math.min(safeTotalPages - 1, currentPage + 1);
24
+
25
+ // Ellipsis after first page
26
+ if (start > 2) {
27
+ pages.push("...");
28
+ }
29
+
30
+ // Pages around current
31
+ for (let i = start; i <= end; i++) {
32
+ pages.push(i);
33
+ }
34
+
35
+ // Ellipsis before last page
36
+ if (end < safeTotalPages - 1) {
37
+ pages.push("...");
38
+ }
39
+
40
+ // Always show last page if more than 1
41
+ if (safeTotalPages > 1) {
42
+ pages.push(safeTotalPages);
43
+ }
44
+
45
+ return pages;
46
+ };
47
+
48
+ const pages = getPageNumbers();
49
+
50
+ return (
51
+ <nav
52
+ className="govuk-pagination"
53
+ aria-label="Pagination"
54
+ style={{ justifyContent: "center" }}
55
+ data-testid="pagination"
56
+ >
57
+ {/* Previous */}
58
+ {currentPage > 1 && (
59
+ <div className="govuk-pagination__prev">
60
+ <a
61
+ className="govuk-link govuk-pagination__link"
62
+ href="#"
63
+ rel="prev"
64
+ onClick={(e) => {
65
+ e.preventDefault();
66
+ onPageChange(currentPage - 1);
67
+ }}
68
+ >
69
+ <svg
70
+ className="govuk-pagination__icon govuk-pagination__icon--prev"
71
+ xmlns="http://www.w3.org/2000/svg"
72
+ height="13"
73
+ width="15"
74
+ aria-hidden="true"
75
+ focusable="false"
76
+ viewBox="0 0 15 13"
77
+ >
78
+ <path d="m6.5938-0.0078125-6.7266 6.7266 6.7441 6.4062 1.377-1.449-4.1856-3.9768h12.896v-2h-12.984l4.2931-4.293-1.414-1.414z" />
79
+ </svg>
80
+ <span className="govuk-pagination__link-title">
81
+ Previous<span className="govuk-visually-hidden"> page</span>
82
+ </span>
83
+ </a>
84
+ </div>
85
+ )}
86
+
87
+ {/* Page numbers */}
88
+ <ul className="govuk-pagination__list">
89
+ {pages.map((page) => (
90
+ <li
91
+ key={page}
92
+ className={`govuk-pagination__item${page === currentPage ? " govuk-pagination__item--current" : ""}`}
93
+ >
94
+ {typeof page === "number" ? (
95
+ <a
96
+ className="govuk-link govuk-pagination__link"
97
+ href="#"
98
+ aria-label={`Page ${page}`}
99
+ aria-current={page === currentPage ? "page" : undefined}
100
+ onClick={(e) => {
101
+ e.preventDefault();
102
+ onPageChange(page);
103
+ }}
104
+ >
105
+ {page}
106
+ </a>
107
+ ) : (
108
+ <span className="govuk-pagination__link-title" aria-hidden="true">
109
+ {page}
110
+ </span>
111
+ )}
112
+ </li>
113
+ ))}
114
+ </ul>
115
+
116
+ {/* Next */}
117
+ {currentPage < safeTotalPages && (
118
+ <div className="govuk-pagination__next">
119
+ <a
120
+ className="govuk-link govuk-pagination__link"
121
+ href="#"
122
+ rel="next"
123
+ onClick={(e) => {
124
+ e.preventDefault();
125
+ onPageChange(currentPage + 1);
126
+ }}
127
+ >
128
+ <span className="govuk-pagination__link-title">
129
+ Next<span className="govuk-visually-hidden"> page</span>
130
+ </span>
131
+ <svg
132
+ className="govuk-pagination__icon govuk-pagination__icon--next"
133
+ xmlns="http://www.w3.org/2000/svg"
134
+ height="13"
135
+ width="15"
136
+ aria-hidden="true"
137
+ focusable="false"
138
+ viewBox="0 0 15 13"
139
+ >
140
+ <path d="m8.107-0.0078125-1.4136 1.414 4.2926 4.293h-12.986v2h12.896l-4.1855 3.9766 1.377 1.4492 6.7441-6.4062-6.7246-6.7266z" />
141
+ </svg>
142
+ </a>
143
+ </div>
144
+ )}
145
+ </nav>
146
+ );
147
+ };
@@ -45,7 +45,7 @@ export const Tabs = ({
45
45
  <a
46
46
  className="govuk-tabs__tab"
47
47
  href={`#${tab.id}`}
48
- onClick={(e) => {
48
+ onClick={ () => {
49
49
  onTabChange?.(tab.id);
50
50
  }}
51
51
  >
package/src/index.ts CHANGED
@@ -17,3 +17,4 @@ export * from "./components/Details/Details";
17
17
  export * from "./components/Tooltip/Tooltip";
18
18
  export * from "./components/Tabs/Tabs";
19
19
  export * from "./components/Table/Table";
20
+ export * from "./components/Pagination/Pagination";