@okta/odyssey-react-mui 1.0.2 → 1.2.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 (274) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +1 -1
  3. package/dist/Autocomplete.js +20 -3
  4. package/dist/Autocomplete.js.map +1 -1
  5. package/dist/Banner.js +3 -1
  6. package/dist/Banner.js.map +1 -1
  7. package/dist/Box.js +8 -4
  8. package/dist/Box.js.map +1 -1
  9. package/dist/Button.js +3 -1
  10. package/dist/Button.js.map +1 -1
  11. package/dist/Callout.js +2 -0
  12. package/dist/Callout.js.map +1 -1
  13. package/dist/Checkbox.js +6 -2
  14. package/dist/Checkbox.js.map +1 -1
  15. package/dist/CheckboxGroup.js +5 -7
  16. package/dist/CheckboxGroup.js.map +1 -1
  17. package/dist/CircularProgress.js +2 -0
  18. package/dist/CircularProgress.js.map +1 -1
  19. package/dist/Dialog.js +2 -0
  20. package/dist/Dialog.js.map +1 -1
  21. package/dist/Field.js.map +1 -1
  22. package/dist/FieldError.js +2 -0
  23. package/dist/FieldError.js.map +1 -1
  24. package/dist/FieldHint.js +2 -0
  25. package/dist/FieldHint.js.map +1 -1
  26. package/dist/FieldLabel.js +3 -1
  27. package/dist/FieldLabel.js.map +1 -1
  28. package/dist/Fieldset.js +3 -1
  29. package/dist/Fieldset.js.map +1 -1
  30. package/dist/Form.js +5 -3
  31. package/dist/Form.js.map +1 -1
  32. package/dist/Link.js +3 -1
  33. package/dist/Link.js.map +1 -1
  34. package/dist/MenuButton.js +8 -2
  35. package/dist/MenuButton.js.map +1 -1
  36. package/dist/MenuItem.js +6 -2
  37. package/dist/MenuItem.js.map +1 -1
  38. package/dist/NativeSelect.js +3 -1
  39. package/dist/NativeSelect.js.map +1 -1
  40. package/dist/OdysseyCacheProvider.js +4 -1
  41. package/dist/OdysseyCacheProvider.js.map +1 -1
  42. package/dist/OdysseyProvider.js +12 -5
  43. package/dist/OdysseyProvider.js.map +1 -1
  44. package/dist/OdysseyThemeProvider.js +8 -7
  45. package/dist/OdysseyThemeProvider.js.map +1 -1
  46. package/dist/OdysseyTranslationProvider.js +1 -1
  47. package/dist/OdysseyTranslationProvider.js.map +1 -1
  48. package/dist/OdysseyTranslationProvider.types.js +1 -1
  49. package/dist/OdysseyTranslationProvider.types.js.map +1 -1
  50. package/dist/PasswordField.js +18 -9
  51. package/dist/PasswordField.js.map +1 -1
  52. package/dist/Radio.js +2 -0
  53. package/dist/Radio.js.map +1 -1
  54. package/dist/RadioGroup.js +5 -2
  55. package/dist/RadioGroup.js.map +1 -1
  56. package/dist/SearchField.js +11 -10
  57. package/dist/SearchField.js.map +1 -1
  58. package/dist/Select.js +39 -35
  59. package/dist/Select.js.map +1 -1
  60. package/dist/SeleniumProps.js +2 -0
  61. package/dist/SeleniumProps.js.map +1 -0
  62. package/dist/Status.js +4 -2
  63. package/dist/Status.js.map +1 -1
  64. package/dist/Tabs.js +11 -4
  65. package/dist/Tabs.js.map +1 -1
  66. package/dist/Tag.js +4 -2
  67. package/dist/Tag.js.map +1 -1
  68. package/dist/TagList.js +3 -1
  69. package/dist/TagList.js.map +1 -1
  70. package/dist/TextField.js +6 -2
  71. package/dist/TextField.js.map +1 -1
  72. package/dist/Toast.js +2 -0
  73. package/dist/Toast.js.map +1 -1
  74. package/dist/Tooltip.js +2 -0
  75. package/dist/Tooltip.js.map +1 -1
  76. package/dist/Typography.js +71 -59
  77. package/dist/Typography.js.map +1 -1
  78. package/dist/createShadowDom.js +26 -0
  79. package/dist/createShadowDom.js.map +1 -0
  80. package/dist/{OdysseyI18n.js → i18n.js} +5 -2
  81. package/dist/i18n.js.map +1 -0
  82. package/dist/index.js +1 -0
  83. package/dist/index.js.map +1 -1
  84. package/dist/labs/DatePicker.js +4 -2
  85. package/dist/labs/DatePicker.js.map +1 -1
  86. package/dist/labs/PaginatedTable.js +6 -4
  87. package/dist/labs/PaginatedTable.js.map +1 -1
  88. package/dist/labs/StaticTable.js +9 -4
  89. package/dist/labs/StaticTable.js.map +1 -1
  90. package/dist/labs/datePickerTheme.js +4 -2
  91. package/dist/labs/datePickerTheme.js.map +1 -1
  92. package/dist/properties/ts/odyssey-react-mui.js +2 -0
  93. package/dist/properties/ts/odyssey-react-mui.js.map +1 -1
  94. package/dist/src/Autocomplete.d.ts +29 -4
  95. package/dist/src/Autocomplete.d.ts.map +1 -1
  96. package/dist/src/Banner.d.ts +3 -2
  97. package/dist/src/Banner.d.ts.map +1 -1
  98. package/dist/src/Box.d.ts +9 -2
  99. package/dist/src/Box.d.ts.map +1 -1
  100. package/dist/src/Button.d.ts +3 -2
  101. package/dist/src/Button.d.ts.map +1 -1
  102. package/dist/src/Callout.d.ts +3 -2
  103. package/dist/src/Callout.d.ts.map +1 -1
  104. package/dist/src/Checkbox.d.ts +8 -3
  105. package/dist/src/Checkbox.d.ts.map +1 -1
  106. package/dist/src/CheckboxGroup.d.ts +3 -6
  107. package/dist/src/CheckboxGroup.d.ts.map +1 -1
  108. package/dist/src/CircularProgress.d.ts +3 -2
  109. package/dist/src/CircularProgress.d.ts.map +1 -1
  110. package/dist/src/Dialog.d.ts +3 -2
  111. package/dist/src/Dialog.d.ts.map +1 -1
  112. package/dist/src/Field.d.ts +2 -1
  113. package/dist/src/Field.d.ts.map +1 -1
  114. package/dist/src/FieldError.d.ts +3 -2
  115. package/dist/src/FieldError.d.ts.map +1 -1
  116. package/dist/src/FieldHint.d.ts +3 -2
  117. package/dist/src/FieldHint.d.ts.map +1 -1
  118. package/dist/src/FieldLabel.d.ts +3 -2
  119. package/dist/src/FieldLabel.d.ts.map +1 -1
  120. package/dist/src/Fieldset.d.ts +3 -2
  121. package/dist/src/Fieldset.d.ts.map +1 -1
  122. package/dist/src/Form.d.ts +3 -2
  123. package/dist/src/Form.d.ts.map +1 -1
  124. package/dist/src/Link.d.ts +3 -2
  125. package/dist/src/Link.d.ts.map +1 -1
  126. package/dist/src/MenuButton.d.ts +12 -3
  127. package/dist/src/MenuButton.d.ts.map +1 -1
  128. package/dist/src/MenuItem.d.ts +5 -4
  129. package/dist/src/MenuItem.d.ts.map +1 -1
  130. package/dist/src/NativeSelect.d.ts +56 -2
  131. package/dist/src/NativeSelect.d.ts.map +1 -1
  132. package/dist/src/OdysseyCacheProvider.d.ts +6 -1
  133. package/dist/src/OdysseyCacheProvider.d.ts.map +1 -1
  134. package/dist/src/OdysseyProvider.d.ts +1 -1
  135. package/dist/src/OdysseyProvider.d.ts.map +1 -1
  136. package/dist/src/OdysseyThemeProvider.d.ts +2 -1
  137. package/dist/src/OdysseyThemeProvider.d.ts.map +1 -1
  138. package/dist/src/OdysseyTranslationProvider.d.ts +1 -1
  139. package/dist/src/OdysseyTranslationProvider.d.ts.map +1 -1
  140. package/dist/src/OdysseyTranslationProvider.types.d.ts +1 -1
  141. package/dist/src/OdysseyTranslationProvider.types.d.ts.map +1 -1
  142. package/dist/src/PasswordField.d.ts +78 -2
  143. package/dist/src/PasswordField.d.ts.map +1 -1
  144. package/dist/src/Radio.d.ts +3 -2
  145. package/dist/src/Radio.d.ts.map +1 -1
  146. package/dist/src/RadioGroup.d.ts +8 -3
  147. package/dist/src/RadioGroup.d.ts.map +1 -1
  148. package/dist/src/SearchField.d.ts +58 -2
  149. package/dist/src/SearchField.d.ts.map +1 -1
  150. package/dist/src/Select.d.ts +7 -2
  151. package/dist/src/Select.d.ts.map +1 -1
  152. package/dist/src/SeleniumProps.d.ts +20 -0
  153. package/dist/src/SeleniumProps.d.ts.map +1 -0
  154. package/dist/src/Status.d.ts +3 -2
  155. package/dist/src/Status.d.ts.map +1 -1
  156. package/dist/src/Tabs.d.ts +9 -3
  157. package/dist/src/Tabs.d.ts.map +1 -1
  158. package/dist/src/Tag.d.ts +3 -2
  159. package/dist/src/Tag.d.ts.map +1 -1
  160. package/dist/src/TagList.d.ts +3 -2
  161. package/dist/src/TagList.d.ts.map +1 -1
  162. package/dist/src/TextField.d.ts +86 -2
  163. package/dist/src/TextField.d.ts.map +1 -1
  164. package/dist/src/Toast.d.ts +3 -2
  165. package/dist/src/Toast.d.ts.map +1 -1
  166. package/dist/src/Tooltip.d.ts +3 -2
  167. package/dist/src/Tooltip.d.ts.map +1 -1
  168. package/dist/src/Typography.d.ts +14 -49
  169. package/dist/src/Typography.d.ts.map +1 -1
  170. package/dist/src/createShadowDom.d.ts +16 -0
  171. package/dist/src/createShadowDom.d.ts.map +1 -0
  172. package/dist/src/{OdysseyI18n.d.ts → i18n.d.ts} +20 -2
  173. package/dist/src/i18n.d.ts.map +1 -0
  174. package/dist/src/index.d.ts +1 -0
  175. package/dist/src/index.d.ts.map +1 -1
  176. package/dist/src/labs/DatePicker.d.ts +5 -1
  177. package/dist/src/labs/DatePicker.d.ts.map +1 -1
  178. package/dist/src/labs/PaginatedTable.d.ts.map +1 -1
  179. package/dist/src/labs/StaticTable.d.ts.map +1 -1
  180. package/dist/src/properties/ts/odyssey-react-mui.d.ts +2 -0
  181. package/dist/src/properties/ts/odyssey-react-mui.d.ts.map +1 -1
  182. package/dist/src/theme/components.d.ts +4 -1
  183. package/dist/src/theme/components.d.ts.map +1 -1
  184. package/dist/src/theme/createOdysseyMuiTheme.d.ts +23 -0
  185. package/dist/src/theme/createOdysseyMuiTheme.d.ts.map +1 -0
  186. package/dist/src/theme/mixins.d.ts +3 -1
  187. package/dist/src/theme/mixins.d.ts.map +1 -1
  188. package/dist/src/theme/palette.d.ts +3 -1
  189. package/dist/src/theme/palette.d.ts.map +1 -1
  190. package/dist/src/theme/shape.d.ts +3 -1
  191. package/dist/src/theme/shape.d.ts.map +1 -1
  192. package/dist/src/theme/spacing.d.ts +3 -1
  193. package/dist/src/theme/spacing.d.ts.map +1 -1
  194. package/dist/src/theme/theme.d.ts +1 -8
  195. package/dist/src/theme/theme.d.ts.map +1 -1
  196. package/dist/src/theme/typography.d.ts +3 -1
  197. package/dist/src/theme/typography.d.ts.map +1 -1
  198. package/dist/theme/components.js +118 -73
  199. package/dist/theme/components.js.map +1 -1
  200. package/dist/theme/createOdysseyMuiTheme.js +51 -0
  201. package/dist/theme/createOdysseyMuiTheme.js.map +1 -0
  202. package/dist/theme/mixins.js +4 -1
  203. package/dist/theme/mixins.js.map +1 -1
  204. package/dist/theme/palette.js +4 -1
  205. package/dist/theme/palette.js.map +1 -1
  206. package/dist/theme/shape.js +4 -1
  207. package/dist/theme/shape.js.map +1 -1
  208. package/dist/theme/spacing.js +4 -1
  209. package/dist/theme/spacing.js.map +1 -1
  210. package/dist/theme/theme.js +1 -20
  211. package/dist/theme/theme.js.map +1 -1
  212. package/dist/theme/typography.js +4 -1
  213. package/dist/theme/typography.js.map +1 -1
  214. package/dist/tsconfig.production.tsbuildinfo +1 -1
  215. package/package.json +7 -6
  216. package/src/Autocomplete.tsx +56 -4
  217. package/src/Banner.tsx +11 -2
  218. package/src/Box.tsx +11 -5
  219. package/src/Button.tsx +6 -1
  220. package/src/Callout.tsx +5 -3
  221. package/src/Checkbox.tsx +14 -4
  222. package/src/CheckboxGroup.tsx +6 -10
  223. package/src/CircularProgress.tsx +5 -1
  224. package/src/Dialog.tsx +5 -2
  225. package/src/Field.tsx +2 -0
  226. package/src/FieldError.tsx +5 -3
  227. package/src/FieldHint.tsx +9 -3
  228. package/src/FieldLabel.tsx +5 -3
  229. package/src/Fieldset.tsx +4 -1
  230. package/src/Form.tsx +7 -4
  231. package/src/Link.tsx +18 -3
  232. package/src/MenuButton.tsx +33 -4
  233. package/src/MenuItem.tsx +11 -6
  234. package/src/NativeSelect.tsx +7 -2
  235. package/src/OdysseyCacheProvider.tsx +9 -1
  236. package/src/OdysseyProvider.tsx +18 -8
  237. package/src/OdysseyThemeProvider.tsx +12 -8
  238. package/src/OdysseyTranslationProvider.test.tsx +2 -2
  239. package/src/OdysseyTranslationProvider.tsx +1 -1
  240. package/src/OdysseyTranslationProvider.types.ts +1 -0
  241. package/src/PasswordField.tsx +37 -13
  242. package/src/Radio.tsx +5 -1
  243. package/src/RadioGroup.tsx +12 -4
  244. package/src/SearchField.tsx +23 -15
  245. package/src/Select.tsx +154 -149
  246. package/src/SeleniumProps.ts +20 -0
  247. package/src/Status.tsx +15 -3
  248. package/src/Tabs.tsx +18 -4
  249. package/src/Tag.tsx +12 -3
  250. package/src/TagList.tsx +4 -2
  251. package/src/TextField.tsx +14 -2
  252. package/src/Toast.tsx +4 -1
  253. package/src/Tooltip.tsx +4 -1
  254. package/src/Typography.tsx +76 -54
  255. package/src/createShadowDom.ts +46 -0
  256. package/src/{OdysseyI18n.ts → i18n.ts} +4 -2
  257. package/src/index.ts +1 -0
  258. package/src/labs/DatePicker.tsx +15 -7
  259. package/src/labs/PaginatedTable.tsx +12 -3
  260. package/src/labs/README.md +2 -2
  261. package/src/labs/StaticTable.tsx +13 -3
  262. package/src/labs/datePickerTheme.tsx +2 -2
  263. package/src/properties/odyssey-react-mui.properties +2 -0
  264. package/src/properties/ts/odyssey-react-mui.ts +1 -1
  265. package/src/theme/components.tsx +69 -18
  266. package/src/theme/createOdysseyMuiTheme.ts +47 -0
  267. package/src/theme/mixins.ts +5 -1
  268. package/src/theme/palette.ts +5 -3
  269. package/src/theme/shape.ts +5 -1
  270. package/src/theme/spacing.ts +5 -3
  271. package/src/theme/theme.ts +1 -26
  272. package/src/theme/typography.ts +5 -3
  273. package/dist/OdysseyI18n.js.map +0 -1
  274. package/dist/src/OdysseyI18n.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okta/odyssey-react-mui",
3
- "version": "1.0.2",
3
+ "version": "1.2.0",
4
4
  "description": "React MUI components for Odyssey, Okta's design system",
5
5
  "author": "Okta, Inc.",
6
6
  "license": "Apache-2.0",
@@ -43,24 +43,25 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@emotion/cache": "^11.10.5",
46
+ "@emotion/react": "^11.11.1",
47
+ "@emotion/styled": "^11.11.0",
46
48
  "@mui/icons-material": "^5.11.0",
47
49
  "@mui/lab": "^5.0.0-alpha.117",
48
50
  "@mui/material": "^5.12.3",
51
+ "@mui/system": "^5.14.9",
49
52
  "@mui/utils": "^5.11.2",
50
53
  "@mui/x-date-pickers": "^5.0.15",
51
- "@okta/odyssey-design-tokens": "1.0.2",
54
+ "@okta/odyssey-design-tokens": "1.2.0",
52
55
  "date-fns": "^2.30.0",
53
- "i18next": "^22.4.15",
56
+ "i18next": "^23.5.1",
54
57
  "material-react-table": "^1.14.0",
55
58
  "react-i18next": "^12.2.2",
56
59
  "ts-node": "^10.9.1",
57
60
  "word-wrap": "~1.2.5"
58
61
  },
59
62
  "peerDependencies": {
60
- "@emotion/react": "^11",
61
- "@emotion/styled": "^11",
62
63
  "react": ">=17 <19",
63
64
  "react-dom": ">=17 <19"
64
65
  },
65
- "gitHead": "06d0b602d3bf239b43a739dd3a63ec2fb7f0ba01"
66
+ "gitHead": "6dc7afd2fce73ec25b0566b0c59aeedf0738b925"
66
67
  }
@@ -18,12 +18,17 @@ import {
18
18
  import { memo, useCallback } from "react";
19
19
 
20
20
  import { Field } from "./Field";
21
+ import type { SeleniumProps } from "./SeleniumProps";
21
22
 
22
23
  export type AutocompleteProps<
23
24
  OptionType,
24
25
  HasMultipleChoices extends boolean | undefined,
25
26
  IsCustomValueAllowed extends boolean | undefined
26
27
  > = {
28
+ /**
29
+ * The error message for the Select
30
+ */
31
+ errorMessage?: string;
27
32
  /**
28
33
  * Enables multiple choice selection
29
34
  */
@@ -37,6 +42,10 @@ export type AutocompleteProps<
37
42
  * The hint text for the Autocomplete input
38
43
  */
39
44
  hint?: string;
45
+ /**
46
+ * The id attribute of the Select
47
+ */
48
+ id?: string;
40
49
  /**
41
50
  * Allows the input of custom values
42
51
  */
@@ -64,6 +73,10 @@ export type AutocompleteProps<
64
73
  undefined,
65
74
  IsCustomValueAllowed
66
75
  >["loading"];
76
+ /**
77
+ * If `true`, the `input` element is not required.
78
+ */
79
+ isOptional?: boolean;
67
80
  /**
68
81
  * Makes the Autocomplete input read-only
69
82
  */
@@ -78,7 +91,20 @@ export type AutocompleteProps<
78
91
  */
79
92
  label: string;
80
93
  /**
81
- * Callback fired when the value of the autocomplete input changes
94
+ * The name of the `input` element. Defaults to the `id` if not set.
95
+ */
96
+ name?: string;
97
+ /**
98
+ * Callback fired when the autocomplete loses focus.
99
+ */
100
+ onBlur?: MuiAutocompleteProps<
101
+ OptionType,
102
+ HasMultipleChoices,
103
+ undefined,
104
+ IsCustomValueAllowed
105
+ >["onBlur"];
106
+ /**
107
+ * Callback fired when a selection is made.
82
108
  */
83
109
  onChange?: MuiAutocompleteProps<
84
110
  OptionType,
@@ -87,7 +113,7 @@ export type AutocompleteProps<
87
113
  IsCustomValueAllowed
88
114
  >["onChange"];
89
115
  /**
90
- * Callback fired when the input value of the autocomplete input changes
116
+ * Callback fired when the textbox receives typed characters.
91
117
  */
92
118
  onInputChange?: MuiAutocompleteProps<
93
119
  OptionType,
@@ -95,6 +121,15 @@ export type AutocompleteProps<
95
121
  undefined,
96
122
  IsCustomValueAllowed
97
123
  >["onInputChange"];
124
+ /**
125
+ * Callback fired when the autocomplete gains focus.
126
+ */
127
+ onFocus?: MuiAutocompleteProps<
128
+ OptionType,
129
+ HasMultipleChoices,
130
+ undefined,
131
+ IsCustomValueAllowed
132
+ >["onFocus"];
98
133
  /**
99
134
  * The options for the Autocomplete input
100
135
  */
@@ -113,56 +148,73 @@ export type AutocompleteProps<
113
148
  undefined,
114
149
  IsCustomValueAllowed
115
150
  >["value"];
116
- };
151
+ } & SeleniumProps;
117
152
 
118
153
  const Autocomplete = <
119
154
  OptionType,
120
155
  HasMultipleChoices extends boolean | undefined,
121
156
  IsCustomValueAllowed extends boolean | undefined
122
157
  >({
158
+ errorMessage,
123
159
  hasMultipleChoices,
160
+ id: idOverride,
124
161
  isCustomValueAllowed,
125
162
  isDisabled,
126
163
  isLoading,
164
+ isOptional = false,
127
165
  isReadOnly,
128
166
  hint,
129
167
  label,
168
+ name: nameOverride,
169
+ onBlur,
130
170
  onChange,
131
171
  onInputChange,
172
+ onFocus,
132
173
  options,
133
174
  value,
175
+ testId,
134
176
  }: AutocompleteProps<OptionType, HasMultipleChoices, IsCustomValueAllowed>) => {
135
177
  const renderInput = useCallback(
136
178
  ({ InputLabelProps, InputProps, ...params }) => (
137
179
  <Field
180
+ errorMessage={errorMessage}
138
181
  fieldType="single"
139
182
  hasVisibleLabel
140
183
  id={InputLabelProps.htmlFor}
141
184
  hint={hint}
142
185
  label={label}
186
+ isOptional={isOptional}
143
187
  renderFieldComponent={({ ariaDescribedBy, id }) => (
144
188
  <InputBase
145
189
  {...params}
146
190
  {...InputProps}
147
191
  aria-describedby={ariaDescribedBy}
148
192
  id={id}
193
+ name={nameOverride ?? id}
194
+ required={!isOptional}
149
195
  />
150
196
  )}
151
197
  />
152
198
  ),
153
- [hint, label]
199
+ [errorMessage, hint, isOptional, label, nameOverride]
154
200
  );
155
201
 
156
202
  return (
157
203
  <MuiAutocomplete
158
204
  // AutoComplete is wrapped in a div within MUI which does not get the disabled attr. So this aria-disabled gets set in the div
159
205
  aria-disabled={isDisabled}
206
+ data-se={testId}
207
+ disableCloseOnSelect={hasMultipleChoices}
160
208
  disabled={isDisabled}
161
209
  freeSolo={isCustomValueAllowed}
210
+ filterSelectedOptions={true}
211
+ id={idOverride}
162
212
  loading={isLoading}
163
213
  multiple={hasMultipleChoices}
214
+ onBlur={onBlur}
164
215
  onChange={onChange}
165
216
  onInputChange={onInputChange}
217
+ onFocus={onFocus}
166
218
  options={options}
167
219
  readOnly={isReadOnly}
168
220
  renderInput={renderInput}
package/src/Banner.tsx CHANGED
@@ -16,6 +16,8 @@ import { ScreenReaderText } from "./ScreenReaderText";
16
16
  import { memo } from "react";
17
17
  import { useTranslation } from "react-i18next";
18
18
 
19
+ import type { SeleniumProps } from "./SeleniumProps";
20
+
19
21
  export const bannerRoleValues = ["status", "alert"] as const;
20
22
  export const bannerSeverityValues: AlertColor[] = [
21
23
  "success",
@@ -54,7 +56,7 @@ export type BannerProps = {
54
56
  * The text content of the alert
55
57
  */
56
58
  text: string;
57
- };
59
+ } & SeleniumProps;
58
60
 
59
61
  const Banner = ({
60
62
  linkUrl,
@@ -63,11 +65,18 @@ const Banner = ({
63
65
  role,
64
66
  severity,
65
67
  text,
68
+ testId,
66
69
  }: BannerProps) => {
67
70
  const { t } = useTranslation();
68
71
 
69
72
  return (
70
- <Alert onClose={onClose} role={role} severity={severity} variant="banner">
73
+ <Alert
74
+ data-se={testId}
75
+ onClose={onClose}
76
+ role={role}
77
+ severity={severity}
78
+ variant="banner"
79
+ >
71
80
  <ScreenReaderText>{t(`severity.${severity}`)}:</ScreenReaderText>
72
81
  <AlertTitle>{text}</AlertTitle>
73
82
  {linkUrl && (
package/src/Box.tsx CHANGED
@@ -11,25 +11,31 @@
11
11
  */
12
12
 
13
13
  import { Box as MuiBox, BoxProps as MuiBoxProps } from "@mui/material";
14
- import { ReactNode, forwardRef } from "react";
14
+ import { ReactNode, forwardRef, memo } from "react";
15
+
16
+ import type { SeleniumProps } from "./SeleniumProps";
15
17
 
16
18
  export type BoxProps = {
17
19
  children?: ReactNode;
18
20
  component?: MuiBoxProps["component"];
19
21
  id?: MuiBoxProps["id"];
20
22
  sx?: MuiBoxProps["sx"];
21
- };
23
+ } & SeleniumProps;
22
24
 
23
- export const Box = forwardRef<HTMLElement, BoxProps>(
24
- ({ children, component, id, sx }, ref) => (
25
+ const Box = forwardRef<HTMLElement, BoxProps>(
26
+ ({ children, component, id, sx, testId }, ref) => (
25
27
  <MuiBox
26
28
  ref={ref}
27
29
  children={children}
28
30
  component={component}
31
+ data-se={testId}
29
32
  id={id}
30
33
  sx={sx}
31
34
  />
32
35
  )
33
36
  );
34
37
 
35
- Box.displayName = "Box";
38
+ const MemoizedBox = memo(Box);
39
+ MemoizedBox.displayName = "Box";
40
+
41
+ export { MemoizedBox as Box };
package/src/Button.tsx CHANGED
@@ -16,6 +16,7 @@ import { memo, ReactElement, useCallback } from "react";
16
16
 
17
17
  import { MuiPropsContext, useMuiProps } from "./MuiPropsContext";
18
18
  import { Tooltip } from "./Tooltip";
19
+ import type { SeleniumProps } from "./SeleniumProps";
19
20
 
20
21
  export const buttonSizeValues = ["small", "medium", "large"] as const;
21
22
  export const buttonTypeValues = ["button", "submit", "reset"] as const;
@@ -100,7 +101,8 @@ export type ButtonProps = {
100
101
  label?: "" | undefined;
101
102
  startIcon?: ReactElement;
102
103
  }
103
- );
104
+ ) &
105
+ SeleniumProps;
104
106
 
105
107
  const Button = ({
106
108
  ariaDescribedBy,
@@ -114,6 +116,7 @@ const Button = ({
114
116
  onClick,
115
117
  size = "medium",
116
118
  startIcon,
119
+ testId,
117
120
  tooltipText,
118
121
  type = "button",
119
122
  variant,
@@ -127,6 +130,7 @@ const Button = ({
127
130
  aria-label={ariaLabel}
128
131
  aria-labelledby={ariaLabelledBy}
129
132
  aria-describedby={ariaDescribedBy}
133
+ data-se={testId}
130
134
  disabled={isDisabled}
131
135
  endIcon={endIcon}
132
136
  fullWidth={isFullWidth}
@@ -152,6 +156,7 @@ const Button = ({
152
156
  onClick,
153
157
  size,
154
158
  startIcon,
159
+ testId,
155
160
  type,
156
161
  variant,
157
162
  ]
package/src/Callout.tsx CHANGED
@@ -15,6 +15,8 @@ import { Alert, AlertTitle, Box } from "@mui/material";
15
15
  import { ScreenReaderText } from "./ScreenReaderText";
16
16
  import { useTranslation } from "react-i18next";
17
17
 
18
+ import type { SeleniumProps } from "./SeleniumProps";
19
+
18
20
  export const calloutRoleValues = ["status", "alert"] as const;
19
21
  export const calloutSeverityValues = [
20
22
  "success",
@@ -42,13 +44,13 @@ export type CalloutProps = {
42
44
  * The title of the Callout
43
45
  */
44
46
  title?: string;
45
- };
47
+ } & SeleniumProps;
46
48
 
47
- const Callout = ({ children, role, severity, title }: CalloutProps) => {
49
+ const Callout = ({ children, role, severity, testId, title }: CalloutProps) => {
48
50
  const { t } = useTranslation();
49
51
 
50
52
  return (
51
- <Alert role={role} severity={severity} variant="callout">
53
+ <Alert data-se={testId} role={role} severity={severity} variant="callout">
52
54
  <ScreenReaderText>{t(`severity.${severity}`)}: </ScreenReaderText>
53
55
  {title && <AlertTitle>{title}</AlertTitle>}
54
56
  <Box component="div">{children}</Box>
package/src/Checkbox.tsx CHANGED
@@ -19,6 +19,8 @@ import { Typography } from "./Typography";
19
19
  import { memo, useCallback, useMemo, useState } from "react";
20
20
  import { useTranslation } from "react-i18next";
21
21
 
22
+ import type { SeleniumProps } from "./SeleniumProps";
23
+
22
24
  export const checkboxValidityValues = ["valid", "invalid", "inherit"] as const;
23
25
 
24
26
  export type CheckboxProps = {
@@ -30,6 +32,10 @@ export type CheckboxProps = {
30
32
  * The ID of the element that labels the Checkbox
31
33
  */
32
34
  ariaLabelledBy?: string;
35
+ /**
36
+ * The id of the `input` element.
37
+ */
38
+ id?: string;
33
39
  /**
34
40
  * Determines whether the Checkbox is checked
35
41
  */
@@ -51,7 +57,7 @@ export type CheckboxProps = {
51
57
  */
52
58
  label?: string;
53
59
  /**
54
- * The name attribute of the Checkbox
60
+ * The name of the `input` element. Defaults to the `id` if not set.
55
61
  */
56
62
  name?: string;
57
63
  /**
@@ -66,18 +72,20 @@ export type CheckboxProps = {
66
72
  * The value attribute of the Checkbox
67
73
  */
68
74
  value?: string;
69
- };
75
+ } & SeleniumProps;
70
76
 
71
77
  const Checkbox = ({
72
78
  ariaLabel,
73
79
  ariaLabelledBy,
80
+ id: idOverride,
74
81
  isDefaultChecked = false,
75
82
  isDisabled,
76
83
  isIndeterminate,
77
84
  isRequired,
78
85
  label: labelProp,
79
- name,
86
+ name: nameOverride,
80
87
  onChange: onChangeProp,
88
+ testId,
81
89
  validity = "inherit",
82
90
  value,
83
91
  }: CheckboxProps) => {
@@ -122,9 +130,11 @@ const Checkbox = ({
122
130
  control={
123
131
  <MuiCheckbox indeterminate={isIndeterminate} required={isRequired} />
124
132
  }
133
+ data-se={testId}
125
134
  disabled={isDisabled}
135
+ id={idOverride}
126
136
  label={label}
127
- name={name}
137
+ name={nameOverride ?? idOverride}
128
138
  onChange={onChange}
129
139
  value={value}
130
140
  required={isRequired}
@@ -15,6 +15,7 @@ import { memo, ReactElement, useCallback } from "react";
15
15
 
16
16
  import { Checkbox } from "./Checkbox";
17
17
  import { Field } from "./Field";
18
+ import type { SeleniumProps } from "./SeleniumProps";
18
19
 
19
20
  export type CheckboxGroupProps = {
20
21
  /**
@@ -31,10 +32,6 @@ export type CheckboxGroupProps = {
31
32
  * The hint text for the CheckboxGroup
32
33
  */
33
34
  hint?: string;
34
- /**
35
- * The id of the `input` element. This will also be the input's `name` field.
36
- */
37
- id?: string;
38
35
  /**
39
36
  * If `true`, the CheckboxGroup is disabled
40
37
  */
@@ -47,24 +44,24 @@ export type CheckboxGroupProps = {
47
44
  * The label text for the CheckboxGroup
48
45
  */
49
46
  label: string;
50
- };
47
+ } & SeleniumProps;
51
48
 
52
49
  const CheckboxGroup = ({
53
50
  children,
54
51
  errorMessage,
55
52
  hint,
56
- id: idOverride,
57
53
  isDisabled,
58
54
  isRequired = false,
59
55
  label,
56
+ testId,
60
57
  }: CheckboxGroupProps) => {
61
58
  const renderFieldComponent = useCallback(
62
- ({ ariaDescribedBy, id }) => (
63
- <MuiFormGroup aria-describedby={ariaDescribedBy} id={id}>
59
+ ({ ariaDescribedBy }) => (
60
+ <MuiFormGroup aria-describedby={ariaDescribedBy} data-se={testId}>
64
61
  {children}
65
62
  </MuiFormGroup>
66
63
  ),
67
- [children]
64
+ [children, testId]
68
65
  );
69
66
 
70
67
  return (
@@ -73,7 +70,6 @@ const CheckboxGroup = ({
73
70
  fieldType="group"
74
71
  hasVisibleLabel={true}
75
72
  hint={hint}
76
- id={idOverride}
77
73
  isDisabled={isDisabled}
78
74
  isOptional={!isRequired}
79
75
  label={label}
@@ -12,6 +12,8 @@
12
12
 
13
13
  import { CircularProgress as MuiCircularProgress } from "@mui/material";
14
14
 
15
+ import type { SeleniumProps } from "./SeleniumProps";
16
+
15
17
  export type CircularProgressProps = {
16
18
  /**
17
19
  * The ARIA label for the progress spinner
@@ -22,13 +24,15 @@ export type CircularProgressProps = {
22
24
  * If undefined, the spinner will spin perpetually.
23
25
  */
24
26
  value?: number;
25
- };
27
+ } & SeleniumProps;
26
28
 
27
29
  export const CircularProgress = ({
28
30
  ariaLabel,
31
+ testId,
29
32
  value,
30
33
  }: CircularProgressProps) => (
31
34
  <MuiCircularProgress
35
+ data-se={testId}
32
36
  value={value}
33
37
  variant={value ? "determinate" : "indeterminate"}
34
38
  aria-label={ariaLabel}
package/src/Dialog.tsx CHANGED
@@ -28,6 +28,8 @@ import {
28
28
  ReactElement,
29
29
  } from "react";
30
30
 
31
+ import type { SeleniumProps } from "./SeleniumProps";
32
+
31
33
  export type DialogProps = {
32
34
  /**
33
35
  * An optional Button object to be situated in the Dialog footer. Should almost always be of variant `primary`.
@@ -58,7 +60,7 @@ export type DialogProps = {
58
60
  */
59
61
  title: string;
60
62
  ariaLabel: string;
61
- };
63
+ } & SeleniumProps;
62
64
 
63
65
  const Dialog = ({
64
66
  callToActionFirstComponent,
@@ -67,6 +69,7 @@ const Dialog = ({
67
69
  children,
68
70
  isOpen,
69
71
  onClose,
72
+ testId,
70
73
  title,
71
74
  ariaLabel,
72
75
  }: DialogProps) => {
@@ -103,7 +106,7 @@ const Dialog = ({
103
106
  );
104
107
 
105
108
  return (
106
- <MuiDialog open={isOpen} onClose={onClose}>
109
+ <MuiDialog data-se={testId} open={isOpen} onClose={onClose}>
107
110
  <DialogTitle>
108
111
  {title}
109
112
  <Button
package/src/Field.tsx CHANGED
@@ -76,9 +76,11 @@ export type FieldProps = {
76
76
  */
77
77
  renderFieldComponent: ({
78
78
  ariaDescribedBy,
79
+ dataSe,
79
80
  id,
80
81
  }: {
81
82
  ariaDescribedBy?: string;
83
+ dataSe?: string;
82
84
  id: string;
83
85
  }) => ReactElement;
84
86
  };
@@ -16,16 +16,18 @@ import { FormHelperText } from "@mui/material";
16
16
  import { ScreenReaderText } from "./ScreenReaderText";
17
17
  import { useTranslation } from "react-i18next";
18
18
 
19
+ import type { SeleniumProps } from "./SeleniumProps";
20
+
19
21
  export type FieldErrorProps = {
20
22
  id?: string;
21
23
  text: string;
22
- };
24
+ } & SeleniumProps;
23
25
 
24
- const FieldError = ({ id, text }: FieldErrorProps) => {
26
+ const FieldError = ({ id, testId, text }: FieldErrorProps) => {
25
27
  const { t } = useTranslation();
26
28
 
27
29
  return (
28
- <FormHelperText error id={id}>
30
+ <FormHelperText data-se={testId} error id={id}>
29
31
  <ScreenReaderText>{`${t(
30
32
  "fielderror.screenreader.text"
31
33
  )}:`}</ScreenReaderText>
package/src/FieldHint.tsx CHANGED
@@ -14,13 +14,19 @@ import { memo } from "react";
14
14
 
15
15
  import { FormHelperText } from "@mui/material";
16
16
 
17
+ import type { SeleniumProps } from "./SeleniumProps";
18
+
17
19
  export type FieldHintProps = {
18
20
  id?: string;
19
21
  text: string;
20
- };
22
+ } & SeleniumProps;
21
23
 
22
- const FieldHint = ({ id, text }: FieldHintProps) => {
23
- return <FormHelperText id={id}>{text}</FormHelperText>;
24
+ const FieldHint = ({ id, testId, text }: FieldHintProps) => {
25
+ return (
26
+ <FormHelperText data-se={testId} id={id}>
27
+ {text}
28
+ </FormHelperText>
29
+ );
24
30
  };
25
31
 
26
32
  const MemoizedFieldHint = memo(FieldHint);
@@ -16,6 +16,7 @@ import { memo, useMemo } from "react";
16
16
  import { useTranslation } from "react-i18next";
17
17
  import { ScreenReaderText } from "./ScreenReaderText";
18
18
  import { Subordinate } from "./Typography";
19
+ import type { SeleniumProps } from "./SeleniumProps";
19
20
 
20
21
  export type FieldLabelProps = {
21
22
  hasVisibleLabel: boolean;
@@ -23,27 +24,28 @@ export type FieldLabelProps = {
23
24
  inputId: string;
24
25
  isOptional: boolean;
25
26
  text: string;
26
- };
27
+ } & SeleniumProps;
27
28
 
28
29
  const FieldLabel = ({
29
30
  hasVisibleLabel,
30
31
  id,
31
32
  inputId,
32
33
  isOptional,
34
+ testId,
33
35
  text,
34
36
  }: FieldLabelProps) => {
35
37
  const { t } = useTranslation();
36
38
 
37
39
  const inputLabel = useMemo(
38
40
  () => (
39
- <MuiInputLabel htmlFor={inputId} id={id}>
41
+ <MuiInputLabel data-se={testId} htmlFor={inputId} id={id}>
40
42
  <span>{text}</span>
41
43
  {isOptional && (
42
44
  <Subordinate>{t("fieldlabel.optional.text")}</Subordinate>
43
45
  )}
44
46
  </MuiInputLabel>
45
47
  ),
46
- [id, inputId, isOptional, text, t]
48
+ [id, inputId, isOptional, testId, text, t]
47
49
  );
48
50
 
49
51
  return hasVisibleLabel ? (
package/src/Fieldset.tsx CHANGED
@@ -18,6 +18,7 @@ import { FieldsetContext } from "./FieldsetContext";
18
18
  import { Legend, Support } from "./Typography";
19
19
  import { useOdysseyDesignTokens } from "./OdysseyDesignTokensContext";
20
20
  import { useUniqueId } from "./useUniqueId";
21
+ import type { SeleniumProps } from "./SeleniumProps";
21
22
 
22
23
  export type FieldsetProps = {
23
24
  /**
@@ -48,7 +49,7 @@ export type FieldsetProps = {
48
49
  * The name associated with the group.
49
50
  */
50
51
  name?: string;
51
- };
52
+ } & SeleniumProps;
52
53
 
53
54
  const Fieldset = ({
54
55
  alert,
@@ -58,6 +59,7 @@ const Fieldset = ({
58
59
  isDisabled = false,
59
60
  legend,
60
61
  name,
62
+ testId,
61
63
  }: FieldsetProps) => {
62
64
  const odysseyDesignTokens = useOdysseyDesignTokens();
63
65
  const id = useUniqueId(idOverride);
@@ -72,6 +74,7 @@ const Fieldset = ({
72
74
  return (
73
75
  <Box
74
76
  component="fieldset"
77
+ data-se={testId}
75
78
  disabled={isDisabled}
76
79
  name={name}
77
80
  id={id}