whitehall-ui 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.
Files changed (122) hide show
  1. package/README.md +108 -0
  2. package/dist/chunk-2QKZ6DPC.js +27 -0
  3. package/dist/chunk-3INCIYDO.js +213 -0
  4. package/dist/chunk-3YIKJK6M.js +181 -0
  5. package/dist/chunk-4MXR4WNS.js +17 -0
  6. package/dist/chunk-5AKGRLG2.js +190 -0
  7. package/dist/chunk-5H55YDJS.js +69 -0
  8. package/dist/chunk-5PIQJ22R.js +106 -0
  9. package/dist/chunk-5TI2WXYU.js +64 -0
  10. package/dist/chunk-5XNKIBMP.js +21 -0
  11. package/dist/chunk-6VXVJERU.js +38 -0
  12. package/dist/chunk-72PH2FMG.js +180 -0
  13. package/dist/chunk-7ZCZQN5N.js +71 -0
  14. package/dist/chunk-AO6HPG4R.js +50 -0
  15. package/dist/chunk-CEPBVMFU.js +34 -0
  16. package/dist/chunk-G6T44BDV.js +75 -0
  17. package/dist/chunk-GUZIKVAE.js +119 -0
  18. package/dist/chunk-JESMK3XK.js +105 -0
  19. package/dist/chunk-JFZN5XP6.js +88 -0
  20. package/dist/chunk-KD4LPFIZ.js +67 -0
  21. package/dist/chunk-KWAC6IEK.js +95 -0
  22. package/dist/chunk-LRNZYPC2.js +107 -0
  23. package/dist/chunk-M6CLPMRP.js +227 -0
  24. package/dist/chunk-N67H5OUQ.js +51 -0
  25. package/dist/chunk-NRXTKHI2.js +169 -0
  26. package/dist/chunk-OP35ZJ4X.js +46 -0
  27. package/dist/chunk-P4GCF5FQ.js +62 -0
  28. package/dist/chunk-PGZHPAT5.js +183 -0
  29. package/dist/chunk-QTSEOPVX.js +94 -0
  30. package/dist/chunk-RPV43YDC.js +93 -0
  31. package/dist/chunk-SK27BMU5.js +140 -0
  32. package/dist/chunk-TXGBUZB4.js +44 -0
  33. package/dist/chunk-UWQFFFTB.js +136 -0
  34. package/dist/chunk-VB6V3PHD.js +67 -0
  35. package/dist/chunk-VQOCX44T.js +41 -0
  36. package/dist/chunk-WONVZ7WK.js +29 -0
  37. package/dist/chunk-WPPWPEFV.js +150 -0
  38. package/dist/chunk-XQOYWPKV.js +48 -0
  39. package/dist/chunk-YAKI4SI7.js +205 -0
  40. package/dist/chunk-YCLGXX3R.js +68 -0
  41. package/dist/index.d.ts +50 -0
  42. package/dist/index.js +39 -0
  43. package/dist/lib/utils.d.ts +5 -0
  44. package/dist/lib/utils.js +1 -0
  45. package/dist/ui/accordion.d.ts +27 -0
  46. package/dist/ui/accordion.js +2 -0
  47. package/dist/ui/back-link.d.ts +9 -0
  48. package/dist/ui/back-link.js +2 -0
  49. package/dist/ui/breadcrumbs.d.ts +22 -0
  50. package/dist/ui/breadcrumbs.js +2 -0
  51. package/dist/ui/button.d.ts +17 -0
  52. package/dist/ui/button.js +2 -0
  53. package/dist/ui/character-count.d.ts +27 -0
  54. package/dist/ui/character-count.js +3 -0
  55. package/dist/ui/checkboxes.d.ts +30 -0
  56. package/dist/ui/checkboxes.js +2 -0
  57. package/dist/ui/cookie-banner.d.ts +24 -0
  58. package/dist/ui/cookie-banner.js +2 -0
  59. package/dist/ui/date-input.d.ts +21 -0
  60. package/dist/ui/date-input.js +2 -0
  61. package/dist/ui/details.d.ts +20 -0
  62. package/dist/ui/details.js +2 -0
  63. package/dist/ui/error-message.d.ts +9 -0
  64. package/dist/ui/error-message.js +2 -0
  65. package/dist/ui/error-summary.d.ts +15 -0
  66. package/dist/ui/error-summary.js +2 -0
  67. package/dist/ui/exit-this-page.d.ts +14 -0
  68. package/dist/ui/exit-this-page.js +3 -0
  69. package/dist/ui/fieldset.d.ts +22 -0
  70. package/dist/ui/fieldset.js +2 -0
  71. package/dist/ui/file-upload.d.ts +19 -0
  72. package/dist/ui/file-upload.js +2 -0
  73. package/dist/ui/footer.d.ts +61 -0
  74. package/dist/ui/footer.js +2 -0
  75. package/dist/ui/generic-header.d.ts +22 -0
  76. package/dist/ui/generic-header.js +2 -0
  77. package/dist/ui/header.d.ts +39 -0
  78. package/dist/ui/header.js +2 -0
  79. package/dist/ui/hint.d.ts +8 -0
  80. package/dist/ui/hint.js +2 -0
  81. package/dist/ui/inset-text.d.ts +8 -0
  82. package/dist/ui/inset-text.js +2 -0
  83. package/dist/ui/label.d.ts +18 -0
  84. package/dist/ui/label.js +2 -0
  85. package/dist/ui/link.d.ts +16 -0
  86. package/dist/ui/link.js +2 -0
  87. package/dist/ui/notification-banner.d.ts +29 -0
  88. package/dist/ui/notification-banner.js +2 -0
  89. package/dist/ui/pagination.d.ts +45 -0
  90. package/dist/ui/pagination.js +2 -0
  91. package/dist/ui/panel.d.ts +16 -0
  92. package/dist/ui/panel.js +2 -0
  93. package/dist/ui/password-input.d.ts +16 -0
  94. package/dist/ui/password-input.js +4 -0
  95. package/dist/ui/phase-banner.d.ts +20 -0
  96. package/dist/ui/phase-banner.js +2 -0
  97. package/dist/ui/radios.d.ts +25 -0
  98. package/dist/ui/radios.js +2 -0
  99. package/dist/ui/select.d.ts +36 -0
  100. package/dist/ui/select.js +2 -0
  101. package/dist/ui/service-navigation.d.ts +30 -0
  102. package/dist/ui/service-navigation.js +2 -0
  103. package/dist/ui/skip-link.d.ts +8 -0
  104. package/dist/ui/skip-link.js +2 -0
  105. package/dist/ui/summary-list.d.ts +49 -0
  106. package/dist/ui/summary-list.js +2 -0
  107. package/dist/ui/table.d.ts +40 -0
  108. package/dist/ui/table.js +2 -0
  109. package/dist/ui/tabs.d.ts +25 -0
  110. package/dist/ui/tabs.js +2 -0
  111. package/dist/ui/tag.d.ts +15 -0
  112. package/dist/ui/tag.js +2 -0
  113. package/dist/ui/task-list.d.ts +30 -0
  114. package/dist/ui/task-list.js +2 -0
  115. package/dist/ui/text-input.d.ts +18 -0
  116. package/dist/ui/text-input.js +2 -0
  117. package/dist/ui/textarea.d.ts +14 -0
  118. package/dist/ui/textarea.js +2 -0
  119. package/dist/ui/warning-text.d.ts +9 -0
  120. package/dist/ui/warning-text.js +2 -0
  121. package/package.json +263 -0
  122. package/registry/default/theme/govuk-tokens.css +434 -0
@@ -0,0 +1,190 @@
1
+ import { cn } from './chunk-WONVZ7WK.js';
2
+ import { useState } from 'react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ var headerLinkStyles = [
6
+ "no-underline text-white",
7
+ "visited:text-white active:text-white",
8
+ "hover:underline hover:govuk-link-underline hover:govuk-link-underline-hover",
9
+ "focus:govuk-link-focus",
10
+ "focus:not-focus:bg-govuk-brand"
11
+ ];
12
+ var Header = ({
13
+ className,
14
+ children,
15
+ fullWidth,
16
+ ref,
17
+ ...props
18
+ }) => /* @__PURE__ */ jsx(
19
+ "header",
20
+ {
21
+ ref,
22
+ className: cn(
23
+ "font-govuk text-govuk-header",
24
+ "border-b border-b-transparent",
25
+ "text-white bg-govuk-brand",
26
+ className
27
+ ),
28
+ ...props,
29
+ children: children ?? /* @__PURE__ */ jsx(HeaderContainer, { fullWidth, children: /* @__PURE__ */ jsx(HeaderLogo, {}) })
30
+ }
31
+ );
32
+ var HeaderContainer = ({
33
+ className,
34
+ fullWidth,
35
+ ref,
36
+ children,
37
+ ...props
38
+ }) => /* @__PURE__ */ jsx(
39
+ "div",
40
+ {
41
+ ref,
42
+ className: cn(
43
+ "flex items-center flex-wrap",
44
+ fullWidth ? "px-govuk-3" : "max-w-240 mx-auto px-govuk-3",
45
+ className
46
+ ),
47
+ ...props,
48
+ children
49
+ }
50
+ );
51
+ var HeaderLogo = ({
52
+ className,
53
+ ref,
54
+ children,
55
+ ...props
56
+ }) => /* @__PURE__ */ jsx(
57
+ "div",
58
+ {
59
+ ref,
60
+ className: cn("box-border py-govuk-2 mr-govuk-2", className),
61
+ ...props,
62
+ children
63
+ }
64
+ );
65
+ var HeaderLink = ({
66
+ className,
67
+ ref,
68
+ children,
69
+ ...props
70
+ }) => /* @__PURE__ */ jsx(
71
+ "a",
72
+ {
73
+ ref,
74
+ className: cn(
75
+ "inline-flex items-center text-govuk-header-link",
76
+ headerLinkStyles,
77
+ className
78
+ ),
79
+ ...props,
80
+ children
81
+ }
82
+ );
83
+ var HeaderServiceName = ({
84
+ className,
85
+ ref,
86
+ children,
87
+ ...props
88
+ }) => /* @__PURE__ */ jsx(
89
+ "a",
90
+ {
91
+ ref,
92
+ className: cn(
93
+ "inline-flex items-center text-govuk-body font-bold",
94
+ "py-govuk-2 mr-govuk-2",
95
+ headerLinkStyles,
96
+ className
97
+ ),
98
+ ...props,
99
+ children
100
+ }
101
+ );
102
+ var HeaderNav = ({ className, ref, children, ...props }) => {
103
+ const [menuOpen, setMenuOpen] = useState(false);
104
+ return /* @__PURE__ */ jsxs(
105
+ "nav",
106
+ {
107
+ ref,
108
+ className: cn("ml-auto max-sm:w-full", className),
109
+ ...props,
110
+ children: [
111
+ /* @__PURE__ */ jsxs(
112
+ "button",
113
+ {
114
+ type: "button",
115
+ className: cn(
116
+ "sm:hidden flex items-center gap-govuk-1 ml-auto py-govuk-2",
117
+ "font-govuk text-govuk-body font-bold",
118
+ "bg-transparent border-0 text-white cursor-pointer",
119
+ "hover:underline focus:govuk-link-focus"
120
+ ),
121
+ onClick: () => setMenuOpen((prev) => !prev),
122
+ "aria-expanded": menuOpen,
123
+ "aria-label": "Show or hide navigation menu",
124
+ children: [
125
+ "Menu",
126
+ /* @__PURE__ */ jsx(
127
+ "svg",
128
+ {
129
+ viewBox: "0 0 10 6",
130
+ width: "10",
131
+ height: "6",
132
+ fill: "currentColor",
133
+ "aria-hidden": "true",
134
+ className: cn("transition-transform", menuOpen && "rotate-180"),
135
+ children: /* @__PURE__ */ jsx("path", { d: "M0 0l5 6 5-6z" })
136
+ }
137
+ )
138
+ ]
139
+ }
140
+ ),
141
+ /* @__PURE__ */ jsx(
142
+ "ul",
143
+ {
144
+ className: cn(
145
+ "list-none m-0 p-0",
146
+ "sm:flex sm:flex-wrap sm:items-center sm:gap-x-govuk-4 sm:gap-y-0",
147
+ menuOpen ? "max-sm:block" : "max-sm:hidden"
148
+ ),
149
+ children
150
+ }
151
+ )
152
+ ]
153
+ }
154
+ );
155
+ };
156
+ var HeaderNavItem = ({
157
+ className,
158
+ active,
159
+ ref,
160
+ children,
161
+ ...props
162
+ }) => /* @__PURE__ */ jsx(
163
+ "li",
164
+ {
165
+ ref,
166
+ className: cn(
167
+ "py-govuk-2",
168
+ active && "border-b-govuk-standard border-b-white -mb-px",
169
+ className
170
+ ),
171
+ ...props,
172
+ children
173
+ }
174
+ );
175
+ var HeaderNavLink = ({
176
+ className,
177
+ ref,
178
+ children,
179
+ ...props
180
+ }) => /* @__PURE__ */ jsx(
181
+ "a",
182
+ {
183
+ ref,
184
+ className: cn("text-govuk-body font-bold", headerLinkStyles, className),
185
+ ...props,
186
+ children
187
+ }
188
+ );
189
+
190
+ export { Header, HeaderContainer, HeaderLink, HeaderLogo, HeaderNav, HeaderNavItem, HeaderNavLink, HeaderServiceName };
@@ -0,0 +1,69 @@
1
+ import { cn } from './chunk-WONVZ7WK.js';
2
+ import { Tabs as Tabs$1 } from '@base-ui/react/tabs';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var Tabs = ({ className, ref, children, ...props }) => /* @__PURE__ */ jsx(
6
+ Tabs$1.Root,
7
+ {
8
+ ref,
9
+ className: cn(
10
+ "mt-govuk-1 mb-govuk-6 font-govuk text-govuk-body text-govuk-black",
11
+ className
12
+ ),
13
+ ...props,
14
+ children
15
+ }
16
+ );
17
+ var TabsList = ({ className, ref, children, ...props }) => /* @__PURE__ */ jsx(
18
+ Tabs$1.List,
19
+ {
20
+ ref,
21
+ activateOnFocus: true,
22
+ className: cn("flex m-0 p-0 border-b border-govuk-mid-grey", className),
23
+ ...props,
24
+ children
25
+ }
26
+ );
27
+ var TabsTab = ({ className, ref, children, ...props }) => /* @__PURE__ */ jsx(
28
+ Tabs$1.Tab,
29
+ {
30
+ ref,
31
+ className: cn(
32
+ "group relative cursor-pointer border-0 outline-none",
33
+ "mr-govuk-1 py-govuk-2 px-govuk-4",
34
+ "bg-govuk-light-grey text-center",
35
+ "govuk-tab",
36
+ className
37
+ ),
38
+ ...props,
39
+ children: /* @__PURE__ */ jsx(
40
+ "span",
41
+ {
42
+ className: cn(
43
+ "text-govuk-black underline govuk-link-underline",
44
+ "group-hover:govuk-link-underline-hover",
45
+ "group-focus-visible:govuk-link-focus group-focus-visible:no-underline",
46
+ "group-data-active:no-underline"
47
+ ),
48
+ children
49
+ }
50
+ )
51
+ }
52
+ );
53
+ var TabsPanel = ({ className, ref, children, ...props }) => /* @__PURE__ */ jsx(
54
+ Tabs$1.Panel,
55
+ {
56
+ ref,
57
+ tabIndex: -1,
58
+ className: cn(
59
+ "py-govuk-6 px-govuk-4",
60
+ "govuk-tab-panel-border",
61
+ "*:last:mb-0",
62
+ className
63
+ ),
64
+ ...props,
65
+ children
66
+ }
67
+ );
68
+
69
+ export { Tabs, TabsList, TabsPanel, TabsTab };
@@ -0,0 +1,106 @@
1
+ import { cn } from './chunk-WONVZ7WK.js';
2
+ import { Button as Button$1 } from '@base-ui/react/button';
3
+ import { cva } from 'class-variance-authority';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var buttonVariants = cva(
7
+ [
8
+ "relative inline-block w-full sm:w-auto",
9
+ "border-2 border-transparent rounded-none",
10
+ "box-border",
11
+ "px-govuk-button-x pt-govuk-button-pt pb-govuk-button-pb",
12
+ "mb-govuk-button-bottom",
13
+ "text-govuk-body font-normal",
14
+ "font-govuk",
15
+ "text-center no-underline",
16
+ "cursor-pointer",
17
+ "appearance-none",
18
+ "active:top-govuk-button-press",
19
+ "focus:border-govuk-yellow focus:outline-3 focus:outline-transparent",
20
+ "focus:shadow-govuk-clear focus:inset-ring-1 focus:inset-ring-govuk-yellow",
21
+ "focus:not-[:active]:not-[:hover]:bg-govuk-yellow",
22
+ "focus:not-[:active]:not-[:hover]:text-govuk-black",
23
+ "focus:not-[:active]:not-[:hover]:shadow-govuk-yellow",
24
+ "focus:not-[:active]:not-[:hover]:inset-ring-0",
25
+ "focus:not-[:active]:not-[:hover]:border-govuk-yellow"
26
+ ],
27
+ {
28
+ variants: {
29
+ variant: {
30
+ default: [
31
+ "bg-govuk-green text-white",
32
+ "shadow-govuk-green",
33
+ "hover:not-data-[disabled]:bg-govuk-green-hover",
34
+ "visited:text-white active:text-white"
35
+ ],
36
+ secondary: [
37
+ "bg-govuk-light-grey text-govuk-black",
38
+ "shadow-govuk-light-grey",
39
+ "hover:not-data-[disabled]:bg-govuk-grey",
40
+ "visited:text-govuk-black active:text-govuk-black"
41
+ ],
42
+ warning: [
43
+ "bg-govuk-red text-white",
44
+ "shadow-govuk-red",
45
+ "hover:not-data-[disabled]:bg-govuk-red-hover",
46
+ "visited:text-white active:text-white"
47
+ ],
48
+ inverse: [
49
+ "bg-white text-govuk-brand",
50
+ "shadow-govuk-inverse",
51
+ "hover:not-data-[disabled]:bg-govuk-inverse-hover",
52
+ "visited:text-govuk-brand active:text-govuk-brand"
53
+ ],
54
+ start: [
55
+ "bg-govuk-green text-white",
56
+ "shadow-govuk-green",
57
+ "hover:not-data-[disabled]:bg-govuk-green-hover",
58
+ "visited:text-white active:text-white",
59
+ "font-bold text-govuk-start",
60
+ "inline-flex items-center justify-center"
61
+ ]
62
+ }
63
+ },
64
+ defaultVariants: {
65
+ variant: "default"
66
+ }
67
+ }
68
+ );
69
+ var disabledStyles = "data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed data-[disabled]:active:top-0";
70
+ var StartIcon = () => /* @__PURE__ */ jsx(
71
+ "svg",
72
+ {
73
+ className: "ml-govuk-1 sm:ml-govuk-2 align-middle shrink-0 self-center forced-color-adjust-auto",
74
+ xmlns: "http://www.w3.org/2000/svg",
75
+ width: "17.5",
76
+ height: "19",
77
+ viewBox: "0 0 33 40",
78
+ "aria-hidden": "true",
79
+ focusable: "false",
80
+ children: /* @__PURE__ */ jsx("path", { fill: "currentColor", d: "M0 0h13l20 20-20 20H0l20-20z" })
81
+ }
82
+ );
83
+ var Button = ({
84
+ className,
85
+ variant = "default",
86
+ disabled = false,
87
+ focusableWhenDisabled = false,
88
+ children,
89
+ ref,
90
+ ...props
91
+ }) => /* @__PURE__ */ jsxs(
92
+ Button$1,
93
+ {
94
+ ref,
95
+ disabled,
96
+ focusableWhenDisabled,
97
+ className: cn(buttonVariants({ variant }), disabledStyles, className),
98
+ ...props,
99
+ children: [
100
+ children,
101
+ variant === "start" && /* @__PURE__ */ jsx(StartIcon, {})
102
+ ]
103
+ }
104
+ );
105
+
106
+ export { Button, buttonVariants };
@@ -0,0 +1,64 @@
1
+ import { cn } from './chunk-WONVZ7WK.js';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ var DateInput = ({ className, children, ref, ...props }) => /* @__PURE__ */ jsx("div", { ref, className: cn("govuk-date-input", className), ...props, children });
5
+ var DateInputItem = ({
6
+ className,
7
+ children,
8
+ ref,
9
+ ...props
10
+ }) => /* @__PURE__ */ jsx(
11
+ "div",
12
+ {
13
+ ref,
14
+ className: cn("inline-block mr-govuk-4 mb-0 align-bottom", className),
15
+ ...props,
16
+ children
17
+ }
18
+ );
19
+ var DateInputLabel = ({
20
+ className,
21
+ children,
22
+ htmlFor,
23
+ ref,
24
+ ...props
25
+ }) => /* @__PURE__ */ jsx(
26
+ "label",
27
+ {
28
+ ref,
29
+ htmlFor,
30
+ className: cn(
31
+ "block font-govuk text-govuk-body text-govuk-black",
32
+ className
33
+ ),
34
+ ...props,
35
+ children
36
+ }
37
+ );
38
+ var DateInputInput = ({
39
+ className,
40
+ error = false,
41
+ ref,
42
+ ...props
43
+ }) => /* @__PURE__ */ jsx(
44
+ "input",
45
+ {
46
+ ref,
47
+ type: "text",
48
+ inputMode: "numeric",
49
+ className: cn(
50
+ "govuk-date-input-field box-border",
51
+ "p-govuk-1 h-10",
52
+ "border-2 border-govuk-black",
53
+ "rounded-none appearance-none",
54
+ "text-govuk-body font-normal font-govuk",
55
+ "focus:outline-3 focus:outline-govuk-yellow focus:outline-offset-0",
56
+ "focus:inset-ring-2 focus:inset-ring-govuk-black",
57
+ error && "border-govuk-error focus:border-govuk-black",
58
+ className
59
+ ),
60
+ ...props
61
+ }
62
+ );
63
+
64
+ export { DateInput, DateInputInput, DateInputItem, DateInputLabel };
@@ -0,0 +1,21 @@
1
+ import { cn } from './chunk-WONVZ7WK.js';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ var InsetText = ({ className, ref, ...props }) => /* @__PURE__ */ jsx(
5
+ "div",
6
+ {
7
+ ref,
8
+ className: cn(
9
+ "clear-both",
10
+ "p-govuk-3",
11
+ "my-govuk-4",
12
+ "border-l-govuk-inset",
13
+ "text-govuk-tag font-normal font-govuk text-govuk-black",
14
+ "*:first:mt-0 *:last:mb-0",
15
+ className
16
+ ),
17
+ ...props
18
+ }
19
+ );
20
+
21
+ export { InsetText };
@@ -0,0 +1,38 @@
1
+ import { cn } from './chunk-WONVZ7WK.js';
2
+ import { cva } from 'class-variance-authority';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var labelVariants = cva(["block", "font-govuk text-govuk-black"], {
6
+ variants: {
7
+ size: {
8
+ xl: "text-govuk-heading-xl font-bold mb-govuk-3",
9
+ l: "text-govuk-heading-l font-bold mb-govuk-3",
10
+ m: "text-govuk-heading-m font-bold mb-govuk-3",
11
+ s: "text-govuk-body font-bold mb-govuk-1"
12
+ }
13
+ },
14
+ defaultVariants: {
15
+ size: void 0
16
+ }
17
+ });
18
+ var Label = ({ className, size, htmlFor, ref, ...props }) => /* @__PURE__ */ jsx(
19
+ "label",
20
+ {
21
+ ref,
22
+ htmlFor,
23
+ className: cn(
24
+ labelVariants({ size }),
25
+ !size && "text-govuk-body mb-govuk-1",
26
+ className
27
+ ),
28
+ ...props
29
+ }
30
+ );
31
+ var LabelWrapper = ({
32
+ as: Tag = "h1",
33
+ className,
34
+ ref,
35
+ ...props
36
+ }) => /* @__PURE__ */ jsx(Tag, { ref, className: cn("m-0", className), ...props });
37
+
38
+ export { Label, LabelWrapper, labelVariants };
@@ -0,0 +1,180 @@
1
+ import { cn } from './chunk-WONVZ7WK.js';
2
+ import { useRef, useState, useId } from 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var fileUploadButtonVariants = cva(
7
+ [
8
+ "group block w-full text-left cursor-pointer appearance-none",
9
+ "font-govuk text-govuk-body text-govuk-black",
10
+ "p-govuk-file-upload sm:p-govuk-file-upload-lg",
11
+ "border-2 bg-white",
12
+ "focus:outline-3 focus:outline-govuk-yellow focus:outline-offset-0",
13
+ "focus:border-govuk-black focus:bg-govuk-light-grey",
14
+ "focus:inset-ring-2 focus:inset-ring-govuk-black",
15
+ "disabled:opacity-50 disabled:pointer-events-none"
16
+ ],
17
+ {
18
+ variants: {
19
+ empty: {
20
+ true: [
21
+ "border-dashed border-govuk-grey",
22
+ "hover:border-govuk-file-upload-hover-border hover:bg-govuk-light-grey"
23
+ ],
24
+ false: [
25
+ "border-solid border-govuk-mid-grey",
26
+ "hover:border-dashed hover:border-govuk-file-upload-hover-border"
27
+ ]
28
+ },
29
+ dragging: {
30
+ true: "border-solid border-govuk-black bg-govuk-light-grey",
31
+ false: ""
32
+ },
33
+ error: {
34
+ true: "border-govuk-error",
35
+ false: ""
36
+ }
37
+ },
38
+ defaultVariants: {
39
+ empty: true,
40
+ dragging: false,
41
+ error: false
42
+ }
43
+ }
44
+ );
45
+ var statusStyles = [
46
+ "block mb-govuk-2 px-govuk-2 py-govuk-3",
47
+ "text-left wrap-break-word font-govuk text-govuk-body"
48
+ ];
49
+ var pseudoButtonStyles = [
50
+ "inline-block leading-none",
51
+ "px-govuk-button-x pt-govuk-button-pt pb-govuk-button-pb",
52
+ "mr-govuk-2 mb-govuk-file-upload-pseudo-mb",
53
+ "border-2 border-transparent",
54
+ "font-govuk text-govuk-body",
55
+ "bg-govuk-light-grey text-govuk-black shadow-govuk-light-grey",
56
+ "group-hover:bg-govuk-mid-grey",
57
+ "group-focus:bg-govuk-yellow group-focus:shadow-govuk-yellow"
58
+ ];
59
+ var instructionStyles = [
60
+ "inline-block mt-govuk-file-upload-instruction-mt mb-0",
61
+ "text-left font-govuk text-govuk-body text-govuk-black"
62
+ ];
63
+ var FileUpload = ({
64
+ className,
65
+ id,
66
+ name,
67
+ disabled = false,
68
+ error = false,
69
+ multiple,
70
+ chooseFileButtonText = "Choose file",
71
+ dropInstructionText = "or drop file",
72
+ noFileChosenText = "No file chosen",
73
+ onChange,
74
+ ref,
75
+ ...props
76
+ }) => {
77
+ const internalRef = useRef(null);
78
+ const [status, setStatus] = useState(noFileChosenText);
79
+ const [empty, setEmpty] = useState(true);
80
+ const [dragging, setDragging] = useState(false);
81
+ const generatedId = useId();
82
+ const buttonId = id ?? generatedId;
83
+ const inputId = `${buttonId}-input`;
84
+ const setRefs = (node) => {
85
+ internalRef.current = node;
86
+ if (typeof ref === "function") {
87
+ ref(node);
88
+ } else if (ref) {
89
+ ref.current = node;
90
+ }
91
+ };
92
+ const updateFromFiles = (files) => {
93
+ if (!files || files.length === 0) {
94
+ setStatus(noFileChosenText);
95
+ setEmpty(true);
96
+ } else if (files.length === 1) {
97
+ setStatus(files[0].name);
98
+ setEmpty(false);
99
+ } else {
100
+ setStatus(`${files.length} files chosen`);
101
+ setEmpty(false);
102
+ }
103
+ };
104
+ const handleChange = (event) => {
105
+ updateFromFiles(event.target.files);
106
+ onChange?.(event);
107
+ };
108
+ const handleDrop = (event) => {
109
+ event.preventDefault();
110
+ setDragging(false);
111
+ if (disabled) {
112
+ return;
113
+ }
114
+ const droppedFiles = event.dataTransfer.files;
115
+ if (droppedFiles.length > 0 && internalRef.current) {
116
+ internalRef.current.files = droppedFiles;
117
+ updateFromFiles(droppedFiles);
118
+ internalRef.current.dispatchEvent(new Event("change", { bubbles: true }));
119
+ }
120
+ };
121
+ return /* @__PURE__ */ jsxs(
122
+ "div",
123
+ {
124
+ className: cn(
125
+ "relative block",
126
+ disabled && "cursor-not-allowed",
127
+ className
128
+ ),
129
+ children: [
130
+ /* @__PURE__ */ jsxs(
131
+ "button",
132
+ {
133
+ type: "button",
134
+ id: buttonId,
135
+ disabled,
136
+ onClick: () => internalRef.current?.click(),
137
+ onDragOver: (event) => event.preventDefault(),
138
+ onDragEnter: () => !disabled && setDragging(true),
139
+ onDragLeave: () => setDragging(false),
140
+ onDrop: handleDrop,
141
+ className: fileUploadButtonVariants({ empty, dragging, error }),
142
+ children: [
143
+ /* @__PURE__ */ jsx(
144
+ "span",
145
+ {
146
+ "aria-live": "polite",
147
+ className: cn(
148
+ statusStyles,
149
+ empty ? "bg-govuk-tag-blue-bg text-govuk-black" : "bg-govuk-brand text-white"
150
+ ),
151
+ children: status
152
+ }
153
+ ),
154
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-wrap items-baseline", children: [
155
+ /* @__PURE__ */ jsx("span", { className: cn(pseudoButtonStyles), children: chooseFileButtonText }),
156
+ /* @__PURE__ */ jsx("span", { className: cn(instructionStyles), children: dropInstructionText })
157
+ ] })
158
+ ]
159
+ }
160
+ ),
161
+ /* @__PURE__ */ jsx(
162
+ "input",
163
+ {
164
+ ref: setRefs,
165
+ id: inputId,
166
+ name,
167
+ type: "file",
168
+ multiple,
169
+ disabled,
170
+ hidden: true,
171
+ onChange: handleChange,
172
+ ...props
173
+ }
174
+ )
175
+ ]
176
+ }
177
+ );
178
+ };
179
+
180
+ export { FileUpload, fileUploadButtonVariants };