@khanacademy/wonder-blocks-modal 4.0.39 → 4.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 +13 -0
- package/dist/components/modal-content.d.ts +8 -9
- package/dist/components/modal-dialog.d.ts +3 -19
- package/dist/components/modal-footer.d.ts +5 -5
- package/dist/components/modal-header.d.ts +6 -7
- package/dist/components/modal-panel.d.ts +13 -14
- package/dist/es/index.js +287 -254
- package/dist/index.js +302 -269
- package/dist/themes/default.d.ts +33 -0
- package/dist/themes/khanmigo.d.ts +36 -0
- package/dist/themes/themed-modal-dialog.d.ts +48 -0
- package/package.json +2 -1
- package/src/components/__tests__/modal-dialog.test.tsx +78 -0
- package/src/components/modal-content.tsx +53 -54
- package/src/components/modal-dialog.tsx +103 -103
- package/src/components/modal-footer.tsx +8 -10
- package/src/components/modal-header.tsx +95 -102
- package/src/components/modal-panel.tsx +66 -73
- package/src/themes/default.ts +36 -0
- package/src/themes/khanmigo.ts +15 -0
- package/src/themes/themed-modal-dialog.tsx +44 -0
- package/tsconfig-build.json +1 -0
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/es/index.js
CHANGED
|
@@ -1,114 +1,174 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { StyleSheet } from 'aphrodite';
|
|
3
|
-
import { MediaLayoutContext, MediaLayout, MEDIA_MODAL_SPEC } from '@khanacademy/wonder-blocks-layout';
|
|
4
2
|
import { View, IDProvider } from '@khanacademy/wonder-blocks-core';
|
|
5
|
-
import
|
|
3
|
+
import { tokens, mergeTheme, createThemeContext, ThemeSwitcherContext, useScopedTheme, useStyles } from '@khanacademy/wonder-blocks-theming';
|
|
4
|
+
import { StyleSheet } from 'aphrodite';
|
|
6
5
|
import Color from '@khanacademy/wonder-blocks-color';
|
|
6
|
+
import Spacing from '@khanacademy/wonder-blocks-spacing';
|
|
7
7
|
import { HeadingMedium, LabelSmall } from '@khanacademy/wonder-blocks-typography';
|
|
8
8
|
import * as ReactDOM from 'react-dom';
|
|
9
9
|
import { withActionScheduler } from '@khanacademy/wonder-blocks-timing';
|
|
10
10
|
import xIcon from '@phosphor-icons/core/regular/x.svg';
|
|
11
11
|
import IconButton from '@khanacademy/wonder-blocks-icon-button';
|
|
12
|
+
import { MediaLayout } from '@khanacademy/wonder-blocks-layout';
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
ssrSize: "large",
|
|
27
|
-
mediaSpec: MEDIA_MODAL_SPEC
|
|
28
|
-
};
|
|
29
|
-
return React.createElement(MediaLayoutContext.Provider, {
|
|
30
|
-
value: contextValue
|
|
31
|
-
}, React.createElement(MediaLayout, {
|
|
32
|
-
styleSheets: styleSheets$3
|
|
33
|
-
}, ({
|
|
34
|
-
styles
|
|
35
|
-
}) => React.createElement(View, {
|
|
36
|
-
style: [styles.wrapper, style]
|
|
37
|
-
}, below && React.createElement(View, {
|
|
38
|
-
style: styles.below
|
|
39
|
-
}, below), React.createElement(View, {
|
|
40
|
-
role: role,
|
|
41
|
-
"aria-modal": "true",
|
|
42
|
-
"aria-labelledby": ariaLabelledBy,
|
|
43
|
-
"aria-describedby": ariaDescribedBy,
|
|
44
|
-
style: styles.dialog,
|
|
45
|
-
testId: testId
|
|
46
|
-
}, children), above && React.createElement(View, {
|
|
47
|
-
style: styles.above
|
|
48
|
-
}, above))));
|
|
49
|
-
}
|
|
14
|
+
function _extends() {
|
|
15
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
16
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
17
|
+
var source = arguments[i];
|
|
18
|
+
for (var key in source) {
|
|
19
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
20
|
+
target[key] = source[key];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return target;
|
|
25
|
+
};
|
|
26
|
+
return _extends.apply(this, arguments);
|
|
50
27
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
width: "100%",
|
|
61
|
-
height: "100%",
|
|
62
|
-
position: "relative"
|
|
28
|
+
|
|
29
|
+
const theme$1 = {
|
|
30
|
+
color: {
|
|
31
|
+
bg: {
|
|
32
|
+
inverse: tokens.color.darkBlue
|
|
33
|
+
},
|
|
34
|
+
text: {
|
|
35
|
+
inverse: tokens.color.white,
|
|
36
|
+
secondary: tokens.color.offBlack64
|
|
63
37
|
},
|
|
38
|
+
shadow: {
|
|
39
|
+
default: tokens.color.offBlack16
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
border: {
|
|
43
|
+
radius: tokens.border.radius.medium_4
|
|
44
|
+
},
|
|
45
|
+
spacing: {
|
|
64
46
|
dialog: {
|
|
65
|
-
|
|
66
|
-
height: "100%",
|
|
67
|
-
borderRadius: 4,
|
|
68
|
-
overflow: "hidden"
|
|
47
|
+
small: tokens.spacing.medium_16
|
|
69
48
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
top: 0,
|
|
74
|
-
left: 0,
|
|
75
|
-
bottom: 0,
|
|
76
|
-
right: 0,
|
|
77
|
-
zIndex: 1
|
|
49
|
+
panel: {
|
|
50
|
+
closeButton: tokens.spacing.medium_16,
|
|
51
|
+
footer: tokens.spacing.xLarge_32
|
|
78
52
|
},
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
bottom: 0,
|
|
85
|
-
right: 0,
|
|
86
|
-
zIndex: -1
|
|
87
|
-
}
|
|
88
|
-
}),
|
|
89
|
-
small: StyleSheet.create({
|
|
90
|
-
wrapper: {
|
|
91
|
-
padding: Spacing.medium_16,
|
|
92
|
-
flexDirection: "column"
|
|
53
|
+
header: {
|
|
54
|
+
xsmall: tokens.spacing.xSmall_8,
|
|
55
|
+
small: tokens.spacing.medium_16,
|
|
56
|
+
medium: tokens.spacing.large_24,
|
|
57
|
+
large: tokens.spacing.xLarge_32
|
|
93
58
|
}
|
|
94
|
-
}
|
|
59
|
+
}
|
|
95
60
|
};
|
|
96
61
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
62
|
+
const theme = mergeTheme(theme$1, {
|
|
63
|
+
color: {
|
|
64
|
+
bg: {
|
|
65
|
+
inverse: tokens.color.eggplant
|
|
66
|
+
}
|
|
100
67
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const themes = {
|
|
71
|
+
default: theme$1,
|
|
72
|
+
khanmigo: theme
|
|
73
|
+
};
|
|
74
|
+
const ModalDialogThemeContext = createThemeContext(theme$1);
|
|
75
|
+
function ThemeModalDialog(props) {
|
|
76
|
+
const currentTheme = React.useContext(ThemeSwitcherContext);
|
|
77
|
+
const theme = themes[currentTheme] || theme$1;
|
|
78
|
+
return React.createElement(ModalDialogThemeContext.Provider, {
|
|
79
|
+
value: theme
|
|
80
|
+
}, props.children);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const ModalDialogCore = React.forwardRef(function ModalDialogCore(props, ref) {
|
|
84
|
+
const {
|
|
85
|
+
above,
|
|
86
|
+
below,
|
|
87
|
+
role = "dialog",
|
|
88
|
+
style,
|
|
89
|
+
children,
|
|
90
|
+
testId,
|
|
91
|
+
"aria-labelledby": ariaLabelledBy,
|
|
92
|
+
"aria-describedby": ariaDescribedBy
|
|
93
|
+
} = props;
|
|
94
|
+
const {
|
|
95
|
+
theme
|
|
96
|
+
} = useScopedTheme(ModalDialogThemeContext);
|
|
97
|
+
const styles = useStyles(themedStylesFn$3, theme);
|
|
98
|
+
return React.createElement(View, {
|
|
99
|
+
style: [styles.wrapper, style]
|
|
100
|
+
}, below && React.createElement(View, {
|
|
101
|
+
style: styles.below
|
|
102
|
+
}, below), React.createElement(View, {
|
|
103
|
+
role: role,
|
|
104
|
+
"aria-modal": "true",
|
|
105
|
+
"aria-labelledby": ariaLabelledBy,
|
|
106
|
+
"aria-describedby": ariaDescribedBy,
|
|
107
|
+
ref: ref,
|
|
108
|
+
style: styles.dialog,
|
|
109
|
+
testId: testId
|
|
110
|
+
}, children), above && React.createElement(View, {
|
|
111
|
+
style: styles.above
|
|
112
|
+
}, above));
|
|
113
|
+
});
|
|
114
|
+
const ModalDialog = React.forwardRef(function ModalDialog(props, ref) {
|
|
115
|
+
return React.createElement(ThemeModalDialog, null, React.createElement(ModalDialogCore, _extends({}, props, {
|
|
116
|
+
ref: ref
|
|
117
|
+
})));
|
|
118
|
+
});
|
|
119
|
+
const small$2 = "@media (max-width: 767px)";
|
|
120
|
+
const themedStylesFn$3 = theme => ({
|
|
121
|
+
wrapper: {
|
|
122
|
+
display: "flex",
|
|
123
|
+
flexDirection: "row",
|
|
124
|
+
alignItems: "stretch",
|
|
125
|
+
width: "100%",
|
|
126
|
+
height: "100%",
|
|
127
|
+
position: "relative",
|
|
128
|
+
[small$2]: {
|
|
129
|
+
padding: theme.spacing.dialog.small,
|
|
130
|
+
flexDirection: "column"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
dialog: {
|
|
134
|
+
width: "100%",
|
|
135
|
+
height: "100%",
|
|
136
|
+
borderRadius: theme.border.radius,
|
|
137
|
+
overflow: "hidden"
|
|
138
|
+
},
|
|
139
|
+
above: {
|
|
140
|
+
pointerEvents: "none",
|
|
141
|
+
position: "absolute",
|
|
142
|
+
top: 0,
|
|
143
|
+
left: 0,
|
|
144
|
+
bottom: 0,
|
|
145
|
+
right: 0,
|
|
146
|
+
zIndex: 1
|
|
147
|
+
},
|
|
148
|
+
below: {
|
|
149
|
+
pointerEvents: "none",
|
|
150
|
+
position: "absolute",
|
|
151
|
+
top: 0,
|
|
152
|
+
left: 0,
|
|
153
|
+
bottom: 0,
|
|
154
|
+
right: 0,
|
|
155
|
+
zIndex: -1
|
|
108
156
|
}
|
|
157
|
+
});
|
|
158
|
+
ModalDialog.displayName = "ModalDialog";
|
|
159
|
+
|
|
160
|
+
function ModalFooter({
|
|
161
|
+
children
|
|
162
|
+
}) {
|
|
163
|
+
return React.createElement(View, {
|
|
164
|
+
style: styles$2.footer
|
|
165
|
+
}, children);
|
|
109
166
|
}
|
|
110
167
|
ModalFooter.__IS_MODAL_FOOTER__ = true;
|
|
111
|
-
|
|
168
|
+
ModalFooter.isComponentOf = instance => {
|
|
169
|
+
return instance && instance.type && instance.type.__IS_MODAL_FOOTER__;
|
|
170
|
+
};
|
|
171
|
+
const styles$2 = StyleSheet.create({
|
|
112
172
|
footer: {
|
|
113
173
|
flex: "0 0 auto",
|
|
114
174
|
boxSizing: "border-box",
|
|
@@ -125,78 +185,73 @@ const styles$3 = StyleSheet.create({
|
|
|
125
185
|
}
|
|
126
186
|
});
|
|
127
187
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
188
|
+
function ModalHeader(props) {
|
|
189
|
+
const {
|
|
190
|
+
breadcrumbs = undefined,
|
|
191
|
+
light,
|
|
192
|
+
subtitle = undefined,
|
|
193
|
+
testId,
|
|
194
|
+
title,
|
|
195
|
+
titleId
|
|
196
|
+
} = props;
|
|
197
|
+
if (subtitle && breadcrumbs) {
|
|
198
|
+
throw new Error("'subtitle' and 'breadcrumbs' can't be used together");
|
|
199
|
+
}
|
|
200
|
+
const {
|
|
201
|
+
theme
|
|
202
|
+
} = useScopedTheme(ModalDialogThemeContext);
|
|
203
|
+
const styles = useStyles(themedStylesFn$2, theme);
|
|
204
|
+
return React.createElement(View, {
|
|
205
|
+
style: [styles.header, !light && styles.dark],
|
|
206
|
+
testId: testId
|
|
207
|
+
}, breadcrumbs && React.createElement(View, {
|
|
208
|
+
style: styles.breadcrumbs
|
|
209
|
+
}, breadcrumbs), React.createElement(HeadingMedium, {
|
|
210
|
+
style: styles.title,
|
|
211
|
+
id: titleId,
|
|
212
|
+
testId: testId && `${testId}-title`
|
|
213
|
+
}, title), subtitle && React.createElement(LabelSmall, {
|
|
214
|
+
style: light && styles.subtitle,
|
|
215
|
+
testId: testId && `${testId}-subtitle`
|
|
216
|
+
}, subtitle));
|
|
217
|
+
}
|
|
218
|
+
const small$1 = "@media (max-width: 767px)";
|
|
219
|
+
const themedStylesFn$2 = theme => ({
|
|
220
|
+
header: {
|
|
221
|
+
boxShadow: `0px 1px 0px ${theme.color.shadow.default}`,
|
|
222
|
+
display: "flex",
|
|
223
|
+
flexDirection: "column",
|
|
224
|
+
minHeight: 66,
|
|
225
|
+
padding: `${theme.spacing.header.medium}px ${theme.spacing.header.large}px`,
|
|
226
|
+
position: "relative",
|
|
227
|
+
width: "100%",
|
|
228
|
+
[small$1]: {
|
|
229
|
+
paddingLeft: theme.spacing.header.small,
|
|
230
|
+
paddingRight: theme.spacing.header.small
|
|
140
231
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
232
|
+
},
|
|
233
|
+
dark: {
|
|
234
|
+
background: theme.color.bg.inverse,
|
|
235
|
+
color: theme.color.text.inverse
|
|
236
|
+
},
|
|
237
|
+
breadcrumbs: {
|
|
238
|
+
color: theme.color.text.secondary,
|
|
239
|
+
marginBottom: theme.spacing.header.xsmall
|
|
240
|
+
},
|
|
241
|
+
title: {
|
|
242
|
+
paddingRight: theme.spacing.header.small,
|
|
243
|
+
[small$1]: {
|
|
244
|
+
paddingRight: theme.spacing.header.large
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
subtitle: {
|
|
248
|
+
color: theme.color.text.secondary,
|
|
249
|
+
marginTop: theme.spacing.header.xsmall
|
|
158
250
|
}
|
|
159
|
-
}
|
|
251
|
+
});
|
|
160
252
|
ModalHeader.defaultProps = {
|
|
161
253
|
light: true
|
|
162
254
|
};
|
|
163
|
-
const styleSheets$2 = {
|
|
164
|
-
all: StyleSheet.create({
|
|
165
|
-
header: {
|
|
166
|
-
boxShadow: `0px 1px 0px ${Color.offBlack16}`,
|
|
167
|
-
display: "flex",
|
|
168
|
-
flexDirection: "column",
|
|
169
|
-
minHeight: 66,
|
|
170
|
-
padding: `${Spacing.large_24}px ${Spacing.xLarge_32}px`,
|
|
171
|
-
position: "relative",
|
|
172
|
-
width: "100%"
|
|
173
|
-
},
|
|
174
|
-
dark: {
|
|
175
|
-
background: Color.darkBlue,
|
|
176
|
-
color: Color.white
|
|
177
|
-
},
|
|
178
|
-
breadcrumbs: {
|
|
179
|
-
color: Color.offBlack64,
|
|
180
|
-
marginBottom: Spacing.xSmall_8
|
|
181
|
-
},
|
|
182
|
-
title: {
|
|
183
|
-
paddingRight: Spacing.medium_16
|
|
184
|
-
},
|
|
185
|
-
subtitle: {
|
|
186
|
-
color: Color.offBlack64,
|
|
187
|
-
marginTop: Spacing.xSmall_8
|
|
188
|
-
}
|
|
189
|
-
}),
|
|
190
|
-
small: StyleSheet.create({
|
|
191
|
-
header: {
|
|
192
|
-
paddingLeft: Spacing.medium_16,
|
|
193
|
-
paddingRight: Spacing.medium_16
|
|
194
|
-
},
|
|
195
|
-
title: {
|
|
196
|
-
paddingRight: Spacing.xLarge_32
|
|
197
|
-
}
|
|
198
|
-
})
|
|
199
|
-
};
|
|
200
255
|
|
|
201
256
|
const FOCUSABLE_ELEMENTS$1 = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
202
257
|
class FocusTrap extends React.Component {
|
|
@@ -260,21 +315,6 @@ class FocusTrap extends React.Component {
|
|
|
260
315
|
}
|
|
261
316
|
}
|
|
262
317
|
|
|
263
|
-
function _extends() {
|
|
264
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
265
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
266
|
-
var source = arguments[i];
|
|
267
|
-
for (var key in source) {
|
|
268
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
269
|
-
target[key] = source[key];
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return target;
|
|
274
|
-
};
|
|
275
|
-
return _extends.apply(this, arguments);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
318
|
const ModalLauncherPortalAttributeName = "data-modal-launcher-portal";
|
|
279
319
|
|
|
280
320
|
const FOCUSABLE_ELEMENTS = 'a[href], details, input, textarea, select, button:not([aria-label^="Close"])';
|
|
@@ -336,14 +376,14 @@ class ModalBackdrop extends React.Component {
|
|
|
336
376
|
[ModalLauncherPortalAttributeName]: true
|
|
337
377
|
};
|
|
338
378
|
return React.createElement(View, _extends({
|
|
339
|
-
style: styles$
|
|
379
|
+
style: styles$1.modalPositioner,
|
|
340
380
|
onMouseDown: this.handleMouseDown,
|
|
341
381
|
onMouseUp: this.handleMouseUp,
|
|
342
382
|
testId: testId
|
|
343
383
|
}, backdropProps), children);
|
|
344
384
|
}
|
|
345
385
|
}
|
|
346
|
-
const styles$
|
|
386
|
+
const styles$1 = StyleSheet.create({
|
|
347
387
|
modalPositioner: {
|
|
348
388
|
position: "fixed",
|
|
349
389
|
left: 0,
|
|
@@ -514,7 +554,7 @@ class ModalLauncher extends React.Component {
|
|
|
514
554
|
closeModal: this.handleCloseModal
|
|
515
555
|
}
|
|
516
556
|
}, renderedChildren, this.state.opened && ReactDOM.createPortal(React.createElement(FocusTrap, {
|
|
517
|
-
style: styles
|
|
557
|
+
style: styles.container
|
|
518
558
|
}, React.createElement(ModalBackdrop, {
|
|
519
559
|
initialFocusId: this.props.initialFocusId,
|
|
520
560
|
testId: this.props.testId,
|
|
@@ -548,59 +588,54 @@ class ModalLauncherKeypressListener extends React.Component {
|
|
|
548
588
|
return null;
|
|
549
589
|
}
|
|
550
590
|
}
|
|
551
|
-
const styles
|
|
591
|
+
const styles = StyleSheet.create({
|
|
552
592
|
container: {
|
|
553
593
|
zIndex: 1080
|
|
554
594
|
}
|
|
555
595
|
});
|
|
556
596
|
var modalLauncher = withActionScheduler(ModalLauncher);
|
|
557
597
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
style: [styles.wrapper, scrollOverflow && styles.scrollOverflow]
|
|
574
|
-
}, React.createElement(View, {
|
|
575
|
-
style: [styles.content, style]
|
|
576
|
-
}, children)));
|
|
577
|
-
}
|
|
598
|
+
function ModalContent(props) {
|
|
599
|
+
const {
|
|
600
|
+
scrollOverflow,
|
|
601
|
+
style,
|
|
602
|
+
children
|
|
603
|
+
} = props;
|
|
604
|
+
const {
|
|
605
|
+
theme
|
|
606
|
+
} = useScopedTheme(ModalDialogThemeContext);
|
|
607
|
+
const styles = useStyles(themedStylesFn$1, theme);
|
|
608
|
+
return React.createElement(View, {
|
|
609
|
+
style: [styles.wrapper, scrollOverflow && styles.scrollOverflow]
|
|
610
|
+
}, React.createElement(View, {
|
|
611
|
+
style: [styles.content, style]
|
|
612
|
+
}, children));
|
|
578
613
|
}
|
|
579
|
-
ModalContent.defaultProps = {
|
|
580
|
-
scrollOverflow: true
|
|
581
|
-
};
|
|
582
614
|
ModalContent.__IS_MODAL_CONTENT__ = true;
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
615
|
+
ModalContent.isComponentOf = instance => {
|
|
616
|
+
return instance && instance.type && instance.type.__IS_MODAL_CONTENT__;
|
|
617
|
+
};
|
|
618
|
+
const small = "@media (max-width: 767px)";
|
|
619
|
+
const themedStylesFn$1 = theme => ({
|
|
620
|
+
wrapper: {
|
|
621
|
+
flex: 1,
|
|
622
|
+
display: "block"
|
|
623
|
+
},
|
|
624
|
+
scrollOverflow: {
|
|
625
|
+
overflow: "auto"
|
|
626
|
+
},
|
|
627
|
+
content: {
|
|
628
|
+
flex: 1,
|
|
629
|
+
minHeight: "100%",
|
|
630
|
+
padding: Spacing.xLarge_32,
|
|
631
|
+
boxSizing: "border-box",
|
|
632
|
+
[small]: {
|
|
601
633
|
padding: `${Spacing.xLarge_32}px ${Spacing.medium_16}px`
|
|
602
634
|
}
|
|
603
|
-
}
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
ModalContent.defaultProps = {
|
|
638
|
+
scrollOverflow: true
|
|
604
639
|
};
|
|
605
640
|
|
|
606
641
|
class CloseButton extends React.Component {
|
|
@@ -630,14 +665,23 @@ class CloseButton extends React.Component {
|
|
|
630
665
|
}
|
|
631
666
|
}
|
|
632
667
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
668
|
+
function ModalPanel({
|
|
669
|
+
closeButtonVisible = true,
|
|
670
|
+
scrollOverflow = true,
|
|
671
|
+
light = true,
|
|
672
|
+
content,
|
|
673
|
+
footer,
|
|
674
|
+
header,
|
|
675
|
+
onClose,
|
|
676
|
+
style,
|
|
677
|
+
testId
|
|
678
|
+
}) {
|
|
679
|
+
const {
|
|
680
|
+
theme
|
|
681
|
+
} = useScopedTheme(ModalDialogThemeContext);
|
|
682
|
+
const styles = useStyles(themedStylesFn, theme);
|
|
683
|
+
const renderMainContent = React.useCallback(() => {
|
|
684
|
+
const mainContent = ModalContent.isComponentOf(content) ? content : React.createElement(ModalContent, null, content);
|
|
641
685
|
if (!mainContent) {
|
|
642
686
|
return mainContent;
|
|
643
687
|
}
|
|
@@ -645,35 +689,24 @@ class ModalPanel extends React.Component {
|
|
|
645
689
|
scrollOverflow,
|
|
646
690
|
style: [!!footer && styles.hasFooter, mainContent.props.style]
|
|
647
691
|
});
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const mainContent = this.renderMainContent();
|
|
660
|
-
return React.createElement(View, {
|
|
661
|
-
style: [styles.wrapper, !light && styles.dark, style],
|
|
662
|
-
testId: testId && `${testId}-panel`
|
|
663
|
-
}, closeButtonVisible && React.createElement(CloseButton, {
|
|
664
|
-
light: !light,
|
|
665
|
-
onClick: onClose,
|
|
666
|
-
style: styles.closeButton,
|
|
667
|
-
testId: testId && `${testId}-close`
|
|
668
|
-
}), header, mainContent, !footer || ModalFooter.isClassOf(footer) ? footer : React.createElement(ModalFooter, null, footer));
|
|
669
|
-
}
|
|
692
|
+
}, [content, footer, scrollOverflow, styles.hasFooter]);
|
|
693
|
+
const mainContent = renderMainContent();
|
|
694
|
+
return React.createElement(View, {
|
|
695
|
+
style: [styles.wrapper, !light && styles.dark, style],
|
|
696
|
+
testId: testId && `${testId}-panel`
|
|
697
|
+
}, closeButtonVisible && React.createElement(CloseButton, {
|
|
698
|
+
light: !light,
|
|
699
|
+
onClick: onClose,
|
|
700
|
+
style: styles.closeButton,
|
|
701
|
+
testId: testId && `${testId}-close`
|
|
702
|
+
}), header, mainContent, !footer || ModalFooter.isComponentOf(footer) ? footer : React.createElement(ModalFooter, null, footer));
|
|
670
703
|
}
|
|
671
704
|
ModalPanel.defaultProps = {
|
|
672
705
|
closeButtonVisible: true,
|
|
673
706
|
scrollOverflow: true,
|
|
674
707
|
light: true
|
|
675
708
|
};
|
|
676
|
-
const
|
|
709
|
+
const themedStylesFn = theme => ({
|
|
677
710
|
wrapper: {
|
|
678
711
|
flex: "1 1 auto",
|
|
679
712
|
position: "relative",
|
|
@@ -687,16 +720,16 @@ const styles = StyleSheet.create({
|
|
|
687
720
|
},
|
|
688
721
|
closeButton: {
|
|
689
722
|
position: "absolute",
|
|
690
|
-
right:
|
|
691
|
-
top:
|
|
723
|
+
right: theme.spacing.panel.closeButton,
|
|
724
|
+
top: theme.spacing.panel.closeButton,
|
|
692
725
|
zIndex: 1
|
|
693
726
|
},
|
|
694
727
|
dark: {
|
|
695
|
-
background:
|
|
696
|
-
color:
|
|
728
|
+
background: theme.color.bg.inverse,
|
|
729
|
+
color: theme.color.text.inverse
|
|
697
730
|
},
|
|
698
731
|
hasFooter: {
|
|
699
|
-
paddingBottom:
|
|
732
|
+
paddingBottom: theme.spacing.panel.footer
|
|
700
733
|
}
|
|
701
734
|
});
|
|
702
735
|
|