@uktrade/react-component-library 0.12.0 → 0.13.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/dist/components/ApiQuery/ApiCreateHooks.d.ts +2 -2
- package/dist/components/ApiQuery/ApiCreateHooks.d.ts.map +1 -1
- package/dist/components/ApiQuery/ApiCreateHooks.js +18 -14
- package/dist/components/Inputs/CheckBoxesInput/CheckBoxGroupInput.d.ts +21 -0
- package/dist/components/Inputs/CheckBoxesInput/CheckBoxGroupInput.d.ts.map +1 -0
- package/dist/components/Inputs/CheckBoxesInput/CheckBoxGroupInput.js +14 -0
- package/dist/components/Inputs/SelectInput/SelectInput.d.ts +21 -0
- package/dist/components/Inputs/SelectInput/SelectInput.d.ts.map +1 -0
- package/dist/components/Inputs/SelectInput/SelectInput.js +18 -0
- package/dist/components/Inputs/TextInput/TextInput.d.ts +17 -0
- package/dist/components/Inputs/TextInput/TextInput.d.ts.map +1 -0
- package/dist/components/Inputs/TextInput/TextInput.js +19 -0
- package/dist/components/Inputs/index.d.ts +4 -0
- package/dist/components/Inputs/index.d.ts.map +1 -0
- package/dist/components/Inputs/index.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +1 -1
- package/src/components/ApiQuery/ApiCreateHooks.tsx +18 -14
- package/src/components/Inputs/CheckBoxesInput/CheckBoxGroupInput.tsx +93 -0
- package/src/components/Inputs/DateInput/.gitkeep +0 -0
- package/src/components/Inputs/RadioInput/.gitkeep +0 -0
- package/src/components/Inputs/SelectInput/SelectInput.tsx +102 -0
- package/src/components/Inputs/TextInput/TextInput.tsx +105 -0
- package/src/components/Inputs/index.ts +3 -0
- package/src/index.ts +1 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PathsWithMethod } from "openapi-typescript-helpers";
|
|
2
2
|
import { createApiClient } from "./ApiCreateClient";
|
|
3
3
|
export declare function createApiHooks<Paths extends {}>(client: ReturnType<typeof createApiClient<Paths>>): {
|
|
4
|
-
get: <P extends PathsWithMethod<Paths, "get">>(path: P,
|
|
4
|
+
get: <P extends PathsWithMethod<Paths, "get">>(path: P, input?: any) => {
|
|
5
5
|
query: import("@tanstack/react-query").UseQueryResult<any, Error>;
|
|
6
6
|
state: {
|
|
7
7
|
data: any;
|
|
@@ -11,7 +11,7 @@ export declare function createApiHooks<Paths extends {}>(client: ReturnType<type
|
|
|
11
11
|
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<any, Error>>;
|
|
12
12
|
};
|
|
13
13
|
};
|
|
14
|
-
post: <P extends PathsWithMethod<Paths, "post">>(path: P,
|
|
14
|
+
post: <P extends PathsWithMethod<Paths, "post">>(path: P, input?: any) => {
|
|
15
15
|
query: import("@tanstack/react-query").UseQueryResult<any, Error>;
|
|
16
16
|
state: {
|
|
17
17
|
data: any;
|
|
@@ -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;
|
|
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;AAKpD,wBAAgB,cAAc,CAAC,KAAK,SAAS,EAAE,EAC7C,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;UAQzC,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,QACrC,CAAC,UACC,GAAG;;;;;;;;;;WAYN,CAAC,SAAS,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,QACvC,CAAC,UACC,GAAG;;;;;;;;;;mBAaE,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,54 +1,58 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createApiClient } from "./ApiCreateClient";
|
|
3
3
|
import { useApi, useApiMutation } from "./ApiProvider";
|
|
4
|
+
// API hook factory that converts a typed OpenAPI client into React hooks (`useApi` and `useApiMutation`) that the UI can use.
|
|
5
|
+
// Provides a simple interface for making API calls and handling loading and error states in your React components.
|
|
4
6
|
export function createApiHooks(client) {
|
|
5
7
|
// ToDo: Generalize this (params?: any) and fight openapi-fetch’s internal generics to get correct types from PathsWithMethod. Same for the mutation methods.
|
|
6
8
|
// type GetParams<P extends PathsWithMethod<Paths, "get">> =
|
|
7
9
|
// Parameters<typeof client.GET<P>>[1];
|
|
10
|
+
// Using useQuery
|
|
8
11
|
return {
|
|
9
|
-
get: (path,
|
|
10
|
-
return useApi(["get", path, JSON.stringify(
|
|
11
|
-
const res = await client.GET(path,
|
|
12
|
+
get: (path, input) => {
|
|
13
|
+
return useApi(["get", path, JSON.stringify(input ?? {})], async () => {
|
|
14
|
+
const res = await client.GET(path, input);
|
|
12
15
|
if (res.error)
|
|
13
16
|
throw res.error;
|
|
14
17
|
return res.data;
|
|
15
18
|
});
|
|
16
19
|
},
|
|
17
|
-
post: (path,
|
|
18
|
-
return useApi(["post", path, JSON.stringify(
|
|
19
|
-
const res = await client.POST(path,
|
|
20
|
+
post: (path, input) => {
|
|
21
|
+
return useApi(["post", path, JSON.stringify(input ?? {})], async () => {
|
|
22
|
+
const res = await client.POST(path, input);
|
|
20
23
|
if (res.error)
|
|
21
24
|
throw res.error;
|
|
22
25
|
return res.data;
|
|
23
26
|
});
|
|
24
27
|
},
|
|
28
|
+
// Using useMutation
|
|
25
29
|
postMutation: (path) => {
|
|
26
|
-
return useApiMutation(async (
|
|
27
|
-
const res = await client.POST(path,
|
|
30
|
+
return useApiMutation(async (input) => {
|
|
31
|
+
const res = await client.POST(path, input);
|
|
28
32
|
if (res.error)
|
|
29
33
|
throw res.error;
|
|
30
34
|
return res.data;
|
|
31
35
|
});
|
|
32
36
|
},
|
|
33
37
|
putMutation: (path) => {
|
|
34
|
-
return useApiMutation(async (
|
|
35
|
-
const res = await client.PUT(path,
|
|
38
|
+
return useApiMutation(async (input) => {
|
|
39
|
+
const res = await client.PUT(path, input);
|
|
36
40
|
if (res.error)
|
|
37
41
|
throw res.error;
|
|
38
42
|
return res.data;
|
|
39
43
|
});
|
|
40
44
|
},
|
|
41
45
|
patchMutation: (path) => {
|
|
42
|
-
return useApiMutation(async (
|
|
43
|
-
const res = await client.PATCH(path,
|
|
46
|
+
return useApiMutation(async (input) => {
|
|
47
|
+
const res = await client.PATCH(path, input);
|
|
44
48
|
if (res.error)
|
|
45
49
|
throw res.error;
|
|
46
50
|
return res.data;
|
|
47
51
|
});
|
|
48
52
|
},
|
|
49
53
|
deleteMutation: (path) => {
|
|
50
|
-
return useApiMutation(async (
|
|
51
|
-
const res = await client.DELETE(path,
|
|
54
|
+
return useApiMutation(async (input) => {
|
|
55
|
+
const res = await client.DELETE(path, input);
|
|
52
56
|
if (res.error)
|
|
53
57
|
throw res.error;
|
|
54
58
|
return res.data;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
type LegendAs = "h1" | "h2" | "h3" | "h4";
|
|
3
|
+
type LegendSize = "s" | "m" | "l" | "xl";
|
|
4
|
+
interface CheckboxOption {
|
|
5
|
+
id: string;
|
|
6
|
+
value: string;
|
|
7
|
+
label: ReactNode;
|
|
8
|
+
checked?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface CheckboxGroupProps {
|
|
11
|
+
legend: ReactNode;
|
|
12
|
+
hint?: ReactNode;
|
|
13
|
+
error?: string;
|
|
14
|
+
options: CheckboxOption[];
|
|
15
|
+
name: string;
|
|
16
|
+
legendAs?: LegendAs;
|
|
17
|
+
legendSize?: LegendSize;
|
|
18
|
+
}
|
|
19
|
+
export declare const CheckboxGroup: ({ legend, hint, error, options, name, legendAs, legendSize, }: CheckboxGroupProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=CheckBoxGroupInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CheckBoxGroupInput.d.ts","sourceRoot":"","sources":["../../../../src/components/Inputs/CheckBoxesInput/CheckBoxGroupInput.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,KAAK,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1C,KAAK,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC;AAEzC,UAAU,cAAc;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,kBAAkB;IACxB,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;CAC3B;AAED,eAAO,MAAM,aAAa,GAAI,+DAQ3B,kBAAkB,4CA0DpB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { createElement } from "react";
|
|
5
|
+
export const CheckboxGroup = ({ legend, hint, error, options, name, legendAs = "h4", legendSize = "m", }) => {
|
|
6
|
+
const hasError = Boolean(error);
|
|
7
|
+
const errorId = hasError ? `${name}-error` : undefined;
|
|
8
|
+
const legendHeading = createElement(legendAs, { className: "govuk-fieldset__heading" }, legend);
|
|
9
|
+
return (_jsx("div", { className: clsx("govuk-form-group", {
|
|
10
|
+
"govuk-form-group--error": hasError,
|
|
11
|
+
}), children: _jsxs("fieldset", { className: "govuk-fieldset", "aria-describedby": errorId, children: [_jsx("legend", { className: clsx("govuk-fieldset__legend", {
|
|
12
|
+
[`govuk-fieldset__legend--${legendSize}`]: legendSize !== "m",
|
|
13
|
+
}), children: legendHeading }), hint && _jsx("div", { className: "govuk-hint", children: hint }), hasError && (_jsxs("p", { id: errorId, className: "govuk-error-message", children: [_jsx("span", { className: "govuk-visually-hidden", children: "Error:" }), " ", error] })), _jsx("div", { className: "govuk-checkboxes", "data-module": "govuk-checkboxes", children: options.map((opt) => (_jsxs("div", { className: "govuk-checkboxes__item", children: [_jsx("input", { className: "govuk-checkboxes__input", id: opt.id, name: name, type: "checkbox", value: opt.value, defaultChecked: opt.checked }), _jsx("label", { className: "govuk-label govuk-checkboxes__label", htmlFor: opt.id, children: opt.label })] }, opt.id))) })] }) }));
|
|
14
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from "react";
|
|
2
|
+
type LabelAs = "h1" | "h2" | "h3" | "h4";
|
|
3
|
+
type LabelSize = "s" | "m" | "l" | "xl";
|
|
4
|
+
type SelectProps = Omit<JSX.IntrinsicElements["select"], "id">;
|
|
5
|
+
interface SelectInputProps extends SelectProps {
|
|
6
|
+
id: string;
|
|
7
|
+
label: ReactNode;
|
|
8
|
+
hint?: ReactNode;
|
|
9
|
+
error?: string;
|
|
10
|
+
options: {
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
}[];
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
labelAs?: LabelAs;
|
|
16
|
+
labelSize?: LabelSize;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const SelectInput: ({ id, label, hint, error, options, placeholder, labelAs, labelSize, className, ...props }: SelectInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=SelectInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectInput.d.ts","sourceRoot":"","sources":["../../../../src/components/Inputs/SelectInput/SelectInput.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,KAAK,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACzC,KAAK,SAAS,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC;AACxC,KAAK,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;AAE/D,UAAU,gBAAiB,SAAQ,WAAW;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,GAAI,2FAWzB,gBAAgB,4CAoElB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { createElement } from "react";
|
|
5
|
+
export const SelectInput = ({ id, label, hint, error, options, placeholder, labelAs, labelSize = "m", className, ...props }) => {
|
|
6
|
+
const hasError = Boolean(error);
|
|
7
|
+
const hintId = hint ? `${id}-hint` : undefined;
|
|
8
|
+
const errorId = hasError ? `${id}-error` : undefined;
|
|
9
|
+
const ariaDescribedBy = [hintId, errorId].filter(Boolean).join(" ") || undefined;
|
|
10
|
+
const labelElement = (_jsx("label", { htmlFor: id, className: clsx("govuk-label", {
|
|
11
|
+
[`govuk-label--${labelSize}`]: labelSize !== "m",
|
|
12
|
+
}), children: label }));
|
|
13
|
+
return (_jsxs("div", { className: clsx("govuk-form-group", {
|
|
14
|
+
"govuk-form-group--error": hasError,
|
|
15
|
+
}), children: [labelAs
|
|
16
|
+
? createElement(labelAs, { className: "govuk-label-wrapper" }, labelElement)
|
|
17
|
+
: labelElement, hint && (_jsx("div", { id: hintId, className: "govuk-hint", children: hint })), hasError && (_jsxs("p", { id: errorId, className: "govuk-error-message", children: [_jsx("span", { className: "govuk-visually-hidden", children: "Error:" }), " ", error] })), _jsxs("select", { id: id, className: clsx("govuk-select", { "govuk-select--error": hasError }, className), "aria-describedby": ariaDescribedBy, ...props, children: [placeholder && (_jsx("option", { value: "", disabled: true, hidden: true, children: placeholder })), options.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value)))] })] }));
|
|
18
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from "react";
|
|
2
|
+
type LabelAs = "h1" | "h2" | "h3" | "h4";
|
|
3
|
+
type InputProps = Omit<JSX.IntrinsicElements["input"], "id">;
|
|
4
|
+
interface TextInputProps extends InputProps {
|
|
5
|
+
id: string;
|
|
6
|
+
label: ReactNode;
|
|
7
|
+
hint?: ReactNode;
|
|
8
|
+
error?: string;
|
|
9
|
+
width?: "10" | "20" | "30";
|
|
10
|
+
labelSize?: "s" | "m" | "l" | "xl";
|
|
11
|
+
labelAs?: LabelAs;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
suffix?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export declare const TextInput: ({ id, label, hint, error, width, labelSize, labelAs, className, placeholder, suffix, ...props }: TextInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=TextInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../../../src/components/Inputs/TextInput/TextInput.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,KAAK,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACzC,KAAK,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;AAE7D,UAAU,cAAe,SAAQ,UAAU;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,eAAO,MAAM,SAAS,GAAI,iGAYvB,cAAc,4CAuEhB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { createElement } from "react";
|
|
5
|
+
export const TextInput = ({ id, label, hint, error, width = "20", labelSize = "m", labelAs, className, placeholder, suffix, ...props }) => {
|
|
6
|
+
const hasError = Boolean(error);
|
|
7
|
+
const hintId = hint ? `${id}-hint` : undefined;
|
|
8
|
+
const errorId = hasError ? `${id}-error` : undefined;
|
|
9
|
+
const describedBy = [hintId, errorId].filter(Boolean).join(" ") || undefined;
|
|
10
|
+
const labelElement = (_jsx("label", { htmlFor: id, className: clsx("govuk-label", {
|
|
11
|
+
[`govuk-label--${labelSize}`]: labelSize !== "m",
|
|
12
|
+
}), children: label }));
|
|
13
|
+
const input = (_jsx("input", { id: id, className: clsx("govuk-input", `govuk-input--width-${width}`, className), "aria-invalid": hasError, "aria-describedby": describedBy, placeholder: placeholder, ...props }));
|
|
14
|
+
return (_jsxs("div", { className: clsx("govuk-form-group", {
|
|
15
|
+
"govuk-form-group--error": hasError,
|
|
16
|
+
}), children: [labelAs
|
|
17
|
+
? createElement(labelAs, { className: "govuk-label-wrapper" }, labelElement)
|
|
18
|
+
: labelElement, hint && (_jsx("div", { id: hintId, className: "govuk-hint", children: hint })), hasError && (_jsxs("p", { id: errorId, className: "govuk-error-message", children: [_jsx("span", { className: "govuk-visually-hidden", children: "Error:" }), " ", error] })), suffix ? (_jsxs("div", { className: "govuk-input__wrapper", children: [input, _jsx("div", { className: "govuk-input__suffix", "aria-hidden": "true", children: suffix })] })) : (input)] }));
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Inputs/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sCAAsC,CAAC;AACrD,cAAc,2BAA2B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ export * from "./components/BackLink";
|
|
|
11
11
|
export * from "./components/LoadingSpinner/LoadingSpinner";
|
|
12
12
|
export * from "./components/ApiBoundary/ApiBoundary";
|
|
13
13
|
export * from "./components/ApiQuery";
|
|
14
|
+
export * from "./components/Inputs";
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|
|
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"}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -5,6 +5,8 @@ import type { PathsWithMethod } from "openapi-typescript-helpers";
|
|
|
5
5
|
import { createApiClient } from "./ApiCreateClient";
|
|
6
6
|
import { useApi, useApiMutation } from "./ApiProvider";
|
|
7
7
|
|
|
8
|
+
// API hook factory that converts a typed OpenAPI client into React hooks (`useApi` and `useApiMutation`) that the UI can use.
|
|
9
|
+
// Provides a simple interface for making API calls and handling loading and error states in your React components.
|
|
8
10
|
export function createApiHooks<Paths extends {}>(
|
|
9
11
|
client: ReturnType<typeof createApiClient<Paths>>
|
|
10
12
|
) {
|
|
@@ -12,15 +14,16 @@ export function createApiHooks<Paths extends {}>(
|
|
|
12
14
|
// type GetParams<P extends PathsWithMethod<Paths, "get">> =
|
|
13
15
|
// Parameters<typeof client.GET<P>>[1];
|
|
14
16
|
|
|
17
|
+
// Using useQuery
|
|
15
18
|
return {
|
|
16
19
|
get: <P extends PathsWithMethod<Paths, "get">>(
|
|
17
20
|
path: P,
|
|
18
|
-
|
|
21
|
+
input?: any
|
|
19
22
|
) => {
|
|
20
23
|
return useApi(
|
|
21
|
-
["get", path, JSON.stringify(
|
|
24
|
+
["get", path, JSON.stringify(input ?? {})],
|
|
22
25
|
async () => {
|
|
23
|
-
const res = await client.GET(path,
|
|
26
|
+
const res = await client.GET(path, input);
|
|
24
27
|
if (res.error) throw res.error;
|
|
25
28
|
return res.data;
|
|
26
29
|
}
|
|
@@ -29,45 +32,46 @@ export function createApiHooks<Paths extends {}>(
|
|
|
29
32
|
|
|
30
33
|
post: <P extends PathsWithMethod<Paths, "post">>(
|
|
31
34
|
path: P,
|
|
32
|
-
|
|
35
|
+
input?: any
|
|
33
36
|
) => {
|
|
34
37
|
return useApi(
|
|
35
|
-
["post", path, JSON.stringify(
|
|
38
|
+
["post", path, JSON.stringify(input ?? {})],
|
|
36
39
|
async () => {
|
|
37
|
-
const res = await client.POST(path,
|
|
40
|
+
const res = await client.POST(path, input);
|
|
38
41
|
if (res.error) throw res.error;
|
|
39
42
|
return res.data;
|
|
40
43
|
}
|
|
41
44
|
);
|
|
42
45
|
},
|
|
43
46
|
|
|
47
|
+
// Using useMutation
|
|
44
48
|
postMutation: <P extends PathsWithMethod<Paths, "post">>(path: P) => {
|
|
45
|
-
return useApiMutation(async (
|
|
46
|
-
const res = await client.POST(path,
|
|
49
|
+
return useApiMutation(async (input: any) => {
|
|
50
|
+
const res = await client.POST(path, input);
|
|
47
51
|
if (res.error) throw res.error;
|
|
48
52
|
return res.data;
|
|
49
53
|
});
|
|
50
54
|
},
|
|
51
55
|
|
|
52
56
|
putMutation: <P extends PathsWithMethod<Paths, "put">>(path: P) => {
|
|
53
|
-
return useApiMutation(async (
|
|
54
|
-
const res = await client.PUT(path,
|
|
57
|
+
return useApiMutation(async (input: any) => {
|
|
58
|
+
const res = await client.PUT(path, input);
|
|
55
59
|
if (res.error) throw res.error;
|
|
56
60
|
return res.data;
|
|
57
61
|
});
|
|
58
62
|
},
|
|
59
63
|
|
|
60
64
|
patchMutation: <P extends PathsWithMethod<Paths, "patch">>(path: P) => {
|
|
61
|
-
return useApiMutation(async (
|
|
62
|
-
const res = await client.PATCH(path,
|
|
65
|
+
return useApiMutation(async (input: any) => {
|
|
66
|
+
const res = await client.PATCH(path, input);
|
|
63
67
|
if (res.error) throw res.error;
|
|
64
68
|
return res.data;
|
|
65
69
|
});
|
|
66
70
|
},
|
|
67
71
|
|
|
68
72
|
deleteMutation: <P extends PathsWithMethod<Paths, "delete">>(path: P) => {
|
|
69
|
-
return useApiMutation(async (
|
|
70
|
-
const res = await client.DELETE(path,
|
|
73
|
+
return useApiMutation(async (input: any) => {
|
|
74
|
+
const res = await client.DELETE(path, input);
|
|
71
75
|
if (res.error) throw res.error;
|
|
72
76
|
return res.data;
|
|
73
77
|
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
import { createElement } from "react";
|
|
6
|
+
|
|
7
|
+
type LegendAs = "h1" | "h2" | "h3" | "h4";
|
|
8
|
+
type LegendSize = "s" | "m" | "l" | "xl";
|
|
9
|
+
|
|
10
|
+
interface CheckboxOption {
|
|
11
|
+
id: string;
|
|
12
|
+
value: string;
|
|
13
|
+
label: ReactNode;
|
|
14
|
+
checked?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface CheckboxGroupProps {
|
|
18
|
+
legend: ReactNode;
|
|
19
|
+
hint?: ReactNode;
|
|
20
|
+
error?: string;
|
|
21
|
+
options: CheckboxOption[];
|
|
22
|
+
name: string;
|
|
23
|
+
legendAs?: LegendAs;
|
|
24
|
+
legendSize?: LegendSize;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const CheckboxGroup = ({
|
|
28
|
+
legend,
|
|
29
|
+
hint,
|
|
30
|
+
error,
|
|
31
|
+
options,
|
|
32
|
+
name,
|
|
33
|
+
legendAs = "h4",
|
|
34
|
+
legendSize = "m",
|
|
35
|
+
}: CheckboxGroupProps) => {
|
|
36
|
+
const hasError = Boolean(error);
|
|
37
|
+
const errorId = hasError ? `${name}-error` : undefined;
|
|
38
|
+
|
|
39
|
+
const legendHeading = createElement(
|
|
40
|
+
legendAs,
|
|
41
|
+
{ className: "govuk-fieldset__heading" },
|
|
42
|
+
legend
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
className={clsx("govuk-form-group", {
|
|
48
|
+
"govuk-form-group--error": hasError,
|
|
49
|
+
})}
|
|
50
|
+
>
|
|
51
|
+
<fieldset className="govuk-fieldset" aria-describedby={errorId}>
|
|
52
|
+
<legend
|
|
53
|
+
className={clsx("govuk-fieldset__legend", {
|
|
54
|
+
[`govuk-fieldset__legend--${legendSize}`]:
|
|
55
|
+
legendSize !== "m",
|
|
56
|
+
})}
|
|
57
|
+
>
|
|
58
|
+
{legendHeading}
|
|
59
|
+
</legend>
|
|
60
|
+
|
|
61
|
+
{hint && <div className="govuk-hint">{hint}</div>}
|
|
62
|
+
|
|
63
|
+
{hasError && (
|
|
64
|
+
<p id={errorId} className="govuk-error-message">
|
|
65
|
+
<span className="govuk-visually-hidden">Error:</span>{" "}
|
|
66
|
+
{error}
|
|
67
|
+
</p>
|
|
68
|
+
)}
|
|
69
|
+
|
|
70
|
+
<div className="govuk-checkboxes" data-module="govuk-checkboxes">
|
|
71
|
+
{options.map((opt) => (
|
|
72
|
+
<div key={opt.id} className="govuk-checkboxes__item">
|
|
73
|
+
<input
|
|
74
|
+
className="govuk-checkboxes__input"
|
|
75
|
+
id={opt.id}
|
|
76
|
+
name={name}
|
|
77
|
+
type="checkbox"
|
|
78
|
+
value={opt.value}
|
|
79
|
+
defaultChecked={opt.checked}
|
|
80
|
+
/>
|
|
81
|
+
<label
|
|
82
|
+
className="govuk-label govuk-checkboxes__label"
|
|
83
|
+
htmlFor={opt.id}
|
|
84
|
+
>
|
|
85
|
+
{opt.label}
|
|
86
|
+
</label>
|
|
87
|
+
</div>
|
|
88
|
+
))}
|
|
89
|
+
</div>
|
|
90
|
+
</fieldset>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import type { JSX, ReactNode } from "react";
|
|
5
|
+
import { createElement } from "react";
|
|
6
|
+
|
|
7
|
+
type LabelAs = "h1" | "h2" | "h3" | "h4";
|
|
8
|
+
type LabelSize = "s" | "m" | "l" | "xl";
|
|
9
|
+
type SelectProps = Omit<JSX.IntrinsicElements["select"], "id">;
|
|
10
|
+
|
|
11
|
+
interface SelectInputProps extends SelectProps {
|
|
12
|
+
id: string;
|
|
13
|
+
label: ReactNode;
|
|
14
|
+
hint?: ReactNode;
|
|
15
|
+
error?: string;
|
|
16
|
+
options: { value: string; label: string }[];
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
labelAs?: LabelAs;
|
|
19
|
+
labelSize?: LabelSize;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const SelectInput = ({
|
|
24
|
+
id,
|
|
25
|
+
label,
|
|
26
|
+
hint,
|
|
27
|
+
error,
|
|
28
|
+
options,
|
|
29
|
+
placeholder,
|
|
30
|
+
labelAs,
|
|
31
|
+
labelSize = "m",
|
|
32
|
+
className,
|
|
33
|
+
...props
|
|
34
|
+
}: SelectInputProps) => {
|
|
35
|
+
const hasError = Boolean(error);
|
|
36
|
+
const hintId = hint ? `${id}-hint` : undefined;
|
|
37
|
+
const errorId = hasError ? `${id}-error` : undefined;
|
|
38
|
+
const ariaDescribedBy =
|
|
39
|
+
[hintId, errorId].filter(Boolean).join(" ") || undefined;
|
|
40
|
+
|
|
41
|
+
const labelElement = (
|
|
42
|
+
<label
|
|
43
|
+
htmlFor={id}
|
|
44
|
+
className={clsx("govuk-label", {
|
|
45
|
+
[`govuk-label--${labelSize}`]: labelSize !== "m",
|
|
46
|
+
})}
|
|
47
|
+
>
|
|
48
|
+
{label}
|
|
49
|
+
</label>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
className={clsx("govuk-form-group", {
|
|
55
|
+
"govuk-form-group--error": hasError,
|
|
56
|
+
})}
|
|
57
|
+
>
|
|
58
|
+
{labelAs
|
|
59
|
+
? createElement(
|
|
60
|
+
labelAs,
|
|
61
|
+
{ className: "govuk-label-wrapper" },
|
|
62
|
+
labelElement
|
|
63
|
+
)
|
|
64
|
+
: labelElement}
|
|
65
|
+
|
|
66
|
+
{hint && (
|
|
67
|
+
<div id={hintId} className="govuk-hint">
|
|
68
|
+
{hint}
|
|
69
|
+
</div>
|
|
70
|
+
)}
|
|
71
|
+
|
|
72
|
+
{hasError && (
|
|
73
|
+
<p id={errorId} className="govuk-error-message">
|
|
74
|
+
<span className="govuk-visually-hidden">Error:</span> {error}
|
|
75
|
+
</p>
|
|
76
|
+
)}
|
|
77
|
+
|
|
78
|
+
<select
|
|
79
|
+
id={id}
|
|
80
|
+
className={clsx(
|
|
81
|
+
"govuk-select",
|
|
82
|
+
{ "govuk-select--error": hasError },
|
|
83
|
+
className
|
|
84
|
+
)}
|
|
85
|
+
aria-describedby={ariaDescribedBy}
|
|
86
|
+
{...props}
|
|
87
|
+
>
|
|
88
|
+
{placeholder && (
|
|
89
|
+
<option value="" disabled hidden>
|
|
90
|
+
{placeholder}
|
|
91
|
+
</option>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
{options.map((opt) => (
|
|
95
|
+
<option key={opt.value} value={opt.value}>
|
|
96
|
+
{opt.label}
|
|
97
|
+
</option>
|
|
98
|
+
))}
|
|
99
|
+
</select>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import type { JSX, ReactNode } from "react";
|
|
5
|
+
import { createElement } from "react";
|
|
6
|
+
|
|
7
|
+
type LabelAs = "h1" | "h2" | "h3" | "h4";
|
|
8
|
+
type InputProps = Omit<JSX.IntrinsicElements["input"], "id">;
|
|
9
|
+
|
|
10
|
+
interface TextInputProps extends InputProps {
|
|
11
|
+
id: string;
|
|
12
|
+
label: ReactNode;
|
|
13
|
+
hint?: ReactNode;
|
|
14
|
+
error?: string;
|
|
15
|
+
width?: "10" | "20" | "30";
|
|
16
|
+
labelSize?: "s" | "m" | "l" | "xl";
|
|
17
|
+
labelAs?: LabelAs;
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
suffix?: ReactNode;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const TextInput = ({
|
|
23
|
+
id,
|
|
24
|
+
label,
|
|
25
|
+
hint,
|
|
26
|
+
error,
|
|
27
|
+
width = "20",
|
|
28
|
+
labelSize = "m",
|
|
29
|
+
labelAs,
|
|
30
|
+
className,
|
|
31
|
+
placeholder,
|
|
32
|
+
suffix,
|
|
33
|
+
...props
|
|
34
|
+
}: TextInputProps) => {
|
|
35
|
+
const hasError = Boolean(error);
|
|
36
|
+
|
|
37
|
+
const hintId = hint ? `${id}-hint` : undefined;
|
|
38
|
+
const errorId = hasError ? `${id}-error` : undefined;
|
|
39
|
+
const describedBy = [hintId, errorId].filter(Boolean).join(" ") || undefined;
|
|
40
|
+
|
|
41
|
+
const labelElement = (
|
|
42
|
+
<label
|
|
43
|
+
htmlFor={id}
|
|
44
|
+
className={clsx("govuk-label", {
|
|
45
|
+
[`govuk-label--${labelSize}`]: labelSize !== "m",
|
|
46
|
+
})}
|
|
47
|
+
>
|
|
48
|
+
{label}
|
|
49
|
+
</label>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const input = (
|
|
53
|
+
<input
|
|
54
|
+
id={id}
|
|
55
|
+
className={clsx(
|
|
56
|
+
"govuk-input",
|
|
57
|
+
`govuk-input--width-${width}`,
|
|
58
|
+
className
|
|
59
|
+
)}
|
|
60
|
+
aria-invalid={hasError}
|
|
61
|
+
aria-describedby={describedBy}
|
|
62
|
+
placeholder={placeholder}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
className={clsx("govuk-form-group", {
|
|
70
|
+
"govuk-form-group--error": hasError,
|
|
71
|
+
})}
|
|
72
|
+
>
|
|
73
|
+
{labelAs
|
|
74
|
+
? createElement(
|
|
75
|
+
labelAs,
|
|
76
|
+
{ className: "govuk-label-wrapper" },
|
|
77
|
+
labelElement
|
|
78
|
+
)
|
|
79
|
+
: labelElement}
|
|
80
|
+
|
|
81
|
+
{hint && (
|
|
82
|
+
<div id={hintId} className="govuk-hint">
|
|
83
|
+
{hint}
|
|
84
|
+
</div>
|
|
85
|
+
)}
|
|
86
|
+
|
|
87
|
+
{hasError && (
|
|
88
|
+
<p id={errorId} className="govuk-error-message">
|
|
89
|
+
<span className="govuk-visually-hidden">Error:</span> {error}
|
|
90
|
+
</p>
|
|
91
|
+
)}
|
|
92
|
+
|
|
93
|
+
{suffix ? (
|
|
94
|
+
<div className="govuk-input__wrapper">
|
|
95
|
+
{input}
|
|
96
|
+
<div className="govuk-input__suffix" aria-hidden="true">
|
|
97
|
+
{suffix}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
) : (
|
|
101
|
+
input
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
};
|
package/src/index.ts
CHANGED