@okta/odyssey-react-mui 1.5.0 → 1.6.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.
- package/CHANGELOG.md +10 -0
- package/dist/PasswordField.js +1 -1
- package/dist/PasswordField.js.map +1 -1
- package/dist/Select.js +23 -25
- package/dist/Select.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/Select.d.ts +14 -8
- package/dist/src/Select.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/theme/components.js +3 -3
- package/dist/theme/components.js.map +1 -1
- package/dist/tsconfig.production.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/PasswordField.tsx +1 -1
- package/src/Select.tsx +64 -45
- package/src/index.ts +1 -0
- package/src/theme/components.tsx +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okta/odyssey-react-mui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
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.
|
|
54
|
+
"@okta/odyssey-design-tokens": "1.6.0",
|
|
55
55
|
"date-fns": "^2.30.0",
|
|
56
56
|
"i18next": "^23.5.1",
|
|
57
57
|
"material-react-table": "^1.14.0",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"react": ">=17 <19",
|
|
64
64
|
"react-dom": ">=17 <19"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "03b8e69263df83250402101d7637a5ede3578099"
|
|
67
67
|
}
|
package/src/PasswordField.tsx
CHANGED
|
@@ -130,7 +130,7 @@ const PasswordField = forwardRef<HTMLInputElement, PasswordFieldProps>(
|
|
|
130
130
|
({ ariaDescribedBy, errorMessageElementId, id, labelElementId }) => (
|
|
131
131
|
<InputBase
|
|
132
132
|
aria-describedby={ariaDescribedBy}
|
|
133
|
-
autoComplete={autoCompleteType}
|
|
133
|
+
autoComplete={inputType === "password" ? autoCompleteType : "off"}
|
|
134
134
|
/* eslint-disable-next-line jsx-a11y/no-autofocus */
|
|
135
135
|
autoFocus={hasInitialFocus}
|
|
136
136
|
data-se={testId}
|
package/src/Select.tsx
CHANGED
|
@@ -10,16 +10,15 @@
|
|
|
10
10
|
* See the License for the specific language governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { memo, useCallback, useMemo, useState } from "react";
|
|
14
14
|
import {
|
|
15
15
|
Box,
|
|
16
|
-
Chip,
|
|
17
16
|
Checkbox as MuiCheckbox,
|
|
17
|
+
Chip,
|
|
18
|
+
ListItemSecondaryAction,
|
|
18
19
|
ListSubheader,
|
|
19
20
|
MenuItem,
|
|
20
21
|
Select as MuiSelect,
|
|
21
|
-
SelectChangeEvent,
|
|
22
|
-
ListItemSecondaryAction,
|
|
23
22
|
} from "@mui/material";
|
|
24
23
|
import { SelectProps as MuiSelectProps } from "@mui/material";
|
|
25
24
|
import { Field } from "./Field";
|
|
@@ -32,11 +31,21 @@ export type SelectOption = {
|
|
|
32
31
|
value?: string;
|
|
33
32
|
};
|
|
34
33
|
|
|
35
|
-
export type
|
|
34
|
+
export type SelectValueType<HasMultipleChoices> =
|
|
35
|
+
HasMultipleChoices extends true ? string[] : string;
|
|
36
|
+
|
|
37
|
+
export type SelectProps<
|
|
38
|
+
Value extends SelectValueType<HasMultipleChoices>,
|
|
39
|
+
HasMultipleChoices extends boolean
|
|
40
|
+
> = {
|
|
36
41
|
/**
|
|
37
42
|
* The error message for the Select
|
|
38
43
|
*/
|
|
39
44
|
errorMessage?: string;
|
|
45
|
+
/**
|
|
46
|
+
* If `true`, the Select allows multiple selections
|
|
47
|
+
*/
|
|
48
|
+
hasMultipleChoices?: HasMultipleChoices;
|
|
40
49
|
/**
|
|
41
50
|
* The hint text for the Select
|
|
42
51
|
*/
|
|
@@ -50,9 +59,10 @@ export type SelectProps = {
|
|
|
50
59
|
*/
|
|
51
60
|
isDisabled?: boolean;
|
|
52
61
|
/**
|
|
53
|
-
*
|
|
62
|
+
* @deprecated Use `hasMultipleChoices` instead.
|
|
54
63
|
*/
|
|
55
|
-
|
|
64
|
+
/** **Deprecated:** use `hasMultipleChoices` */
|
|
65
|
+
isMultiSelect?: HasMultipleChoices;
|
|
56
66
|
/**
|
|
57
67
|
* If `true`, the Select is optional
|
|
58
68
|
*/
|
|
@@ -68,15 +78,15 @@ export type SelectProps = {
|
|
|
68
78
|
/**
|
|
69
79
|
* Callback fired when the Select loses focus
|
|
70
80
|
*/
|
|
71
|
-
onBlur?: MuiSelectProps["onBlur"];
|
|
81
|
+
onBlur?: MuiSelectProps<Value>["onBlur"];
|
|
72
82
|
/**
|
|
73
83
|
* Callback fired when the value of the Select changes
|
|
74
84
|
*/
|
|
75
|
-
onChange?: MuiSelectProps["onChange"];
|
|
85
|
+
onChange?: MuiSelectProps<Value>["onChange"];
|
|
76
86
|
/**
|
|
77
87
|
* Callback fired when the Select gains focus
|
|
78
88
|
*/
|
|
79
|
-
onFocus?: MuiSelectProps["onFocus"];
|
|
89
|
+
onFocus?: MuiSelectProps<Value>["onFocus"];
|
|
80
90
|
/**
|
|
81
91
|
* The options for the Select
|
|
82
92
|
*/
|
|
@@ -84,7 +94,7 @@ export type SelectProps = {
|
|
|
84
94
|
/**
|
|
85
95
|
* The value or values selected in the Select
|
|
86
96
|
*/
|
|
87
|
-
value?:
|
|
97
|
+
value?: Value;
|
|
88
98
|
} & SeleniumProps;
|
|
89
99
|
|
|
90
100
|
/**
|
|
@@ -102,50 +112,59 @@ export type SelectProps = {
|
|
|
102
112
|
* - { text: string, type: "heading" } — Used to display a group heading with the text
|
|
103
113
|
*/
|
|
104
114
|
|
|
105
|
-
const Select =
|
|
115
|
+
const Select = <
|
|
116
|
+
Value extends SelectValueType<HasMultipleChoices>,
|
|
117
|
+
HasMultipleChoices extends boolean
|
|
118
|
+
>({
|
|
106
119
|
errorMessage,
|
|
120
|
+
hasMultipleChoices: hasMultipleChoicesProp,
|
|
107
121
|
hint,
|
|
108
122
|
id: idOverride,
|
|
109
123
|
isDisabled = false,
|
|
110
|
-
isMultiSelect
|
|
124
|
+
isMultiSelect,
|
|
111
125
|
isOptional = false,
|
|
112
126
|
label,
|
|
113
127
|
name: nameOverride,
|
|
114
128
|
onBlur,
|
|
115
129
|
onChange: onChangeProp,
|
|
116
130
|
onFocus,
|
|
117
|
-
value,
|
|
118
|
-
testId,
|
|
119
131
|
options,
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
testId,
|
|
133
|
+
value,
|
|
134
|
+
}: SelectProps<Value, HasMultipleChoices>) => {
|
|
135
|
+
const hasMultipleChoices = useMemo(
|
|
136
|
+
() =>
|
|
137
|
+
hasMultipleChoicesProp === undefined
|
|
138
|
+
? isMultiSelect
|
|
139
|
+
: hasMultipleChoicesProp,
|
|
140
|
+
[hasMultipleChoicesProp, isMultiSelect]
|
|
141
|
+
);
|
|
126
142
|
|
|
127
|
-
const
|
|
143
|
+
const formattedValueForMultiSelect = isMultiSelect
|
|
144
|
+
? ([] as string[] as Value)
|
|
145
|
+
: ("" as string as Value);
|
|
128
146
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
147
|
+
const [selectedValue, setSelectedValue] = useState(
|
|
148
|
+
value === undefined ? formattedValueForMultiSelect : value
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const onChange = useCallback<NonNullable<MuiSelectProps<Value>["onChange"]>>(
|
|
152
|
+
(event, child) => {
|
|
153
|
+
const valueFromEvent = event.target.value;
|
|
134
154
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
155
|
+
if (typeof valueFromEvent === "string") {
|
|
156
|
+
if (hasMultipleChoices) {
|
|
157
|
+
setSelectedValue(valueFromEvent.split(",") as Value);
|
|
158
|
+
} else {
|
|
159
|
+
setSelectedValue(valueFromEvent as Value);
|
|
160
|
+
}
|
|
139
161
|
} else {
|
|
140
|
-
setSelectedValue(
|
|
162
|
+
setSelectedValue(valueFromEvent);
|
|
141
163
|
}
|
|
142
164
|
|
|
143
|
-
|
|
144
|
-
if (onChangeProp) {
|
|
145
|
-
onChangeProp(event, child);
|
|
146
|
-
}
|
|
165
|
+
onChangeProp?.(event, child);
|
|
147
166
|
},
|
|
148
|
-
[
|
|
167
|
+
[hasMultipleChoices, onChangeProp, setSelectedValue]
|
|
149
168
|
);
|
|
150
169
|
|
|
151
170
|
// Normalize the options array to accommodate the various
|
|
@@ -165,7 +184,7 @@ const Select = ({
|
|
|
165
184
|
);
|
|
166
185
|
|
|
167
186
|
const renderValue = useCallback(
|
|
168
|
-
(selected:
|
|
187
|
+
(selected: Value) => {
|
|
169
188
|
// If the selected value isn't an array, then we don't need to display
|
|
170
189
|
// chips and should fall back to the default render behavior
|
|
171
190
|
if (typeof selected === "string") {
|
|
@@ -209,7 +228,7 @@ const Select = ({
|
|
|
209
228
|
|
|
210
229
|
return (
|
|
211
230
|
<MenuItem key={option.value} value={option.value}>
|
|
212
|
-
{
|
|
231
|
+
{hasMultipleChoices && (
|
|
213
232
|
<MuiCheckbox checked={selectedValue.includes(option.value)} />
|
|
214
233
|
)}
|
|
215
234
|
{option.text}
|
|
@@ -221,30 +240,30 @@ const Select = ({
|
|
|
221
240
|
</MenuItem>
|
|
222
241
|
);
|
|
223
242
|
}),
|
|
224
|
-
[
|
|
243
|
+
[hasMultipleChoices, normalizedOptions, selectedValue]
|
|
225
244
|
);
|
|
226
245
|
|
|
227
246
|
const renderFieldComponent = useCallback(
|
|
228
247
|
({ ariaDescribedBy, errorMessageElementId, id, labelElementId }) => (
|
|
229
248
|
<MuiSelect
|
|
249
|
+
aria-describedby={ariaDescribedBy}
|
|
250
|
+
aria-errormessage={errorMessageElementId}
|
|
230
251
|
children={children}
|
|
231
252
|
data-se={testId}
|
|
232
253
|
id={id}
|
|
233
|
-
aria-errormessage={errorMessageElementId}
|
|
234
|
-
aria-describedby={ariaDescribedBy}
|
|
235
254
|
labelId={labelElementId}
|
|
236
|
-
multiple={
|
|
255
|
+
multiple={hasMultipleChoices}
|
|
237
256
|
name={nameOverride ?? id}
|
|
238
257
|
onBlur={onBlur}
|
|
239
258
|
onChange={onChange}
|
|
240
259
|
onFocus={onFocus}
|
|
241
|
-
renderValue={
|
|
260
|
+
renderValue={hasMultipleChoices ? renderValue : undefined}
|
|
242
261
|
value={selectedValue}
|
|
243
262
|
/>
|
|
244
263
|
),
|
|
245
264
|
[
|
|
246
265
|
children,
|
|
247
|
-
|
|
266
|
+
hasMultipleChoices,
|
|
248
267
|
nameOverride,
|
|
249
268
|
onBlur,
|
|
250
269
|
onChange,
|
package/src/index.ts
CHANGED
|
@@ -66,6 +66,7 @@ export * from "./Callout";
|
|
|
66
66
|
export * from "./Checkbox";
|
|
67
67
|
export * from "./CheckboxGroup";
|
|
68
68
|
export * from "./CircularProgress";
|
|
69
|
+
export * from "./createShadowDom";
|
|
69
70
|
export * from "./createUniqueId";
|
|
70
71
|
export * from "./Dialog";
|
|
71
72
|
export * from "./Fieldset";
|
package/src/theme/components.tsx
CHANGED
|
@@ -1675,7 +1675,7 @@ export const components = ({
|
|
|
1675
1675
|
styleOverrides: {
|
|
1676
1676
|
root: {
|
|
1677
1677
|
color: odysseyTokens.TypographyColorAction,
|
|
1678
|
-
textDecoration: "
|
|
1678
|
+
textDecoration: "none",
|
|
1679
1679
|
cursor: "pointer",
|
|
1680
1680
|
|
|
1681
1681
|
"&:visited": {
|
|
@@ -1703,11 +1703,11 @@ export const components = ({
|
|
|
1703
1703
|
},
|
|
1704
1704
|
|
|
1705
1705
|
".Link-indicator": {
|
|
1706
|
-
marginInlineStart: odysseyTokens.
|
|
1706
|
+
marginInlineStart: odysseyTokens.Spacing1,
|
|
1707
1707
|
},
|
|
1708
1708
|
|
|
1709
1709
|
".Link-icon": {
|
|
1710
|
-
marginInlineEnd: odysseyTokens.
|
|
1710
|
+
marginInlineEnd: odysseyTokens.Spacing1,
|
|
1711
1711
|
},
|
|
1712
1712
|
svg: {
|
|
1713
1713
|
fontSize: "1em",
|