@tpzdsp/next-toolkit 2.5.1 → 3.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 (355) hide show
  1. package/package.json +21 -12
  2. package/src/assets/styles/globals.css +75 -95
  3. package/src/assets/styles/ol.css +57 -16
  4. package/src/assets/styles/utils.css +80 -0
  5. package/src/components/Accordion/Accordion.css +85 -0
  6. package/src/components/Accordion/Accordion.stories.tsx +264 -0
  7. package/src/components/Accordion/Accordion.tsx +98 -0
  8. package/src/components/Alert/Alert.css +129 -0
  9. package/src/components/Alert/Alert.stories.tsx +291 -0
  10. package/src/components/Alert/Alert.tsx +76 -0
  11. package/src/components/BackLink/BackLink.css +12 -0
  12. package/src/components/BackLink/BackLink.stories.tsx +52 -0
  13. package/src/components/BackLink/BackLink.tsx +44 -0
  14. package/src/components/BackToTop/BackToTop.css +23 -0
  15. package/src/components/BackToTop/BackToTop.stories.tsx +41 -0
  16. package/src/components/BackToTop/BackToTop.tsx +48 -0
  17. package/src/components/Breadcrumb/Breadcrumb.css +42 -0
  18. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +94 -0
  19. package/src/components/Breadcrumb/Breadcrumb.tsx +135 -0
  20. package/src/components/Button/Button.css +229 -0
  21. package/src/components/Button/Button.stories.tsx +140 -20
  22. package/src/components/Button/Button.tsx +53 -28
  23. package/src/components/Button/ButtonSkeleton.stories.tsx +50 -0
  24. package/src/components/Button/ButtonSkeleton.tsx +14 -0
  25. package/src/components/ButtonGroup/ButtonGroup.css +52 -0
  26. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +156 -0
  27. package/src/components/ButtonGroup/ButtonGroup.tsx +50 -0
  28. package/src/components/ButtonLink/ButtonLink.css +114 -0
  29. package/src/components/ButtonLink/ButtonLink.stories.tsx +38 -51
  30. package/src/components/ButtonLink/ButtonLink.tsx +54 -23
  31. package/src/components/Card/Card.css +13 -0
  32. package/src/components/Card/Card.stories.tsx +98 -57
  33. package/src/components/Card/Card.tsx +4 -13
  34. package/src/components/CardGroup/CardGroup.css +10 -0
  35. package/src/components/CardGroup/CardGroup.stories.tsx +81 -0
  36. package/src/components/CardGroup/CardGroup.tsx +9 -0
  37. package/src/components/Checkbox/Checkbox.css +49 -0
  38. package/src/components/Checkbox/Checkbox.stories.tsx +86 -0
  39. package/src/components/Checkbox/Checkbox.tsx +32 -0
  40. package/src/components/Chip/Chip.css +54 -0
  41. package/src/components/Chip/Chip.stories.tsx +94 -0
  42. package/src/components/Chip/Chip.tsx +34 -0
  43. package/src/components/CookieBanner/CookieBanner.css +19 -0
  44. package/src/components/CookieBanner/CookieBanner.stories.tsx +52 -0
  45. package/src/components/CookieBanner/CookieBanner.tsx +55 -0
  46. package/src/components/CopyButton/CopyButton.stories.tsx +28 -0
  47. package/src/components/CopyButton/CopyButton.tsx +65 -0
  48. package/src/components/DateInput/DateInput.css +13 -0
  49. package/src/components/DateInput/DateInput.stories.tsx +131 -0
  50. package/src/components/DateInput/DateInput.test.tsx +21 -0
  51. package/src/components/DateInput/DateInput.tsx +98 -0
  52. package/src/components/Details/Details.css +28 -0
  53. package/src/components/Details/Details.stories.tsx +48 -0
  54. package/src/components/Details/Details.tsx +41 -0
  55. package/src/components/Dropdown/Dropdown.css +81 -0
  56. package/src/components/Dropdown/Dropdown.stories.tsx +131 -0
  57. package/src/components/Dropdown/Dropdown.tsx +69 -0
  58. package/src/components/ErrorBoundary/ErrorBoundary.stories.tsx +4 -39
  59. package/src/components/ErrorBoundary/ErrorBoundary.tsx +7 -4
  60. package/src/components/ErrorBoundary/ErrorFallback.tsx +32 -66
  61. package/src/components/ErrorModal/ErrorModal.css +32 -0
  62. package/src/components/ErrorModal/ErrorModal.stories.tsx +101 -0
  63. package/src/components/ErrorModal/ErrorModal.tsx +120 -0
  64. package/src/components/ErrorText/ErrorText.css +22 -0
  65. package/src/components/ErrorText/ErrorText.stories.tsx +42 -27
  66. package/src/components/ErrorText/ErrorText.tsx +10 -8
  67. package/src/components/ExternalLink/ExternalLink.css +12 -0
  68. package/src/components/ExternalLink/ExternalLink.stories.tsx +43 -0
  69. package/src/components/ExternalLink/ExternalLink.tsx +43 -0
  70. package/src/components/Fieldset/Fieldset.css +103 -0
  71. package/src/components/Fieldset/Fieldset.stories.tsx +304 -0
  72. package/src/components/Fieldset/Fieldset.tsx +38 -0
  73. package/src/components/FileUpload/FileUpload.css +85 -0
  74. package/src/components/FileUpload/FileUpload.stories.tsx +106 -0
  75. package/src/components/FileUpload/FileUpload.tsx +99 -0
  76. package/src/components/{layout/footer → Footer}/Copyright.tsx +4 -2
  77. package/src/components/Footer/Footer.stories.tsx +24 -0
  78. package/src/components/Footer/Footer.tsx +41 -0
  79. package/src/components/Footer/Licence.tsx +18 -0
  80. package/src/components/{layout/footer → Footer}/MetaLinks.tsx +8 -3
  81. package/src/components/Footer/Small/SmallFooter.tsx +43 -42
  82. package/src/components/Form/FormGroup.css +18 -0
  83. package/src/components/Form/FormGroup.stories.tsx +87 -0
  84. package/src/components/Form/FormGroup.tsx +16 -0
  85. package/src/components/{layout/header → Header}/Header.stories.tsx +26 -12
  86. package/src/components/Header/Header.test.tsx +87 -0
  87. package/src/components/Header/Header.tsx +303 -0
  88. package/src/components/Header/HeaderAppContent.tsx +120 -0
  89. package/src/components/Heading/Heading.css +40 -0
  90. package/src/components/Heading/Heading.stories.tsx +15 -5
  91. package/src/components/Heading/Heading.tsx +21 -44
  92. package/src/components/Heading/HeadingSkeleton.stories.tsx +30 -0
  93. package/src/components/Heading/HeadingSkeleton.tsx +14 -0
  94. package/src/components/Hero/Hero.css +19 -0
  95. package/src/components/Hero/Hero.stories.tsx +41 -0
  96. package/src/components/Hero/Hero.tsx +14 -0
  97. package/src/components/HintText/HintText.css +5 -0
  98. package/src/components/HintText/HintText.stories.tsx +29 -0
  99. package/src/components/HintText/HintText.tsx +13 -0
  100. package/src/components/InfoBox/InfoBox.css +38 -0
  101. package/src/components/InfoBox/InfoBox.stories.tsx +51 -403
  102. package/src/components/InfoBox/InfoBox.tsx +31 -158
  103. package/src/components/Input/Input.css +77 -0
  104. package/src/components/Input/Input.stories.tsx +123 -0
  105. package/src/components/Input/Input.tsx +74 -0
  106. package/src/components/InputGroup/InputGroup.css +140 -0
  107. package/src/components/InputGroup/InputGroup.stories.tsx +125 -0
  108. package/src/components/InputGroup/InputGroup.tsx +47 -0
  109. package/src/components/InsetText/InsetText.css +5 -0
  110. package/src/components/InsetText/InsetText.stories.tsx +30 -0
  111. package/src/components/InsetText/InsetText.tsx +9 -0
  112. package/src/components/Keyboard/Keyboard.css +9 -0
  113. package/src/components/Keyboard/Keyboard.stories.tsx +63 -0
  114. package/src/components/Keyboard/Keyboard.tsx +30 -0
  115. package/src/components/Label/Label.css +27 -0
  116. package/src/components/Label/Label.stories.tsx +40 -0
  117. package/src/components/Label/Label.tsx +17 -0
  118. package/src/components/LayerSwitcher/LayerSwitcher.css +59 -0
  119. package/src/components/LayerSwitcher/LayerSwitcher.stories.tsx +112 -0
  120. package/src/components/LayerSwitcher/LayerSwitcher.tsx +61 -0
  121. package/src/components/Layout/401/401.stories.tsx +23 -0
  122. package/src/components/Layout/401/401.tsx +1 -0
  123. package/src/components/Layout/403/403.stories.tsx +23 -0
  124. package/src/components/Layout/403/403.tsx +21 -0
  125. package/src/components/Layout/404/404.stories.tsx +23 -0
  126. package/src/components/Layout/404/404.tsx +28 -0
  127. package/src/components/Layout/500/500.stories.tsx +56 -0
  128. package/src/components/Layout/500/500.tsx +63 -0
  129. package/src/components/Layout/ButtonGroup/ButtonGroup.css +52 -0
  130. package/src/components/Layout/ButtonGroup/ButtonGroup.stories.tsx +156 -0
  131. package/src/components/Layout/ButtonGroup/ButtonGroup.tsx +50 -0
  132. package/src/components/Layout/HeadingGroup/HeadingGroup.css +21 -0
  133. package/src/components/Layout/HeadingGroup/HeadingGroup.stories.tsx +84 -0
  134. package/src/components/Layout/HeadingGroup/HeadingGroup.tsx +9 -0
  135. package/src/components/Layout/MainWrapper/MainWrapper.css +12 -0
  136. package/src/components/Layout/MainWrapper/MainWrapper.stories.tsx +36 -0
  137. package/src/components/Layout/MainWrapper/MainWrapper.tsx +14 -0
  138. package/src/components/Layout/PageShell/PageShell.css +42 -0
  139. package/src/components/Layout/PageShell/PageShell.stories.tsx +108 -0
  140. package/src/components/Layout/PageShell/PageShell.tsx +31 -0
  141. package/src/components/Layout/ParagraphGroup/ParagraphGroup.css +5 -0
  142. package/src/components/Layout/ParagraphGroup/ParagraphGroup.stories.tsx +34 -0
  143. package/src/components/Layout/ParagraphGroup/ParagraphGroup.tsx +9 -0
  144. package/src/components/Layout/Stack/Stack.css +29 -0
  145. package/src/components/Layout/Stack/Stack.stories.tsx +83 -0
  146. package/src/components/Layout/Stack/Stack.tsx +19 -0
  147. package/src/components/Layout/WidthContainer/WidthContainer.css +17 -0
  148. package/src/components/Layout/WidthContainer/WidthContainer.stories.tsx +59 -0
  149. package/src/components/Layout/WidthContainer/WidthContainer.tsx +13 -0
  150. package/src/components/Legend/Legend.css +95 -0
  151. package/src/components/Legend/Legend.stories.tsx +81 -0
  152. package/src/components/Legend/Legend.tsx +32 -0
  153. package/src/components/Legend/LegendDot.tsx +15 -0
  154. package/src/components/Legend/LegendPanel.stories.tsx +101 -0
  155. package/src/components/Legend/LegendPanel.tsx +68 -0
  156. package/src/components/Legend/LegendSkeleton.stories.tsx +87 -0
  157. package/src/components/Legend/LegendSkeleton.tsx +73 -0
  158. package/src/components/LegendSelect/LegendSelect.css +8 -0
  159. package/src/components/LegendSelect/LegendSelect.stories.tsx +80 -0
  160. package/src/components/LegendSelect/LegendSelect.tsx +26 -0
  161. package/src/components/Link/Link.css +98 -0
  162. package/src/components/Link/Link.stories.tsx +70 -0
  163. package/src/components/Link/Link.tsx +52 -0
  164. package/src/components/LinkButton/LinkButton.css +67 -0
  165. package/src/components/LinkButton/LinkButton.stories.tsx +90 -42
  166. package/src/components/LinkButton/LinkButton.tsx +50 -63
  167. package/src/components/LinkList/LinkList.css +28 -0
  168. package/src/components/LinkList/LinkList.stories.tsx +46 -0
  169. package/src/components/LinkList/LinkList.tsx +23 -0
  170. package/src/components/List/Li.tsx +9 -0
  171. package/src/components/List/List.css +9 -0
  172. package/src/components/List/OrderedList.stories.tsx +36 -0
  173. package/src/components/List/OrderedList.tsx +9 -0
  174. package/src/components/List/UnorderedList.stories.tsx +36 -0
  175. package/src/components/List/UnorderedList.tsx +9 -0
  176. package/src/components/LoadingBox/LoadingBox.css +27 -0
  177. package/src/components/LoadingBox/LoadingBox.stories.tsx +66 -0
  178. package/src/components/LoadingBox/LoadingBox.tsx +40 -0
  179. package/src/components/Modal/Modal.css +114 -0
  180. package/src/components/Modal/Modal.stories.tsx +41 -160
  181. package/src/components/Modal/Modal.tsx +132 -75
  182. package/src/components/NoScriptBanner/NoScriptBanner.css +17 -0
  183. package/src/components/NoScriptBanner/NoScriptBanner.stories.tsx +46 -0
  184. package/src/components/NoScriptBanner/NoScriptBanner.tsx +26 -0
  185. package/src/components/Paragraph/Paragraph.css +22 -0
  186. package/src/components/Paragraph/Paragraph.stories.tsx +1 -42
  187. package/src/components/Paragraph/Paragraph.tsx +4 -3
  188. package/src/components/Paragraph/ParagraphSkeleton.stories.tsx +44 -0
  189. package/src/components/Paragraph/ParagraphSkeleton.tsx +33 -0
  190. package/src/components/PasswordInput/PasswordInput.css +3 -0
  191. package/src/components/PasswordInput/PasswordInput.stories.tsx +47 -0
  192. package/src/components/PasswordInput/PasswordInput.tsx +45 -0
  193. package/src/components/PhaseBanner/PhaseBanner.css +12 -0
  194. package/src/components/PhaseBanner/PhaseBanner.stories.tsx +61 -0
  195. package/src/components/PhaseBanner/PhaseBanner.tsx +17 -0
  196. package/src/components/Popover/Popover.css +43 -0
  197. package/src/components/Popover/Popover.stories.tsx +102 -0
  198. package/src/components/Popover/Popover.tsx +40 -0
  199. package/src/components/Radio/Radio.css +69 -0
  200. package/src/components/Radio/Radio.stories.tsx +169 -0
  201. package/src/components/Radio/Radio.tsx +56 -0
  202. package/src/components/Resizable/Resizable.css +86 -0
  203. package/src/components/Resizable/Resizable.stories.tsx +123 -0
  204. package/src/components/Resizable/Resizable.tsx +86 -0
  205. package/src/components/ScrollArea/ScrollArea.css +9 -0
  206. package/src/components/ScrollArea/ScrollArea.stories.tsx +42 -0
  207. package/src/components/ScrollArea/ScrollArea.tsx +11 -0
  208. package/src/components/SearchBox/SearchBox.stories.tsx +88 -0
  209. package/src/components/SearchBox/SearchBox.tsx +36 -0
  210. package/src/components/Select/AsyncSelect.stories.tsx +84 -0
  211. package/src/components/Select/AsyncSelect.tsx +41 -0
  212. package/src/components/Select/Select.css +194 -0
  213. package/src/components/Select/Select.stories.tsx +162 -0
  214. package/src/components/Select/Select.test.tsx +36 -0
  215. package/src/components/Select/Select.tsx +291 -0
  216. package/src/components/Select/SelectSkeleton.stories.tsx +51 -0
  217. package/src/components/Select/SelectSkeleton.tsx +23 -0
  218. package/src/components/Separator/Separator.css +41 -0
  219. package/src/components/Separator/Separator.stories.tsx +63 -0
  220. package/src/components/Separator/Separator.tsx +42 -0
  221. package/src/components/Sidebar/ResizableSidebar.tsx +118 -0
  222. package/src/components/Sidebar/Sidebar.css +203 -0
  223. package/src/components/Sidebar/Sidebar.stories.tsx +438 -0
  224. package/src/components/Sidebar/Sidebar.tsx +225 -0
  225. package/src/components/Skeleton/Skeleton.css +16 -0
  226. package/src/components/Skeleton/Skeleton.stories.tsx +39 -0
  227. package/src/components/Skeleton/Skeleton.tsx +12 -0
  228. package/src/components/SkipLink/SkipLink.css +16 -0
  229. package/src/components/SkipLink/SkipLink.stories.tsx +40 -0
  230. package/src/components/SkipLink/SkipLink.tsx +15 -0
  231. package/src/components/Spinner/Spinner.css +30 -0
  232. package/src/components/Spinner/Spinner.stories.tsx +36 -0
  233. package/src/components/Spinner/Spinner.tsx +45 -0
  234. package/src/components/StartButton/StartButton.css +13 -0
  235. package/src/components/StartButton/StartButton.stories.tsx +68 -0
  236. package/src/components/StartButton/StartButton.tsx +50 -0
  237. package/src/components/SubmitButton/SubmitButton.stories.tsx +31 -0
  238. package/src/components/SubmitButton/SubmitButton.tsx +14 -0
  239. package/src/components/SummaryList/SummaryList.css +71 -0
  240. package/src/components/SummaryList/SummaryList.stories.tsx +211 -0
  241. package/src/components/SummaryList/SummaryList.tsx +41 -0
  242. package/src/components/SummaryList/SummaryListSkeleton.stories.tsx +67 -0
  243. package/src/components/SummaryList/SummaryListSkeleton.tsx +40 -0
  244. package/src/components/Tabs/Tabs.css +84 -0
  245. package/src/components/Tabs/Tabs.stories.tsx +133 -0
  246. package/src/components/Tabs/Tabs.tsx +66 -0
  247. package/src/components/Tag/Tag.css +8 -0
  248. package/src/components/Tag/Tag.stories.tsx +96 -0
  249. package/src/components/Tag/Tag.tsx +34 -0
  250. package/src/components/Textarea/Textarea.css +38 -0
  251. package/src/components/Textarea/Textarea.stories.tsx +131 -0
  252. package/src/components/Textarea/Textarea.tsx +50 -0
  253. package/src/components/TextareaCount/TextareaCount.css +17 -0
  254. package/src/components/TextareaCount/TextareaCount.stories.tsx +131 -0
  255. package/src/components/TextareaCount/TextareaCount.tsx +108 -0
  256. package/src/components/Tooltip/Tooltip.css +43 -0
  257. package/src/components/Tooltip/Tooltip.stories.tsx +110 -0
  258. package/src/components/Tooltip/Tooltip.tsx +53 -0
  259. package/src/components/WarningText/WarningText.css +20 -0
  260. package/src/components/WarningText/WarningText.stories.tsx +29 -0
  261. package/src/components/WarningText/WarningText.tsx +17 -0
  262. package/src/components/index.ts +342 -61
  263. package/src/errors/errorDisplay.ts +70 -0
  264. package/src/errors/index.ts +1 -0
  265. package/src/http/constants.ts +1 -0
  266. package/src/http/fetch.ts +7 -3
  267. package/src/map/LayerSwitcherPanel.tsx +2 -173
  268. package/src/map/LegendShim.tsx +2 -0
  269. package/src/map/MapComponent.tsx +7 -17
  270. package/src/map/MapControlsOverlay.tsx +68 -175
  271. package/src/map/Popup.tsx +71 -24
  272. package/src/map/geocoder/Geocoder.test.tsx +46 -3
  273. package/src/map/geocoder/Geocoder.tsx +155 -278
  274. package/src/map/index.ts +1 -1
  275. package/src/types/utils.ts +0 -10
  276. package/src/utils/components.ts +96 -0
  277. package/src/utils/index.ts +1 -0
  278. package/src/utils/utils.ts +0 -12
  279. package/src/assets/images/defra-logo.svg +0 -51
  280. package/src/assets/images/ea-logo.svg +0 -58
  281. package/src/assets/images/ogl.svg +0 -1
  282. package/src/components/Button/Button.test.tsx +0 -53
  283. package/src/components/ButtonLink/ButtonLink.test.tsx +0 -154
  284. package/src/components/Card/Card.test.tsx +0 -51
  285. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +0 -75
  286. package/src/components/ErrorBoundary/ErrorFallback.test.tsx +0 -107
  287. package/src/components/ErrorText/ErrorText.test.tsx +0 -33
  288. package/src/components/Heading/Heading.test.tsx +0 -22
  289. package/src/components/Hint/Hint.stories.tsx +0 -58
  290. package/src/components/Hint/Hint.test.tsx +0 -33
  291. package/src/components/Hint/Hint.tsx +0 -12
  292. package/src/components/InfoBox/InfoBox.test.tsx +0 -330
  293. package/src/components/InfoBox/types.ts +0 -6
  294. package/src/components/LinkButton/LinkButton.test.tsx +0 -177
  295. package/src/components/Modal/Modal.test.tsx +0 -246
  296. package/src/components/NotificationBanner/NotificationBanner.stories.tsx +0 -45
  297. package/src/components/NotificationBanner/NotificationBanner.test.tsx +0 -58
  298. package/src/components/NotificationBanner/NotificationBanner.tsx +0 -45
  299. package/src/components/Paragraph/Paragraph.test.tsx +0 -10
  300. package/src/components/SlidingPanel/SlidingPanel.stories.tsx +0 -129
  301. package/src/components/SlidingPanel/SlidingPanel.test.tsx +0 -83
  302. package/src/components/SlidingPanel/SlidingPanel.tsx +0 -258
  303. package/src/components/accordion/Accordion.stories.tsx +0 -234
  304. package/src/components/accordion/Accordion.test.tsx +0 -192
  305. package/src/components/accordion/Accordion.tsx +0 -73
  306. package/src/components/backToTop/BackToTop.stories.tsx +0 -407
  307. package/src/components/backToTop/BackToTop.test.tsx +0 -57
  308. package/src/components/backToTop/BackToTop.tsx +0 -134
  309. package/src/components/chip/Chip.stories.tsx +0 -61
  310. package/src/components/chip/Chip.test.tsx +0 -31
  311. package/src/components/chip/Chip.tsx +0 -23
  312. package/src/components/container/Container.tsx +0 -42
  313. package/src/components/cookieBanner/CookieBanner.stories.tsx +0 -257
  314. package/src/components/cookieBanner/CookieBanner.test.tsx +0 -68
  315. package/src/components/cookieBanner/CookieBanner.tsx +0 -73
  316. package/src/components/divider/RuleDivider.stories.tsx +0 -254
  317. package/src/components/divider/RuleDivider.test.tsx +0 -164
  318. package/src/components/divider/RuleDivider.tsx +0 -23
  319. package/src/components/dropdown/DropdownMenu.test.tsx +0 -211
  320. package/src/components/dropdown/DropdownMenu.tsx +0 -108
  321. package/src/components/dropdown/useDropdownMenu.ts +0 -249
  322. package/src/components/form/Input.stories.tsx +0 -435
  323. package/src/components/form/Input.test.tsx +0 -206
  324. package/src/components/form/Input.tsx +0 -23
  325. package/src/components/form/TextArea.stories.tsx +0 -464
  326. package/src/components/form/TextArea.test.tsx +0 -232
  327. package/src/components/form/TextArea.tsx +0 -23
  328. package/src/components/layout/footer/Footer.tsx +0 -26
  329. package/src/components/layout/footer/Licence.tsx +0 -19
  330. package/src/components/layout/header/Header.test.tsx +0 -36
  331. package/src/components/layout/header/Header.tsx +0 -90
  332. package/src/components/layout/header/HeaderAuthClient.test.tsx +0 -45
  333. package/src/components/layout/header/HeaderAuthClient.tsx +0 -40
  334. package/src/components/layout/header/HeaderNavClient.test.tsx +0 -44
  335. package/src/components/layout/header/HeaderNavClient.tsx +0 -67
  336. package/src/components/link/ExternalLink.test.tsx +0 -102
  337. package/src/components/link/ExternalLink.tsx +0 -29
  338. package/src/components/link/Link.tsx +0 -26
  339. package/src/components/select/Select.stories.tsx +0 -336
  340. package/src/components/select/Select.test.tsx +0 -474
  341. package/src/components/select/Select.tsx +0 -125
  342. package/src/components/select/SelectSkeleton.stories.tsx +0 -194
  343. package/src/components/select/SelectSkeleton.test.tsx +0 -104
  344. package/src/components/select/SelectSkeleton.tsx +0 -23
  345. package/src/components/select/common.ts +0 -3
  346. package/src/components/select/index.ts +0 -18
  347. package/src/components/skipLink/SkipLink.stories.tsx +0 -346
  348. package/src/components/skipLink/SkipLink.test.tsx +0 -22
  349. package/src/components/skipLink/SkipLink.tsx +0 -49
  350. package/src/map/LegendPanel.tsx +0 -85
  351. /package/src/{components → assets}/images/DefraLogo.tsx +0 -0
  352. /package/src/{components → assets}/images/EaLogo.tsx +0 -0
  353. /package/src/{components → assets}/images/OglLogo.tsx +0 -0
  354. /package/src/components/{googleAnalytics → GoogleAnalytics}/GlobalVars.tsx +0 -0
  355. /package/src/components/{googleAnalytics → GoogleAnalytics}/GoogleAnalytics.tsx +0 -0
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+
3
+ import { useId, type ComponentProps } from 'react';
4
+
5
+ import { LuSearch } from 'react-icons/lu';
6
+
7
+ import { Button } from '../Button/Button';
8
+ import { Input } from '../Input/Input';
9
+ import { InputGroup, InputSuffix } from '../InputGroup/InputGroup';
10
+
11
+ export type SearchBoxProps = Omit<ComponentProps<typeof Input>, 'type'> & {
12
+ buttonLabel?: string;
13
+ };
14
+
15
+ export const SearchBox = ({ id, buttonLabel = 'Search', disabled, ...props }: SearchBoxProps) => {
16
+ const generatedId = useId();
17
+ const inputId = id ?? generatedId;
18
+
19
+ return (
20
+ <InputGroup aria-disabled={disabled}>
21
+ <Input id={inputId} type="search" disabled={disabled} {...props} />
22
+
23
+ <InputSuffix>
24
+ <Button
25
+ type="submit"
26
+ appearance="primary"
27
+ variant="icon"
28
+ aria-label={buttonLabel}
29
+ disabled={disabled}
30
+ >
31
+ <LuSearch aria-hidden />
32
+ </Button>
33
+ </InputSuffix>
34
+ </InputGroup>
35
+ );
36
+ };
@@ -0,0 +1,84 @@
1
+ import { useCallback, useRef } from 'react';
2
+
3
+ import type { OptionsOrGroups } from 'react-select';
4
+
5
+ import type { Meta, StoryObj } from '@storybook/react-vite';
6
+
7
+ import { AsyncSelect } from './AsyncSelect';
8
+ import { Label } from '../Label/Label';
9
+
10
+ const meta: Meta<typeof AsyncSelect> = {
11
+ title: 'Components/Select/AsyncSelect',
12
+ component: AsyncSelect,
13
+ tags: ['autodocs'],
14
+ parameters: {
15
+ docs: {
16
+ description: {
17
+ component:
18
+ "Select with remote, `loadOptions`-driven options instead of a fixed local list, for search-as-you-type against an API. Composes react-select's own `useAsync` and `useStateManager` directly onto this project's Select, so it shares the exact same styling and indicator overrides (including the loading spinner). `loadOptions` isn't debounced by react-select itself, it fires on every keystroke, wrap it in your own debounce as shown here.",
19
+ },
20
+ },
21
+ },
22
+ };
23
+
24
+ export default meta;
25
+
26
+ type Story = StoryObj<typeof AsyncSelect>;
27
+
28
+ type Country = { id: string; label: string };
29
+
30
+ const COUNTRIES: Country[] = [
31
+ { id: 'eng', label: 'England' },
32
+ { id: 'sco', label: 'Scotland' },
33
+ { id: 'wal', label: 'Wales' },
34
+ { id: 'nir', label: 'Northern Ireland' },
35
+ ];
36
+
37
+ // Stands in for a real API call, filters the local list after a short delay
38
+ // so the loading indicator is visible.
39
+ const fakeSearch = (query: string): Promise<Country[]> =>
40
+ new Promise((resolve) => {
41
+ setTimeout(() => {
42
+ resolve(
43
+ COUNTRIES.filter((country) => country.label.toLowerCase().includes(query.toLowerCase())),
44
+ );
45
+ }, 600);
46
+ });
47
+
48
+ const DebouncedExample = () => {
49
+ const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
50
+
51
+ const loadOptions = useCallback(
52
+ (inputValue: string, callback: (options: OptionsOrGroups<Country, never>) => void) => {
53
+ if (debounceRef.current) {
54
+ clearTimeout(debounceRef.current);
55
+ }
56
+
57
+ debounceRef.current = setTimeout(async () => {
58
+ callback(await fakeSearch(inputValue));
59
+ }, 300);
60
+ },
61
+ [],
62
+ );
63
+
64
+ return (
65
+ <div>
66
+ <Label htmlFor="async-country">Country</Label>
67
+
68
+ <AsyncSelect<Country>
69
+ inputId="async-country"
70
+ loadOptions={loadOptions}
71
+ getOptionLabel={(option) => option.label}
72
+ getOptionValue={(option) => option.id}
73
+ placeholder="Search for a country"
74
+ noOptionsMessage={({ inputValue }) =>
75
+ inputValue ? 'No countries found' : 'Start typing to search'
76
+ }
77
+ />
78
+ </div>
79
+ );
80
+ };
81
+
82
+ export const Default: Story = {
83
+ render: () => <DebouncedExample />,
84
+ };
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+
3
+ import type { GroupBase } from 'react-select';
4
+ import { useStateManager } from 'react-select';
5
+ import { useAsync } from 'react-select/async';
6
+ import type { AsyncProps } from 'react-select/async';
7
+
8
+ import { Select } from './Select';
9
+ import type { SelectProps } from './Select';
10
+
11
+ export type AsyncSelectProps<
12
+ Option = unknown,
13
+ IsMulti extends boolean = false,
14
+ Group extends GroupBase<Option> = GroupBase<Option>,
15
+ > = Omit<SelectProps<Option, IsMulti, Group>, keyof AsyncProps<Option, IsMulti, Group>> &
16
+ AsyncProps<Option, IsMulti, Group>;
17
+
18
+ /**
19
+ * Select with remote, `loadOptions`-driven options instead of a fixed local
20
+ * list. Composes react-select's own `useAsync` (manages the loading state
21
+ * and current options) and `useStateManager` (controlled/uncontrolled
22
+ * value/inputValue bridging) directly onto our own styled Select, the same
23
+ * way react-select's own AsyncSelect composes them onto its unstyled one, so
24
+ * this gets identical behaviour with our styling and indicator overrides.
25
+ *
26
+ * `loadOptions` is not debounced by react-select itself, it fires on every
27
+ * keystroke, wrap it in your own debounce (e.g. a timeout cleared on each
28
+ * call) if that's not the desired behaviour.
29
+ */
30
+ export const AsyncSelect = <
31
+ Option = unknown,
32
+ IsMulti extends boolean = false,
33
+ Group extends GroupBase<Option> = GroupBase<Option>,
34
+ >(
35
+ props: AsyncSelectProps<Option, IsMulti, Group>,
36
+ ) => {
37
+ const asyncProps = useAsync(props);
38
+ const statefulProps = useStateManager(asyncProps);
39
+
40
+ return <Select {...statefulProps} />;
41
+ };
@@ -0,0 +1,194 @@
1
+ @layer components {
2
+ /* MARK: Select
3
+ Styled to match the GDS text input: same height, border, padding, and
4
+ focus ring. The dropdown menu uses panel (white bg, form-weight border)
5
+ with no border-radius, matching GDS panel conventions. */
6
+
7
+ /* MARK: Container
8
+ w-full mirrors .cn-input: harmless in normal block flow (already full
9
+ width there), but needed as a flex item (e.g. the main field in an
10
+ InputGroup row alongside InputPrefix/InputSuffix), where it would
11
+ otherwise shrink to the width of its content instead of filling the
12
+ remaining row space. InputGroup.css overrides this back to w-auto when
13
+ a Select is used as a narrow addon nested inside a prefix/suffix. */
14
+ .cn-select-container {
15
+ @apply relative w-full;
16
+ }
17
+
18
+ /* MARK: Control
19
+ Mirrors .cn-input: 40px height, 2px border, 5px horizontal padding. */
20
+ .cn-select-control {
21
+ @apply cn-form-border h-10 px-gds-1 bg-white flex items-center cursor-default text-base
22
+ box-border;
23
+ }
24
+
25
+ .cn-select-control-focused {
26
+ @apply outline-focus outline-offset-0;
27
+ box-shadow: inset 0 0 0 var(--border-width-form) var(--color-divider-input);
28
+ }
29
+
30
+ .cn-select-control-invalid {
31
+ @apply border-error;
32
+ }
33
+
34
+ .cn-select-control-disabled {
35
+ @apply opacity-50 cursor-not-allowed;
36
+ }
37
+
38
+ /* MARK: Value area */
39
+
40
+ .cn-select-value-container {
41
+ @apply flex flex-1 items-center flex-wrap h-full overflow-hidden;
42
+ }
43
+
44
+ .cn-select-value-container-multi {
45
+ /* The visible gap between chips equals the gap property value: the 3px white
46
+ borders on each side of each chip are part of the perceived separation, not
47
+ subtracted from it (border-to-border = gap - 6, but visible = gap - 6 + 3 + 3 = gap).
48
+ Edge gap = px-gds-1 (5px) + chip border (3px) = 8px, so gap-2 (8px) matches. */
49
+ @apply gap-2;
50
+
51
+ &:has(.cn-select-multi-value) {
52
+ /* Horizontal padding only, vertical padding reduces the centering area
53
+ from 40px to 34px and shifts chips off-centre. The chip's focus border
54
+ (3px) sits 5.5px from the top/bottom container edges, so no vertical
55
+ padding is needed to protect it from overflow: hidden. */
56
+ padding-right: var(--focus-ring-width);
57
+ padding-left: var(--focus-ring-width);
58
+ }
59
+ }
60
+
61
+ .cn-select-single-value {
62
+ @apply text-body truncate;
63
+ }
64
+
65
+ .cn-select-placeholder {
66
+ @apply text-body-secondary;
67
+ }
68
+
69
+ /* The hidden search input react-select renders inside the control */
70
+ .cn-select-input {
71
+ @apply text-base text-body;
72
+ }
73
+
74
+ /* MARK: Indicators */
75
+
76
+ .cn-select-indicators {
77
+ @apply flex items-center gap-1 flex-none;
78
+ }
79
+
80
+ .cn-select-dropdown-indicator {
81
+ @apply w-5 h-5 flex items-center justify-center text-body;
82
+ }
83
+
84
+ .cn-select-dropdown-indicator-open {
85
+ @apply rotate-180;
86
+ }
87
+
88
+ .cn-select-clear-indicator {
89
+ @apply w-5 h-5 flex items-center justify-center cursor-pointer text-body-secondary
90
+ hover:text-body;
91
+ }
92
+
93
+ .cn-select-loading-indicator {
94
+ @apply w-5 h-5 flex items-center justify-center text-body-secondary;
95
+ }
96
+
97
+ /* MARK: Menu */
98
+
99
+ .cn-select-menu {
100
+ @apply panel absolute w-full mt-1 overflow-hidden cn-z-overlay;
101
+ }
102
+
103
+ .cn-select-menu-list {
104
+ @apply flex flex-col overflow-y-auto max-h-60;
105
+ }
106
+
107
+ /* MARK: Options */
108
+
109
+ .cn-select-option {
110
+ @apply px-gds-1 py-1 text-base text-body cursor-pointer;
111
+ }
112
+
113
+ .cn-select-option-focused {
114
+ @apply bg-wash;
115
+ }
116
+
117
+ .cn-select-option-selected {
118
+ @apply bg-accent text-on-accent;
119
+ }
120
+
121
+ .cn-select-option-disabled {
122
+ @apply opacity-50 cursor-not-allowed;
123
+ }
124
+
125
+ .cn-select-no-options {
126
+ @apply px-gds-1 py-gds-1 text-base text-body select-none;
127
+ }
128
+
129
+ /* MARK: Groups */
130
+
131
+ .cn-select-group:first-child {
132
+ @apply pt-2;
133
+ }
134
+
135
+ /* MARK: Multi-value chips
136
+ The entire chip is a <button> that removes the value on click, giving a
137
+ larger, GDS-compliant touch target rather than a tiny X icon alone. */
138
+
139
+ .cn-select-multi-value {
140
+ /* The margin cancels the space the 3px border takes up in the flex layout so
141
+ chips look the same size as they would without a border. */
142
+ @apply cn-chip-size-sm cn-chip-appearance-neutral flex items-center gap-1 cursor-pointer
143
+ border-solid border-panel outline-none;
144
+ border-width: var(--focus-ring-width);
145
+ margin: 0 calc(var(--focus-ring-width) * -1) 0 calc(var(--focus-ring-width) * -1);
146
+
147
+ &:focus {
148
+ @apply border-focus;
149
+ }
150
+ }
151
+
152
+ .cn-select-multi-value-remove {
153
+ @apply w-3.5 h-3.5 flex-none;
154
+ }
155
+
156
+ /* MARK: Tags below
157
+ Used when `tagsPlacement="below"`: selected values render in a row under
158
+ the control instead of as inline chips, so the control keeps a fixed
159
+ 40px height regardless of how many values are selected. */
160
+
161
+ .cn-select-tags {
162
+ @apply flex flex-wrap gap-2 mt-2;
163
+ }
164
+
165
+ .cn-select-tag {
166
+ /* Same margin-cancels-border trick as .cn-select-multi-value, so the gap
167
+ between tags matches the gap between inline chips exactly. */
168
+ @apply cn-chip-size-sm cn-chip-appearance-neutral flex items-center gap-1 cursor-pointer
169
+ border-solid border-panel outline-none;
170
+ border-width: var(--focus-ring-width);
171
+ margin: 0 calc(var(--focus-ring-width) * -1) 0 calc(var(--focus-ring-width) * -1);
172
+
173
+ &:focus {
174
+ @apply border-focus;
175
+ }
176
+
177
+ &:disabled {
178
+ @apply opacity-50 cursor-not-allowed;
179
+ }
180
+ }
181
+
182
+ /* MARK: Skeleton
183
+ SelectSkeleton reuses cn-select-container/control/value-container/
184
+ indicators directly, so its dimensions (40px height, border, padding,
185
+ the flex-1 vs flex-none split) always match the real control, these
186
+ two are just the decorative placeholder shapes inside it. */
187
+ .cn-select-skeleton-value {
188
+ @apply h-4 w-24;
189
+ }
190
+
191
+ .cn-select-skeleton-indicator {
192
+ @apply size-4;
193
+ }
194
+ }
@@ -0,0 +1,162 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+
3
+ import { Select } from './Select';
4
+ import { ErrorText } from '../ErrorText/ErrorText';
5
+ import { FormGroup } from '../Form/FormGroup';
6
+ import { Label } from '../Label/Label';
7
+
8
+ const meta: Meta<typeof Select> = {
9
+ title: 'Components/Select/Select',
10
+ component: Select,
11
+ tags: ['autodocs'],
12
+ parameters: {
13
+ docs: {
14
+ description: {
15
+ component:
16
+ 'Searchable select built on react-select. Styled to match the GDS text input, same height, border, and focus ring. The dropdown uses the standard GDS panel (white background, black border, no border-radius). Supports single and multi-select, option groups, async loading, and creatable options via react-select props.',
17
+ },
18
+ },
19
+ },
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj<typeof Select>;
25
+
26
+ const SELECT_A_COUNTRY = 'Select a country';
27
+
28
+ const COUNTRIES = [
29
+ { value: 'eng', label: 'England' },
30
+ { value: 'sco', label: 'Scotland' },
31
+ { value: 'wal', label: 'Wales' },
32
+ { value: 'nir', label: 'Northern Ireland' },
33
+ ];
34
+
35
+ const SPECIES = [
36
+ {
37
+ label: 'Birds',
38
+ options: [
39
+ { value: 'lapwing', label: 'Lapwing' },
40
+ { value: 'curlew', label: 'Curlew' },
41
+ { value: 'redshank', label: 'Redshank' },
42
+ ],
43
+ },
44
+ {
45
+ label: 'Mammals',
46
+ options: [
47
+ { value: 'otter', label: 'Otter' },
48
+ { value: 'water-vole', label: 'Water vole' },
49
+ { value: 'hedgehog', label: 'Hedgehog' },
50
+ ],
51
+ },
52
+ {
53
+ label: 'Plants',
54
+ options: [
55
+ { value: 'bluebell', label: 'Bluebell' },
56
+ { value: 'meadow-buttercup', label: 'Meadow buttercup' },
57
+ ],
58
+ },
59
+ ];
60
+
61
+ export const Default: Story = {
62
+ args: {
63
+ options: COUNTRIES,
64
+ placeholder: SELECT_A_COUNTRY,
65
+ },
66
+ };
67
+
68
+ export const Clearable: Story = {
69
+ args: {
70
+ options: COUNTRIES,
71
+ placeholder: SELECT_A_COUNTRY,
72
+ isClearable: true,
73
+ defaultValue: COUNTRIES[0],
74
+ },
75
+ };
76
+
77
+ export const MultiSelect: Story = {
78
+ args: {
79
+ options: COUNTRIES,
80
+ placeholder: 'Select countries',
81
+ isMulti: true,
82
+ isClearable: true,
83
+ defaultValue: [COUNTRIES[0], COUNTRIES[2]],
84
+ },
85
+ };
86
+
87
+ export const MultiSelectTagsBelow: Story = {
88
+ parameters: {
89
+ docs: {
90
+ description: {
91
+ story:
92
+ 'Set `tagsPlacement="below"` to list selected values under the control instead of as inline chips. The control keeps a fixed height regardless of how many values are selected.',
93
+ },
94
+ },
95
+ },
96
+ args: {
97
+ options: COUNTRIES,
98
+ placeholder: 'Select countries',
99
+ isMulti: true,
100
+ isClearable: true,
101
+ tagsPlacement: 'below',
102
+ defaultValue: [COUNTRIES[0], COUNTRIES[2]],
103
+ },
104
+ };
105
+
106
+ export const WithGroups: Story = {
107
+ args: {
108
+ options: SPECIES,
109
+ placeholder: 'Select a species',
110
+ isClearable: true,
111
+ },
112
+ };
113
+
114
+ export const Disabled: Story = {
115
+ args: {
116
+ options: COUNTRIES,
117
+ placeholder: SELECT_A_COUNTRY,
118
+ isDisabled: true,
119
+ defaultValue: COUNTRIES[1],
120
+ },
121
+ };
122
+
123
+ export const Invalid: Story = {
124
+ parameters: {
125
+ docs: {
126
+ description: {
127
+ story: 'Pass `invalid` to show the error border. Clears when the control receives focus.',
128
+ },
129
+ },
130
+ },
131
+ render: () => (
132
+ <FormGroup invalid>
133
+ <Label htmlFor="select-invalid">Country</Label>
134
+
135
+ <ErrorText id="select-invalid-error">Select a country</ErrorText>
136
+
137
+ <Select
138
+ inputId="select-invalid"
139
+ aria-describedby="select-invalid-error"
140
+ options={COUNTRIES}
141
+ placeholder={SELECT_A_COUNTRY}
142
+ invalid
143
+ />
144
+ </FormGroup>
145
+ ),
146
+ };
147
+
148
+ export const NonSearchable: Story = {
149
+ parameters: {
150
+ docs: {
151
+ description: {
152
+ story:
153
+ 'Set `isSearchable={false}` for short lists where filtering adds no value. The cursor becomes a pointer to reinforce non-editable behaviour.',
154
+ },
155
+ },
156
+ },
157
+ args: {
158
+ options: COUNTRIES,
159
+ placeholder: 'Select a country',
160
+ isSearchable: false,
161
+ },
162
+ };
@@ -0,0 +1,36 @@
1
+ import { Select } from './Select';
2
+ import { render, screen } from '../../test/renderers';
3
+
4
+ const COUNTRIES = [
5
+ { value: 'eng', label: 'England' },
6
+ { value: 'sco', label: 'Scotland' },
7
+ ];
8
+
9
+ const ERROR_ID = 'country-error';
10
+
11
+ describe('Select', () => {
12
+ it('merges aria-describedby alongside react-select’s own value, rather than replacing it', () => {
13
+ render(
14
+ <Select
15
+ inputId="country"
16
+ options={COUNTRIES}
17
+ aria-describedby={ERROR_ID}
18
+ aria-label="Country"
19
+ />,
20
+ );
21
+
22
+ const describedBy = screen.getByRole('combobox').getAttribute('aria-describedby');
23
+
24
+ expect(describedBy).toContain(ERROR_ID);
25
+ // react-select's own placeholder/live-region id is still present, not replaced.
26
+ expect(describedBy?.split(' ').length).toBeGreaterThan(1);
27
+ });
28
+
29
+ it('omits the extra id when aria-describedby is not provided', () => {
30
+ render(<Select inputId="country" options={COUNTRIES} aria-label="Country" />);
31
+
32
+ const describedBy = screen.getByRole('combobox').getAttribute('aria-describedby');
33
+
34
+ expect(describedBy).not.toContain(ERROR_ID);
35
+ });
36
+ });