@coopdigital/react 0.45.0 → 0.47.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 (207) hide show
  1. package/dist/components/AlertBanner/AlertBanner.d.ts +4 -2
  2. package/dist/components/AlertBanner/AlertBanner.js +2 -2
  3. package/dist/components/Author/Author.d.ts +4 -2
  4. package/dist/components/Author/Author.js +2 -2
  5. package/dist/components/Button/Button.d.ts +6 -4
  6. package/dist/components/Button/Button.js +4 -7
  7. package/dist/components/Card/Card.d.ts +4 -2
  8. package/dist/components/Card/Card.js +4 -4
  9. package/dist/components/Checkbox/Checkbox.d.ts +4 -2
  10. package/dist/components/Checkbox/Checkbox.js +2 -2
  11. package/dist/components/Expandable/Expandable.d.ts +4 -2
  12. package/dist/components/Expandable/Expandable.js +4 -4
  13. package/dist/components/Field/Field.d.ts +4 -2
  14. package/dist/components/Field/Field.js +7 -8
  15. package/dist/components/FieldMarkers/Error.d.ts +4 -2
  16. package/dist/components/FieldMarkers/Error.js +2 -2
  17. package/dist/components/FieldMarkers/Hint.d.ts +5 -3
  18. package/dist/components/FieldMarkers/Hint.js +2 -2
  19. package/dist/components/FieldMarkers/Label.d.ts +4 -2
  20. package/dist/components/FieldMarkers/Label.js +6 -2
  21. package/dist/components/FieldMarkers/Legend.d.ts +4 -2
  22. package/dist/components/FieldMarkers/Legend.js +2 -2
  23. package/dist/components/Fieldset/Fieldset.d.ts +4 -2
  24. package/dist/components/Fieldset/Fieldset.js +2 -4
  25. package/dist/components/Flourish/Flourish.d.ts +4 -2
  26. package/dist/components/Flourish/Flourish.js +2 -2
  27. package/dist/components/Icon/AddIcon.d.ts +1 -1
  28. package/dist/components/Icon/AddIcon.js +6 -5
  29. package/dist/components/Icon/ArrowDownIcon.d.ts +1 -1
  30. package/dist/components/Icon/ArrowDownIcon.js +6 -5
  31. package/dist/components/Icon/ArrowLeftIcon.d.ts +1 -1
  32. package/dist/components/Icon/ArrowLeftIcon.js +6 -5
  33. package/dist/components/Icon/ArrowRightIcon.d.ts +1 -1
  34. package/dist/components/Icon/ArrowRightIcon.js +6 -5
  35. package/dist/components/Icon/ArrowUpIcon.d.ts +1 -1
  36. package/dist/components/Icon/ArrowUpIcon.js +6 -5
  37. package/dist/components/Icon/AvatarAltIcon.d.ts +1 -1
  38. package/dist/components/Icon/AvatarAltIcon.js +6 -5
  39. package/dist/components/Icon/AvatarIcon.d.ts +1 -1
  40. package/dist/components/Icon/AvatarIcon.js +6 -5
  41. package/dist/components/Icon/BasketIcon.d.ts +1 -1
  42. package/dist/components/Icon/BasketIcon.js +6 -5
  43. package/dist/components/Icon/CalendarIcon.d.ts +1 -1
  44. package/dist/components/Icon/CalendarIcon.js +6 -5
  45. package/dist/components/Icon/ChevronDownIcon.d.ts +1 -1
  46. package/dist/components/Icon/ChevronDownIcon.js +6 -5
  47. package/dist/components/Icon/ChevronLeftIcon.d.ts +1 -1
  48. package/dist/components/Icon/ChevronLeftIcon.js +6 -5
  49. package/dist/components/Icon/ChevronRightIcon.d.ts +1 -1
  50. package/dist/components/Icon/ChevronRightIcon.js +6 -5
  51. package/dist/components/Icon/ChevronUpIcon.d.ts +1 -1
  52. package/dist/components/Icon/ChevronUpIcon.js +6 -5
  53. package/dist/components/Icon/ClockIcon.d.ts +1 -1
  54. package/dist/components/Icon/ClockIcon.js +6 -5
  55. package/dist/components/Icon/CloseAltIcon.d.ts +1 -1
  56. package/dist/components/Icon/CloseAltIcon.js +6 -5
  57. package/dist/components/Icon/CloseIcon.d.ts +1 -1
  58. package/dist/components/Icon/CloseIcon.js +6 -5
  59. package/dist/components/Icon/CoopCardIcon.d.ts +1 -1
  60. package/dist/components/Icon/CoopCardIcon.js +6 -5
  61. package/dist/components/Icon/CoopIcon.d.ts +1 -1
  62. package/dist/components/Icon/CoopIcon.js +6 -5
  63. package/dist/components/Icon/CoopLocationIcon.d.ts +1 -1
  64. package/dist/components/Icon/CoopLocationIcon.js +6 -5
  65. package/dist/components/Icon/DownloadIcon.d.ts +1 -1
  66. package/dist/components/Icon/DownloadIcon.js +6 -5
  67. package/dist/components/Icon/HomeIcon.d.ts +1 -1
  68. package/dist/components/Icon/HomeIcon.js +6 -5
  69. package/dist/components/Icon/InformationIcon.d.ts +1 -1
  70. package/dist/components/Icon/InformationIcon.js +6 -5
  71. package/dist/components/Icon/LoadingIcon.d.ts +1 -1
  72. package/dist/components/Icon/LoadingIcon.js +6 -5
  73. package/dist/components/Icon/LocationIcon.d.ts +1 -1
  74. package/dist/components/Icon/LocationIcon.js +6 -5
  75. package/dist/components/Icon/MailIcon.d.ts +1 -1
  76. package/dist/components/Icon/MailIcon.js +6 -5
  77. package/dist/components/Icon/MenuIcon.d.ts +1 -1
  78. package/dist/components/Icon/MenuIcon.js +6 -5
  79. package/dist/components/Icon/MessageIcon.d.ts +1 -1
  80. package/dist/components/Icon/MessageIcon.js +6 -5
  81. package/dist/components/Icon/MinusIcon.d.ts +1 -1
  82. package/dist/components/Icon/MinusIcon.js +6 -5
  83. package/dist/components/Icon/OpenNewIcon.d.ts +1 -1
  84. package/dist/components/Icon/OpenNewIcon.js +6 -5
  85. package/dist/components/Icon/PencilIcon.d.ts +1 -1
  86. package/dist/components/Icon/PencilIcon.js +6 -5
  87. package/dist/components/Icon/PhoneIcon.d.ts +1 -1
  88. package/dist/components/Icon/PhoneIcon.js +6 -5
  89. package/dist/components/Icon/QuestionIcon.d.ts +1 -1
  90. package/dist/components/Icon/QuestionIcon.js +6 -5
  91. package/dist/components/Icon/ScooterIcon.d.ts +1 -1
  92. package/dist/components/Icon/ScooterIcon.js +6 -5
  93. package/dist/components/Icon/SearchIcon.d.ts +1 -1
  94. package/dist/components/Icon/SearchIcon.js +6 -5
  95. package/dist/components/Icon/SettingsIcon.d.ts +1 -1
  96. package/dist/components/Icon/SettingsIcon.js +6 -5
  97. package/dist/components/Icon/TickAltIcon.d.ts +1 -1
  98. package/dist/components/Icon/TickAltIcon.js +6 -5
  99. package/dist/components/Icon/TickIcon.d.ts +1 -1
  100. package/dist/components/Icon/TickIcon.js +6 -5
  101. package/dist/components/Icon/VanIcon.d.ts +1 -1
  102. package/dist/components/Icon/VanIcon.js +6 -5
  103. package/dist/components/Icon/WarningIcon.d.ts +1 -1
  104. package/dist/components/Icon/WarningIcon.js +6 -5
  105. package/dist/components/Icon/WriteIcon.d.ts +1 -1
  106. package/dist/components/Icon/WriteIcon.js +6 -5
  107. package/dist/components/Image/Image.d.ts +4 -2
  108. package/dist/components/Image/Image.js +2 -2
  109. package/dist/components/Pill/Pill.d.ts +4 -2
  110. package/dist/components/Pill/Pill.js +7 -8
  111. package/dist/components/Radio/Radio.d.ts +20 -0
  112. package/dist/components/Radio/Radio.js +21 -0
  113. package/dist/components/Radio/index.d.ts +4 -0
  114. package/dist/components/{SearchBox/SearchBox.d.ts → Searchbox/Searchbox.d.ts} +10 -8
  115. package/dist/components/{SearchBox/SearchBox.js → Searchbox/Searchbox.js} +16 -11
  116. package/dist/components/Searchbox/index.d.ts +4 -0
  117. package/dist/components/Signpost/Signpost.d.ts +6 -4
  118. package/dist/components/Signpost/Signpost.js +3 -6
  119. package/dist/components/SkipNav/SkipNav.d.ts +4 -2
  120. package/dist/components/SkipNav/SkipNav.js +2 -2
  121. package/dist/components/Squircle/Squircle.d.ts +4 -2
  122. package/dist/components/Squircle/Squircle.js +2 -2
  123. package/dist/components/Tag/Tag.d.ts +5 -3
  124. package/dist/components/Tag/Tag.js +3 -6
  125. package/dist/components/TextInput/TextInput.d.ts +5 -3
  126. package/dist/components/TextInput/TextInput.js +2 -2
  127. package/dist/components/Textarea/Textarea.d.ts +4 -2
  128. package/dist/components/Textarea/Textarea.js +4 -5
  129. package/dist/{utils/slots.d.ts → hooks/useSlots.d.ts} +1 -1
  130. package/dist/{utils/slots.js → hooks/useSlots.js} +2 -2
  131. package/dist/index.d.ts +2 -2
  132. package/dist/index.js +2 -2
  133. package/package.json +3 -3
  134. package/src/components/AlertBanner/AlertBanner.tsx +6 -2
  135. package/src/components/Author/Author.tsx +5 -2
  136. package/src/components/Button/Button.tsx +10 -15
  137. package/src/components/Card/Card.tsx +7 -5
  138. package/src/components/Checkbox/Checkbox.tsx +6 -2
  139. package/src/components/Expandable/Expandable.tsx +12 -5
  140. package/src/components/Field/Field.tsx +10 -9
  141. package/src/components/FieldMarkers/Error.tsx +9 -3
  142. package/src/components/FieldMarkers/Hint.tsx +10 -4
  143. package/src/components/FieldMarkers/Label.tsx +9 -3
  144. package/src/components/FieldMarkers/Legend.tsx +9 -3
  145. package/src/components/Fieldset/Fieldset.tsx +9 -4
  146. package/src/components/Flourish/Flourish.tsx +5 -2
  147. package/src/components/Icon/AddIcon.tsx +9 -6
  148. package/src/components/Icon/ArrowDownIcon.tsx +9 -6
  149. package/src/components/Icon/ArrowLeftIcon.tsx +9 -6
  150. package/src/components/Icon/ArrowRightIcon.tsx +9 -6
  151. package/src/components/Icon/ArrowUpIcon.tsx +9 -6
  152. package/src/components/Icon/AvatarAltIcon.tsx +9 -6
  153. package/src/components/Icon/AvatarIcon.tsx +9 -6
  154. package/src/components/Icon/BasketIcon.tsx +9 -6
  155. package/src/components/Icon/CalendarIcon.tsx +9 -6
  156. package/src/components/Icon/ChevronDownIcon.tsx +9 -6
  157. package/src/components/Icon/ChevronLeftIcon.tsx +9 -6
  158. package/src/components/Icon/ChevronRightIcon.tsx +9 -6
  159. package/src/components/Icon/ChevronUpIcon.tsx +9 -6
  160. package/src/components/Icon/ClockIcon.tsx +9 -6
  161. package/src/components/Icon/CloseAltIcon.tsx +9 -6
  162. package/src/components/Icon/CloseIcon.tsx +9 -6
  163. package/src/components/Icon/CoopCardIcon.tsx +9 -6
  164. package/src/components/Icon/CoopIcon.tsx +9 -6
  165. package/src/components/Icon/CoopLocationIcon.tsx +9 -6
  166. package/src/components/Icon/DownloadIcon.tsx +9 -6
  167. package/src/components/Icon/HomeIcon.tsx +9 -6
  168. package/src/components/Icon/InformationIcon.tsx +9 -6
  169. package/src/components/Icon/LoadingIcon.tsx +9 -6
  170. package/src/components/Icon/LocationIcon.tsx +9 -6
  171. package/src/components/Icon/MailIcon.tsx +9 -6
  172. package/src/components/Icon/MenuIcon.tsx +9 -6
  173. package/src/components/Icon/MessageIcon.tsx +9 -6
  174. package/src/components/Icon/MinusIcon.tsx +9 -6
  175. package/src/components/Icon/OpenNewIcon.tsx +9 -6
  176. package/src/components/Icon/PencilIcon.tsx +9 -6
  177. package/src/components/Icon/PhoneIcon.tsx +9 -6
  178. package/src/components/Icon/QuestionIcon.tsx +9 -6
  179. package/src/components/Icon/ScooterIcon.tsx +9 -6
  180. package/src/components/Icon/SearchIcon.tsx +9 -6
  181. package/src/components/Icon/SettingsIcon.tsx +9 -6
  182. package/src/components/Icon/TickAltIcon.tsx +9 -6
  183. package/src/components/Icon/TickIcon.tsx +9 -6
  184. package/src/components/Icon/VanIcon.tsx +9 -6
  185. package/src/components/Icon/WarningIcon.tsx +9 -6
  186. package/src/components/Icon/WriteIcon.tsx +9 -6
  187. package/src/components/Image/Image.tsx +5 -2
  188. package/src/components/Pill/Pill.tsx +10 -9
  189. package/src/components/Radio/Radio.tsx +50 -0
  190. package/src/components/Radio/index.ts +5 -0
  191. package/src/components/{SearchBox/SearchBox.tsx → Searchbox/Searchbox.tsx} +33 -30
  192. package/src/components/Searchbox/index.ts +5 -0
  193. package/src/components/Signpost/Signpost.tsx +8 -8
  194. package/src/components/SkipNav/SkipNav.tsx +5 -2
  195. package/src/components/Squircle/Squircle.tsx +5 -2
  196. package/src/components/Tag/Tag.tsx +9 -8
  197. package/src/components/TextInput/TextInput.tsx +18 -3
  198. package/src/components/Textarea/Textarea.tsx +8 -6
  199. package/src/{utils/slots.ts → hooks/useSlots.ts} +1 -1
  200. package/src/index.ts +2 -2
  201. package/dist/components/RadioButton/RadioButton.d.ts +0 -18
  202. package/dist/components/RadioButton/RadioButton.js +0 -22
  203. package/dist/components/RadioButton/index.d.ts +0 -4
  204. package/dist/components/SearchBox/index.d.ts +0 -4
  205. package/src/components/RadioButton/RadioButton.tsx +0 -48
  206. package/src/components/RadioButton/index.ts +0 -5
  207. package/src/components/SearchBox/index.ts +0 -5
@@ -1,24 +1,27 @@
1
1
  import clsx from "clsx"
2
- import { type SVGProps, useId } from "react"
2
+ import { type SVGProps } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
3
5
 
4
6
  interface IconProps extends SVGProps<SVGSVGElement> {
5
7
  alt?: string
6
8
  }
7
9
 
8
- export const SearchIcon = ({ alt, className, fill, ...props }: IconProps) => {
9
- const id = useId()
10
+ export const SearchIcon = ({ alt, className, fill, id, ref, ...props }: IconProps) => {
11
+ const uid = useId(id)
10
12
  const componentProps = {
11
- "aria-labelledby": alt ? id : undefined,
13
+ "aria-labelledby": alt ? uid + "-title" : undefined,
12
14
  className: clsx("coop-icon", className),
13
15
  "data-icon": "search",
14
16
  fill: fill ?? "none",
17
+ id: uid,
15
18
  role: alt ? "img" : undefined,
16
19
  viewBox: "0 0 32 32",
17
20
  ...props,
18
21
  }
19
22
  return (
20
- <svg {...componentProps}>
21
- {alt ? <title id={id}>{alt}</title> : null}
23
+ <svg {...componentProps} ref={ref}>
24
+ {alt ? <title id={uid + "-title"}>{alt}</title> : null}
22
25
  <path
23
26
  d="M13.25 25.49a12.25 12.25 0 1 1 12.24-12.24 12.25 12.25 0 0 1-12.24 12.24m0-22.61a10.37 10.37 0 1 0 10.36 10.37A10.38 10.38 0 0 0 13.25 2.88"
24
27
  fill={fill ?? "currentColor"}
@@ -1,24 +1,27 @@
1
1
  import clsx from "clsx"
2
- import { type SVGProps, useId } from "react"
2
+ import { type SVGProps } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
3
5
 
4
6
  interface IconProps extends SVGProps<SVGSVGElement> {
5
7
  alt?: string
6
8
  }
7
9
 
8
- export const SettingsIcon = ({ alt, className, fill, ...props }: IconProps) => {
9
- const id = useId()
10
+ export const SettingsIcon = ({ alt, className, fill, id, ref, ...props }: IconProps) => {
11
+ const uid = useId(id)
10
12
  const componentProps = {
11
- "aria-labelledby": alt ? id : undefined,
13
+ "aria-labelledby": alt ? uid + "-title" : undefined,
12
14
  className: clsx("coop-icon", className),
13
15
  "data-icon": "settings",
14
16
  fill: fill ?? "none",
17
+ id: uid,
15
18
  role: alt ? "img" : undefined,
16
19
  viewBox: "0 0 32 32",
17
20
  ...props,
18
21
  }
19
22
  return (
20
- <svg {...componentProps}>
21
- {alt ? <title id={id}>{alt}</title> : null}
23
+ <svg {...componentProps} ref={ref}>
24
+ {alt ? <title id={uid + "-title"}>{alt}</title> : null}
22
25
  <path
23
26
  d="M16 2a14 14 0 0 1 2.13.16v3.57l1.34.47a10.2 10.2 0 0 1 3.27 1.89l1.08.91 1.23-.71 1.86-1.08a14 14 0 0 1 2.14 3.69L27.18 12l-1.18.7.26 1.39a10.6 10.6 0 0 1 0 3.8L26 19.28l1.23.71 1.88 1.09a14.2 14.2 0 0 1-2.14 3.69l-1.86-1.08-1.28-.69-1.07.92a10.6 10.6 0 0 1-3.3 1.9l-1.33.47v3.57A14 14 0 0 1 16 30a14 14 0 0 1-2.13-.16v-3.57l-1.34-.47a10.2 10.2 0 0 1-3.27-1.9L8.18 23 7 23.69l-1.91 1.08A14.1 14.1 0 0 1 3 21.08L4.82 20l1.23-.71-.26-1.39a10.6 10.6 0 0 1 0-3.8l.26-1.39L4.82 12 3 10.92a14.5 14.5 0 0 1 2.08-3.69l1.86 1.08L8.16 9l1.08-.9a10.6 10.6 0 0 1 3.3-1.9l1.33-.47V2.16A14 14 0 0 1 16 2m0 21a7 7 0 1 0-7-7 7 7 0 0 0 7 7m0-23a16 16 0 0 0-3.53.39.76.76 0 0 0-.6.75v3.18a12.7 12.7 0 0 0-3.93 2.26L5.2 5a.75.75 0 0 0-.38-.1.77.77 0 0 0-.57.25 15.9 15.9 0 0 0-3.53 6.1.78.78 0 0 0 .35.91l2.75 1.59a12.3 12.3 0 0 0 0 4.52l-2.75 1.58a.79.79 0 0 0-.35.9 16 16 0 0 0 3.53 6.11.8.8 0 0 0 .57.25.7.7 0 0 0 .38-.11L8 25.42a12.3 12.3 0 0 0 3.92 2.26v3.18a.77.77 0 0 0 .61.75A16.2 16.2 0 0 0 16 32a16 16 0 0 0 3.53-.39.76.76 0 0 0 .6-.75v-3.18a12.5 12.5 0 0 0 3.92-2.26L26.8 27a.79.79 0 0 0 1-.15 16 16 0 0 0 3.53-6.11.8.8 0 0 0-.36-.9l-2.75-1.59a12.8 12.8 0 0 0 0-4.53l2.75-1.59a.78.78 0 0 0 .35-.9 16.1 16.1 0 0 0-3.53-6.1.76.76 0 0 0-.57-.26.73.73 0 0 0-.42.13l-2.75 1.57a12.3 12.3 0 0 0-3.92-2.26V1.14a.77.77 0 0 0-.61-.75A16.2 16.2 0 0 0 16 0m0 21a5 5 0 1 1 5-5 5 5 0 0 1-5 5"
24
27
  fill={fill ?? "currentColor"}
@@ -1,24 +1,27 @@
1
1
  import clsx from "clsx"
2
- import { type SVGProps, useId } from "react"
2
+ import { type SVGProps } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
3
5
 
4
6
  interface IconProps extends SVGProps<SVGSVGElement> {
5
7
  alt?: string
6
8
  }
7
9
 
8
- export const TickAltIcon = ({ alt, className, fill, ...props }: IconProps) => {
9
- const id = useId()
10
+ export const TickAltIcon = ({ alt, className, fill, id, ref, ...props }: IconProps) => {
11
+ const uid = useId(id)
10
12
  const componentProps = {
11
- "aria-labelledby": alt ? id : undefined,
13
+ "aria-labelledby": alt ? uid + "-title" : undefined,
12
14
  className: clsx("coop-icon", className),
13
15
  "data-icon": "tick-alt",
14
16
  fill: fill ?? "none",
17
+ id: uid,
15
18
  role: alt ? "img" : undefined,
16
19
  viewBox: "0 0 32 32",
17
20
  ...props,
18
21
  }
19
22
  return (
20
- <svg {...componentProps}>
21
- {alt ? <title id={id}>{alt}</title> : null}
23
+ <svg {...componentProps} ref={ref}>
24
+ {alt ? <title id={uid + "-title"}>{alt}</title> : null}
22
25
  <path
23
26
  d="M12.7 22a1 1 0 0 1-.71-.29L8.3 18a1 1 0 0 1 0-1.42 1 1 0 0 1 1.41 0l3 3 9.41-9.38a1 1 0 0 1 1.42 0 1 1 0 0 1 0 1.41L13.4 21.69a1 1 0 0 1-.7.31"
24
27
  fill={fill ?? "currentColor"}
@@ -1,24 +1,27 @@
1
1
  import clsx from "clsx"
2
- import { type SVGProps, useId } from "react"
2
+ import { type SVGProps } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
3
5
 
4
6
  interface IconProps extends SVGProps<SVGSVGElement> {
5
7
  alt?: string
6
8
  }
7
9
 
8
- export const TickIcon = ({ alt, className, fill, ...props }: IconProps) => {
9
- const id = useId()
10
+ export const TickIcon = ({ alt, className, fill, id, ref, ...props }: IconProps) => {
11
+ const uid = useId(id)
10
12
  const componentProps = {
11
- "aria-labelledby": alt ? id : undefined,
13
+ "aria-labelledby": alt ? uid + "-title" : undefined,
12
14
  className: clsx("coop-icon", className),
13
15
  "data-icon": "tick",
14
16
  fill: fill ?? "none",
17
+ id: uid,
15
18
  role: alt ? "img" : undefined,
16
19
  viewBox: "0 0 32 32",
17
20
  ...props,
18
21
  }
19
22
  return (
20
- <svg {...componentProps}>
21
- {alt ? <title id={id}>{alt}</title> : null}
23
+ <svg {...componentProps} ref={ref}>
24
+ {alt ? <title id={uid + "-title"}>{alt}</title> : null}
22
25
  <path
23
26
  d="M10.41 26a1 1 0 0 1-.71-.3l-6.42-6.59a1 1 0 0 1 1.44-1.39l5.69 5.85L27.28 6.3a1 1 0 1 1 1.44 1.4l-17.59 18a1 1 0 0 1-.72.3"
24
27
  fill={fill ?? "currentColor"}
@@ -1,24 +1,27 @@
1
1
  import clsx from "clsx"
2
- import { type SVGProps, useId } from "react"
2
+ import { type SVGProps } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
3
5
 
4
6
  interface IconProps extends SVGProps<SVGSVGElement> {
5
7
  alt?: string
6
8
  }
7
9
 
8
- export const VanIcon = ({ alt, className, fill, ...props }: IconProps) => {
9
- const id = useId()
10
+ export const VanIcon = ({ alt, className, fill, id, ref, ...props }: IconProps) => {
11
+ const uid = useId(id)
10
12
  const componentProps = {
11
- "aria-labelledby": alt ? id : undefined,
13
+ "aria-labelledby": alt ? uid + "-title" : undefined,
12
14
  className: clsx("coop-icon", className),
13
15
  "data-icon": "van",
14
16
  fill: fill ?? "none",
17
+ id: uid,
15
18
  role: alt ? "img" : undefined,
16
19
  viewBox: "0 0 32 32",
17
20
  ...props,
18
21
  }
19
22
  return (
20
- <svg {...componentProps}>
21
- {alt ? <title id={id}>{alt}</title> : null}
23
+ <svg {...componentProps} ref={ref}>
24
+ {alt ? <title id={uid + "-title"}>{alt}</title> : null}
22
25
  <path
23
26
  d="M31.05 3H9.8a1 1 0 0 0-1 1v.2H3.06a1 1 0 0 0-1 .86L.89 12.64a1 1 0 0 0-.89 1v10a1 1 0 0 0 1 1h3a5 5 0 0 0 9.9 0H18a5 5 0 0 0 9.89 0h3.21a1 1 0 0 0 .72-.3 1 1 0 0 0 .18-.72V4a1 1 0 0 0-.95-1M3.91 6.24H8.8v6.38H2.93ZM8.92 27A3 3 0 0 1 6 24.71a2.9 2.9 0 0 1-.12-.83 3.1 3.1 0 0 1 .25-1.22 3 3 0 0 1 5.53 0 3.3 3.3 0 0 1 .24 1.22 3.3 3.3 0 0 1-.11.83A3 3 0 0 1 8.92 27M23 27a3 3 0 0 1-2.89-2.24 2.9 2.9 0 0 1-.12-.83 3.1 3.1 0 0 1 .25-1.22 3 3 0 0 1 5.53 0 3.3 3.3 0 0 1 .23 1.17 3.3 3.3 0 0 1-.11.83A3 3 0 0 1 23 27m4.87-4.29a5 5 0 0 0-9.74 0H13.8a5 5 0 0 0-9.75 0H2v-8h7.8a1 1 0 0 0 1-1V5.05H30v17.61Z"
24
27
  fill={fill ?? "currentColor"}
@@ -1,24 +1,27 @@
1
1
  import clsx from "clsx"
2
- import { type SVGProps, useId } from "react"
2
+ import { type SVGProps } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
3
5
 
4
6
  interface IconProps extends SVGProps<SVGSVGElement> {
5
7
  alt?: string
6
8
  }
7
9
 
8
- export const WarningIcon = ({ alt, className, fill, ...props }: IconProps) => {
9
- const id = useId()
10
+ export const WarningIcon = ({ alt, className, fill, id, ref, ...props }: IconProps) => {
11
+ const uid = useId(id)
10
12
  const componentProps = {
11
- "aria-labelledby": alt ? id : undefined,
13
+ "aria-labelledby": alt ? uid + "-title" : undefined,
12
14
  className: clsx("coop-icon", className),
13
15
  "data-icon": "warning",
14
16
  fill: fill ?? "none",
17
+ id: uid,
15
18
  role: alt ? "img" : undefined,
16
19
  viewBox: "0 0 32 32",
17
20
  ...props,
18
21
  }
19
22
  return (
20
- <svg {...componentProps}>
21
- {alt ? <title id={id}>{alt}</title> : null}
23
+ <svg {...componentProps} ref={ref}>
24
+ {alt ? <title id={uid + "-title"}>{alt}</title> : null}
22
25
  <path
23
26
  d="M2.35 28.08 16.06 4.46l13.71 23.62Zm29.32-.7L17.56 3.07A1.73 1.73 0 0 0 16.06 2a1.94 1.94 0 0 0-1.5 1.1L.35 27.38C-.45 28.77.15 30 1.85 30h28.32a1.6 1.6 0 0 0 1.5-2.62"
24
27
  fill={fill ?? "currentColor"}
@@ -1,24 +1,27 @@
1
1
  import clsx from "clsx"
2
- import { type SVGProps, useId } from "react"
2
+ import { type SVGProps } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
3
5
 
4
6
  interface IconProps extends SVGProps<SVGSVGElement> {
5
7
  alt?: string
6
8
  }
7
9
 
8
- export const WriteIcon = ({ alt, className, fill, ...props }: IconProps) => {
9
- const id = useId()
10
+ export const WriteIcon = ({ alt, className, fill, id, ref, ...props }: IconProps) => {
11
+ const uid = useId(id)
10
12
  const componentProps = {
11
- "aria-labelledby": alt ? id : undefined,
13
+ "aria-labelledby": alt ? uid + "-title" : undefined,
12
14
  className: clsx("coop-icon", className),
13
15
  "data-icon": "write",
14
16
  fill: fill ?? "none",
17
+ id: uid,
15
18
  role: alt ? "img" : undefined,
16
19
  viewBox: "0 0 32 32",
17
20
  ...props,
18
21
  }
19
22
  return (
20
- <svg {...componentProps}>
21
- {alt ? <title id={id}>{alt}</title> : null}
23
+ <svg {...componentProps} ref={ref}>
24
+ {alt ? <title id={uid + "-title"}>{alt}</title> : null}
22
25
  <path
23
26
  d="M19.67 10.13 17.9 11.9H7a1 1 0 0 1 0-2h12a1 1 0 0 1 .67.23M14.9 14.9l-2 2H7a1 1 0 0 1 0-2ZM20 15.9a1 1 0 0 1-1 1h-1.87l2-2a1 1 0 0 1 .82.59.85.85 0 0 1 .05.41M19 21.9H7a1 1 0 0 1 0-2h12a1 1 0 1 1 0 2"
24
27
  fill={fill ?? "currentColor"}
@@ -1,4 +1,4 @@
1
- import type { HTMLAttributes, JSX } from "react"
1
+ import type { HTMLAttributes, JSX, Ref } from "react"
2
2
 
3
3
  export interface ImageProps extends HTMLAttributes<HTMLImageElement> {
4
4
  /** Specify text to describe the image. Refer to Experience Library guidelines on writing good alt text. */
@@ -7,6 +7,8 @@ export interface ImageProps extends HTMLAttributes<HTMLImageElement> {
7
7
  crop?: "square" | "wide" | "none"
8
8
  /** **(Optional)** Specify the height of the image. */
9
9
  height?: string
10
+ /** **(Optional)** Specify a custom React ref for this component. */
11
+ ref?: Ref<HTMLImageElement>
10
12
  /** Specify the Image source URL. */
11
13
  src: string
12
14
  /** **(Optional)** Specify the width of the image. */
@@ -38,6 +40,7 @@ export const Image = ({
38
40
  alt,
39
41
  crop,
40
42
  height,
43
+ ref,
41
44
  src,
42
45
  width = "640",
43
46
  ...props
@@ -56,7 +59,7 @@ export const Image = ({
56
59
 
57
60
  return (
58
61
  <picture>
59
- <img alt={alt} loading="lazy" src={params.src} {...dimensions} {...props} />
62
+ <img alt={alt} loading="lazy" src={params.src} {...dimensions} {...props} ref={ref} />
60
63
  </picture>
61
64
  )
62
65
  }
@@ -1,11 +1,11 @@
1
- import type { ForwardRefExoticComponent, HTMLAttributes, JSX } from "react"
1
+ import type { ForwardRefExoticComponent, HTMLAttributes, JSX, Ref } from "react"
2
2
 
3
3
  import clsx from "clsx"
4
4
  import React from "react"
5
5
  import { StandardSizes } from "src/types"
6
6
 
7
+ import { useSlots } from "../../hooks/useSlots"
7
8
  import { hasUserBg } from "../../utils"
8
- import { getSlots } from "../../utils/slots"
9
9
 
10
10
  export interface PillProps extends HTMLAttributes<HTMLAnchorElement> {
11
11
  /** **(Optional)** Specify a custom element to override default `a` or `span`. */
@@ -17,6 +17,8 @@ export interface PillProps extends HTMLAttributes<HTMLAnchorElement> {
17
17
  className?: string
18
18
  /** **(Optional)** Specify the URL that the Pill component will link to when clicked. */
19
19
  href?: string
20
+ /** **(Optional)** Specify a custom React ref for this component. */
21
+ ref?: Ref<HTMLElement>
20
22
  /** **(Optional)** Specify the Pill size. */
21
23
  size?: StandardSizes
22
24
  }
@@ -38,16 +40,13 @@ export const Pill = ({
38
40
  children,
39
41
  className,
40
42
  href,
43
+ ref,
41
44
  size = "md",
42
45
  ...props
43
46
  }: PillProps): JSX.Element => {
44
- let element: PillProps["as"] = href ? "a" : "span"
47
+ const element: PillProps["as"] = as ?? (href ? "a" : "span")
45
48
 
46
- const slots = getSlots(componentSlots, children)
47
-
48
- if (as) {
49
- element = as
50
- }
49
+ const slots = useSlots(componentSlots, children)
51
50
 
52
51
  const componentProps = {
53
52
  className: clsx("coop-pill", !hasUserBg(className) && "bg-tint-grey", className),
@@ -56,7 +55,9 @@ export const Pill = ({
56
55
  ...props,
57
56
  }
58
57
 
59
- return React.createElement(element, { ...componentProps }, slots.PillBadge, slots.Children)
58
+ // https://github.com/facebook/react/issues/34775
59
+ // eslint-disable-next-line react-hooks/refs
60
+ return React.createElement(element, { ...componentProps, ref }, slots.PillBadge, slots.Children)
60
61
  }
61
62
 
62
63
  const PillBadge = ({ children, className }: PillBadgeProps) => {
@@ -0,0 +1,50 @@
1
+ import clsx from "clsx"
2
+ import { type InputHTMLAttributes, type JSX, Ref } from "react"
3
+
4
+ import { useId } from "../../hooks/useId"
5
+ import { StandardSizes } from "../../types"
6
+
7
+ export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
8
+ /** **(Optional)** Specify additional CSS classes to be applied to the component. */
9
+ className?: string
10
+ /** **(Optional)** Specify whether the Radio should be disabled. Refer to Experience Library guidance on disabled form controls and accessibility. */
11
+ disabled?: boolean
12
+ /** **(Optional)** Specify the Radio error state. */
13
+ error?: boolean
14
+ /** **(Optional)** Specify the Radio id. Will be auto-generated if not set. */
15
+ id?: string
16
+ /** Specify the Radio name. */
17
+ name: string
18
+ /** **(Optional)** Specify a custom React ref for this component. */
19
+ ref?: Ref<HTMLInputElement>
20
+ /** **(Optional)** Specify the Radio size. */
21
+ size?: StandardSizes
22
+ }
23
+
24
+ export const Radio = ({
25
+ className,
26
+ disabled,
27
+ error = false,
28
+ id,
29
+ name,
30
+ ref,
31
+ size = "md",
32
+ ...props
33
+ }: RadioProps): JSX.Element => {
34
+ const uid = useId(id)
35
+
36
+ const componentProps = {
37
+ className: clsx("coop-radio", className),
38
+ "data-error": error || undefined,
39
+ "data-size": size.length && size !== "md" ? size : undefined,
40
+ disabled,
41
+ id: uid,
42
+ name,
43
+ type: "radio",
44
+ ...props,
45
+ }
46
+ //const formItemProps = { "aria-disabled": disabled ? true : undefined }
47
+ return <input {...componentProps} ref={ref} />
48
+ }
49
+
50
+ export default Radio
@@ -0,0 +1,5 @@
1
+ import Radio from "./Radio"
2
+
3
+ export default Radio
4
+ export { Radio }
5
+ export * from "./Radio"
@@ -1,17 +1,18 @@
1
1
  "use client"
2
2
 
3
- import type { InputHTMLAttributes, JSX } from "react"
3
+ import type { InputHTMLAttributes, JSX, Ref } from "react"
4
4
 
5
5
  import clsx from "clsx"
6
- import React, { useCallback, useId, useState } from "react"
6
+ import React, { useCallback, useState } from "react"
7
7
 
8
- import { StandardSizes } from "../../../src/types"
8
+ import { useId } from "../../hooks/useId"
9
+ import { StandardSizes } from "../../types"
9
10
  import { Button, type ButtonProps } from "../Button"
10
11
  import { Label as FieldLabel } from "../FieldMarkers/Label"
11
12
  import { SearchIcon } from "../Icon"
12
13
  import TextInput, { TextInputProps } from "../TextInput"
13
14
 
14
- export interface SearchBoxProps
15
+ export interface SearchboxProps
15
16
  extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "type"> {
16
17
  /** **(Optional)** Specify a server endpoint to submit the form. Will be ignored if onSubmit is also set. */
17
18
  action?: string
@@ -27,13 +28,15 @@ export interface SearchBoxProps
27
28
  labelVisible?: boolean
28
29
  /** **(Optional)** Specify the TextInput name, also used as the URL search parameter. Defaults to `query`. */
29
30
  name?: string
30
- /** **(Optional)** Callback to run when the form is submitted. If this is an async function, it will be awaited and the SearchBox will be in a pending state until the promise is resolved. */
31
+ /** **(Optional)** Callback to run when the form is submitted. If this is an async function, it will be awaited and the Searchbox will be in a pending state until the promise is resolved. */
31
32
  onSubmit?: React.FormEventHandler<HTMLElement> | undefined
32
33
  /** **(Optional)** Specify the TextInput placeholder text Do not use in place of a form label. */
33
34
  placeholder?: string
34
- /** **(Optional)** Specify the SearchBox size. */
35
+ /** **(Optional)** Specify a custom React ref for this component. */
36
+ ref?: Ref<HTMLFormElement>
37
+ /** **(Optional)** Specify the Searchbox size. */
35
38
  size?: StandardSizes
36
- /** **(Optional)** Specify the SearchBox variant. */
39
+ /** **(Optional)** Specify the Searchbox variant. */
37
40
  variant?:
38
41
  | "green"
39
42
  | "blue"
@@ -45,12 +48,12 @@ export interface SearchBoxProps
45
48
  | "grey-ghost"
46
49
  }
47
50
 
48
- const defaultButtonProps: SearchBoxProps["button"] = {
51
+ const defaultButtonProps: SearchboxProps["button"] = {
49
52
  label: React.createElement(SearchIcon, { alt: "Search", stroke: "currentColor", strokeWidth: 2 }),
50
53
  loadingText: "",
51
54
  }
52
55
 
53
- export const SearchBox = ({
56
+ export const Searchbox = ({
54
57
  action,
55
58
  "aria-placeholder": ariaPlaceholder,
56
59
  autoCapitalize = "off",
@@ -64,14 +67,13 @@ export const SearchBox = ({
64
67
  name = "query",
65
68
  onSubmit,
66
69
  placeholder,
70
+ ref,
67
71
  size = "md",
68
72
  variant = "green",
69
73
  ...props
70
- }: SearchBoxProps): JSX.Element => {
74
+ }: SearchboxProps): JSX.Element => {
71
75
  const [isPending, setIsPending] = useState(false)
72
- const internalId = useId()
73
-
74
- id = id ?? internalId
76
+ const uid = useId(id)
75
77
 
76
78
  const handleSubmit = useCallback(
77
79
  async (event: React.FormEvent<HTMLFormElement>) => {
@@ -92,46 +94,47 @@ export const SearchBox = ({
92
94
 
93
95
  const formProps = {
94
96
  action: action ?? undefined,
95
- className: clsx("coop-search-box", className),
97
+ className: clsx("coop-searchbox", className),
96
98
  "data-size": size && size !== "md" ? size : undefined,
97
99
  "data-variant": variant.length && variant !== "green" ? variant : undefined,
100
+ id: uid,
98
101
  onSubmit: onSubmit ? handleSubmit : undefined,
99
102
  }
100
103
 
101
- const buttonProps = {
104
+ const buttonProps: ButtonProps = {
102
105
  className: button?.className,
103
106
  isLoading: isPending,
104
107
  loadingText: button?.loadingText ?? "",
105
- size: size as keyof ButtonProps["size"],
106
- variant: variant as keyof ButtonProps["variant"],
108
+ size,
109
+ variant,
107
110
  }
108
111
 
109
- const inputProps = {
112
+ const inputProps: TextInputProps = {
110
113
  "aria-placeholder": placeholder ?? ariaPlaceholder ?? undefined,
111
114
  autoCapitalize,
112
115
  autoComplete,
113
- id,
116
+ id: uid + "--input",
114
117
  name,
115
118
  placeholder,
116
- size: size as keyof TextInputProps["size"],
117
- type: "search" as keyof TextInputProps["type"],
119
+ size,
120
+ type: "search",
118
121
  ...props,
119
122
  }
120
123
 
124
+ const labelProps = {
125
+ htmlFor: uid + "--input",
126
+ isVisible: labelVisible,
127
+ }
128
+
121
129
  return (
122
- <form {...formProps}>
123
- {label && (
124
- <FieldLabel htmlFor={id} isVisible={labelVisible}>
125
- {label}
126
- </FieldLabel>
127
- )}
128
- <div className="coop-search-box--inner">
130
+ <form {...formProps} ref={ref}>
131
+ {label && <FieldLabel {...labelProps}>{label}</FieldLabel>}
132
+ <div className="coop-searchbox--inner">
129
133
  <TextInput {...inputProps} />
130
-
131
134
  <Button {...buttonProps}>{button.label}</Button>
132
135
  </div>
133
136
  </form>
134
137
  )
135
138
  }
136
139
 
137
- export default SearchBox
140
+ export default Searchbox
@@ -0,0 +1,5 @@
1
+ import Searchbox from "./Searchbox"
2
+
3
+ export default Searchbox
4
+ export { Searchbox }
5
+ export * from "./Searchbox"
@@ -1,4 +1,4 @@
1
- import type { AnchorHTMLAttributes, ForwardRefExoticComponent, HTMLAttributes, JSX } from "react"
1
+ import type { ForwardRefExoticComponent, HTMLAttributes, JSX, Ref } from "react"
2
2
 
3
3
  import clsx from "clsx"
4
4
  import React from "react"
@@ -9,7 +9,7 @@ import { Image, ImageProps } from "../Image"
9
9
  export interface SignpostProps extends HTMLAttributes<HTMLDivElement> {
10
10
  /** **(Optional)** Specify a custom element to override default `a`. */
11
11
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
- as?: React.FC<AnchorHTMLAttributes<HTMLElement>> | ForwardRefExoticComponent<any> | string
12
+ as?: React.FC<any> | ForwardRefExoticComponent<any> | string
13
13
  /** Main content inside the component. It can be any valid JSX or string. */
14
14
  children: React.ReactNode
15
15
  /** **(Optional)** Specify additional CSS classes to be applied to the component. */
@@ -17,9 +17,11 @@ export interface SignpostProps extends HTMLAttributes<HTMLDivElement> {
17
17
  /** **(Optional)** Specify the level of the Signpost heading. */
18
18
  headingLevel?: "h2" | "h3" | "h4" | "h5" | "h6"
19
19
  /** Specify the URL that the Signpost component will link to when clicked. */
20
- href: string
20
+ href?: string
21
21
  /** **(Optional)** Specify properties of the Signpost Image. */
22
22
  image?: ImageProps
23
+ /** **(Optional)** Specify a custom React ref for this component. */
24
+ ref?: Ref<HTMLDivElement>
23
25
  }
24
26
 
25
27
  export const Signpost = ({
@@ -29,12 +31,10 @@ export const Signpost = ({
29
31
  headingLevel = "h3",
30
32
  href,
31
33
  image,
34
+ ref,
32
35
  ...props
33
36
  }: SignpostProps): JSX.Element => {
34
- let element: SignpostProps["as"] = "a"
35
- if (as) {
36
- element = as
37
- }
37
+ const element: SignpostProps["as"] = as ?? "a"
38
38
 
39
39
  const componentProps = {
40
40
  className: clsx("coop-signpost", className),
@@ -42,7 +42,7 @@ export const Signpost = ({
42
42
  }
43
43
 
44
44
  return (
45
- <div {...componentProps}>
45
+ <div {...componentProps} ref={ref}>
46
46
  {image && <Image crop="wide" {...image} />}
47
47
  {React.createElement(
48
48
  element,
@@ -1,4 +1,4 @@
1
- import type { HTMLAttributes, JSX } from "react"
1
+ import type { HTMLAttributes, JSX, Ref } from "react"
2
2
 
3
3
  import clsx from "clsx"
4
4
 
@@ -15,6 +15,8 @@ export interface SkipNavProps extends HTMLAttributes<HTMLDivElement> {
15
15
  /** **(Optional)** Specify links to show in the SkipNav.
16
16
  * Each item needs a `href` and `label`. Defaults to a single link anchored to `#main`. */
17
17
  links?: SkipNavLink[]
18
+ /** **(Optional)** Specify a custom React ref for this component. */
19
+ ref?: Ref<HTMLDivElement>
18
20
  }
19
21
 
20
22
  const defaultLinks = [{ href: "#main", label: "Skip to main content" }]
@@ -23,6 +25,7 @@ export const SkipNav = ({
23
25
  className,
24
26
  isVisible = false,
25
27
  links = defaultLinks,
28
+ ref,
26
29
  ...props
27
30
  }: SkipNavProps): JSX.Element => {
28
31
  const componentProps = {
@@ -31,7 +34,7 @@ export const SkipNav = ({
31
34
  }
32
35
  const navLinks = links.length > 0 ? links : defaultLinks
33
36
  return (
34
- <nav {...componentProps}>
37
+ <nav {...componentProps} ref={ref}>
35
38
  <ul>
36
39
  {navLinks.map((link) => {
37
40
  const linkProps = {
@@ -1,4 +1,4 @@
1
- import type { HTMLAttributes, JSX } from "react"
1
+ import type { HTMLAttributes, JSX, Ref } from "react"
2
2
 
3
3
  import clsx from "clsx"
4
4
 
@@ -8,6 +8,8 @@ export interface SquircleProps extends HTMLAttributes<HTMLDivElement> {
8
8
  children?: React.ReactNode
9
9
  /** **(Optional)** Specify additional CSS classes to be applied to the component. */
10
10
  className?: string
11
+ /** **(Optional)** Specify a custom React ref for this component. */
12
+ ref?: Ref<HTMLDivElement>
11
13
  /** **(Optional)** Specify the Squircle size. */
12
14
  size?: "sm" | "md" | "lg"
13
15
  }
@@ -15,6 +17,7 @@ export interface SquircleProps extends HTMLAttributes<HTMLDivElement> {
15
17
  export const Squircle = ({
16
18
  children,
17
19
  className,
20
+ ref,
18
21
  size = "lg",
19
22
  ...props
20
23
  }: SquircleProps): JSX.Element => {
@@ -25,7 +28,7 @@ export const Squircle = ({
25
28
  }
26
29
 
27
30
  return (
28
- <figure {...componentProps}>
31
+ <figure {...componentProps} ref={ref}>
29
32
  <figcaption>{children}</figcaption>
30
33
  </figure>
31
34
  )