@khanacademy/wonder-blocks-modal 3.0.7 → 3.0.9
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 +44 -0
- package/dist/components/close-button.d.ts +31 -0
- package/dist/components/close-button.js.flow +43 -0
- package/dist/components/focus-trap.d.ts +57 -0
- package/dist/components/focus-trap.js.flow +69 -0
- package/dist/components/modal-backdrop.d.ts +50 -0
- package/dist/components/modal-backdrop.js.flow +63 -0
- package/dist/components/modal-content.d.ts +23 -0
- package/dist/components/modal-content.js.flow +39 -0
- package/dist/components/modal-context.d.ts +6 -0
- package/dist/components/modal-context.js.flow +14 -0
- package/dist/components/modal-dialog.d.ts +60 -0
- package/dist/components/modal-dialog.js.flow +75 -0
- package/dist/components/modal-footer.d.ts +27 -0
- package/dist/components/modal-footer.js.flow +34 -0
- package/dist/components/modal-header.d.ts +93 -0
- package/dist/components/modal-header.js.flow +110 -0
- package/dist/components/modal-launcher.d.ts +17 -0
- package/dist/components/modal-launcher.js.flow +34 -0
- package/dist/components/modal-panel.d.ts +84 -0
- package/dist/components/modal-panel.js.flow +102 -0
- package/dist/components/one-pane-dialog.d.ts +124 -0
- package/dist/components/one-pane-dialog.js.flow +153 -0
- package/dist/components/scroll-disabler.d.ts +24 -0
- package/dist/components/scroll-disabler.js.flow +21 -0
- package/dist/es/index.js +222 -210
- package/dist/index.d.ts +8 -0
- package/dist/index.js +237 -226
- package/dist/index.js.flow +23 -2
- package/dist/util/constants.d.ts +5 -0
- package/dist/util/constants.js.flow +12 -0
- package/dist/util/find-focusable-nodes.d.ts +1 -0
- package/dist/util/find-focusable-nodes.js.flow +10 -0
- package/dist/util/maybe-get-portal-mounted-modal-host-element.d.ts +9 -0
- package/dist/util/maybe-get-portal-mounted-modal-host-element.js.flow +18 -0
- package/dist/util/types.d.ts +12 -0
- package/dist/util/types.js.flow +20 -0
- package/package.json +13 -13
- package/src/components/__tests__/{close-button.test.js → close-button.test.tsx} +0 -1
- package/src/components/__tests__/{focus-trap.test.js → focus-trap.test.tsx} +0 -1
- package/src/components/__tests__/{modal-backdrop.test.js → modal-backdrop.test.tsx} +0 -1
- package/src/components/__tests__/{modal-header.test.js → modal-header.test.tsx} +3 -2
- package/src/components/__tests__/{modal-launcher.test.js → modal-launcher.test.tsx} +11 -15
- package/src/components/__tests__/{modal-panel.test.js → modal-panel.test.tsx} +0 -1
- package/src/components/__tests__/{one-pane-dialog.test.js → one-pane-dialog.test.tsx} +0 -1
- package/src/components/{close-button.js → close-button.tsx} +7 -11
- package/src/components/{focus-trap.js → focus-trap.tsx} +12 -12
- package/src/components/{modal-backdrop.js → modal-backdrop.tsx} +20 -18
- package/src/components/{modal-content.js → modal-content.tsx} +11 -12
- package/src/components/modal-context.ts +13 -0
- package/src/components/{modal-dialog.js → modal-dialog.tsx} +15 -23
- package/src/components/{modal-footer.js → modal-footer.tsx} +5 -6
- package/src/components/{modal-header.js → modal-header.tsx} +20 -26
- package/src/components/{modal-launcher.js → modal-launcher.tsx} +29 -50
- package/src/components/{modal-panel.js → modal-panel.tsx} +27 -28
- package/src/components/{one-pane-dialog.js → one-pane-dialog.tsx} +37 -45
- package/src/components/{scroll-disabler.js → scroll-disabler.ts} +3 -4
- package/src/{index.js → index.ts} +0 -1
- package/src/util/{constants.js → constants.ts} +0 -2
- package/src/util/{find-focusable-nodes.js → find-focusable-nodes.ts} +0 -2
- package/src/util/{maybe-get-portal-mounted-modal-host-element.test.js → maybe-get-portal-mounted-modal-host-element.test.tsx} +4 -5
- package/src/util/{maybe-get-portal-mounted-modal-host-element.js → maybe-get-portal-mounted-modal-host-element.ts} +5 -4
- package/src/util/{types.js → types.ts} +3 -2
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/src/components/__docs__/modal-dialog.stories.js +0 -308
- package/src/components/__docs__/modal-footer.stories.js +0 -337
- package/src/components/__docs__/modal-header.argtypes.js +0 -76
- package/src/components/__docs__/modal-header.stories.js +0 -294
- package/src/components/__docs__/modal-launcher.argtypes.js +0 -78
- package/src/components/__docs__/modal-launcher.stories.js +0 -513
- package/src/components/__docs__/modal-panel.stories.js +0 -414
- package/src/components/__docs__/one-pane-dialog.argtypes.js +0 -108
- package/src/components/__docs__/one-pane-dialog.stories.js +0 -582
- package/src/components/modal-context.js +0 -14
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {StyleSheet} from "aphrodite";
|
|
4
3
|
import {
|
|
@@ -11,57 +10,50 @@ import type {StyleType} from "@khanacademy/wonder-blocks-core";
|
|
|
11
10
|
import type {MediaLayoutContextValue} from "@khanacademy/wonder-blocks-layout";
|
|
12
11
|
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
13
12
|
|
|
14
|
-
type Props = {
|
|
13
|
+
type Props = {
|
|
15
14
|
/**
|
|
16
15
|
* The dialog content
|
|
17
16
|
*/
|
|
18
|
-
children: React.
|
|
19
|
-
|
|
17
|
+
children: React.ReactNode;
|
|
20
18
|
/**
|
|
21
19
|
* When set, provides a component that can render content above the top of the modal;
|
|
22
20
|
* when not set, no additional content is shown above the modal.
|
|
23
21
|
* This prop is passed down to the ModalDialog.
|
|
24
22
|
*/
|
|
25
|
-
above?: React.
|
|
26
|
-
|
|
23
|
+
above?: React.ReactNode;
|
|
27
24
|
/**
|
|
28
25
|
* When set, provides a component that will render content below the bottom of the modal;
|
|
29
26
|
* when not set, no additional content is shown below the modal.
|
|
30
27
|
* This prop is passed down to the ModalDialog.
|
|
31
28
|
*/
|
|
32
|
-
below?: React.
|
|
33
|
-
|
|
29
|
+
below?: React.ReactNode;
|
|
34
30
|
/**
|
|
35
31
|
* When set, overrides the default role value. Default role is "dialog"
|
|
36
32
|
* Roles other than dialog and alertdialog aren't appropriate for this
|
|
37
33
|
* component
|
|
38
34
|
*/
|
|
39
|
-
role?: "dialog" | "alertdialog"
|
|
40
|
-
|
|
35
|
+
role?: "dialog" | "alertdialog";
|
|
41
36
|
/**
|
|
42
37
|
* Custom styles
|
|
43
38
|
*/
|
|
44
|
-
style?: StyleType
|
|
45
|
-
|
|
39
|
+
style?: StyleType;
|
|
46
40
|
/**
|
|
47
41
|
* Test ID used for e2e testing.
|
|
48
42
|
*/
|
|
49
|
-
testId?: string
|
|
50
|
-
|
|
43
|
+
testId?: string;
|
|
51
44
|
/**
|
|
52
45
|
* The ID of the content labelling this dialog, if applicable.
|
|
53
46
|
*/
|
|
54
|
-
"aria-labelledby"?: string
|
|
55
|
-
|
|
47
|
+
["aria-labelledby"]?: string;
|
|
56
48
|
/**
|
|
57
49
|
* The ID of the content describing this dialog, if applicable.
|
|
58
50
|
*/
|
|
59
|
-
"aria-describedby"?: string
|
|
60
|
-
|
|
51
|
+
["aria-describedby"]?: string;
|
|
52
|
+
};
|
|
61
53
|
|
|
62
|
-
type DefaultProps = {
|
|
63
|
-
role:
|
|
64
|
-
|
|
54
|
+
type DefaultProps = {
|
|
55
|
+
role: Props["role"];
|
|
56
|
+
};
|
|
65
57
|
|
|
66
58
|
/**
|
|
67
59
|
* `ModalDialog` is a component that contains these elements:
|
|
@@ -78,7 +70,7 @@ export default class ModalDialog extends React.Component<Props> {
|
|
|
78
70
|
role: "dialog",
|
|
79
71
|
};
|
|
80
72
|
|
|
81
|
-
render(): React.
|
|
73
|
+
render(): React.ReactElement {
|
|
82
74
|
const {
|
|
83
75
|
above,
|
|
84
76
|
below,
|
|
@@ -171,4 +163,4 @@ const styleSheets = {
|
|
|
171
163
|
flexDirection: "column",
|
|
172
164
|
},
|
|
173
165
|
}),
|
|
174
|
-
};
|
|
166
|
+
} as const;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {StyleSheet} from "aphrodite";
|
|
4
3
|
import Color from "@khanacademy/wonder-blocks-color";
|
|
5
4
|
import {View} from "@khanacademy/wonder-blocks-core";
|
|
6
5
|
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
7
6
|
|
|
8
|
-
type Props = {
|
|
9
|
-
children: React.
|
|
10
|
-
|
|
7
|
+
type Props = {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
};
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Modal footer included after the content.
|
|
@@ -30,9 +29,9 @@ export default class ModalFooter extends React.Component<Props> {
|
|
|
30
29
|
static isClassOf(instance: any): boolean {
|
|
31
30
|
return instance && instance.type && instance.type.__IS_MODAL_FOOTER__;
|
|
32
31
|
}
|
|
33
|
-
static __IS_MODAL_FOOTER__
|
|
32
|
+
static __IS_MODAL_FOOTER__ = true;
|
|
34
33
|
|
|
35
|
-
render(): React.
|
|
34
|
+
render(): React.ReactElement {
|
|
36
35
|
const {children} = this.props;
|
|
37
36
|
return <View style={styles.footer}>{children}</View>;
|
|
38
37
|
}
|
|
@@ -1,30 +1,26 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {StyleSheet} from "aphrodite";
|
|
4
|
-
import {
|
|
3
|
+
import {Breadcrumbs} from "@khanacademy/wonder-blocks-breadcrumbs";
|
|
5
4
|
import Color from "@khanacademy/wonder-blocks-color";
|
|
6
5
|
import {View} from "@khanacademy/wonder-blocks-core";
|
|
7
6
|
import {MediaLayout} from "@khanacademy/wonder-blocks-layout";
|
|
8
7
|
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
9
8
|
import {HeadingMedium, LabelSmall} from "@khanacademy/wonder-blocks-typography";
|
|
10
9
|
|
|
11
|
-
type Common = {
|
|
10
|
+
type Common = {
|
|
12
11
|
/**
|
|
13
12
|
* The main title rendered in larger bold text.
|
|
14
13
|
*/
|
|
15
|
-
title: string
|
|
16
|
-
|
|
14
|
+
title: string;
|
|
17
15
|
/**
|
|
18
16
|
* Whether to display the "light" version of this component instead, for
|
|
19
17
|
* use when the item is used on a dark background.
|
|
20
18
|
*/
|
|
21
|
-
light: boolean
|
|
22
|
-
|
|
19
|
+
light: boolean;
|
|
23
20
|
/**
|
|
24
21
|
* An id to provide a selector for the title element.
|
|
25
22
|
*/
|
|
26
|
-
titleId: string
|
|
27
|
-
|
|
23
|
+
titleId: string;
|
|
28
24
|
/**
|
|
29
25
|
* Test ID used for e2e testing.
|
|
30
26
|
*
|
|
@@ -36,32 +32,28 @@ type Common = {|
|
|
|
36
32
|
* For testId="some-random-id"
|
|
37
33
|
* The result will be: `some-random-id-modal-header`
|
|
38
34
|
*/
|
|
39
|
-
testId?: string
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
type WithSubtitle = {|
|
|
43
|
-
...Common,
|
|
35
|
+
testId?: string;
|
|
36
|
+
};
|
|
44
37
|
|
|
38
|
+
type WithSubtitle = Common & {
|
|
45
39
|
/**
|
|
46
40
|
* The dialog subtitle.
|
|
47
41
|
*/
|
|
48
|
-
subtitle: string
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
type WithBreadcrumbs = {|
|
|
52
|
-
...Common,
|
|
42
|
+
subtitle: string;
|
|
43
|
+
};
|
|
53
44
|
|
|
45
|
+
type WithBreadcrumbs = Common & {
|
|
54
46
|
/**
|
|
55
47
|
* Adds a breadcrumb-trail, appearing in the ModalHeader, above the title.
|
|
56
48
|
*/
|
|
57
|
-
breadcrumbs: React.
|
|
58
|
-
|
|
49
|
+
breadcrumbs: React.ReactElement<React.ComponentProps<typeof Breadcrumbs>>;
|
|
50
|
+
};
|
|
59
51
|
|
|
60
52
|
type Props = Common | WithSubtitle | WithBreadcrumbs;
|
|
61
53
|
|
|
62
|
-
type DefaultProps = {
|
|
63
|
-
light:
|
|
64
|
-
|
|
54
|
+
type DefaultProps = {
|
|
55
|
+
light: Props["light"];
|
|
56
|
+
};
|
|
65
57
|
|
|
66
58
|
/**
|
|
67
59
|
* This is a helper component that is never rendered by itself. It is always
|
|
@@ -111,10 +103,12 @@ export default class ModalHeader extends React.Component<Props> {
|
|
|
111
103
|
light: true,
|
|
112
104
|
};
|
|
113
105
|
|
|
114
|
-
render(): React.
|
|
106
|
+
render(): React.ReactElement {
|
|
115
107
|
const {
|
|
108
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'breadcrumbs' does not exist on type 'Readonly<Props> & Readonly<{ children?: ReactNode; }>'.
|
|
116
109
|
breadcrumbs = undefined,
|
|
117
110
|
light,
|
|
111
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'subtitle' does not exist on type 'Readonly<Props> & Readonly<{ children?: ReactNode; }>'.
|
|
118
112
|
subtitle = undefined,
|
|
119
113
|
testId,
|
|
120
114
|
title,
|
|
@@ -204,4 +198,4 @@ const styleSheets = {
|
|
|
204
198
|
paddingRight: Spacing.xLarge_32,
|
|
205
199
|
},
|
|
206
200
|
}),
|
|
207
|
-
};
|
|
201
|
+
} as const;
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import * as ReactDOM from "react-dom";
|
|
4
3
|
import {StyleSheet} from "aphrodite";
|
|
5
4
|
|
|
6
5
|
import {withActionScheduler} from "@khanacademy/wonder-blocks-timing";
|
|
7
|
-
import type {
|
|
8
|
-
WithActionSchedulerProps,
|
|
9
|
-
WithoutActionScheduler,
|
|
10
|
-
} from "@khanacademy/wonder-blocks-timing";
|
|
6
|
+
import type {WithActionSchedulerProps} from "@khanacademy/wonder-blocks-timing";
|
|
11
7
|
|
|
12
8
|
import FocusTrap from "./focus-trap";
|
|
13
9
|
import ModalBackdrop from "./modal-backdrop";
|
|
@@ -16,7 +12,7 @@ import type {ModalElement} from "../util/types";
|
|
|
16
12
|
import ModalContext from "./modal-context";
|
|
17
13
|
|
|
18
14
|
// TODO(FEI-5000): Convert back to conditional props after TS migration is complete.
|
|
19
|
-
type Props = {
|
|
15
|
+
type Props = {
|
|
20
16
|
/**
|
|
21
17
|
* The modal to render.
|
|
22
18
|
*
|
|
@@ -30,31 +26,26 @@ type Props = {|
|
|
|
30
26
|
* Note: Don't call `closeModal` while rendering! It should be used to
|
|
31
27
|
* respond to user intearction, like `onClick`.
|
|
32
28
|
*/
|
|
33
|
-
modal: ModalElement |
|
|
34
|
-
|
|
29
|
+
modal: ModalElement | React.FC<{closeModal: () => void}>;
|
|
35
30
|
/**
|
|
36
31
|
* Enables the backdrop to dismiss the modal on click/tap
|
|
37
32
|
*/
|
|
38
|
-
backdropDismissEnabled?: boolean
|
|
39
|
-
|
|
33
|
+
backdropDismissEnabled?: boolean;
|
|
40
34
|
/**
|
|
41
35
|
* The selector for the element that will be focused when the dialog shows.
|
|
42
36
|
* When not set, the first tabbable element within the dialog will be used.
|
|
43
37
|
*/
|
|
44
|
-
initialFocusId?: string
|
|
45
|
-
|
|
38
|
+
initialFocusId?: string;
|
|
46
39
|
/**
|
|
47
40
|
* The selector for the element that will be focused after the dialog
|
|
48
41
|
* closes. When not set, the last element focused outside the modal will
|
|
49
42
|
* be used if it exists.
|
|
50
43
|
*/
|
|
51
|
-
closedFocusId?: string
|
|
52
|
-
|
|
44
|
+
closedFocusId?: string;
|
|
53
45
|
/**
|
|
54
46
|
* Test ID used for e2e testing. It's set on the ModalBackdrop
|
|
55
47
|
*/
|
|
56
|
-
testId?: string
|
|
57
|
-
|
|
48
|
+
testId?: string;
|
|
58
49
|
/**
|
|
59
50
|
* Renders the modal when true, renders nothing when false.
|
|
60
51
|
*
|
|
@@ -64,8 +55,7 @@ type Props = {|
|
|
|
64
55
|
* should never be used with this prop. Not doing so will result in an
|
|
65
56
|
* error being thrown.
|
|
66
57
|
*/
|
|
67
|
-
opened?: boolean
|
|
68
|
-
|
|
58
|
+
opened?: boolean;
|
|
69
59
|
/**
|
|
70
60
|
* If the parent needs to be notified when the modal is closed, use this
|
|
71
61
|
* prop. You probably want to use this instead of `onClose` on the modals
|
|
@@ -77,25 +67,22 @@ type Props = {|
|
|
|
77
67
|
* This prop must be used when the component is being used as a controlled
|
|
78
68
|
* component.
|
|
79
69
|
*/
|
|
80
|
-
onClose?: () =>
|
|
81
|
-
|
|
70
|
+
onClose?: () => unknown;
|
|
82
71
|
/**
|
|
83
72
|
* WARNING: This props should only be used when using the component as a
|
|
84
73
|
* controlled component.
|
|
85
74
|
*/
|
|
86
|
-
children?: ({
|
|
75
|
+
children?: (arg1: {openModal: () => unknown}) => React.ReactNode;
|
|
76
|
+
} & WithActionSchedulerProps;
|
|
87
77
|
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
type DefaultProps = {
|
|
79
|
+
backdropDismissEnabled: Props["backdropDismissEnabled"];
|
|
80
|
+
};
|
|
90
81
|
|
|
91
|
-
type
|
|
92
|
-
backdropDismissEnabled: $PropertyType<Props, "backdropDismissEnabled">,
|
|
93
|
-
|};
|
|
94
|
-
|
|
95
|
-
type State = {|
|
|
82
|
+
type State = {
|
|
96
83
|
/** Whether the modal should currently be open. */
|
|
97
|
-
opened: boolean
|
|
98
|
-
|
|
84
|
+
opened: boolean;
|
|
85
|
+
};
|
|
99
86
|
|
|
100
87
|
/**
|
|
101
88
|
* This component enables you to launch a modal, covering the screen.
|
|
@@ -118,7 +105,7 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
118
105
|
* The most recent element _outside this component_ that received focus.
|
|
119
106
|
* Be default, it captures the element that triggered the modal opening
|
|
120
107
|
*/
|
|
121
|
-
lastElementFocusedOutsideModal:
|
|
108
|
+
lastElementFocusedOutsideModal: HTMLElement | null | undefined;
|
|
122
109
|
|
|
123
110
|
static defaultProps: DefaultProps = {
|
|
124
111
|
backdropDismissEnabled: true,
|
|
@@ -127,7 +114,7 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
127
114
|
static getDerivedStateFromProps(
|
|
128
115
|
props: Props,
|
|
129
116
|
state: State,
|
|
130
|
-
):
|
|
117
|
+
): Partial<State> {
|
|
131
118
|
if (typeof props.opened === "boolean" && props.children) {
|
|
132
119
|
// eslint-disable-next-line no-console
|
|
133
120
|
console.warn("'children' and 'opened' can't be used together");
|
|
@@ -157,6 +144,7 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
157
144
|
|
|
158
145
|
_saveLastElementFocused: () => void = () => {
|
|
159
146
|
// keep a reference of the element that triggers the modal
|
|
147
|
+
// @ts-expect-error [FEI-5019] - TS2322 - Type 'Element | null' is not assignable to type 'HTMLElement | null | undefined'.
|
|
160
148
|
this.lastElementFocusedOutsideModal = document.activeElement;
|
|
161
149
|
};
|
|
162
150
|
|
|
@@ -171,9 +159,9 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
171
159
|
|
|
172
160
|
// Focus on the specified element after closing the modal.
|
|
173
161
|
if (closedFocusId) {
|
|
174
|
-
const focusElement =
|
|
162
|
+
const focusElement = ReactDOM.findDOMNode(
|
|
175
163
|
document.getElementById(closedFocusId),
|
|
176
|
-
)
|
|
164
|
+
) as any;
|
|
177
165
|
|
|
178
166
|
if (focusElement) {
|
|
179
167
|
// Wait for the modal to leave the DOM before trying
|
|
@@ -198,7 +186,7 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
198
186
|
this.setState({opened: false}, () => {
|
|
199
187
|
const {onClose} = this.props;
|
|
200
188
|
|
|
201
|
-
onClose
|
|
189
|
+
onClose?.();
|
|
202
190
|
this._returnFocus();
|
|
203
191
|
});
|
|
204
192
|
};
|
|
@@ -213,7 +201,7 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
213
201
|
}
|
|
214
202
|
}
|
|
215
203
|
|
|
216
|
-
render(): React.
|
|
204
|
+
render(): React.ReactElement | null {
|
|
217
205
|
const renderedChildren = this.props.children
|
|
218
206
|
? this.props.children({
|
|
219
207
|
openModal: this._openModal,
|
|
@@ -226,9 +214,6 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
226
214
|
}
|
|
227
215
|
|
|
228
216
|
return (
|
|
229
|
-
// This flow check is valid, it's the babel plugin which is broken,
|
|
230
|
-
// see modal-context.js for details.
|
|
231
|
-
// $FlowFixMe
|
|
232
217
|
<ModalContext.Provider value={{closeModal: this.handleCloseModal}}>
|
|
233
218
|
{renderedChildren}
|
|
234
219
|
{this.state.opened &&
|
|
@@ -262,9 +247,9 @@ class ModalLauncher extends React.Component<Props, State> {
|
|
|
262
247
|
}
|
|
263
248
|
|
|
264
249
|
/** A component that, when mounted, calls `onClose` when Escape is pressed. */
|
|
265
|
-
class ModalLauncherKeypressListener extends React.Component<{
|
|
266
|
-
onClose: () =>
|
|
267
|
-
|
|
250
|
+
class ModalLauncherKeypressListener extends React.Component<{
|
|
251
|
+
onClose: () => unknown;
|
|
252
|
+
}> {
|
|
268
253
|
componentDidMount() {
|
|
269
254
|
window.addEventListener("keyup", this._handleKeyup);
|
|
270
255
|
}
|
|
@@ -290,7 +275,7 @@ class ModalLauncherKeypressListener extends React.Component<{|
|
|
|
290
275
|
}
|
|
291
276
|
};
|
|
292
277
|
|
|
293
|
-
render(): React.
|
|
278
|
+
render(): React.ReactElement | null {
|
|
294
279
|
return null;
|
|
295
280
|
}
|
|
296
281
|
}
|
|
@@ -306,10 +291,4 @@ const styles = StyleSheet.create({
|
|
|
306
291
|
},
|
|
307
292
|
});
|
|
308
293
|
|
|
309
|
-
|
|
310
|
-
React.ElementConfig<typeof ModalLauncher>,
|
|
311
|
-
>;
|
|
312
|
-
|
|
313
|
-
export default (withActionScheduler(
|
|
314
|
-
ModalLauncher,
|
|
315
|
-
): React.ComponentType<ExportProps>);
|
|
294
|
+
export default withActionScheduler(ModalLauncher);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {StyleSheet} from "aphrodite";
|
|
4
3
|
import Color from "@khanacademy/wonder-blocks-color";
|
|
@@ -11,45 +10,44 @@ import ModalHeader from "./modal-header";
|
|
|
11
10
|
import ModalFooter from "./modal-footer";
|
|
12
11
|
import CloseButton from "./close-button";
|
|
13
12
|
|
|
14
|
-
type Props = {
|
|
13
|
+
type Props = {
|
|
15
14
|
/**
|
|
16
15
|
* The main contents of the ModalPanel. All other parts of the panel
|
|
17
16
|
* are positioned around it.
|
|
18
17
|
*/
|
|
19
|
-
content:
|
|
20
|
-
|
|
18
|
+
content:
|
|
19
|
+
| React.ReactElement<React.ComponentProps<typeof ModalContent>>
|
|
20
|
+
| React.ReactNode;
|
|
21
21
|
/**
|
|
22
22
|
* The modal header to show at the top of the panel.
|
|
23
23
|
*/
|
|
24
|
-
header?:
|
|
25
|
-
|
|
24
|
+
header?:
|
|
25
|
+
| React.ReactElement<React.ComponentProps<typeof ModalHeader>>
|
|
26
|
+
| React.ReactNode;
|
|
26
27
|
/**
|
|
27
28
|
* A footer to show beneath the contents.
|
|
28
29
|
*/
|
|
29
|
-
footer?:
|
|
30
|
-
|
|
30
|
+
footer?:
|
|
31
|
+
| React.ReactElement<React.ComponentProps<typeof ModalFooter>>
|
|
32
|
+
| React.ReactNode;
|
|
31
33
|
/**
|
|
32
34
|
* When true, the close button is shown; otherwise, the close button is not shown.
|
|
33
35
|
*/
|
|
34
|
-
closeButtonVisible: boolean
|
|
35
|
-
|
|
36
|
+
closeButtonVisible: boolean;
|
|
36
37
|
/**
|
|
37
38
|
* Should the contents of the panel become scrollable should they
|
|
38
39
|
* become too tall?
|
|
39
40
|
*/
|
|
40
|
-
scrollOverflow: boolean
|
|
41
|
-
|
|
41
|
+
scrollOverflow: boolean;
|
|
42
42
|
/**
|
|
43
43
|
* Whether to display the "light" version of this component instead, for
|
|
44
44
|
* use when the item is used on a dark background.
|
|
45
45
|
*/
|
|
46
|
-
light: boolean
|
|
47
|
-
|
|
46
|
+
light: boolean;
|
|
48
47
|
/**
|
|
49
48
|
* Any optional styling to apply to the panel.
|
|
50
49
|
*/
|
|
51
|
-
style?: StyleType
|
|
52
|
-
|
|
50
|
+
style?: StyleType;
|
|
53
51
|
/**
|
|
54
52
|
* Called when the close button is clicked.
|
|
55
53
|
*
|
|
@@ -57,22 +55,21 @@ type Props = {|
|
|
|
57
55
|
* Instead, to listen for when the modal closes, add an `onClose` handler
|
|
58
56
|
* to the `ModalLauncher`. Doing so will throw an error.
|
|
59
57
|
*/
|
|
60
|
-
onClose?: () =>
|
|
61
|
-
|
|
58
|
+
onClose?: () => unknown;
|
|
62
59
|
/**
|
|
63
60
|
* Test ID used for e2e testing.
|
|
64
61
|
*
|
|
65
62
|
* In this case, this `testId` comes from the `testId` prop defined in the
|
|
66
63
|
* Dialog variant (e.g. OnePaneDialog).
|
|
67
64
|
*/
|
|
68
|
-
testId?: string
|
|
69
|
-
|
|
65
|
+
testId?: string;
|
|
66
|
+
};
|
|
70
67
|
|
|
71
|
-
type DefaultProps = {
|
|
72
|
-
closeButtonVisible:
|
|
73
|
-
scrollOverflow:
|
|
74
|
-
light:
|
|
75
|
-
|
|
68
|
+
type DefaultProps = {
|
|
69
|
+
closeButtonVisible: Props["closeButtonVisible"];
|
|
70
|
+
scrollOverflow: Props["scrollOverflow"];
|
|
71
|
+
light: Props["light"];
|
|
72
|
+
};
|
|
76
73
|
|
|
77
74
|
/**
|
|
78
75
|
* ModalPanel is the content container.
|
|
@@ -101,11 +98,13 @@ export default class ModalPanel extends React.Component<Props> {
|
|
|
101
98
|
light: true,
|
|
102
99
|
};
|
|
103
100
|
|
|
104
|
-
renderMainContent(): React.
|
|
101
|
+
renderMainContent(): React.ReactNode {
|
|
105
102
|
const {content, footer, scrollOverflow} = this.props;
|
|
106
103
|
|
|
107
104
|
const mainContent = ModalContent.isClassOf(content) ? (
|
|
108
|
-
(
|
|
105
|
+
(content as React.ReactElement<
|
|
106
|
+
React.ComponentProps<typeof ModalContent>
|
|
107
|
+
>)
|
|
109
108
|
) : (
|
|
110
109
|
<ModalContent>{content}</ModalContent>
|
|
111
110
|
);
|
|
@@ -125,7 +124,7 @@ export default class ModalPanel extends React.Component<Props> {
|
|
|
125
124
|
});
|
|
126
125
|
}
|
|
127
126
|
|
|
128
|
-
render(): React.
|
|
127
|
+
render(): React.ReactElement {
|
|
129
128
|
const {
|
|
130
129
|
closeButtonVisible,
|
|
131
130
|
footer,
|