@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.
- package/CHANGELOG.md +54 -0
- package/README.md +1 -1
- package/dist/Autocomplete.js +20 -3
- package/dist/Autocomplete.js.map +1 -1
- package/dist/Banner.js +3 -1
- package/dist/Banner.js.map +1 -1
- package/dist/Box.js +8 -4
- package/dist/Box.js.map +1 -1
- package/dist/Button.js +3 -1
- package/dist/Button.js.map +1 -1
- package/dist/Callout.js +2 -0
- package/dist/Callout.js.map +1 -1
- package/dist/Checkbox.js +6 -2
- package/dist/Checkbox.js.map +1 -1
- package/dist/CheckboxGroup.js +5 -7
- package/dist/CheckboxGroup.js.map +1 -1
- package/dist/CircularProgress.js +2 -0
- package/dist/CircularProgress.js.map +1 -1
- package/dist/Dialog.js +2 -0
- package/dist/Dialog.js.map +1 -1
- package/dist/Field.js.map +1 -1
- package/dist/FieldError.js +2 -0
- package/dist/FieldError.js.map +1 -1
- package/dist/FieldHint.js +2 -0
- package/dist/FieldHint.js.map +1 -1
- package/dist/FieldLabel.js +3 -1
- package/dist/FieldLabel.js.map +1 -1
- package/dist/Fieldset.js +3 -1
- package/dist/Fieldset.js.map +1 -1
- package/dist/Form.js +5 -3
- package/dist/Form.js.map +1 -1
- package/dist/Link.js +3 -1
- package/dist/Link.js.map +1 -1
- package/dist/MenuButton.js +8 -2
- package/dist/MenuButton.js.map +1 -1
- package/dist/MenuItem.js +6 -2
- package/dist/MenuItem.js.map +1 -1
- package/dist/NativeSelect.js +3 -1
- package/dist/NativeSelect.js.map +1 -1
- package/dist/OdysseyCacheProvider.js +4 -1
- package/dist/OdysseyCacheProvider.js.map +1 -1
- package/dist/OdysseyProvider.js +12 -5
- package/dist/OdysseyProvider.js.map +1 -1
- package/dist/OdysseyThemeProvider.js +8 -7
- package/dist/OdysseyThemeProvider.js.map +1 -1
- package/dist/OdysseyTranslationProvider.js +1 -1
- package/dist/OdysseyTranslationProvider.js.map +1 -1
- package/dist/OdysseyTranslationProvider.types.js +1 -1
- package/dist/OdysseyTranslationProvider.types.js.map +1 -1
- package/dist/PasswordField.js +18 -9
- package/dist/PasswordField.js.map +1 -1
- package/dist/Radio.js +2 -0
- package/dist/Radio.js.map +1 -1
- package/dist/RadioGroup.js +5 -2
- package/dist/RadioGroup.js.map +1 -1
- package/dist/SearchField.js +11 -10
- package/dist/SearchField.js.map +1 -1
- package/dist/Select.js +39 -35
- package/dist/Select.js.map +1 -1
- package/dist/SeleniumProps.js +2 -0
- package/dist/SeleniumProps.js.map +1 -0
- package/dist/Status.js +4 -2
- package/dist/Status.js.map +1 -1
- package/dist/Tabs.js +11 -4
- package/dist/Tabs.js.map +1 -1
- package/dist/Tag.js +4 -2
- package/dist/Tag.js.map +1 -1
- package/dist/TagList.js +3 -1
- package/dist/TagList.js.map +1 -1
- package/dist/TextField.js +6 -2
- package/dist/TextField.js.map +1 -1
- package/dist/Toast.js +2 -0
- package/dist/Toast.js.map +1 -1
- package/dist/Tooltip.js +2 -0
- package/dist/Tooltip.js.map +1 -1
- package/dist/Typography.js +71 -59
- package/dist/Typography.js.map +1 -1
- package/dist/createShadowDom.js +26 -0
- package/dist/createShadowDom.js.map +1 -0
- package/dist/{OdysseyI18n.js → i18n.js} +5 -2
- package/dist/i18n.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/labs/DatePicker.js +4 -2
- package/dist/labs/DatePicker.js.map +1 -1
- package/dist/labs/PaginatedTable.js +6 -4
- package/dist/labs/PaginatedTable.js.map +1 -1
- package/dist/labs/StaticTable.js +9 -4
- package/dist/labs/StaticTable.js.map +1 -1
- package/dist/labs/datePickerTheme.js +4 -2
- package/dist/labs/datePickerTheme.js.map +1 -1
- package/dist/properties/ts/odyssey-react-mui.js +2 -0
- package/dist/properties/ts/odyssey-react-mui.js.map +1 -1
- package/dist/src/Autocomplete.d.ts +29 -4
- package/dist/src/Autocomplete.d.ts.map +1 -1
- package/dist/src/Banner.d.ts +3 -2
- package/dist/src/Banner.d.ts.map +1 -1
- package/dist/src/Box.d.ts +9 -2
- package/dist/src/Box.d.ts.map +1 -1
- package/dist/src/Button.d.ts +3 -2
- package/dist/src/Button.d.ts.map +1 -1
- package/dist/src/Callout.d.ts +3 -2
- package/dist/src/Callout.d.ts.map +1 -1
- package/dist/src/Checkbox.d.ts +8 -3
- package/dist/src/Checkbox.d.ts.map +1 -1
- package/dist/src/CheckboxGroup.d.ts +3 -6
- package/dist/src/CheckboxGroup.d.ts.map +1 -1
- package/dist/src/CircularProgress.d.ts +3 -2
- package/dist/src/CircularProgress.d.ts.map +1 -1
- package/dist/src/Dialog.d.ts +3 -2
- package/dist/src/Dialog.d.ts.map +1 -1
- package/dist/src/Field.d.ts +2 -1
- package/dist/src/Field.d.ts.map +1 -1
- package/dist/src/FieldError.d.ts +3 -2
- package/dist/src/FieldError.d.ts.map +1 -1
- package/dist/src/FieldHint.d.ts +3 -2
- package/dist/src/FieldHint.d.ts.map +1 -1
- package/dist/src/FieldLabel.d.ts +3 -2
- package/dist/src/FieldLabel.d.ts.map +1 -1
- package/dist/src/Fieldset.d.ts +3 -2
- package/dist/src/Fieldset.d.ts.map +1 -1
- package/dist/src/Form.d.ts +3 -2
- package/dist/src/Form.d.ts.map +1 -1
- package/dist/src/Link.d.ts +3 -2
- package/dist/src/Link.d.ts.map +1 -1
- package/dist/src/MenuButton.d.ts +12 -3
- package/dist/src/MenuButton.d.ts.map +1 -1
- package/dist/src/MenuItem.d.ts +5 -4
- package/dist/src/MenuItem.d.ts.map +1 -1
- package/dist/src/NativeSelect.d.ts +56 -2
- package/dist/src/NativeSelect.d.ts.map +1 -1
- package/dist/src/OdysseyCacheProvider.d.ts +6 -1
- package/dist/src/OdysseyCacheProvider.d.ts.map +1 -1
- package/dist/src/OdysseyProvider.d.ts +1 -1
- package/dist/src/OdysseyProvider.d.ts.map +1 -1
- package/dist/src/OdysseyThemeProvider.d.ts +2 -1
- package/dist/src/OdysseyThemeProvider.d.ts.map +1 -1
- package/dist/src/OdysseyTranslationProvider.d.ts +1 -1
- package/dist/src/OdysseyTranslationProvider.d.ts.map +1 -1
- package/dist/src/OdysseyTranslationProvider.types.d.ts +1 -1
- package/dist/src/OdysseyTranslationProvider.types.d.ts.map +1 -1
- package/dist/src/PasswordField.d.ts +78 -2
- package/dist/src/PasswordField.d.ts.map +1 -1
- package/dist/src/Radio.d.ts +3 -2
- package/dist/src/Radio.d.ts.map +1 -1
- package/dist/src/RadioGroup.d.ts +8 -3
- package/dist/src/RadioGroup.d.ts.map +1 -1
- package/dist/src/SearchField.d.ts +58 -2
- package/dist/src/SearchField.d.ts.map +1 -1
- package/dist/src/Select.d.ts +7 -2
- package/dist/src/Select.d.ts.map +1 -1
- package/dist/src/SeleniumProps.d.ts +20 -0
- package/dist/src/SeleniumProps.d.ts.map +1 -0
- package/dist/src/Status.d.ts +3 -2
- package/dist/src/Status.d.ts.map +1 -1
- package/dist/src/Tabs.d.ts +9 -3
- package/dist/src/Tabs.d.ts.map +1 -1
- package/dist/src/Tag.d.ts +3 -2
- package/dist/src/Tag.d.ts.map +1 -1
- package/dist/src/TagList.d.ts +3 -2
- package/dist/src/TagList.d.ts.map +1 -1
- package/dist/src/TextField.d.ts +86 -2
- package/dist/src/TextField.d.ts.map +1 -1
- package/dist/src/Toast.d.ts +3 -2
- package/dist/src/Toast.d.ts.map +1 -1
- package/dist/src/Tooltip.d.ts +3 -2
- package/dist/src/Tooltip.d.ts.map +1 -1
- package/dist/src/Typography.d.ts +14 -49
- package/dist/src/Typography.d.ts.map +1 -1
- package/dist/src/createShadowDom.d.ts +16 -0
- package/dist/src/createShadowDom.d.ts.map +1 -0
- package/dist/src/{OdysseyI18n.d.ts → i18n.d.ts} +20 -2
- package/dist/src/i18n.d.ts.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/labs/DatePicker.d.ts +5 -1
- package/dist/src/labs/DatePicker.d.ts.map +1 -1
- package/dist/src/labs/PaginatedTable.d.ts.map +1 -1
- package/dist/src/labs/StaticTable.d.ts.map +1 -1
- package/dist/src/properties/ts/odyssey-react-mui.d.ts +2 -0
- package/dist/src/properties/ts/odyssey-react-mui.d.ts.map +1 -1
- package/dist/src/theme/components.d.ts +4 -1
- package/dist/src/theme/components.d.ts.map +1 -1
- package/dist/src/theme/createOdysseyMuiTheme.d.ts +23 -0
- package/dist/src/theme/createOdysseyMuiTheme.d.ts.map +1 -0
- package/dist/src/theme/mixins.d.ts +3 -1
- package/dist/src/theme/mixins.d.ts.map +1 -1
- package/dist/src/theme/palette.d.ts +3 -1
- package/dist/src/theme/palette.d.ts.map +1 -1
- package/dist/src/theme/shape.d.ts +3 -1
- package/dist/src/theme/shape.d.ts.map +1 -1
- package/dist/src/theme/spacing.d.ts +3 -1
- package/dist/src/theme/spacing.d.ts.map +1 -1
- package/dist/src/theme/theme.d.ts +1 -8
- package/dist/src/theme/theme.d.ts.map +1 -1
- package/dist/src/theme/typography.d.ts +3 -1
- package/dist/src/theme/typography.d.ts.map +1 -1
- package/dist/theme/components.js +118 -73
- package/dist/theme/components.js.map +1 -1
- package/dist/theme/createOdysseyMuiTheme.js +51 -0
- package/dist/theme/createOdysseyMuiTheme.js.map +1 -0
- package/dist/theme/mixins.js +4 -1
- package/dist/theme/mixins.js.map +1 -1
- package/dist/theme/palette.js +4 -1
- package/dist/theme/palette.js.map +1 -1
- package/dist/theme/shape.js +4 -1
- package/dist/theme/shape.js.map +1 -1
- package/dist/theme/spacing.js +4 -1
- package/dist/theme/spacing.js.map +1 -1
- package/dist/theme/theme.js +1 -20
- package/dist/theme/theme.js.map +1 -1
- package/dist/theme/typography.js +4 -1
- package/dist/theme/typography.js.map +1 -1
- package/dist/tsconfig.production.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/Autocomplete.tsx +56 -4
- package/src/Banner.tsx +11 -2
- package/src/Box.tsx +11 -5
- package/src/Button.tsx +6 -1
- package/src/Callout.tsx +5 -3
- package/src/Checkbox.tsx +14 -4
- package/src/CheckboxGroup.tsx +6 -10
- package/src/CircularProgress.tsx +5 -1
- package/src/Dialog.tsx +5 -2
- package/src/Field.tsx +2 -0
- package/src/FieldError.tsx +5 -3
- package/src/FieldHint.tsx +9 -3
- package/src/FieldLabel.tsx +5 -3
- package/src/Fieldset.tsx +4 -1
- package/src/Form.tsx +7 -4
- package/src/Link.tsx +18 -3
- package/src/MenuButton.tsx +33 -4
- package/src/MenuItem.tsx +11 -6
- package/src/NativeSelect.tsx +7 -2
- package/src/OdysseyCacheProvider.tsx +9 -1
- package/src/OdysseyProvider.tsx +18 -8
- package/src/OdysseyThemeProvider.tsx +12 -8
- package/src/OdysseyTranslationProvider.test.tsx +2 -2
- package/src/OdysseyTranslationProvider.tsx +1 -1
- package/src/OdysseyTranslationProvider.types.ts +1 -0
- package/src/PasswordField.tsx +37 -13
- package/src/Radio.tsx +5 -1
- package/src/RadioGroup.tsx +12 -4
- package/src/SearchField.tsx +23 -15
- package/src/Select.tsx +154 -149
- package/src/SeleniumProps.ts +20 -0
- package/src/Status.tsx +15 -3
- package/src/Tabs.tsx +18 -4
- package/src/Tag.tsx +12 -3
- package/src/TagList.tsx +4 -2
- package/src/TextField.tsx +14 -2
- package/src/Toast.tsx +4 -1
- package/src/Tooltip.tsx +4 -1
- package/src/Typography.tsx +76 -54
- package/src/createShadowDom.ts +46 -0
- package/src/{OdysseyI18n.ts → i18n.ts} +4 -2
- package/src/index.ts +1 -0
- package/src/labs/DatePicker.tsx +15 -7
- package/src/labs/PaginatedTable.tsx +12 -3
- package/src/labs/README.md +2 -2
- package/src/labs/StaticTable.tsx +13 -3
- package/src/labs/datePickerTheme.tsx +2 -2
- package/src/properties/odyssey-react-mui.properties +2 -0
- package/src/properties/ts/odyssey-react-mui.ts +1 -1
- package/src/theme/components.tsx +69 -18
- package/src/theme/createOdysseyMuiTheme.ts +47 -0
- package/src/theme/mixins.ts +5 -1
- package/src/theme/palette.ts +5 -3
- package/src/theme/shape.ts +5 -1
- package/src/theme/spacing.ts +5 -3
- package/src/theme/theme.ts +1 -26
- package/src/theme/typography.ts +5 -3
- package/dist/OdysseyI18n.js.map +0 -1
- package/dist/src/OdysseyI18n.d.ts.map +0 -1
package/src/SearchField.tsx
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { useState, useEffect } from "react";
|
|
14
|
-
import { InputAdornment, InputBase } from "@mui/material";
|
|
14
|
+
import { InputAdornment, InputBase, IconButton } from "@mui/material";
|
|
15
15
|
import {
|
|
16
16
|
ChangeEventHandler,
|
|
17
17
|
FocusEventHandler,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
|
|
24
24
|
import { CloseCircleFilledIcon, SearchIcon } from "./icons.generated";
|
|
25
25
|
import { Field } from "./Field";
|
|
26
|
-
import {
|
|
26
|
+
import type { SeleniumProps } from "./SeleniumProps";
|
|
27
27
|
|
|
28
28
|
export type SearchFieldProps = {
|
|
29
29
|
/**
|
|
@@ -48,6 +48,10 @@ export type SearchFieldProps = {
|
|
|
48
48
|
* This label won't show up visually, but it's required for accessibility.
|
|
49
49
|
*/
|
|
50
50
|
label: string;
|
|
51
|
+
/**
|
|
52
|
+
* The name of the `input` element. Defaults to the `id` if not set.
|
|
53
|
+
*/
|
|
54
|
+
name?: string;
|
|
51
55
|
/**
|
|
52
56
|
* Callback fired when the `input` element loses focus.
|
|
53
57
|
*/
|
|
@@ -72,7 +76,7 @@ export type SearchFieldProps = {
|
|
|
72
76
|
* The value of the `input` element, required for a controlled component.
|
|
73
77
|
*/
|
|
74
78
|
value?: string;
|
|
75
|
-
};
|
|
79
|
+
} & SeleniumProps;
|
|
76
80
|
|
|
77
81
|
const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
|
|
78
82
|
(
|
|
@@ -82,11 +86,13 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
|
|
|
82
86
|
id: idOverride,
|
|
83
87
|
isDisabled = false,
|
|
84
88
|
label,
|
|
89
|
+
name: nameOverride,
|
|
85
90
|
onChange: onChangeProp,
|
|
86
91
|
onFocus,
|
|
87
92
|
onBlur,
|
|
88
93
|
onClear: onClearProp,
|
|
89
94
|
placeholder,
|
|
95
|
+
testId,
|
|
90
96
|
value: controlledValue,
|
|
91
97
|
},
|
|
92
98
|
ref
|
|
@@ -120,26 +126,26 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
|
|
|
120
126
|
autoComplete={autoCompleteType}
|
|
121
127
|
/* eslint-disable-next-line jsx-a11y/no-autofocus */
|
|
122
128
|
autoFocus={hasInitialFocus}
|
|
129
|
+
data-se={testId}
|
|
123
130
|
endAdornment={
|
|
124
131
|
uncontrolledValue && (
|
|
125
132
|
<InputAdornment position="end">
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
label=""
|
|
133
|
+
<IconButton
|
|
134
|
+
aria-label="Clear"
|
|
135
|
+
disabled={isDisabled}
|
|
130
136
|
onClick={onClear}
|
|
131
137
|
size="small"
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
>
|
|
139
|
+
<CloseCircleFilledIcon />
|
|
140
|
+
</IconButton>
|
|
135
141
|
</InputAdornment>
|
|
136
142
|
)
|
|
137
143
|
}
|
|
138
144
|
id={id}
|
|
139
|
-
name={id}
|
|
145
|
+
name={nameOverride ?? id}
|
|
146
|
+
onBlur={onBlur}
|
|
140
147
|
onChange={onChange}
|
|
141
148
|
onFocus={onFocus}
|
|
142
|
-
onBlur={onBlur}
|
|
143
149
|
placeholder={placeholder}
|
|
144
150
|
ref={ref}
|
|
145
151
|
startAdornment={
|
|
@@ -155,15 +161,17 @@ const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(
|
|
|
155
161
|
),
|
|
156
162
|
[
|
|
157
163
|
autoCompleteType,
|
|
164
|
+
controlledValue,
|
|
158
165
|
hasInitialFocus,
|
|
159
166
|
isDisabled,
|
|
160
|
-
|
|
167
|
+
nameOverride,
|
|
168
|
+
onBlur,
|
|
161
169
|
onChange,
|
|
170
|
+
onClear,
|
|
162
171
|
onFocus,
|
|
163
|
-
onBlur,
|
|
164
172
|
placeholder,
|
|
165
173
|
ref,
|
|
166
|
-
|
|
174
|
+
testId,
|
|
167
175
|
uncontrolledValue,
|
|
168
176
|
]
|
|
169
177
|
);
|
package/src/Select.tsx
CHANGED
|
@@ -10,18 +10,19 @@
|
|
|
10
10
|
* See the License for the specific language governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { ReactNode,
|
|
13
|
+
import { ReactNode, memo, useCallback, useMemo, useState } from "react";
|
|
14
14
|
import {
|
|
15
15
|
Box,
|
|
16
16
|
Chip,
|
|
17
|
+
Checkbox as MuiCheckbox,
|
|
17
18
|
ListSubheader,
|
|
18
19
|
MenuItem,
|
|
19
20
|
Select as MuiSelect,
|
|
20
21
|
SelectChangeEvent,
|
|
21
22
|
} from "@mui/material";
|
|
22
23
|
import { SelectProps as MuiSelectProps } from "@mui/material";
|
|
23
|
-
import { Checkbox } from "./Checkbox";
|
|
24
24
|
import { Field } from "./Field";
|
|
25
|
+
import type { SeleniumProps } from "./SeleniumProps";
|
|
25
26
|
|
|
26
27
|
export type SelectOption = {
|
|
27
28
|
text: string;
|
|
@@ -58,6 +59,10 @@ export type SelectProps = {
|
|
|
58
59
|
* The label text for the Select
|
|
59
60
|
*/
|
|
60
61
|
label: string;
|
|
62
|
+
/**
|
|
63
|
+
* The name of the `input` element. Defaults to the `id` if not set.
|
|
64
|
+
*/
|
|
65
|
+
name?: string;
|
|
61
66
|
/**
|
|
62
67
|
* Callback fired when the Select loses focus
|
|
63
68
|
*/
|
|
@@ -78,7 +83,7 @@ export type SelectProps = {
|
|
|
78
83
|
* The value or values selected in the Select
|
|
79
84
|
*/
|
|
80
85
|
value?: string | string[];
|
|
81
|
-
};
|
|
86
|
+
} & SeleniumProps;
|
|
82
87
|
|
|
83
88
|
/**
|
|
84
89
|
* Options in Odyssey <Select> are passed as an array, which can contain any combination
|
|
@@ -95,168 +100,168 @@ export type SelectProps = {
|
|
|
95
100
|
* - { text: string, type: "heading" } — Used to display a group heading with the text
|
|
96
101
|
*/
|
|
97
102
|
|
|
98
|
-
const Select =
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
value = isMultiSelect ? [] : "";
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const [selectedValue, setSelectedValue] = useState<string | string[]>(
|
|
123
|
-
value
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
const onChange = useCallback(
|
|
127
|
-
(event: SelectChangeEvent<string | string[]>, child: ReactNode) => {
|
|
128
|
-
const {
|
|
129
|
-
target: { value },
|
|
130
|
-
} = event;
|
|
103
|
+
const Select = ({
|
|
104
|
+
errorMessage,
|
|
105
|
+
hint,
|
|
106
|
+
id: idOverride,
|
|
107
|
+
isDisabled = false,
|
|
108
|
+
isMultiSelect = false,
|
|
109
|
+
isOptional = false,
|
|
110
|
+
label,
|
|
111
|
+
name: nameOverride,
|
|
112
|
+
onBlur,
|
|
113
|
+
onChange: onChangeProp,
|
|
114
|
+
onFocus,
|
|
115
|
+
value,
|
|
116
|
+
testId,
|
|
117
|
+
options,
|
|
118
|
+
}: SelectProps) => {
|
|
119
|
+
// If there's no value set, we set it to a blank string (if it's a single-select)
|
|
120
|
+
// or an empty array (if it's a multi-select)
|
|
121
|
+
if (typeof value === "undefined") {
|
|
122
|
+
value = isMultiSelect ? [] : "";
|
|
123
|
+
}
|
|
131
124
|
|
|
132
|
-
|
|
133
|
-
// for multi-selects
|
|
134
|
-
if (isMultiSelect) {
|
|
135
|
-
setSelectedValue(
|
|
136
|
-
typeof value === "string" ? value.split(",") : value
|
|
137
|
-
);
|
|
138
|
-
} else {
|
|
139
|
-
setSelectedValue(value);
|
|
140
|
-
}
|
|
125
|
+
const [selectedValue, setSelectedValue] = useState<string | string[]>(value);
|
|
141
126
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
[isMultiSelect, onChangeProp, setSelectedValue]
|
|
148
|
-
);
|
|
127
|
+
const onChange = useCallback(
|
|
128
|
+
(event: SelectChangeEvent<string | string[]>, child: ReactNode) => {
|
|
129
|
+
const {
|
|
130
|
+
target: { value },
|
|
131
|
+
} = event;
|
|
149
132
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
value: option.value || option.text,
|
|
157
|
-
type: option.type === "heading" ? "heading" : "option",
|
|
158
|
-
};
|
|
133
|
+
// Set the field value, with some additional logic to handle array values
|
|
134
|
+
// for multi-selects
|
|
135
|
+
if (isMultiSelect) {
|
|
136
|
+
setSelectedValue(typeof value === "string" ? value.split(",") : value);
|
|
137
|
+
} else {
|
|
138
|
+
setSelectedValue(value);
|
|
159
139
|
}
|
|
160
140
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (typeof selected === "string") {
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Convert the selected options array into <Chip>s
|
|
173
|
-
const renderedChips = selected
|
|
174
|
-
.map((item: string) => {
|
|
175
|
-
const selectedOption = normalizedOptions.find(
|
|
176
|
-
(option) => option.value === item
|
|
177
|
-
);
|
|
141
|
+
// Trigger the onChange event, if one has been passed
|
|
142
|
+
if (onChangeProp) {
|
|
143
|
+
onChangeProp(event, child);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
[isMultiSelect, onChangeProp, setSelectedValue]
|
|
147
|
+
);
|
|
178
148
|
|
|
179
|
-
|
|
180
|
-
|
|
149
|
+
// Normalize the options array to accommodate the various
|
|
150
|
+
// data types that might be passed
|
|
151
|
+
const normalizedOptions = useMemo(
|
|
152
|
+
() =>
|
|
153
|
+
options.map((option) =>
|
|
154
|
+
typeof option === "object"
|
|
155
|
+
? {
|
|
156
|
+
text: option.text,
|
|
157
|
+
value: option.value || option.text,
|
|
158
|
+
type: option.type === "heading" ? "heading" : "option",
|
|
181
159
|
}
|
|
160
|
+
: { text: option, value: option, type: "option" }
|
|
161
|
+
),
|
|
162
|
+
[options]
|
|
163
|
+
);
|
|
182
164
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
165
|
+
const renderValue = useCallback(
|
|
166
|
+
(selected: string | string[]) => {
|
|
167
|
+
// If the selected value isn't an array, then we don't need to display
|
|
168
|
+
// chips and should fall back to the default render behavior
|
|
169
|
+
if (typeof selected === "string") {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
186
172
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
173
|
+
// Convert the selected options array into <Chip>s
|
|
174
|
+
const renderedChips = selected
|
|
175
|
+
.map((item: string) => {
|
|
176
|
+
const selectedOption = normalizedOptions.find(
|
|
177
|
+
(option) => option.value === item
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
if (!selectedOption) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
190
183
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
},
|
|
195
|
-
[normalizedOptions]
|
|
196
|
-
);
|
|
184
|
+
return <Chip key={item} label={selectedOption.text} />;
|
|
185
|
+
})
|
|
186
|
+
.filter(Boolean);
|
|
197
187
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const children = normalizedOptions.map((option) => {
|
|
201
|
-
if (option.type === "heading") {
|
|
202
|
-
return <ListSubheader key={option.text}>{option.text}</ListSubheader>;
|
|
188
|
+
if (renderedChips.length === 0) {
|
|
189
|
+
return null;
|
|
203
190
|
}
|
|
204
191
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
</MenuItem>
|
|
212
|
-
);
|
|
213
|
-
});
|
|
192
|
+
// We need the <Box> to surround the <Chip>s for
|
|
193
|
+
// proper styling
|
|
194
|
+
return <Box>{renderedChips}</Box>;
|
|
195
|
+
},
|
|
196
|
+
[normalizedOptions]
|
|
197
|
+
);
|
|
214
198
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
onChange,
|
|
236
|
-
onFocus,
|
|
237
|
-
ref,
|
|
238
|
-
children,
|
|
239
|
-
renderValue,
|
|
240
|
-
selectedValue,
|
|
241
|
-
label,
|
|
242
|
-
]
|
|
243
|
-
);
|
|
199
|
+
// Convert the options into the ReactNode children
|
|
200
|
+
// that will populate the <Select>
|
|
201
|
+
const children = useMemo(
|
|
202
|
+
() =>
|
|
203
|
+
normalizedOptions.map((option) => {
|
|
204
|
+
if (option.type === "heading") {
|
|
205
|
+
return <ListSubheader key={option.text}>{option.text}</ListSubheader>;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<MenuItem key={option.value} value={option.value}>
|
|
210
|
+
{isMultiSelect && (
|
|
211
|
+
<MuiCheckbox checked={selectedValue.includes(option.value)} />
|
|
212
|
+
)}
|
|
213
|
+
{option.text}
|
|
214
|
+
</MenuItem>
|
|
215
|
+
);
|
|
216
|
+
}),
|
|
217
|
+
[isMultiSelect, normalizedOptions, selectedValue]
|
|
218
|
+
);
|
|
244
219
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
id={
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
220
|
+
const renderFieldComponent = useCallback(
|
|
221
|
+
({ ariaDescribedBy, id }) => (
|
|
222
|
+
<MuiSelect
|
|
223
|
+
aria-describedby={ariaDescribedBy}
|
|
224
|
+
children={children}
|
|
225
|
+
data-se={testId}
|
|
226
|
+
id={id}
|
|
227
|
+
labelId={label}
|
|
228
|
+
multiple={isMultiSelect}
|
|
229
|
+
name={nameOverride ?? id}
|
|
230
|
+
onBlur={onBlur}
|
|
231
|
+
onChange={onChange}
|
|
232
|
+
onFocus={onFocus}
|
|
233
|
+
renderValue={isMultiSelect ? renderValue : undefined}
|
|
234
|
+
value={selectedValue}
|
|
256
235
|
/>
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
|
|
236
|
+
),
|
|
237
|
+
[
|
|
238
|
+
children,
|
|
239
|
+
isMultiSelect,
|
|
240
|
+
label,
|
|
241
|
+
nameOverride,
|
|
242
|
+
onBlur,
|
|
243
|
+
onChange,
|
|
244
|
+
onFocus,
|
|
245
|
+
renderValue,
|
|
246
|
+
selectedValue,
|
|
247
|
+
testId,
|
|
248
|
+
]
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<Field
|
|
253
|
+
errorMessage={errorMessage}
|
|
254
|
+
fieldType="single"
|
|
255
|
+
hasVisibleLabel
|
|
256
|
+
hint={hint}
|
|
257
|
+
id={idOverride}
|
|
258
|
+
isDisabled={isDisabled}
|
|
259
|
+
isOptional={isOptional}
|
|
260
|
+
label={label}
|
|
261
|
+
renderFieldComponent={renderFieldComponent}
|
|
262
|
+
/>
|
|
263
|
+
);
|
|
264
|
+
};
|
|
260
265
|
|
|
261
266
|
const MemoizedSelect = memo(Select);
|
|
262
267
|
MemoizedSelect.displayName = "Select";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
|
|
3
|
+
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
|
|
4
|
+
*
|
|
5
|
+
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
7
|
+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
8
|
+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
9
|
+
*
|
|
10
|
+
* See the License for the specific language governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export type SeleniumProps = {
|
|
14
|
+
/**
|
|
15
|
+
* This prop puts a `data` attribute on an HTML element in this component with the value provided.
|
|
16
|
+
*
|
|
17
|
+
* @deprecated **WARNING:** You should be using Semantic Selectors instead of this property. This is a temporary measure for backwards compatibility with existing Selenium tests.
|
|
18
|
+
*/
|
|
19
|
+
testId?: string;
|
|
20
|
+
};
|
package/src/Status.tsx
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { Chip } from "@mui/material";
|
|
14
14
|
|
|
15
15
|
import { useMuiProps } from "./MuiPropsContext";
|
|
16
|
+
import type { SeleniumProps } from "./SeleniumProps";
|
|
16
17
|
|
|
17
18
|
export const statusSeverityValues = [
|
|
18
19
|
"default",
|
|
@@ -35,12 +36,23 @@ export type StatusProps = {
|
|
|
35
36
|
* The style of the Status indicator
|
|
36
37
|
*/
|
|
37
38
|
variant?: (typeof statusVariantValues)[number];
|
|
38
|
-
};
|
|
39
|
+
} & SeleniumProps;
|
|
39
40
|
|
|
40
|
-
export const Status = ({
|
|
41
|
+
export const Status = ({
|
|
42
|
+
label,
|
|
43
|
+
severity,
|
|
44
|
+
testId,
|
|
45
|
+
variant = "lamp",
|
|
46
|
+
}: StatusProps) => {
|
|
41
47
|
const muiProps = useMuiProps();
|
|
42
48
|
|
|
43
49
|
return (
|
|
44
|
-
<Chip
|
|
50
|
+
<Chip
|
|
51
|
+
{...muiProps}
|
|
52
|
+
color={severity}
|
|
53
|
+
data-se={testId}
|
|
54
|
+
label={label}
|
|
55
|
+
variant={variant}
|
|
56
|
+
/>
|
|
45
57
|
);
|
|
46
58
|
};
|
package/src/Tabs.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import React, {
|
|
|
15
15
|
ReactNode,
|
|
16
16
|
memo,
|
|
17
17
|
useCallback,
|
|
18
|
+
useEffect,
|
|
18
19
|
useState,
|
|
19
20
|
} from "react";
|
|
20
21
|
import { Tab as MuiTab } from "@mui/material";
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
TabPanel as MuiTabPanel,
|
|
24
25
|
TabContext as MuiTabContext,
|
|
25
26
|
} from "@mui/lab";
|
|
27
|
+
import { SeleniumProps } from "./SeleniumProps";
|
|
26
28
|
|
|
27
29
|
export type TabItemProps = {
|
|
28
30
|
/**
|
|
@@ -45,7 +47,7 @@ export type TabItemProps = {
|
|
|
45
47
|
* The value associated with the TabItem
|
|
46
48
|
*/
|
|
47
49
|
value?: string;
|
|
48
|
-
};
|
|
50
|
+
} & SeleniumProps;
|
|
49
51
|
|
|
50
52
|
export type TabsProps = {
|
|
51
53
|
/**
|
|
@@ -53,17 +55,22 @@ export type TabsProps = {
|
|
|
53
55
|
*/
|
|
54
56
|
ariaLabel?: string;
|
|
55
57
|
/**
|
|
56
|
-
*
|
|
58
|
+
* @deprecated please use the `value` prop instead
|
|
59
|
+
* When `value` is provided, `initialValue` isn't used.
|
|
57
60
|
*/
|
|
58
61
|
initialValue?: string;
|
|
59
62
|
/**
|
|
60
63
|
* The TabItems to be included in the Tabs group
|
|
61
64
|
*/
|
|
62
65
|
tabs: TabItemProps[];
|
|
66
|
+
/**
|
|
67
|
+
* Identifier for the selected tab.
|
|
68
|
+
*/
|
|
69
|
+
value?: string;
|
|
63
70
|
};
|
|
64
71
|
|
|
65
|
-
const Tabs = ({ ariaLabel, initialValue
|
|
66
|
-
const [tabState, setTabState] = useState(initialValue);
|
|
72
|
+
const Tabs = ({ ariaLabel, initialValue, tabs, value }: TabsProps) => {
|
|
73
|
+
const [tabState, setTabState] = useState(initialValue ?? value ?? "0");
|
|
67
74
|
|
|
68
75
|
const onChange = useCallback(
|
|
69
76
|
(_event: React.SyntheticEvent, newState: string) => {
|
|
@@ -72,11 +79,18 @@ const Tabs = ({ ariaLabel, initialValue = "0", tabs }: TabsProps) => {
|
|
|
72
79
|
[]
|
|
73
80
|
);
|
|
74
81
|
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (value !== undefined) {
|
|
84
|
+
setTabState(value);
|
|
85
|
+
}
|
|
86
|
+
}, [value]);
|
|
87
|
+
|
|
75
88
|
return (
|
|
76
89
|
<MuiTabContext value={tabState}>
|
|
77
90
|
<MuiTabList onChange={onChange} aria-label={ariaLabel}>
|
|
78
91
|
{tabs.map((tab, index) => (
|
|
79
92
|
<MuiTab
|
|
93
|
+
data-se={tab.testId}
|
|
80
94
|
disabled={tab.isDisabled}
|
|
81
95
|
icon={tab.startIcon}
|
|
82
96
|
label={tab.label}
|
package/src/Tag.tsx
CHANGED
|
@@ -14,6 +14,7 @@ import { Chip as MuiChip, ChipProps as MuiChipProps } from "@mui/material";
|
|
|
14
14
|
import { memo, ReactElement, useCallback, useContext } from "react";
|
|
15
15
|
import { TagListContext } from "./TagListContext";
|
|
16
16
|
import { MuiPropsContext } from "./MuiPropsContext";
|
|
17
|
+
import { SeleniumProps } from "./SeleniumProps";
|
|
17
18
|
|
|
18
19
|
export type TagProps = {
|
|
19
20
|
icon?: ReactElement;
|
|
@@ -30,9 +31,16 @@ export type TagProps = {
|
|
|
30
31
|
* Callback fired when the remove button of the Tag is clicked
|
|
31
32
|
*/
|
|
32
33
|
onRemove?: MuiChipProps["onDelete"];
|
|
33
|
-
};
|
|
34
|
+
} & SeleniumProps;
|
|
34
35
|
|
|
35
|
-
const Tag = ({
|
|
36
|
+
const Tag = ({
|
|
37
|
+
icon,
|
|
38
|
+
isDisabled,
|
|
39
|
+
label,
|
|
40
|
+
onClick,
|
|
41
|
+
onRemove,
|
|
42
|
+
testId,
|
|
43
|
+
}: TagProps) => {
|
|
36
44
|
const { chipElementType } = useContext(TagListContext);
|
|
37
45
|
|
|
38
46
|
const renderTag = useCallback(
|
|
@@ -42,6 +50,7 @@ const Tag = ({ icon, isDisabled, label, onClick, onRemove }: TagProps) => {
|
|
|
42
50
|
aria-disabled={isDisabled}
|
|
43
51
|
clickable={onClick ? true : false}
|
|
44
52
|
component={chipElementType}
|
|
53
|
+
data-se={testId}
|
|
45
54
|
disabled={isDisabled}
|
|
46
55
|
icon={icon}
|
|
47
56
|
label={label}
|
|
@@ -49,7 +58,7 @@ const Tag = ({ icon, isDisabled, label, onClick, onRemove }: TagProps) => {
|
|
|
49
58
|
onDelete={onRemove}
|
|
50
59
|
/>
|
|
51
60
|
),
|
|
52
|
-
[chipElementType, icon, isDisabled, label, onClick, onRemove]
|
|
61
|
+
[chipElementType, icon, isDisabled, label, onClick, onRemove, testId]
|
|
53
62
|
);
|
|
54
63
|
|
|
55
64
|
return <MuiPropsContext.Consumer>{renderTag}</MuiPropsContext.Consumer>;
|
package/src/TagList.tsx
CHANGED
|
@@ -14,15 +14,16 @@ import { Tag } from "./Tag";
|
|
|
14
14
|
import { Stack } from "@mui/material";
|
|
15
15
|
import { memo, ReactElement, useMemo } from "react";
|
|
16
16
|
import { ChipElementType, TagListContext } from "./TagListContext";
|
|
17
|
+
import { SeleniumProps } from "./SeleniumProps";
|
|
17
18
|
|
|
18
19
|
export type TagListProps = {
|
|
19
20
|
/**
|
|
20
21
|
* The Tag or array of Tags within the TagList
|
|
21
22
|
*/
|
|
22
23
|
children: ReactElement<typeof Tag> | Array<ReactElement<typeof Tag>>;
|
|
23
|
-
};
|
|
24
|
+
} & SeleniumProps;
|
|
24
25
|
|
|
25
|
-
const TagList = ({ children }: TagListProps) => {
|
|
26
|
+
const TagList = ({ children, testId }: TagListProps) => {
|
|
26
27
|
const providerValue = useMemo<{
|
|
27
28
|
chipElementType: ChipElementType;
|
|
28
29
|
}>(
|
|
@@ -35,6 +36,7 @@ const TagList = ({ children }: TagListProps) => {
|
|
|
35
36
|
return (
|
|
36
37
|
<Stack
|
|
37
38
|
component="ul"
|
|
39
|
+
data-se={testId}
|
|
38
40
|
direction="row"
|
|
39
41
|
spacing={2}
|
|
40
42
|
useFlexGap
|