@okta/odyssey-react-mui 1.13.9 → 1.13.11
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 +8 -0
- package/dist/Button.js +5 -2
- package/dist/Button.js.map +1 -1
- package/dist/ButtonContext.js +18 -0
- package/dist/ButtonContext.js.map +1 -0
- package/dist/Form.js +5 -2
- package/dist/Form.js.map +1 -1
- package/dist/MenuContext.js.map +1 -1
- package/dist/Tile.js +94 -0
- package/dist/Tile.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/Button.d.ts +1 -1
- package/dist/src/Button.d.ts.map +1 -1
- package/dist/src/ButtonContext.d.ts +18 -0
- package/dist/src/ButtonContext.d.ts.map +1 -0
- package/dist/src/Form.d.ts +8 -3
- package/dist/src/Form.d.ts.map +1 -1
- package/dist/src/MenuContext.d.ts.map +1 -1
- package/dist/src/Tile.d.ts +33 -0
- package/dist/src/Tile.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/theme/components.d.ts.map +1 -1
- package/dist/theme/components.js +58 -0
- package/dist/theme/components.js.map +1 -1
- package/dist/tsconfig.production.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/Button.tsx +9 -1
- package/src/ButtonContext.tsx +23 -0
- package/src/Form.tsx +15 -6
- package/src/MenuContext.ts +1 -1
- package/src/Tile.tsx +147 -0
- package/src/index.ts +1 -0
- package/src/theme/components.tsx +64 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okta/odyssey-react-mui",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.11",
|
|
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.13.
|
|
54
|
+
"@okta/odyssey-design-tokens": "1.13.11",
|
|
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": "056c36afdaaae83d531f50b9dd04eca4b8b5fb4c"
|
|
67
67
|
}
|
package/src/Button.tsx
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
ReactElement,
|
|
20
20
|
useCallback,
|
|
21
21
|
useImperativeHandle,
|
|
22
|
+
useMemo,
|
|
22
23
|
useRef,
|
|
23
24
|
} from "react";
|
|
24
25
|
|
|
@@ -26,6 +27,7 @@ import { MuiPropsContext, useMuiProps } from "./MuiPropsContext";
|
|
|
26
27
|
import { Tooltip } from "./Tooltip";
|
|
27
28
|
import type { HtmlProps } from "./HtmlProps";
|
|
28
29
|
import { FocusHandle } from "./inputUtils";
|
|
30
|
+
import { useButton } from "./ButtonContext";
|
|
29
31
|
|
|
30
32
|
export const buttonSizeValues = ["small", "medium", "large"] as const;
|
|
31
33
|
export const buttonTypeValues = ["button", "submit", "reset"] as const;
|
|
@@ -142,7 +144,7 @@ const Button = ({
|
|
|
142
144
|
endIcon,
|
|
143
145
|
id,
|
|
144
146
|
isDisabled,
|
|
145
|
-
isFullWidth,
|
|
147
|
+
isFullWidth: isFullWidthProp,
|
|
146
148
|
label = "",
|
|
147
149
|
onClick,
|
|
148
150
|
size = "medium",
|
|
@@ -160,6 +162,12 @@ const Button = ({
|
|
|
160
162
|
// "secondary" in lieu of making a breaking change
|
|
161
163
|
const variant = variantProp === "tertiary" ? "secondary" : variantProp;
|
|
162
164
|
const localButtonRef = useRef<HTMLButtonElement>(null);
|
|
165
|
+
const buttonContext = useButton();
|
|
166
|
+
const isFullWidth = useMemo(
|
|
167
|
+
() =>
|
|
168
|
+
buttonContext.isFullWidth ? buttonContext.isFullWidth : isFullWidthProp,
|
|
169
|
+
[buttonContext, isFullWidthProp]
|
|
170
|
+
);
|
|
163
171
|
|
|
164
172
|
useImperativeHandle(
|
|
165
173
|
buttonRef,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2024-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
|
+
import { createContext, useContext } from "react";
|
|
14
|
+
|
|
15
|
+
export type ButtonContextValue = {
|
|
16
|
+
isFullWidth: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const ButtonContext = createContext<ButtonContextValue>({
|
|
20
|
+
isFullWidth: false,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const useButton = () => useContext(ButtonContext);
|
package/src/Form.tsx
CHANGED
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
* See the License for the specific language governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { memo, ReactElement } from "react";
|
|
14
|
-
|
|
13
|
+
import { FormEventHandler, memo, ReactElement } from "react";
|
|
15
14
|
import { Box } from "@mui/material";
|
|
15
|
+
|
|
16
16
|
import { Button } from "./Button";
|
|
17
17
|
import { Callout } from "./Callout";
|
|
18
|
+
import { FieldComponentProps } from "./FieldComponentProps";
|
|
19
|
+
import type { HtmlProps } from "./HtmlProps";
|
|
18
20
|
import { Heading4, Support } from "./Typography";
|
|
19
21
|
import { useUniqueId } from "./useUniqueId";
|
|
20
|
-
import type { HtmlProps } from "./HtmlProps";
|
|
21
22
|
|
|
22
23
|
export const formEncodingTypeValues = [
|
|
23
24
|
"application/x-www-form-urlencoded",
|
|
@@ -76,6 +77,10 @@ export type FormProps = {
|
|
|
76
77
|
* it can be overridden by a formnovalidate attribute on a <button>, <input type="submit">, or <input type="image"> element belonging to the form.
|
|
77
78
|
*/
|
|
78
79
|
noValidate?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Callback that passes the submit event to the consumer
|
|
82
|
+
*/
|
|
83
|
+
onSubmit?: FormEventHandler<HTMLFormElement>;
|
|
79
84
|
/**
|
|
80
85
|
* Indicates where to display the response after submitting the form. It is a name/keyword for a browsing context (for example, tab, window, or iframe).
|
|
81
86
|
* This value can be overridden by a formtarget attribute on a <button>, <input type="submit">, or <input type="image"> element.
|
|
@@ -85,7 +90,8 @@ export type FormProps = {
|
|
|
85
90
|
* The title of the Form
|
|
86
91
|
*/
|
|
87
92
|
title?: string;
|
|
88
|
-
} &
|
|
93
|
+
} & Pick<FieldComponentProps, "isFullWidth"> &
|
|
94
|
+
HtmlProps;
|
|
89
95
|
|
|
90
96
|
const Form = ({
|
|
91
97
|
alert,
|
|
@@ -95,9 +101,11 @@ const Form = ({
|
|
|
95
101
|
encodingType,
|
|
96
102
|
formActions,
|
|
97
103
|
id: idOverride,
|
|
104
|
+
isFullWidth,
|
|
98
105
|
method,
|
|
99
106
|
name,
|
|
100
107
|
noValidate = false,
|
|
108
|
+
onSubmit,
|
|
101
109
|
target,
|
|
102
110
|
testId,
|
|
103
111
|
title,
|
|
@@ -115,9 +123,10 @@ const Form = ({
|
|
|
115
123
|
method={method}
|
|
116
124
|
name={name}
|
|
117
125
|
noValidate={noValidate}
|
|
126
|
+
onSubmit={onSubmit}
|
|
118
127
|
target={target}
|
|
119
128
|
sx={{
|
|
120
|
-
maxWidth: (theme) => theme.mixins.maxWidth,
|
|
129
|
+
maxWidth: (theme) => (isFullWidth ? "100%" : theme.mixins.maxWidth),
|
|
121
130
|
margin: (theme) => theme.spacing(0),
|
|
122
131
|
padding: (theme) => theme.spacing(0),
|
|
123
132
|
}}
|
|
@@ -142,7 +151,7 @@ const Form = ({
|
|
|
142
151
|
component="div"
|
|
143
152
|
sx={{
|
|
144
153
|
display: "flex",
|
|
145
|
-
justifyContent: "flex-
|
|
154
|
+
justifyContent: "flex-end",
|
|
146
155
|
gap: (theme) => theme.spacing(1),
|
|
147
156
|
marginBlockStart: (theme) => theme.spacing(7),
|
|
148
157
|
}}
|
package/src/MenuContext.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* See the License for the specific language governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { MouseEventHandler, createContext } from "react";
|
|
14
14
|
|
|
15
15
|
export type MenuContextType = {
|
|
16
16
|
closeMenu: () => void;
|
package/src/Tile.tsx
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2022-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
|
+
import { ReactElement, memo, useMemo } from "react";
|
|
14
|
+
|
|
15
|
+
import { NullElement } from "./NullElement";
|
|
16
|
+
import {
|
|
17
|
+
Card as MuiCard,
|
|
18
|
+
CardActions as MuiCardActions,
|
|
19
|
+
CardActionArea as MuiCardActionArea,
|
|
20
|
+
} from "@mui/material";
|
|
21
|
+
import { Button } from "./Button";
|
|
22
|
+
import { ButtonContext } from "./ButtonContext";
|
|
23
|
+
import { Heading5, Paragraph, Support } from "./Typography";
|
|
24
|
+
import { MoreIcon } from "./icons.generated";
|
|
25
|
+
import { HtmlProps } from "./HtmlProps";
|
|
26
|
+
import styled from "@emotion/styled";
|
|
27
|
+
import {
|
|
28
|
+
DesignTokens,
|
|
29
|
+
useOdysseyDesignTokens,
|
|
30
|
+
} from "./OdysseyDesignTokensContext";
|
|
31
|
+
import { MenuButton } from "./MenuButton";
|
|
32
|
+
|
|
33
|
+
export type TileProps = {
|
|
34
|
+
description?: string;
|
|
35
|
+
image?: ReactElement | NullElement; // Icon or image
|
|
36
|
+
menuItems?: ReactElement;
|
|
37
|
+
overline?: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
} & ( // You can't have actions and onClick at the same time
|
|
40
|
+
| {
|
|
41
|
+
onClick: () => void;
|
|
42
|
+
button?: never;
|
|
43
|
+
menuItems?: never;
|
|
44
|
+
}
|
|
45
|
+
| {
|
|
46
|
+
onClick?: never;
|
|
47
|
+
button?: ReactElement<typeof Button> | NullElement;
|
|
48
|
+
menuItems?: ReactElement;
|
|
49
|
+
}
|
|
50
|
+
) &
|
|
51
|
+
HtmlProps;
|
|
52
|
+
|
|
53
|
+
const ImageContainer = styled.div<{
|
|
54
|
+
odysseyDesignTokens: DesignTokens;
|
|
55
|
+
hasMenuItems: boolean;
|
|
56
|
+
}>`
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: flex-start;
|
|
59
|
+
max-height: 64px;
|
|
60
|
+
margin-block-end: ${(props) => props.odysseyDesignTokens.Spacing5};
|
|
61
|
+
padding-right: ${(props) =>
|
|
62
|
+
props.hasMenuItems ? props.odysseyDesignTokens.Spacing5 : 0};
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
const MenuButtonContainer = styled.div<{ odysseyDesignTokens: DesignTokens }>`
|
|
66
|
+
position: absolute;
|
|
67
|
+
right: ${(props) => props.odysseyDesignTokens.Spacing3};
|
|
68
|
+
top: ${(props) => props.odysseyDesignTokens.Spacing3};
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
const Tile = ({
|
|
72
|
+
button,
|
|
73
|
+
description,
|
|
74
|
+
image,
|
|
75
|
+
menuItems,
|
|
76
|
+
onClick,
|
|
77
|
+
overline,
|
|
78
|
+
title,
|
|
79
|
+
}: TileProps) => {
|
|
80
|
+
const odysseyDesignTokens = useOdysseyDesignTokens();
|
|
81
|
+
|
|
82
|
+
const cardContent = useMemo(() => {
|
|
83
|
+
return (
|
|
84
|
+
<>
|
|
85
|
+
{image && (
|
|
86
|
+
<ImageContainer
|
|
87
|
+
odysseyDesignTokens={odysseyDesignTokens}
|
|
88
|
+
hasMenuItems={Boolean(menuItems)}
|
|
89
|
+
>
|
|
90
|
+
{image}
|
|
91
|
+
</ImageContainer>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
{overline && <Support component="div">{overline}</Support>}
|
|
95
|
+
{title && <Heading5 component="div">{title}</Heading5>}
|
|
96
|
+
{description && (
|
|
97
|
+
<Paragraph color="textSecondary">{description}</Paragraph>
|
|
98
|
+
)}
|
|
99
|
+
|
|
100
|
+
{button && (
|
|
101
|
+
<MuiCardActions>
|
|
102
|
+
<ButtonContext.Provider value={{ isFullWidth: true }}>
|
|
103
|
+
{button}
|
|
104
|
+
</ButtonContext.Provider>
|
|
105
|
+
</MuiCardActions>
|
|
106
|
+
)}
|
|
107
|
+
</>
|
|
108
|
+
);
|
|
109
|
+
}, [
|
|
110
|
+
button,
|
|
111
|
+
description,
|
|
112
|
+
image,
|
|
113
|
+
menuItems,
|
|
114
|
+
overline,
|
|
115
|
+
title,
|
|
116
|
+
odysseyDesignTokens,
|
|
117
|
+
]);
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<MuiCard className={onClick ? "isClickable" : ""}>
|
|
121
|
+
{onClick && (
|
|
122
|
+
<MuiCardActionArea onClick={onClick}>{cardContent}</MuiCardActionArea>
|
|
123
|
+
)}
|
|
124
|
+
|
|
125
|
+
{!onClick && cardContent}
|
|
126
|
+
|
|
127
|
+
{menuItems && (
|
|
128
|
+
<MenuButtonContainer odysseyDesignTokens={odysseyDesignTokens}>
|
|
129
|
+
<MenuButton
|
|
130
|
+
endIcon={<MoreIcon />}
|
|
131
|
+
ariaLabel="Tile menu"
|
|
132
|
+
buttonVariant="floating"
|
|
133
|
+
menuAlignment="right"
|
|
134
|
+
size="small"
|
|
135
|
+
>
|
|
136
|
+
{menuItems}
|
|
137
|
+
</MenuButton>
|
|
138
|
+
</MenuButtonContainer>
|
|
139
|
+
)}
|
|
140
|
+
</MuiCard>
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const MemoizedTile = memo(Tile);
|
|
145
|
+
MemoizedTile.displayName = "Tile";
|
|
146
|
+
|
|
147
|
+
export { MemoizedTile as Tile };
|
package/src/index.ts
CHANGED
package/src/theme/components.tsx
CHANGED
|
@@ -701,6 +701,70 @@ export const components = ({
|
|
|
701
701
|
disableRipple: true,
|
|
702
702
|
},
|
|
703
703
|
},
|
|
704
|
+
MuiCard: {
|
|
705
|
+
styleOverrides: {
|
|
706
|
+
root: () => ({
|
|
707
|
+
backgroundColor: odysseyTokens.HueNeutralWhite,
|
|
708
|
+
borderRadius: odysseyTokens.BorderRadiusOuter,
|
|
709
|
+
boxShadow: odysseyTokens.DepthMedium,
|
|
710
|
+
padding: odysseyTokens.Spacing5,
|
|
711
|
+
position: "relative",
|
|
712
|
+
transition: `all ${odysseyTokens.TransitionDurationMain} ${odysseyTokens.TransitionTimingMain}`,
|
|
713
|
+
|
|
714
|
+
"& img": {
|
|
715
|
+
height: "64px",
|
|
716
|
+
},
|
|
717
|
+
|
|
718
|
+
"&.isClickable:hover": {
|
|
719
|
+
backgroundColor: odysseyTokens.HueNeutral50,
|
|
720
|
+
boxShadow: odysseyTokens.DepthHigh,
|
|
721
|
+
},
|
|
722
|
+
|
|
723
|
+
[`& .${typographyClasses.h5}`]: {
|
|
724
|
+
lineHeight: odysseyTokens.TypographyLineHeightHeading5,
|
|
725
|
+
marginBottom: odysseyTokens.Spacing3,
|
|
726
|
+
},
|
|
727
|
+
|
|
728
|
+
[`& .${typographyClasses.subtitle2}`]: {
|
|
729
|
+
marginBottom: odysseyTokens.Spacing1,
|
|
730
|
+
textTransform: "uppercase",
|
|
731
|
+
fontWeight: odysseyTokens.TypographyWeightBodyBold,
|
|
732
|
+
fontSize: odysseyTokens.TypographySizeOverline,
|
|
733
|
+
lineHeight: odysseyTokens.TypographyLineHeightOverline,
|
|
734
|
+
color: odysseyTokens.TypographyColorSubordinate,
|
|
735
|
+
letterSpacing: 1.3,
|
|
736
|
+
},
|
|
737
|
+
|
|
738
|
+
[`& .${typographyClasses.body1}`]: {
|
|
739
|
+
fontSize: odysseyTokens.TypographySizeSubordinate,
|
|
740
|
+
lineHeight: odysseyTokens.TypographyLineHeightBody,
|
|
741
|
+
},
|
|
742
|
+
}),
|
|
743
|
+
},
|
|
744
|
+
},
|
|
745
|
+
MuiCardActionArea: {
|
|
746
|
+
styleOverrides: {
|
|
747
|
+
root: () => ({
|
|
748
|
+
margin: `-${odysseyTokens.Spacing5}`,
|
|
749
|
+
padding: odysseyTokens.Spacing5,
|
|
750
|
+
width: `calc(100% + (${odysseyTokens.Spacing5} * 2))`,
|
|
751
|
+
|
|
752
|
+
"&:hover": {
|
|
753
|
+
"& .MuiCardActionArea-focusHighlight": {
|
|
754
|
+
display: "none",
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
}),
|
|
758
|
+
},
|
|
759
|
+
},
|
|
760
|
+
MuiCardActions: {
|
|
761
|
+
styleOverrides: {
|
|
762
|
+
root: () => ({
|
|
763
|
+
marginBlockStart: odysseyTokens.Spacing5,
|
|
764
|
+
padding: 0,
|
|
765
|
+
}),
|
|
766
|
+
},
|
|
767
|
+
},
|
|
704
768
|
MuiCheckbox: {
|
|
705
769
|
defaultProps: {
|
|
706
770
|
size: "small",
|