@uktrade/react-component-library 0.11.0 → 0.12.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.
@@ -1 +1 @@
1
- {"version":3,"file":"ApiBoundary.d.ts","sourceRoot":"","sources":["../../../src/components/ApiBoundary/ApiBoundary.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAGD,eAAO,MAAM,WAAW,GAAI,mDAMzB,gBAAgB,4CAuBlB,CAAC"}
1
+ {"version":3,"file":"ApiBoundary.d.ts","sourceRoot":"","sources":["../../../src/components/ApiBoundary/ApiBoundary.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAGD,eAAO,MAAM,WAAW,GAAI,mDAMzB,gBAAgB,4CAwBlB,CAAC"}
@@ -4,4 +4,4 @@ import { LoadingSpinner } from "../LoadingSpinner/LoadingSpinner";
4
4
  import styles from "./ApiBoundary.module.css";
5
5
  import { Button } from "../Button";
6
6
  /* Boundary for API-related states: loading, success, and error */
7
- export const ApiBoundary = ({ isLoading, isError, error, onRetry, children, }) => (_jsxs("div", { className: styles.root, "aria-live": "polite", children: [isLoading && _jsx(LoadingSpinner, {}), !isLoading && !isError && children, isError && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.errorBackdrop }), _jsxs("section", { className: styles.error, children: [_jsx("h2", { className: "govuk-heading-m", children: "Error!" }), _jsx("pre", { className: styles.description, children: typeof error === "string" ? error : JSON.stringify(error, null, 2) }), _jsx(Button, { variant: "warning", onClick: onRetry, children: "Retry" })] })] }))] }));
7
+ export const ApiBoundary = ({ isLoading, isError, error, onRetry, children, }) => (_jsxs("div", { className: styles.root, "aria-live": "polite", children: [isLoading && _jsx(LoadingSpinner, {}), !isLoading && !isError && children, isError && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.errorBackdrop }), _jsxs("section", { className: styles.error, children: [_jsx("h2", { className: "govuk-heading-m", children: "Error!" }), _jsx("pre", { className: styles.description, children: typeof error === "string" ? error : JSON.stringify(error, null, 2) }), onRetry && (_jsx(Button, { variant: "warning", onClick: onRetry, children: "Retry" }))] })] }))] }));
@@ -21,5 +21,45 @@ export declare function createApiHooks<Paths extends {}>(client: ReturnType<type
21
21
  refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<any, Error>>;
22
22
  };
23
23
  };
24
+ postMutation: <P extends PathsWithMethod<Paths, "post">>(path: P) => {
25
+ mutation: import("@tanstack/react-query").UseMutationResult<any, unknown, any, unknown>;
26
+ state: {
27
+ data: any;
28
+ isLoading: boolean;
29
+ isError: boolean;
30
+ error: unknown;
31
+ mutate: import("@tanstack/react-query").UseMutateFunction<any, unknown, any, unknown>;
32
+ };
33
+ };
34
+ putMutation: <P extends PathsWithMethod<Paths, "put">>(path: P) => {
35
+ mutation: import("@tanstack/react-query").UseMutationResult<any, unknown, any, unknown>;
36
+ state: {
37
+ data: any;
38
+ isLoading: boolean;
39
+ isError: boolean;
40
+ error: unknown;
41
+ mutate: import("@tanstack/react-query").UseMutateFunction<any, unknown, any, unknown>;
42
+ };
43
+ };
44
+ patchMutation: <P extends PathsWithMethod<Paths, "patch">>(path: P) => {
45
+ mutation: import("@tanstack/react-query").UseMutationResult<any, unknown, any, unknown>;
46
+ state: {
47
+ data: any;
48
+ isLoading: boolean;
49
+ isError: boolean;
50
+ error: unknown;
51
+ mutate: import("@tanstack/react-query").UseMutateFunction<any, unknown, any, unknown>;
52
+ };
53
+ };
54
+ deleteMutation: <P extends PathsWithMethod<Paths, "delete">>(path: P) => {
55
+ mutation: import("@tanstack/react-query").UseMutationResult<any, unknown, any, unknown>;
56
+ state: {
57
+ data: any;
58
+ isLoading: boolean;
59
+ isError: boolean;
60
+ error: unknown;
61
+ mutate: import("@tanstack/react-query").UseMutateFunction<any, unknown, any, unknown>;
62
+ };
63
+ };
24
64
  };
25
65
  //# sourceMappingURL=ApiCreateHooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApiCreateHooks.d.ts","sourceRoot":"","sources":["../../../src/components/ApiQuery/ApiCreateHooks.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,wBAAgB,cAAc,CAAC,KAAK,SAAS,EAAE,EAC7C,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;UAMzC,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,QACrC,CAAC,WACE,GAAG;;;;;;;;;;WAYP,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,QACvC,CAAC,WACE,GAAG;;;;;;;;;;EA6CjB"}
1
+ {"version":3,"file":"ApiCreateHooks.d.ts","sourceRoot":"","sources":["../../../src/components/ApiQuery/ApiCreateHooks.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,wBAAgB,cAAc,CAAC,KAAK,SAAS,EAAE,EAC7C,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;UAOzC,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,QACrC,CAAC,WACE,GAAG;;;;;;;;;;WAYP,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,QACvC,CAAC,WACE,GAAG;;;;;;;;;;mBAYC,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC;;;;;;;;;;kBAQlD,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC;;;;;;;;;;oBAQ9C,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC;;;;;;;;;;qBAQjD,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC;;;;;;;;;;EAQvE"}
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { createApiClient } from "./ApiCreateClient";
3
- import { useApi } from "./ApiProvider";
3
+ import { useApi, useApiMutation } from "./ApiProvider";
4
4
  export function createApiHooks(client) {
5
+ // ToDo: Generalize this (params?: any) and fight openapi-fetch’s internal generics to get correct types from PathsWithMethod. Same for the mutation methods.
5
6
  // type GetParams<P extends PathsWithMethod<Paths, "get">> =
6
7
  // Parameters<typeof client.GET<P>>[1];
7
8
  return {
8
- get: (path, params // GetParams<P> More work to be done to fight openapi-fetch’s internal generics!!!!
9
- ) => {
9
+ get: (path, params) => {
10
10
  return useApi(["get", path, JSON.stringify(params ?? {})], async () => {
11
11
  const res = await client.GET(path, params);
12
12
  if (res.error)
@@ -14,8 +14,7 @@ export function createApiHooks(client) {
14
14
  return res.data;
15
15
  });
16
16
  },
17
- post: (path, params // GetParams<P> More work to be done to fight openapi-fetch’s internal generics!!!!
18
- ) => {
17
+ post: (path, params) => {
19
18
  return useApi(["post", path, JSON.stringify(params ?? {})], async () => {
20
19
  const res = await client.POST(path, params);
21
20
  if (res.error)
@@ -23,33 +22,37 @@ export function createApiHooks(client) {
23
22
  return res.data;
24
23
  });
25
24
  },
26
- // TODO: implement other methods (put, delete), furthermore generalize the mutation method
27
- // for all methods (No GET) to avoid React Query’s useQuery from running automatically on mount
28
- // Same here (params?: any)
29
- // postMutation: <P extends PathsWithMethod<Paths, "post">>(path: P, params?: any) => {
30
- // return useApiMutation(async () => {
31
- // const res = await client.POST(path, params);
32
- // if (res.error) throw res.error;
33
- // return res.data;
34
- // });
35
- // },
36
- // mutation: <
37
- // M extends "post" | "put" | "patch" | "delete",
38
- // P extends PathsWithMethod<Paths, M>
39
- // >(
40
- // method: M,
41
- // path: P,
42
- // params?: any
43
- // ) => {
44
- // return useApiMutation(async () => {
45
- // const res = await client[method.toUpperCase() as "POST" | "PUT" | "PATCH" | "DELETE"](path, params);
46
- // if (res.error) throw res.error;
47
- // return res.data;
48
- // });
49
- // }
50
- // ToDo: Generalize this:
51
- // const res = await client.POST(path, params);
52
- // if (res.error) throw res.error;
53
- // return res.data;
25
+ postMutation: (path) => {
26
+ return useApiMutation(async (params) => {
27
+ const res = await client.POST(path, params);
28
+ if (res.error)
29
+ throw res.error;
30
+ return res.data;
31
+ });
32
+ },
33
+ putMutation: (path) => {
34
+ return useApiMutation(async (params) => {
35
+ const res = await client.PUT(path, params);
36
+ if (res.error)
37
+ throw res.error;
38
+ return res.data;
39
+ });
40
+ },
41
+ patchMutation: (path) => {
42
+ return useApiMutation(async (params) => {
43
+ const res = await client.PATCH(path, params);
44
+ if (res.error)
45
+ throw res.error;
46
+ return res.data;
47
+ });
48
+ },
49
+ deleteMutation: (path) => {
50
+ return useApiMutation(async (params) => {
51
+ const res = await client.DELETE(path, params);
52
+ if (res.error)
53
+ throw res.error;
54
+ return res.data;
55
+ });
56
+ },
54
57
  };
55
58
  }
@@ -21,14 +21,14 @@ export declare function useApi<T>(key: QueryKey, queryFn: () => Promise<T>): {
21
21
  refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").NoInfer<T>, Error>>;
22
22
  };
23
23
  };
24
- export declare function useApiMutation<T>(mutationFn: () => Promise<T>): {
25
- mutation: import("@tanstack/react-query").UseMutationResult<T, Error, void, unknown>;
24
+ export declare function useApiMutation<TData, TVariables = void>(mutationFn: (variables: TVariables) => Promise<TData>): {
25
+ mutation: import("@tanstack/react-query").UseMutationResult<TData, unknown, TVariables, unknown>;
26
26
  state: {
27
- data: T | undefined;
27
+ data: TData | undefined;
28
28
  isLoading: boolean;
29
29
  isError: boolean;
30
- error: Error | null;
31
- mutate: import("@tanstack/react-query").UseMutateFunction<T, Error, void, unknown>;
30
+ error: unknown;
31
+ mutate: import("@tanstack/react-query").UseMutateFunction<TData, unknown, TVariables, unknown>;
32
32
  };
33
33
  };
34
34
  //# sourceMappingURL=ApiProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApiProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ApiQuery/ApiProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EAIX,KAAK,QAAQ,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC,wBAAgB,cAAc,gBAa7B;AAMD,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAMhE;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAYF,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC;;;;;;;;;EAgBjE;AAYD,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC;;;;;;;;;EAa7D"}
1
+ {"version":3,"file":"ApiProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ApiQuery/ApiProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EAIX,KAAK,QAAQ,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC,wBAAgB,cAAc,gBAa7B;AAMD,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAMhE;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAYF,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC;;;;;;;;;EAgBjE;AAYD,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,EACrD,UAAU,EAAE,CAAC,SAAS,EAAE,UAAU,KAAK,OAAO,CAAC,KAAK,CAAC;;;;;;;;;EAgBtD"}
@@ -65,9 +65,11 @@ It accepts `mutationFn` as function that performs the mutation request, and It r
65
65
  - `state` — a simplified structure with commonly used properties like `data`, `isLoading`, `isError`
66
66
  */
67
67
  export function useApiMutation(mutationFn) {
68
- const mutation = useMutation({ mutationFn });
68
+ const mutation = useMutation({
69
+ mutationFn,
70
+ });
69
71
  return {
70
- mutation, // Full React Query object
72
+ mutation,
71
73
  state: {
72
74
  data: mutation.data,
73
75
  isLoading: mutation.isPending,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uktrade/react-component-library",
3
- "version": "0.11.0",
3
+ "version": "0.12.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",
@@ -33,10 +33,11 @@ export const ApiBoundary = ({
33
33
  {typeof error === "string" ? error : JSON.stringify(error, null, 2)}
34
34
  </pre>
35
35
 
36
- {/* TODO: Make this button optional since it cannot always be required */}
37
- <Button variant="warning" onClick={onRetry}>
38
- Retry
39
- </Button>
36
+ {onRetry && (
37
+ <Button variant="warning" onClick={onRetry}>
38
+ Retry
39
+ </Button>
40
+ )}
40
41
  </section>
41
42
  </>
42
43
  )}
@@ -3,18 +3,19 @@
3
3
  import type { PathsWithMethod } from "openapi-typescript-helpers";
4
4
 
5
5
  import { createApiClient } from "./ApiCreateClient";
6
- import { useApi } from "./ApiProvider";
6
+ import { useApi, useApiMutation } from "./ApiProvider";
7
7
 
8
8
  export function createApiHooks<Paths extends {}>(
9
9
  client: ReturnType<typeof createApiClient<Paths>>
10
10
  ) {
11
+ // ToDo: Generalize this (params?: any) and fight openapi-fetch’s internal generics to get correct types from PathsWithMethod. Same for the mutation methods.
11
12
  // type GetParams<P extends PathsWithMethod<Paths, "get">> =
12
13
  // Parameters<typeof client.GET<P>>[1];
13
14
 
14
15
  return {
15
16
  get: <P extends PathsWithMethod<Paths, "get">>(
16
17
  path: P,
17
- params?: any // GetParams<P> More work to be done to fight openapi-fetch’s internal generics!!!!
18
+ params?: any
18
19
  ) => {
19
20
  return useApi(
20
21
  ["get", path, JSON.stringify(params ?? {})],
@@ -28,7 +29,7 @@ export function createApiHooks<Paths extends {}>(
28
29
 
29
30
  post: <P extends PathsWithMethod<Paths, "post">>(
30
31
  path: P,
31
- params?: any // GetParams<P> More work to be done to fight openapi-fetch’s internal generics!!!!
32
+ params?: any
32
33
  ) => {
33
34
  return useApi(
34
35
  ["post", path, JSON.stringify(params ?? {})],
@@ -40,37 +41,36 @@ export function createApiHooks<Paths extends {}>(
40
41
  );
41
42
  },
42
43
 
43
- // TODO: implement other methods (put, delete), furthermore generalize the mutation method
44
- // for all methods (No GET) to avoid React Query’s useQuery from running automatically on mount
45
-
46
- // Same here (params?: any)
47
- // postMutation: <P extends PathsWithMethod<Paths, "post">>(path: P, params?: any) => {
48
- // return useApiMutation(async () => {
49
- // const res = await client.POST(path, params);
50
- // if (res.error) throw res.error;
51
- // return res.data;
52
- // });
53
- // },
44
+ postMutation: <P extends PathsWithMethod<Paths, "post">>(path: P) => {
45
+ return useApiMutation(async (params: any) => {
46
+ const res = await client.POST(path, params);
47
+ if (res.error) throw res.error;
48
+ return res.data;
49
+ });
50
+ },
54
51
 
55
- // mutation: <
56
- // M extends "post" | "put" | "patch" | "delete",
57
- // P extends PathsWithMethod<Paths, M>
58
- // >(
59
- // method: M,
60
- // path: P,
61
- // params?: any
62
- // ) => {
63
- // return useApiMutation(async () => {
64
- // const res = await client[method.toUpperCase() as "POST" | "PUT" | "PATCH" | "DELETE"](path, params);
65
- // if (res.error) throw res.error;
66
- // return res.data;
67
- // });
68
- // }
52
+ putMutation: <P extends PathsWithMethod<Paths, "put">>(path: P) => {
53
+ return useApiMutation(async (params: any) => {
54
+ const res = await client.PUT(path, params);
55
+ if (res.error) throw res.error;
56
+ return res.data;
57
+ });
58
+ },
69
59
 
70
- // ToDo: Generalize this:
71
- // const res = await client.POST(path, params);
72
- // if (res.error) throw res.error;
73
- // return res.data;
60
+ patchMutation: <P extends PathsWithMethod<Paths, "patch">>(path: P) => {
61
+ return useApiMutation(async (params: any) => {
62
+ const res = await client.PATCH(path, params);
63
+ if (res.error) throw res.error;
64
+ return res.data;
65
+ });
66
+ },
74
67
 
68
+ deleteMutation: <P extends PathsWithMethod<Paths, "delete">>(path: P) => {
69
+ return useApiMutation(async (params: any) => {
70
+ const res = await client.DELETE(path, params);
71
+ if (res.error) throw res.error;
72
+ return res.data;
73
+ });
74
+ },
75
75
  };
76
76
  }
@@ -89,11 +89,15 @@ It accepts `mutationFn` as function that performs the mutation request, and It r
89
89
  - `mutation` — the full React Query mutation object
90
90
  - `state` — a simplified structure with commonly used properties like `data`, `isLoading`, `isError`
91
91
  */
92
- export function useApiMutation<T>(mutationFn: () => Promise<T>) {
93
- const mutation = useMutation({ mutationFn });
92
+ export function useApiMutation<TData, TVariables = void>(
93
+ mutationFn: (variables: TVariables) => Promise<TData>
94
+ ) {
95
+ const mutation = useMutation<TData, unknown, TVariables>({
96
+ mutationFn,
97
+ });
94
98
 
95
99
  return {
96
- mutation, // Full React Query object
100
+ mutation,
97
101
  state: {
98
102
  data: mutation.data,
99
103
  isLoading: mutation.isPending,
@@ -103,3 +107,4 @@ export function useApiMutation<T>(mutationFn: () => Promise<T>) {
103
107
  },
104
108
  };
105
109
  }
110
+