@okta/odyssey-react-mui 1.11.0 → 1.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/@types/react-augment.d.js.map +1 -1
- package/dist/Autocomplete.js +3 -3
- package/dist/Autocomplete.js.map +1 -1
- package/dist/Button.js +5 -6
- package/dist/Button.js.map +1 -1
- package/dist/Checkbox.js +8 -7
- package/dist/Checkbox.js.map +1 -1
- package/dist/Link.js +5 -6
- package/dist/Link.js.map +1 -1
- package/dist/NativeSelect.js +16 -4
- package/dist/NativeSelect.js.map +1 -1
- package/dist/PasswordField.js +6 -7
- package/dist/PasswordField.js.map +1 -1
- package/dist/Radio.js +8 -7
- package/dist/Radio.js.map +1 -1
- package/dist/Select.js +8 -7
- package/dist/Select.js.map +1 -1
- package/dist/TextField.js +6 -7
- package/dist/TextField.js.map +1 -1
- package/dist/Typography.js +5 -6
- package/dist/Typography.js.map +1 -1
- package/dist/inputUtils.js.map +1 -1
- package/dist/labs/Switch.js +3 -3
- package/dist/labs/Switch.js.map +1 -1
- package/dist/labs/VirtualizedAutocomplete.js +3 -3
- package/dist/labs/VirtualizedAutocomplete.js.map +1 -1
- package/dist/src/Autocomplete.d.ts.map +1 -1
- package/dist/src/Button.d.ts +4 -4
- package/dist/src/Button.d.ts.map +1 -1
- package/dist/src/Checkbox.d.ts +4 -4
- package/dist/src/Checkbox.d.ts.map +1 -1
- package/dist/src/Link.d.ts +4 -4
- package/dist/src/Link.d.ts.map +1 -1
- package/dist/src/NativeSelect.d.ts +12 -1
- package/dist/src/NativeSelect.d.ts.map +1 -1
- package/dist/src/PasswordField.d.ts +5 -5
- package/dist/src/PasswordField.d.ts.map +1 -1
- package/dist/src/Radio.d.ts +4 -4
- package/dist/src/Radio.d.ts.map +1 -1
- package/dist/src/Select.d.ts +4 -4
- package/dist/src/Select.d.ts.map +1 -1
- package/dist/src/TextField.d.ts +5 -5
- package/dist/src/TextField.d.ts.map +1 -1
- package/dist/src/Typography.d.ts +4 -4
- package/dist/src/Typography.d.ts.map +1 -1
- package/dist/src/inputUtils.d.ts +3 -0
- package/dist/src/inputUtils.d.ts.map +1 -1
- package/dist/src/labs/Switch.d.ts.map +1 -1
- package/dist/src/labs/VirtualizedAutocomplete.d.ts.map +1 -1
- package/dist/tsconfig.production.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/@types/react-augment.d.ts +8 -4
- package/src/Autocomplete.tsx +2 -1
- package/src/Button.tsx +8 -9
- package/src/Checkbox.tsx +15 -11
- package/src/Link.tsx +8 -9
- package/src/NativeSelect.tsx +33 -2
- package/src/PasswordField.tsx +9 -11
- package/src/Radio.tsx +16 -10
- package/src/Select.tsx +9 -10
- package/src/TextField.tsx +9 -11
- package/src/Typography.tsx +8 -9
- package/src/inputUtils.ts +4 -0
- package/src/labs/Switch.tsx +2 -1
- package/src/labs/VirtualizedAutocomplete.tsx +10 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okta/odyssey-react-mui",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.1",
|
|
4
4
|
"description": "React MUI components for Odyssey, Okta's design system",
|
|
5
5
|
"author": "Okta, Inc.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@mui/system": "^5.14.9",
|
|
52
52
|
"@mui/utils": "^5.11.2",
|
|
53
53
|
"@mui/x-date-pickers": "^5.0.15",
|
|
54
|
-
"@okta/odyssey-design-tokens": "1.11.
|
|
54
|
+
"@okta/odyssey-design-tokens": "1.11.1",
|
|
55
55
|
"date-fns": "^2.30.0",
|
|
56
56
|
"i18next": "^23.5.1",
|
|
57
57
|
"material-react-table": "^2.0.2",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"react": ">=17 <19",
|
|
64
64
|
"react-dom": ">=17 <19"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "3318d342f74b82e7b957bf881007fe0f78556635"
|
|
67
67
|
}
|
|
@@ -11,13 +11,17 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { FC } from "react";
|
|
14
|
-
|
|
15
14
|
export interface ForwardRefWithType extends FC<WithForwardRefProps<Option>> {
|
|
16
15
|
<T extends Option>(props: WithForwardRefProps<T>): ReturnType<
|
|
17
16
|
FC<WithForwardRefProps<T>>
|
|
18
17
|
>;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
declare module "react" {
|
|
21
|
+
type DataAttributeKey = `data-${string}`;
|
|
22
|
+
interface InputHTMLAttributes<T> extends HTMLAttributes<T> {
|
|
23
|
+
// Allows data-* props to be passed to inputProps in nested MUI components
|
|
24
|
+
// see: https://github.com/mui/material-ui/issues/20160
|
|
25
|
+
[dataAttribute: DataAttributeKey]: string | undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/Autocomplete.tsx
CHANGED
|
@@ -267,6 +267,7 @@ const Autocomplete = <
|
|
|
267
267
|
...params.inputProps,
|
|
268
268
|
"aria-errormessage": errorMessageElementId,
|
|
269
269
|
"aria-labelledby": labelElementId,
|
|
270
|
+
"data-se": testId,
|
|
270
271
|
}}
|
|
271
272
|
aria-describedby={ariaDescribedBy}
|
|
272
273
|
id={id}
|
|
@@ -284,6 +285,7 @@ const Autocomplete = <
|
|
|
284
285
|
isOptional,
|
|
285
286
|
label,
|
|
286
287
|
nameOverride,
|
|
288
|
+
testId,
|
|
287
289
|
]
|
|
288
290
|
);
|
|
289
291
|
const onChange = useCallback<
|
|
@@ -324,7 +326,6 @@ const Autocomplete = <
|
|
|
324
326
|
{...inputValueProp}
|
|
325
327
|
// AutoComplete is wrapped in a div within MUI which does not get the disabled attr. So this aria-disabled gets set in the div
|
|
326
328
|
aria-disabled={isDisabled}
|
|
327
|
-
data-se={testId}
|
|
328
329
|
disableCloseOnSelect={hasMultipleChoices}
|
|
329
330
|
disabled={isDisabled}
|
|
330
331
|
freeSolo={isCustomValueAllowed}
|
package/src/Button.tsx
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
import { MuiPropsContext, useMuiProps } from "./MuiPropsContext";
|
|
24
24
|
import { Tooltip } from "./Tooltip";
|
|
25
25
|
import type { AllowedProps } from "./AllowedProps";
|
|
26
|
-
import { FocusHandle } from "
|
|
26
|
+
import { FocusHandle } from "./inputUtils";
|
|
27
27
|
|
|
28
28
|
export const buttonSizeValues = ["small", "medium", "large"] as const;
|
|
29
29
|
export const buttonTypeValues = ["button", "submit", "reset"] as const;
|
|
@@ -49,9 +49,9 @@ export type ButtonProps = {
|
|
|
49
49
|
*/
|
|
50
50
|
ariaDescribedBy?: string;
|
|
51
51
|
/**
|
|
52
|
-
* The ref forwarded to the Button
|
|
52
|
+
* The ref forwarded to the Button
|
|
53
53
|
*/
|
|
54
|
-
|
|
54
|
+
buttonRef?: React.RefObject<FocusHandle>;
|
|
55
55
|
/**
|
|
56
56
|
* The icon element to display at the end of the Button
|
|
57
57
|
*/
|
|
@@ -119,7 +119,7 @@ const Button = ({
|
|
|
119
119
|
ariaDescribedBy,
|
|
120
120
|
ariaLabel,
|
|
121
121
|
ariaLabelledBy,
|
|
122
|
-
|
|
122
|
+
buttonRef,
|
|
123
123
|
endIcon,
|
|
124
124
|
id,
|
|
125
125
|
isDisabled,
|
|
@@ -136,14 +136,13 @@ const Button = ({
|
|
|
136
136
|
}: ButtonProps) => {
|
|
137
137
|
const muiProps = useMuiProps();
|
|
138
138
|
|
|
139
|
-
const
|
|
139
|
+
const localButtonRef = useRef<HTMLButtonElement>(null);
|
|
140
140
|
useImperativeHandle(
|
|
141
|
-
|
|
141
|
+
buttonRef,
|
|
142
142
|
() => {
|
|
143
|
-
const element = ref.current;
|
|
144
143
|
return {
|
|
145
144
|
focus: () => {
|
|
146
|
-
|
|
145
|
+
localButtonRef.current?.focus();
|
|
147
146
|
},
|
|
148
147
|
};
|
|
149
148
|
},
|
|
@@ -163,7 +162,7 @@ const Button = ({
|
|
|
163
162
|
fullWidth={isFullWidth}
|
|
164
163
|
id={id}
|
|
165
164
|
onClick={onClick}
|
|
166
|
-
ref={
|
|
165
|
+
ref={localButtonRef}
|
|
167
166
|
size={size}
|
|
168
167
|
startIcon={startIcon}
|
|
169
168
|
translate={translate}
|
package/src/Checkbox.tsx
CHANGED
|
@@ -23,9 +23,12 @@ import {
|
|
|
23
23
|
import { FieldComponentProps } from "./FieldComponentProps";
|
|
24
24
|
import { Typography } from "./Typography";
|
|
25
25
|
import type { AllowedProps } from "./AllowedProps";
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
ComponentControlledState,
|
|
28
|
+
FocusHandle,
|
|
29
|
+
getControlState,
|
|
30
|
+
} from "./inputUtils";
|
|
27
31
|
import { CheckedFieldProps } from "./FormCheckedProps";
|
|
28
|
-
import { FocusHandle } from "./@types/react-augment";
|
|
29
32
|
|
|
30
33
|
export const checkboxValidityValues = ["valid", "invalid", "inherit"] as const;
|
|
31
34
|
|
|
@@ -43,9 +46,9 @@ export type CheckboxProps = {
|
|
|
43
46
|
*/
|
|
44
47
|
id?: string;
|
|
45
48
|
/**
|
|
46
|
-
* The ref forwarded to the Checkbox
|
|
49
|
+
* The ref forwarded to the Checkbox
|
|
47
50
|
*/
|
|
48
|
-
|
|
51
|
+
inputRef?: React.RefObject<FocusHandle>;
|
|
49
52
|
/**
|
|
50
53
|
* Determines whether the Checkbox is disabled
|
|
51
54
|
*/
|
|
@@ -86,7 +89,7 @@ const Checkbox = ({
|
|
|
86
89
|
ariaLabel,
|
|
87
90
|
ariaLabelledBy,
|
|
88
91
|
id: idOverride,
|
|
89
|
-
|
|
92
|
+
inputRef,
|
|
90
93
|
isChecked,
|
|
91
94
|
isDefaultChecked,
|
|
92
95
|
isDisabled,
|
|
@@ -116,14 +119,13 @@ const Checkbox = ({
|
|
|
116
119
|
return { defaultChecked: isDefaultChecked };
|
|
117
120
|
}, [isDefaultChecked, isChecked]);
|
|
118
121
|
|
|
119
|
-
const
|
|
122
|
+
const localInputRef = useRef<HTMLInputElement>(null);
|
|
120
123
|
useImperativeHandle(
|
|
121
|
-
|
|
124
|
+
inputRef,
|
|
122
125
|
() => {
|
|
123
|
-
const element = inputRef.current;
|
|
124
126
|
return {
|
|
125
127
|
focus: () => {
|
|
126
|
-
|
|
128
|
+
localInputRef.current?.focus();
|
|
127
129
|
},
|
|
128
130
|
};
|
|
129
131
|
},
|
|
@@ -179,13 +181,15 @@ const Checkbox = ({
|
|
|
179
181
|
indeterminate={isIndeterminate}
|
|
180
182
|
onChange={onChange}
|
|
181
183
|
required={isRequired}
|
|
182
|
-
|
|
184
|
+
inputProps={{
|
|
185
|
+
"data-se": testId,
|
|
186
|
+
}}
|
|
187
|
+
inputRef={localInputRef}
|
|
183
188
|
sx={() => ({
|
|
184
189
|
marginBlockStart: "2px",
|
|
185
190
|
})}
|
|
186
191
|
/>
|
|
187
192
|
}
|
|
188
|
-
data-se={testId}
|
|
189
193
|
disabled={isDisabled}
|
|
190
194
|
id={idOverride}
|
|
191
195
|
label={label}
|
package/src/Link.tsx
CHANGED
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
import { memo, ReactElement, useImperativeHandle, useRef } from "react";
|
|
14
14
|
import { ExternalLinkIcon } from "./icons.generated";
|
|
15
15
|
import type { AllowedProps } from "./AllowedProps";
|
|
16
|
+
import { FocusHandle } from "./inputUtils";
|
|
16
17
|
|
|
17
18
|
import { Link as MuiLink, LinkProps as MuiLinkProps } from "@mui/material";
|
|
18
|
-
import { FocusHandle } from "./@types/react-augment";
|
|
19
19
|
|
|
20
20
|
export const linkVariantValues = ["default", "monochrome"] as const;
|
|
21
21
|
|
|
@@ -33,9 +33,9 @@ export type LinkProps = {
|
|
|
33
33
|
*/
|
|
34
34
|
icon?: ReactElement;
|
|
35
35
|
/**
|
|
36
|
-
* The ref forwarded to the TextField
|
|
36
|
+
* The ref forwarded to the TextField
|
|
37
37
|
*/
|
|
38
|
-
|
|
38
|
+
linkRef?: React.RefObject<FocusHandle>;
|
|
39
39
|
/**
|
|
40
40
|
* The click event handler for the Link
|
|
41
41
|
*/
|
|
@@ -63,7 +63,7 @@ const Link = ({
|
|
|
63
63
|
children,
|
|
64
64
|
href,
|
|
65
65
|
icon,
|
|
66
|
-
|
|
66
|
+
linkRef,
|
|
67
67
|
rel,
|
|
68
68
|
target,
|
|
69
69
|
testId,
|
|
@@ -71,14 +71,13 @@ const Link = ({
|
|
|
71
71
|
variant,
|
|
72
72
|
onClick,
|
|
73
73
|
}: LinkProps) => {
|
|
74
|
-
const
|
|
74
|
+
const localLinkRef = useRef<HTMLAnchorElement>(null);
|
|
75
75
|
useImperativeHandle(
|
|
76
|
-
|
|
76
|
+
linkRef,
|
|
77
77
|
() => {
|
|
78
|
-
const element = ref.current;
|
|
79
78
|
return {
|
|
80
79
|
focus: () => {
|
|
81
|
-
|
|
80
|
+
localLinkRef.current?.focus();
|
|
82
81
|
},
|
|
83
82
|
};
|
|
84
83
|
},
|
|
@@ -89,7 +88,7 @@ const Link = ({
|
|
|
89
88
|
<MuiLink
|
|
90
89
|
data-se={testId}
|
|
91
90
|
href={href}
|
|
92
|
-
ref={
|
|
91
|
+
ref={localLinkRef}
|
|
93
92
|
rel={rel}
|
|
94
93
|
target={target}
|
|
95
94
|
translate={translate}
|
package/src/NativeSelect.tsx
CHANGED
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import React, {
|
|
14
|
+
InputHTMLAttributes,
|
|
14
15
|
ReactElement,
|
|
15
16
|
forwardRef,
|
|
16
17
|
memo,
|
|
17
18
|
useCallback,
|
|
19
|
+
useImperativeHandle,
|
|
18
20
|
useMemo,
|
|
19
21
|
useRef,
|
|
20
22
|
} from "react";
|
|
@@ -25,7 +27,7 @@ import {
|
|
|
25
27
|
import { Field } from "./Field";
|
|
26
28
|
import { FieldComponentProps } from "./FieldComponentProps";
|
|
27
29
|
import type { AllowedProps } from "./AllowedProps";
|
|
28
|
-
import { getControlState, useInputValues } from "./inputUtils";
|
|
30
|
+
import { FocusHandle, getControlState, useInputValues } from "./inputUtils";
|
|
29
31
|
import { ForwardRefWithType } from "./@types/react-augment";
|
|
30
32
|
|
|
31
33
|
export type NativeSelectOption = {
|
|
@@ -41,6 +43,12 @@ export type NativeSelectProps<
|
|
|
41
43
|
Value extends NativeSelectValueType<HasMultipleChoices>,
|
|
42
44
|
HasMultipleChoices extends boolean
|
|
43
45
|
> = {
|
|
46
|
+
/**
|
|
47
|
+
* This prop helps users to fill forms faster, especially on mobile devices.
|
|
48
|
+
* The name can be confusing, as it's more like an autofill.
|
|
49
|
+
* @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill
|
|
50
|
+
*/
|
|
51
|
+
autoCompleteType?: InputHTMLAttributes<HTMLInputElement>["autoComplete"];
|
|
44
52
|
/**
|
|
45
53
|
* The options or optgroup elements within the NativeSelect
|
|
46
54
|
*/
|
|
@@ -53,6 +61,10 @@ export type NativeSelectProps<
|
|
|
53
61
|
* If `true`, the Select allows multiple selections
|
|
54
62
|
*/
|
|
55
63
|
hasMultipleChoices?: HasMultipleChoices;
|
|
64
|
+
/**
|
|
65
|
+
* The ref forwarded to the NativeSelect
|
|
66
|
+
*/
|
|
67
|
+
inputRef?: React.RefObject<FocusHandle>;
|
|
56
68
|
/**
|
|
57
69
|
* @deprecated Use `hasMultipleChoices` instead
|
|
58
70
|
*/
|
|
@@ -98,6 +110,7 @@ const NativeSelect: ForwardRefWithType = forwardRef(
|
|
|
98
110
|
HasMultipleChoices extends boolean
|
|
99
111
|
>(
|
|
100
112
|
{
|
|
113
|
+
autoCompleteType,
|
|
101
114
|
defaultValue,
|
|
102
115
|
errorMessage,
|
|
103
116
|
errorMessageList,
|
|
@@ -105,6 +118,7 @@ const NativeSelect: ForwardRefWithType = forwardRef(
|
|
|
105
118
|
hint,
|
|
106
119
|
HintLinkComponent,
|
|
107
120
|
id: idOverride,
|
|
121
|
+
inputRef,
|
|
108
122
|
isDisabled = false,
|
|
109
123
|
isFullWidth = false,
|
|
110
124
|
isMultiSelect,
|
|
@@ -126,6 +140,20 @@ const NativeSelect: ForwardRefWithType = forwardRef(
|
|
|
126
140
|
uncontrolledValue: defaultValue,
|
|
127
141
|
})
|
|
128
142
|
);
|
|
143
|
+
const localInputRef = useRef<HTMLSelectElement>(null);
|
|
144
|
+
|
|
145
|
+
useImperativeHandle(
|
|
146
|
+
inputRef,
|
|
147
|
+
() => {
|
|
148
|
+
return {
|
|
149
|
+
focus: () => {
|
|
150
|
+
localInputRef.current?.focus();
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
[]
|
|
155
|
+
);
|
|
156
|
+
|
|
129
157
|
const inputValues = useInputValues({
|
|
130
158
|
defaultValue,
|
|
131
159
|
value,
|
|
@@ -153,13 +181,15 @@ const NativeSelect: ForwardRefWithType = forwardRef(
|
|
|
153
181
|
<MuiSelect
|
|
154
182
|
{...inputValues}
|
|
155
183
|
aria-describedby={ariaDescribedBy}
|
|
184
|
+
autoComplete={autoCompleteType}
|
|
156
185
|
children={children}
|
|
157
|
-
data-se={testId}
|
|
158
186
|
id={idOverride}
|
|
159
187
|
inputProps={{
|
|
160
188
|
"aria-errormessage": errorMessageElementId,
|
|
161
189
|
"aria-labelledby": labelElementId,
|
|
190
|
+
"data-se": testId,
|
|
162
191
|
}}
|
|
192
|
+
inputRef={localInputRef}
|
|
163
193
|
name={idOverride}
|
|
164
194
|
multiple={hasMultipleChoices}
|
|
165
195
|
native={true}
|
|
@@ -171,6 +201,7 @@ const NativeSelect: ForwardRefWithType = forwardRef(
|
|
|
171
201
|
/>
|
|
172
202
|
),
|
|
173
203
|
[
|
|
204
|
+
autoCompleteType,
|
|
174
205
|
children,
|
|
175
206
|
idOverride,
|
|
176
207
|
inputValues,
|
package/src/PasswordField.tsx
CHANGED
|
@@ -27,8 +27,7 @@ import { Field } from "./Field";
|
|
|
27
27
|
import { FieldComponentProps } from "./FieldComponentProps";
|
|
28
28
|
import type { AllowedProps } from "./AllowedProps";
|
|
29
29
|
import { useTranslation } from "react-i18next";
|
|
30
|
-
import { getControlState, useInputValues } from "./inputUtils";
|
|
31
|
-
import { FocusHandle } from "./@types/react-augment";
|
|
30
|
+
import { FocusHandle, getControlState, useInputValues } from "./inputUtils";
|
|
32
31
|
|
|
33
32
|
export type PasswordFieldProps = {
|
|
34
33
|
/**
|
|
@@ -50,9 +49,9 @@ export type PasswordFieldProps = {
|
|
|
50
49
|
*/
|
|
51
50
|
hasShowPassword?: boolean;
|
|
52
51
|
/**
|
|
53
|
-
* The ref forwarded to the TextField
|
|
52
|
+
* The ref forwarded to the TextField
|
|
54
53
|
*/
|
|
55
|
-
|
|
54
|
+
inputRef?: React.RefObject<FocusHandle>;
|
|
56
55
|
/**
|
|
57
56
|
* The label for the `input` element.
|
|
58
57
|
*/
|
|
@@ -90,7 +89,7 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
|
|
|
90
89
|
hasInitialFocus,
|
|
91
90
|
hint,
|
|
92
91
|
id: idOverride,
|
|
93
|
-
|
|
92
|
+
inputRef,
|
|
94
93
|
isDisabled = false,
|
|
95
94
|
isFullWidth = false,
|
|
96
95
|
isOptional = false,
|
|
@@ -129,14 +128,13 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
|
|
|
129
128
|
controlState: controlledStateRef.current,
|
|
130
129
|
});
|
|
131
130
|
|
|
132
|
-
const
|
|
131
|
+
const localInputRef = useRef<HTMLInputElement>(null);
|
|
133
132
|
useImperativeHandle(
|
|
134
|
-
|
|
133
|
+
inputRef,
|
|
135
134
|
() => {
|
|
136
|
-
const element = inputRef.current;
|
|
137
135
|
return {
|
|
138
136
|
focus: () => {
|
|
139
|
-
|
|
137
|
+
localInputRef.current?.focus();
|
|
140
138
|
},
|
|
141
139
|
};
|
|
142
140
|
},
|
|
@@ -160,7 +158,6 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
|
|
|
160
158
|
autoComplete={inputType === "password" ? autoCompleteType : "off"}
|
|
161
159
|
/* eslint-disable-next-line jsx-a11y/no-autofocus */
|
|
162
160
|
autoFocus={hasInitialFocus}
|
|
163
|
-
data-se={testId}
|
|
164
161
|
endAdornment={
|
|
165
162
|
hasShowPassword && (
|
|
166
163
|
<InputAdornment position="end">
|
|
@@ -183,10 +180,11 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
|
|
|
183
180
|
inputProps={{
|
|
184
181
|
"aria-errormessage": errorMessageElementId,
|
|
185
182
|
"aria-labelledby": labelElementId,
|
|
183
|
+
"data-se": testId,
|
|
186
184
|
// role: "textbox" Added because password inputs don't have an implicit role assigned. This causes problems with element selection.
|
|
187
185
|
role: "textbox",
|
|
188
186
|
}}
|
|
189
|
-
inputRef={
|
|
187
|
+
inputRef={localInputRef}
|
|
190
188
|
name={nameOverride ?? id}
|
|
191
189
|
onChange={onChange}
|
|
192
190
|
onFocus={onFocus}
|
package/src/Radio.tsx
CHANGED
|
@@ -20,13 +20,13 @@ import { memo, useCallback, useRef, useImperativeHandle } from "react";
|
|
|
20
20
|
|
|
21
21
|
import { FieldComponentProps } from "./FieldComponentProps";
|
|
22
22
|
import type { AllowedProps } from "./AllowedProps";
|
|
23
|
-
import { FocusHandle } from "
|
|
23
|
+
import { FocusHandle } from "./inputUtils";
|
|
24
24
|
|
|
25
25
|
export type RadioProps = {
|
|
26
26
|
/**
|
|
27
|
-
* The ref forwarded to the Radio
|
|
27
|
+
* The ref forwarded to the Radio
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
inputRef?: React.RefObject<FocusHandle>;
|
|
30
30
|
/**
|
|
31
31
|
* If `true`, the Radio is selected
|
|
32
32
|
*/
|
|
@@ -55,7 +55,7 @@ export type RadioProps = {
|
|
|
55
55
|
AllowedProps;
|
|
56
56
|
|
|
57
57
|
const Radio = ({
|
|
58
|
-
|
|
58
|
+
inputRef,
|
|
59
59
|
isChecked,
|
|
60
60
|
isDisabled,
|
|
61
61
|
isInvalid,
|
|
@@ -67,14 +67,13 @@ const Radio = ({
|
|
|
67
67
|
onChange: onChangeProp,
|
|
68
68
|
onBlur: onBlurProp,
|
|
69
69
|
}: RadioProps) => {
|
|
70
|
-
const
|
|
70
|
+
const localInputRef = useRef<HTMLInputElement>(null);
|
|
71
71
|
useImperativeHandle(
|
|
72
|
-
|
|
72
|
+
inputRef,
|
|
73
73
|
() => {
|
|
74
|
-
const element = ref.current;
|
|
75
74
|
return {
|
|
76
75
|
focus: () => {
|
|
77
|
-
|
|
76
|
+
localInputRef.current?.focus();
|
|
78
77
|
},
|
|
79
78
|
};
|
|
80
79
|
},
|
|
@@ -99,8 +98,15 @@ const Radio = ({
|
|
|
99
98
|
<FormControlLabel
|
|
100
99
|
checked={isChecked}
|
|
101
100
|
className={isInvalid ? "Mui-error" : ""}
|
|
102
|
-
control={
|
|
103
|
-
|
|
101
|
+
control={
|
|
102
|
+
<MuiRadio
|
|
103
|
+
inputProps={{
|
|
104
|
+
"data-se": testId,
|
|
105
|
+
}}
|
|
106
|
+
inputRef={localInputRef}
|
|
107
|
+
onChange={onChange}
|
|
108
|
+
/>
|
|
109
|
+
}
|
|
104
110
|
disabled={isDisabled}
|
|
105
111
|
label={label}
|
|
106
112
|
name={name}
|
package/src/Select.tsx
CHANGED
|
@@ -36,10 +36,10 @@ import { CheckIcon } from "./icons.generated";
|
|
|
36
36
|
import type { AllowedProps } from "./AllowedProps";
|
|
37
37
|
import {
|
|
38
38
|
ComponentControlledState,
|
|
39
|
+
FocusHandle,
|
|
39
40
|
useInputValues,
|
|
40
41
|
getControlState,
|
|
41
42
|
} from "./inputUtils";
|
|
42
|
-
import { FocusHandle } from "./@types/react-augment";
|
|
43
43
|
|
|
44
44
|
export type SelectOption = {
|
|
45
45
|
text: string;
|
|
@@ -63,9 +63,9 @@ export type SelectProps<
|
|
|
63
63
|
*/
|
|
64
64
|
hasMultipleChoices?: HasMultipleChoices;
|
|
65
65
|
/**
|
|
66
|
-
* The ref forwarded to the Select
|
|
66
|
+
* The ref forwarded to the Select
|
|
67
67
|
*/
|
|
68
|
-
|
|
68
|
+
inputRef?: React.RefObject<FocusHandle>;
|
|
69
69
|
/**
|
|
70
70
|
* @deprecated Use `hasMultipleChoices` instead.
|
|
71
71
|
*/
|
|
@@ -136,7 +136,7 @@ const Select = <
|
|
|
136
136
|
hint,
|
|
137
137
|
HintLinkComponent,
|
|
138
138
|
id: idOverride,
|
|
139
|
-
|
|
139
|
+
inputRef,
|
|
140
140
|
isDisabled = false,
|
|
141
141
|
isFullWidth = false,
|
|
142
142
|
isMultiSelect,
|
|
@@ -164,15 +164,14 @@ const Select = <
|
|
|
164
164
|
const [internalSelectedValues, setInternalSelectedValues] = useState(
|
|
165
165
|
controlledStateRef.current === CONTROLLED ? value : defaultValue
|
|
166
166
|
);
|
|
167
|
-
const
|
|
167
|
+
const localInputRef = useRef<HTMLSelectElement>(null);
|
|
168
168
|
|
|
169
169
|
useImperativeHandle(
|
|
170
|
-
|
|
170
|
+
inputRef,
|
|
171
171
|
() => {
|
|
172
|
-
const element = inputRef.current;
|
|
173
172
|
return {
|
|
174
173
|
focus: () => {
|
|
175
|
-
|
|
174
|
+
localInputRef.current?.focus();
|
|
176
175
|
},
|
|
177
176
|
};
|
|
178
177
|
},
|
|
@@ -290,9 +289,9 @@ const Select = <
|
|
|
290
289
|
aria-describedby={ariaDescribedBy}
|
|
291
290
|
aria-errormessage={errorMessageElementId}
|
|
292
291
|
children={children}
|
|
293
|
-
data-se={testId}
|
|
294
292
|
id={id}
|
|
295
|
-
|
|
293
|
+
inputProps={{ "data-se": testId }}
|
|
294
|
+
inputRef={localInputRef}
|
|
296
295
|
labelId={labelElementId}
|
|
297
296
|
multiple={hasMultipleChoices}
|
|
298
297
|
name={nameOverride ?? id}
|
package/src/TextField.tsx
CHANGED
|
@@ -26,8 +26,7 @@ import { InputAdornment, InputBase } from "@mui/material";
|
|
|
26
26
|
import { FieldComponentProps } from "./FieldComponentProps";
|
|
27
27
|
import { Field } from "./Field";
|
|
28
28
|
import { AllowedProps } from "./AllowedProps";
|
|
29
|
-
import { useInputValues, getControlState } from "./inputUtils";
|
|
30
|
-
import { FocusHandle } from "./@types/react-augment";
|
|
29
|
+
import { FocusHandle, useInputValues, getControlState } from "./inputUtils";
|
|
31
30
|
|
|
32
31
|
export const textFieldTypeValues = [
|
|
33
32
|
"email",
|
|
@@ -57,9 +56,9 @@ export type TextFieldProps = {
|
|
|
57
56
|
*/
|
|
58
57
|
hasInitialFocus?: boolean;
|
|
59
58
|
/**
|
|
60
|
-
* The ref forwarded to the TextField
|
|
59
|
+
* The ref forwarded to the TextField
|
|
61
60
|
*/
|
|
62
|
-
|
|
61
|
+
inputRef?: React.RefObject<FocusHandle>;
|
|
63
62
|
/**
|
|
64
63
|
* Hints at the type of data that might be entered by the user while editing the element or its contents
|
|
65
64
|
* @see https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute
|
|
@@ -116,7 +115,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
116
115
|
hint,
|
|
117
116
|
HintLinkComponent,
|
|
118
117
|
id: idOverride,
|
|
119
|
-
|
|
118
|
+
inputRef,
|
|
120
119
|
inputMode,
|
|
121
120
|
isDisabled = false,
|
|
122
121
|
isFullWidth = false,
|
|
@@ -149,14 +148,13 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
149
148
|
controlState: controlledStateRef.current,
|
|
150
149
|
});
|
|
151
150
|
|
|
152
|
-
const
|
|
151
|
+
const localInputRef = useRef<HTMLInputElement>(null);
|
|
153
152
|
useImperativeHandle(
|
|
154
|
-
|
|
153
|
+
inputRef,
|
|
155
154
|
() => {
|
|
156
|
-
const element = inputRef.current;
|
|
157
155
|
return {
|
|
158
156
|
focus: () => {
|
|
159
|
-
|
|
157
|
+
localInputRef.current?.focus();
|
|
160
158
|
},
|
|
161
159
|
};
|
|
162
160
|
},
|
|
@@ -180,7 +178,6 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
180
178
|
autoComplete={autoCompleteType}
|
|
181
179
|
/* eslint-disable-next-line jsx-a11y/no-autofocus */
|
|
182
180
|
autoFocus={hasInitialFocus}
|
|
183
|
-
data-se={testId}
|
|
184
181
|
endAdornment={
|
|
185
182
|
endAdornment && (
|
|
186
183
|
<InputAdornment position="end" translate={translate}>
|
|
@@ -192,9 +189,10 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
192
189
|
inputProps={{
|
|
193
190
|
"aria-errormessage": errorMessageElementId,
|
|
194
191
|
"aria-labelledby": labelElementId,
|
|
192
|
+
"data-se": testId,
|
|
195
193
|
inputmode: inputMode,
|
|
196
194
|
}}
|
|
197
|
-
inputRef={
|
|
195
|
+
inputRef={localInputRef}
|
|
198
196
|
multiline={isMultiline}
|
|
199
197
|
name={nameOverride ?? id}
|
|
200
198
|
onBlur={onBlur}
|
package/src/Typography.tsx
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
useImperativeHandle,
|
|
24
24
|
} from "react";
|
|
25
25
|
import { AllowedProps } from "./AllowedProps";
|
|
26
|
-
import { FocusHandle } from "
|
|
26
|
+
import { FocusHandle } from "./inputUtils";
|
|
27
27
|
|
|
28
28
|
export type TypographyVariantValue =
|
|
29
29
|
| "h1"
|
|
@@ -87,9 +87,9 @@ export type TypographyProps = {
|
|
|
87
87
|
*/
|
|
88
88
|
component?: ElementType;
|
|
89
89
|
/**
|
|
90
|
-
* The ref forwarded to the Typography
|
|
90
|
+
* The ref forwarded to the Typography
|
|
91
91
|
*/
|
|
92
|
-
|
|
92
|
+
typographyRef?: React.RefObject<FocusHandle>;
|
|
93
93
|
/**
|
|
94
94
|
* The variant of Typography to render.
|
|
95
95
|
*/
|
|
@@ -105,7 +105,7 @@ const Typography = ({
|
|
|
105
105
|
component: componentProp,
|
|
106
106
|
testId,
|
|
107
107
|
translate,
|
|
108
|
-
|
|
108
|
+
typographyRef,
|
|
109
109
|
variant = "body",
|
|
110
110
|
}: TypographyProps) => {
|
|
111
111
|
const component = useMemo(() => {
|
|
@@ -121,14 +121,13 @@ const Typography = ({
|
|
|
121
121
|
return componentProp;
|
|
122
122
|
}, [componentProp, variant]);
|
|
123
123
|
|
|
124
|
-
const
|
|
124
|
+
const localTypographyRef = useRef<HTMLElement>(null);
|
|
125
125
|
useImperativeHandle(
|
|
126
|
-
|
|
126
|
+
typographyRef,
|
|
127
127
|
() => {
|
|
128
|
-
const element = ref.current;
|
|
129
128
|
return {
|
|
130
129
|
focus: () => {
|
|
131
|
-
|
|
130
|
+
localTypographyRef.current?.focus();
|
|
132
131
|
},
|
|
133
132
|
};
|
|
134
133
|
},
|
|
@@ -144,7 +143,7 @@ const Typography = ({
|
|
|
144
143
|
color={color}
|
|
145
144
|
component={component}
|
|
146
145
|
data-se={testId}
|
|
147
|
-
ref={
|
|
146
|
+
ref={localTypographyRef}
|
|
148
147
|
tabIndex={-1}
|
|
149
148
|
translate={translate}
|
|
150
149
|
variant={typographyVariantMapping[variant]}
|