@khanacademy/wonder-blocks-modal 3.0.7 → 3.0.8

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/components/close-button.d.ts +31 -0
  3. package/dist/components/close-button.js.flow +43 -0
  4. package/dist/components/focus-trap.d.ts +57 -0
  5. package/dist/components/focus-trap.js.flow +69 -0
  6. package/dist/components/modal-backdrop.d.ts +50 -0
  7. package/dist/components/modal-backdrop.js.flow +63 -0
  8. package/dist/components/modal-content.d.ts +23 -0
  9. package/dist/components/modal-content.js.flow +39 -0
  10. package/dist/components/modal-context.d.ts +6 -0
  11. package/dist/components/modal-context.js.flow +14 -0
  12. package/dist/components/modal-dialog.d.ts +60 -0
  13. package/dist/components/modal-dialog.js.flow +75 -0
  14. package/dist/components/modal-footer.d.ts +27 -0
  15. package/dist/components/modal-footer.js.flow +34 -0
  16. package/dist/components/modal-header.d.ts +93 -0
  17. package/dist/components/modal-header.js.flow +110 -0
  18. package/dist/components/modal-launcher.d.ts +17 -0
  19. package/dist/components/modal-launcher.js.flow +34 -0
  20. package/dist/components/modal-panel.d.ts +84 -0
  21. package/dist/components/modal-panel.js.flow +102 -0
  22. package/dist/components/one-pane-dialog.d.ts +124 -0
  23. package/dist/components/one-pane-dialog.js.flow +153 -0
  24. package/dist/components/scroll-disabler.d.ts +24 -0
  25. package/dist/components/scroll-disabler.js.flow +21 -0
  26. package/dist/es/index.js +222 -210
  27. package/dist/index.d.ts +8 -0
  28. package/dist/index.js +237 -226
  29. package/dist/index.js.flow +23 -2
  30. package/dist/util/constants.d.ts +5 -0
  31. package/dist/util/constants.js.flow +12 -0
  32. package/dist/util/find-focusable-nodes.d.ts +1 -0
  33. package/dist/util/find-focusable-nodes.js.flow +10 -0
  34. package/dist/util/maybe-get-portal-mounted-modal-host-element.d.ts +9 -0
  35. package/dist/util/maybe-get-portal-mounted-modal-host-element.js.flow +18 -0
  36. package/dist/util/types.d.ts +12 -0
  37. package/dist/util/types.js.flow +20 -0
  38. package/package.json +13 -13
  39. package/src/components/__tests__/{close-button.test.js → close-button.test.tsx} +0 -1
  40. package/src/components/__tests__/{focus-trap.test.js → focus-trap.test.tsx} +0 -1
  41. package/src/components/__tests__/{modal-backdrop.test.js → modal-backdrop.test.tsx} +0 -1
  42. package/src/components/__tests__/{modal-header.test.js → modal-header.test.tsx} +3 -2
  43. package/src/components/__tests__/{modal-launcher.test.js → modal-launcher.test.tsx} +11 -15
  44. package/src/components/__tests__/{modal-panel.test.js → modal-panel.test.tsx} +0 -1
  45. package/src/components/__tests__/{one-pane-dialog.test.js → one-pane-dialog.test.tsx} +0 -1
  46. package/src/components/{close-button.js → close-button.tsx} +7 -11
  47. package/src/components/{focus-trap.js → focus-trap.tsx} +12 -12
  48. package/src/components/{modal-backdrop.js → modal-backdrop.tsx} +20 -18
  49. package/src/components/{modal-content.js → modal-content.tsx} +11 -12
  50. package/src/components/modal-context.ts +13 -0
  51. package/src/components/{modal-dialog.js → modal-dialog.tsx} +15 -23
  52. package/src/components/{modal-footer.js → modal-footer.tsx} +5 -6
  53. package/src/components/{modal-header.js → modal-header.tsx} +20 -26
  54. package/src/components/{modal-launcher.js → modal-launcher.tsx} +29 -50
  55. package/src/components/{modal-panel.js → modal-panel.tsx} +27 -28
  56. package/src/components/{one-pane-dialog.js → one-pane-dialog.tsx} +37 -45
  57. package/src/components/{scroll-disabler.js → scroll-disabler.ts} +3 -4
  58. package/src/{index.js → index.ts} +0 -1
  59. package/src/util/{constants.js → constants.ts} +0 -2
  60. package/src/util/{find-focusable-nodes.js → find-focusable-nodes.ts} +0 -2
  61. package/src/util/{maybe-get-portal-mounted-modal-host-element.test.js → maybe-get-portal-mounted-modal-host-element.test.tsx} +4 -5
  62. package/src/util/{maybe-get-portal-mounted-modal-host-element.js → maybe-get-portal-mounted-modal-host-element.ts} +5 -4
  63. package/src/util/{types.js → types.ts} +3 -2
  64. package/tsconfig.json +20 -0
  65. package/tsconfig.tsbuildinfo +1 -0
  66. package/src/components/__docs__/modal-dialog.stories.js +0 -308
  67. package/src/components/__docs__/modal-footer.stories.js +0 -337
  68. package/src/components/__docs__/modal-header.argtypes.js +0 -76
  69. package/src/components/__docs__/modal-header.stories.js +0 -294
  70. package/src/components/__docs__/modal-launcher.argtypes.js +0 -78
  71. package/src/components/__docs__/modal-launcher.stories.js +0 -513
  72. package/src/components/__docs__/modal-panel.stories.js +0 -414
  73. package/src/components/__docs__/one-pane-dialog.argtypes.js +0 -108
  74. package/src/components/__docs__/one-pane-dialog.stories.js +0 -582
  75. package/src/components/modal-context.js +0 -14
@@ -1,2 +1,23 @@
1
- // @flow
2
- export * from "../src/index";
1
+ /**
2
+ * Flowtype definitions for index
3
+ * Generated by Flowgen from a Typescript Definition
4
+ * Flowgen v1.21.0
5
+ * @flow
6
+ */
7
+
8
+ import ModalDialog from "./components/modal-dialog";
9
+ import ModalFooter from "./components/modal-footer";
10
+ import ModalHeader from "./components/modal-header";
11
+ import ModalLauncher from "./components/modal-launcher";
12
+ import ModalPanel from "./components/modal-panel";
13
+ import OnePaneDialog from "./components/one-pane-dialog";
14
+ import maybeGetPortalMountedModalHostElement from "./util/maybe-get-portal-mounted-modal-host-element";
15
+ declare export {
16
+ ModalHeader,
17
+ ModalFooter,
18
+ ModalDialog,
19
+ ModalPanel,
20
+ ModalLauncher,
21
+ OnePaneDialog,
22
+ maybeGetPortalMountedModalHostElement,
23
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The attribute used to identify a modal launcher portal.
3
+ */
4
+ declare const ModalLauncherPortalAttributeName = "data-modal-launcher-portal";
5
+ export { ModalLauncherPortalAttributeName };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Flowtype definitions for constants
3
+ * Generated by Flowgen from a Typescript Definition
4
+ * Flowgen v1.21.0
5
+ * @flow
6
+ */
7
+
8
+ /**
9
+ * The attribute used to identify a modal launcher portal.
10
+ */
11
+ declare var ModalLauncherPortalAttributeName: "data-modal-launcher-portal";
12
+ declare export { ModalLauncherPortalAttributeName };
@@ -0,0 +1 @@
1
+ export declare function findFocusableNodes(root: HTMLElement | Document): Array<HTMLElement>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Flowtype definitions for find-focusable-nodes
3
+ * Generated by Flowgen from a Typescript Definition
4
+ * Flowgen v1.21.0
5
+ * @flow
6
+ */
7
+
8
+ declare export function findFocusableNodes(
9
+ root: HTMLElement | Document
10
+ ): Array<HTMLElement>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * From a given element, finds the next modal host that has been mounted in
3
+ * a modal portal.
4
+ * @param {?(Element | Text)} element The element whose ancestors are to be
5
+ * walked.
6
+ * @returns {?Element} The next portal-mounted modal host element.
7
+ * TODO(kevinb): look into getting rid of this
8
+ */
9
+ export default function maybeGetPortalMountedModalHostElement(element?: Element | Text | null): Element | null | undefined;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Flowtype definitions for maybe-get-portal-mounted-modal-host-element
3
+ * Generated by Flowgen from a Typescript Definition
4
+ * Flowgen v1.21.0
5
+ * @flow
6
+ */
7
+
8
+ /**
9
+ * From a given element, finds the next modal host that has been mounted in
10
+ * a modal portal.
11
+ * @param {?(Element | Text)} element The element whose ancestors are to be
12
+ * walked.
13
+ * @returns {?Element} The next portal-mounted modal host element.
14
+ * TODO(kevinb): look into getting rid of this
15
+ */
16
+ declare export default function maybeGetPortalMountedModalHostElement(
17
+ element?: Element | Text | null
18
+ ): Element | null | void;
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ /**
3
+ * A `ModalElement` is a React element that should either itself be a modal
4
+ * (OnePaneDialog), or wrap a modal.
5
+ *
6
+ * If it's a wrapper component, then its props must be passed along to the child
7
+ * modal, because we clone this element and add new props in order to capture
8
+ * `onClose` events.
9
+ *
10
+ * NOTE(kevinb): we include `| null` here because that's what React.FC<> returns.
11
+ */
12
+ export type ModalElement = React.ReactElement | null;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Flowtype definitions for types
3
+ * Generated by Flowgen from a Typescript Definition
4
+ * Flowgen v1.21.0
5
+ * @flow
6
+ */
7
+
8
+ import * as React from "react";
9
+
10
+ /**
11
+ * A `ModalElement` is a React element that should either itself be a modal
12
+ * (OnePaneDialog), or wrap a modal.
13
+ *
14
+ * If it's a wrapper component, then its props must be passed along to the child
15
+ * modal, because we clone this element and add new props in order to capture
16
+ * `onClose` events.
17
+ *
18
+ * NOTE(kevinb): we include `| null` here because that's what React.FC<> returns.
19
+ */
20
+ export type ModalElement = React.Element<> | null;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-modal",
3
- "version": "3.0.7",
3
+ "version": "3.0.8",
4
4
  "design": "v2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "description": "",
9
9
  "main": "dist/index.js",
10
- "source": "src/index.js",
10
+ "types": "dist/index.d.ts",
11
11
  "module": "dist/es/index.js",
12
12
  "scripts": {
13
13
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -16,15 +16,15 @@
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
18
  "@babel/runtime": "^7.18.6",
19
- "@khanacademy/wonder-blocks-breadcrumbs": "^1.0.38",
20
- "@khanacademy/wonder-blocks-color": "^1.2.1",
21
- "@khanacademy/wonder-blocks-core": "^4.7.0",
22
- "@khanacademy/wonder-blocks-icon": "^1.2.37",
23
- "@khanacademy/wonder-blocks-icon-button": "^3.4.21",
24
- "@khanacademy/wonder-blocks-layout": "^1.4.16",
25
- "@khanacademy/wonder-blocks-spacing": "^3.0.5",
26
- "@khanacademy/wonder-blocks-timing": "^2.1.1",
27
- "@khanacademy/wonder-blocks-typography": "^1.1.38"
19
+ "@khanacademy/wonder-blocks-breadcrumbs": "^1.0.39",
20
+ "@khanacademy/wonder-blocks-color": "^1.2.2",
21
+ "@khanacademy/wonder-blocks-core": "^4.8.0",
22
+ "@khanacademy/wonder-blocks-icon": "^1.2.38",
23
+ "@khanacademy/wonder-blocks-icon-button": "^3.4.22",
24
+ "@khanacademy/wonder-blocks-layout": "^1.4.17",
25
+ "@khanacademy/wonder-blocks-spacing": "^3.0.6",
26
+ "@khanacademy/wonder-blocks-timing": "^2.1.2",
27
+ "@khanacademy/wonder-blocks-typography": "^1.1.39"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "aphrodite": "^1.2.5",
@@ -32,7 +32,7 @@
32
32
  "react-dom": "16.14.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@khanacademy/wonder-blocks-breadcrumbs": "^1.0.38",
36
- "wb-dev-build-settings": "^0.7.1"
35
+ "@khanacademy/wonder-blocks-breadcrumbs": "^1.0.39",
36
+ "wb-dev-build-settings": "^0.7.2"
37
37
  }
38
38
  }
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {render, screen} from "@testing-library/react";
4
3
 
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {render, screen} from "@testing-library/react";
4
3
  import userEvent from "@testing-library/user-event";
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {render, screen, fireEvent, waitFor} from "@testing-library/react";
4
3
  import userEvent from "@testing-library/user-event";
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {render, screen} from "@testing-library/react";
4
3
 
@@ -9,7 +8,9 @@ import {
9
8
 
10
9
  import ModalHeader from "../modal-header";
11
10
 
12
- const exampleBreadcrumbs: React.Element<typeof Breadcrumbs> = (
11
+ const exampleBreadcrumbs: React.ReactElement<
12
+ React.ComponentProps<typeof Breadcrumbs>
13
+ > = (
13
14
  <Breadcrumbs>
14
15
  <BreadcrumbsItem>breadcrumb item</BreadcrumbsItem>
15
16
  </Breadcrumbs>
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {render, screen, waitFor} from "@testing-library/react";
4
3
  import userEvent from "@testing-library/user-event";
@@ -23,7 +22,7 @@ describe("ModalLauncher", () => {
23
22
  // Arrange
24
23
  render(
25
24
  <ModalLauncher modal={exampleModal} testId="modal-launcher-portal">
26
- {({openModal}) => <button onClick={openModal} />}
25
+ {({openModal}: any) => <button onClick={openModal} />}
27
26
  </ModalLauncher>,
28
27
  );
29
28
 
@@ -38,7 +37,7 @@ describe("ModalLauncher", () => {
38
37
 
39
38
  test("Modal can be manually opened and closed", () => {
40
39
  // Arrange
41
- const UnderTest = ({opened}: {|opened: boolean|}) => (
40
+ const UnderTest = ({opened}: {opened: boolean}) => (
42
41
  <ModalLauncher
43
42
  modal={exampleModal}
44
43
  opened={opened}
@@ -62,7 +61,7 @@ describe("ModalLauncher", () => {
62
61
 
63
62
  test("Modal can close itself after launching", async () => {
64
63
  // Arrange
65
- const modalFn = ({closeModal}: {|closeModal: () => void|}) => (
64
+ const modalFn = ({closeModal}: {closeModal: () => void}) => (
66
65
  <OnePaneDialog
67
66
  title="Modal launcher test"
68
67
  content={
@@ -83,7 +82,7 @@ describe("ModalLauncher", () => {
83
82
  onClose={onCloseMock}
84
83
  testId="modal-launcher-portal"
85
84
  >
86
- {({openModal}) => <button onClick={openModal} />}
85
+ {({openModal}: any) => <button onClick={openModal} />}
87
86
  </ModalLauncher>,
88
87
  );
89
88
 
@@ -103,7 +102,7 @@ describe("ModalLauncher", () => {
103
102
  // Arrange
104
103
  render(
105
104
  <ModalLauncher modal={exampleModal}>
106
- {({openModal}) => <button onClick={openModal} />}
105
+ {({openModal}: any) => <button onClick={openModal} />}
107
106
  </ModalLauncher>,
108
107
  );
109
108
 
@@ -126,7 +125,7 @@ describe("ModalLauncher", () => {
126
125
  // Arrange
127
126
  render(
128
127
  <ModalLauncher modal={exampleModal}>
129
- {({openModal}) => <button onClick={openModal} />}
128
+ {({openModal}: any) => <button onClick={openModal} />}
130
129
  </ModalLauncher>,
131
130
  );
132
131
 
@@ -146,7 +145,7 @@ describe("ModalLauncher", () => {
146
145
  // Arrange
147
146
  render(
148
147
  <ModalLauncher modal={exampleModal}>
149
- {({openModal}) => <button onClick={openModal} />}
148
+ {({openModal}: any) => <button onClick={openModal} />}
150
149
  </ModalLauncher>,
151
150
  );
152
151
 
@@ -169,13 +168,12 @@ describe("ModalLauncher", () => {
169
168
 
170
169
  // Act
171
170
  render(
172
- // $FlowIgnore
173
171
  <ModalLauncher
174
172
  modal={exampleModal}
175
173
  opened={false}
176
174
  onClose={() => {}}
177
175
  >
178
- {({openModal}) => <button onClick={openModal} />}
176
+ {({openModal}: any) => <button onClick={openModal} />}
179
177
  </ModalLauncher>,
180
178
  );
181
179
 
@@ -191,7 +189,6 @@ describe("ModalLauncher", () => {
191
189
  jest.spyOn(console, "warn");
192
190
 
193
191
  // Act
194
- // $FlowIgnore
195
192
  render(<ModalLauncher modal={exampleModal} opened={false} />);
196
193
 
197
194
  // Assert
@@ -206,7 +203,6 @@ describe("ModalLauncher", () => {
206
203
  jest.spyOn(console, "warn");
207
204
 
208
205
  // Act
209
- // $FlowIgnore
210
206
  render(<ModalLauncher modal={exampleModal} />);
211
207
 
212
208
  // Assert
@@ -253,7 +249,7 @@ describe("ModalLauncher", () => {
253
249
  />
254
250
  }
255
251
  >
256
- {({openModal}) => (
252
+ {({openModal}: any) => (
257
253
  <button onClick={openModal}>Open modal</button>
258
254
  )}
259
255
  </ModalLauncher>,
@@ -303,7 +299,7 @@ describe("ModalLauncher", () => {
303
299
  <ModalLauncher
304
300
  onClose={() => handleClose()}
305
301
  opened={opened}
306
- modal={({closeModal}) => (
302
+ modal={({closeModal}: any) => (
307
303
  <OnePaneDialog
308
304
  title="Regular modal"
309
305
  content={<View>Hello World</View>}
@@ -371,7 +367,7 @@ describe("ModalLauncher", () => {
371
367
  onClose={() => handleClose()}
372
368
  opened={opened}
373
369
  closedFocusId="button-to-focus-on"
374
- modal={({closeModal}) => (
370
+ modal={({closeModal}: any) => (
375
371
  <OnePaneDialog
376
372
  title="Triggered from action menu"
377
373
  content={<View>Hello World</View>}
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {render, screen} from "@testing-library/react";
4
3
 
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {render, screen} from "@testing-library/react";
4
3
 
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {icons} from "@khanacademy/wonder-blocks-icon";
4
3
  import IconButton from "@khanacademy/wonder-blocks-icon-button";
@@ -6,21 +5,18 @@ import type {StyleType} from "@khanacademy/wonder-blocks-core";
6
5
 
7
6
  import ModalContext from "./modal-context";
8
7
 
9
- type Props = {|
8
+ type Props = {
10
9
  /**
11
10
  * Whether the button is on a dark/colored background.
12
11
  *
13
12
  * Sets primary button background color to white, and secondary and
14
13
  * tertiary button title to color.
15
14
  */
16
- light?: boolean,
17
-
15
+ light?: boolean;
18
16
  /** Optional click handler */
19
- onClick?: () => mixed,
20
-
17
+ onClick?: () => unknown;
21
18
  /** Optional custom styles. */
22
- style?: StyleType,
23
-
19
+ style?: StyleType;
24
20
  /**
25
21
  * Test ID used for e2e testing.
26
22
  *
@@ -32,11 +28,11 @@ type Props = {|
32
28
  * For testId="some-random-id"
33
29
  * The result will be: `some-random-id-modal-panel`
34
30
  */
35
- testId?: string,
36
- |};
31
+ testId?: string;
32
+ };
37
33
 
38
34
  export default class CloseButton extends React.Component<Props> {
39
- render(): React.Node {
35
+ render(): React.ReactElement {
40
36
  const {light, onClick, style, testId} = this.props;
41
37
 
42
38
  return (
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import * as ReactDOM from "react-dom";
4
3
 
@@ -30,24 +29,23 @@ const FOCUSABLE_ELEMENTS =
30
29
  * instead if we were to generalize!
31
30
  */
32
31
 
33
- type Props = {|
34
- children: React.Node,
35
-
32
+ type Props = {
33
+ children: React.ReactNode;
36
34
  /**
37
35
  * Style applied to the View containing children.
38
36
  * TODO(kevinb): only allow z-index to be specified. We'll be able to remove
39
37
  * this prop once we remove all uses of z-indexes from webapp.
40
38
  */
41
- style?: StyleType,
42
- |};
39
+ style?: StyleType;
40
+ };
43
41
 
44
42
  export default class FocusTrap extends React.Component<Props> {
45
43
  /**
46
44
  * Tabbing is restricted to descendents of this element.
47
45
  */
48
- modalRoot: ?Node;
46
+ modalRoot: Node | null | undefined;
49
47
 
50
- getModalRoot: (node: any) => void = (node) => {
48
+ getModalRoot: (node?: any) => void = (node) => {
51
49
  if (!node) {
52
50
  // The component is being umounted
53
51
  return;
@@ -65,11 +63,11 @@ export default class FocusTrap extends React.Component<Props> {
65
63
  /**
66
64
  * Try to focus the given node. Return true if successful.
67
65
  */
68
- tryToFocus(node: Node): ?boolean {
66
+ tryToFocus(node: Node): boolean | null | undefined {
69
67
  if (node instanceof HTMLElement) {
70
68
  try {
71
69
  node.focus();
72
- } catch (e) {
70
+ } catch (e: any) {
73
71
  // ignore error
74
72
  }
75
73
 
@@ -84,7 +82,7 @@ export default class FocusTrap extends React.Component<Props> {
84
82
  * First element within the modal, false = Last element within the modal.
85
83
  */
86
84
  focusElementIn(isLast: boolean) {
87
- const modalRootAsHtmlEl = ((this.modalRoot: any): HTMLElement);
85
+ const modalRootAsHtmlEl = this.modalRoot as HTMLElement;
88
86
  // Get the list of available focusable elements within the modal.
89
87
  const focusableNodes = Array.from(
90
88
  modalRootAsHtmlEl.querySelectorAll(FOCUSABLE_ELEMENTS),
@@ -112,7 +110,7 @@ export default class FocusTrap extends React.Component<Props> {
112
110
  this.focusElementIn(true);
113
111
  };
114
112
 
115
- render(): React.Node {
113
+ render(): React.ReactElement {
116
114
  const {style} = this.props;
117
115
 
118
116
  return (
@@ -130,6 +128,7 @@ export default class FocusTrap extends React.Component<Props> {
130
128
  * they're always in view, this prevents page scrolling when
131
129
  * tabbing. */}
132
130
  <div
131
+ // @ts-expect-error [FEI-5019] - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
133
132
  tabIndex="0"
134
133
  className="modal-focus-trap-first"
135
134
  onFocus={this.handleFocusMoveToLast}
@@ -139,6 +138,7 @@ export default class FocusTrap extends React.Component<Props> {
139
138
  {this.props.children}
140
139
  </View>
141
140
  <div
141
+ // @ts-expect-error [FEI-5019] - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
142
142
  tabIndex="0"
143
143
  className="modal-focus-trap-last"
144
144
  onFocus={this.handleFocusMoveToFirst}
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import * as ReactDOM from "react-dom";
4
3
  import {StyleSheet} from "aphrodite";
@@ -11,20 +10,19 @@ import {findFocusableNodes} from "../util/find-focusable-nodes";
11
10
 
12
11
  import type {ModalElement} from "../util/types";
13
12
 
14
- type Props = {|
15
- children: ModalElement,
16
- onCloseModal: () => mixed,
13
+ type Props = {
14
+ children: ModalElement;
15
+ onCloseModal: () => unknown;
17
16
  /**
18
17
  * The selector for the element that will be focused when the dialog shows.
19
18
  * When not set, the first tabbable element within the dialog will be used.
20
19
  */
21
- initialFocusId?: string,
22
-
20
+ initialFocusId?: string;
23
21
  /**
24
22
  * Test ID used for e2e testing.
25
23
  */
26
- testId?: string,
27
- |};
24
+ testId?: string;
25
+ };
28
26
 
29
27
  /**
30
28
  * A private component used by ModalLauncher. This is the fixed-position
@@ -38,7 +36,7 @@ type Props = {|
38
36
  */
39
37
  export default class ModalBackdrop extends React.Component<Props> {
40
38
  componentDidMount() {
41
- const node: HTMLElement = (ReactDOM.findDOMNode(this): any);
39
+ const node: HTMLElement = ReactDOM.findDOMNode(this) as any;
42
40
  if (!node) {
43
41
  return;
44
42
  }
@@ -57,7 +55,7 @@ export default class ModalBackdrop extends React.Component<Props> {
57
55
  }, 0);
58
56
  }
59
57
 
60
- _mousePressedOutside: boolean = false;
58
+ _mousePressedOutside = false;
61
59
 
62
60
  /**
63
61
  * Returns an element specified by the user
@@ -69,9 +67,9 @@ export default class ModalBackdrop extends React.Component<Props> {
69
67
  return null;
70
68
  }
71
69
 
72
- return (ReactDOM.findDOMNode(
70
+ return ReactDOM.findDOMNode(
73
71
  node.querySelector(`#${initialFocusId}`),
74
- ): any);
72
+ ) as any;
75
73
  }
76
74
 
77
75
  /**
@@ -95,9 +93,9 @@ export default class ModalBackdrop extends React.Component<Props> {
95
93
  _getDialogElement(node: HTMLElement): HTMLElement {
96
94
  // If no focusable elements are found,
97
95
  // the dialog content element itself will receive focus.
98
- const dialogElement: HTMLElement = (ReactDOM.findDOMNode(
96
+ const dialogElement: HTMLElement = ReactDOM.findDOMNode(
99
97
  node.querySelector('[role="dialog"]'),
100
- ): any);
98
+ ) as any;
101
99
  // add tabIndex to make the Dialog focusable
102
100
  dialogElement.tabIndex = -1;
103
101
 
@@ -109,12 +107,16 @@ export default class ModalBackdrop extends React.Component<Props> {
109
107
  * _directly_ from the positioner, not bubbled up from its children), close
110
108
  * the modal.
111
109
  */
112
- handleMouseDown: (e: SyntheticEvent<>) => void = (e: SyntheticEvent<>) => {
110
+ handleMouseDown: (e: React.SyntheticEvent) => void = (
111
+ e: React.SyntheticEvent,
112
+ ) => {
113
113
  // Confirm that it is the backdrop that is being clicked, not the child
114
114
  this._mousePressedOutside = e.target === e.currentTarget;
115
115
  };
116
116
 
117
- handleMouseUp: (e: SyntheticEvent<>) => void = (e: SyntheticEvent<>) => {
117
+ handleMouseUp: (e: React.SyntheticEvent) => void = (
118
+ e: React.SyntheticEvent,
119
+ ) => {
118
120
  // Confirm that it is the backdrop that is being clicked, not the child
119
121
  // and that the mouse was pressed in the backdrop first.
120
122
  if (e.target === e.currentTarget && this._mousePressedOutside) {
@@ -123,11 +125,11 @@ export default class ModalBackdrop extends React.Component<Props> {
123
125
  this._mousePressedOutside = false;
124
126
  };
125
127
 
126
- render(): React.Node {
128
+ render(): React.ReactElement {
127
129
  const {children, testId} = this.props;
128
130
  const backdropProps = {
129
131
  [ModalLauncherPortalAttributeName]: true,
130
- };
132
+ } as const;
131
133
 
132
134
  return (
133
135
  <View
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {StyleSheet} from "aphrodite";
4
3
  import {View} from "@khanacademy/wonder-blocks-core";
@@ -7,18 +6,18 @@ import Spacing from "@khanacademy/wonder-blocks-spacing";
7
6
 
8
7
  import type {StyleType} from "@khanacademy/wonder-blocks-core";
9
8
 
10
- type Props = {|
9
+ type Props = {
11
10
  /** Should the content scroll on overflow, or just expand. */
12
- scrollOverflow: boolean,
11
+ scrollOverflow: boolean;
13
12
  /** The contents of the ModalContent */
14
- children: React.Node,
13
+ children: React.ReactNode;
15
14
  /** Optional styling to apply to the contents. */
16
- style?: StyleType,
17
- |};
15
+ style?: StyleType;
16
+ };
18
17
 
19
- type DefaultProps = {|
20
- scrollOverflow: $PropertyType<Props, "scrollOverflow">,
21
- |};
18
+ type DefaultProps = {
19
+ scrollOverflow: Props["scrollOverflow"];
20
+ };
22
21
 
23
22
  /**
24
23
  * The Modal content included after the header
@@ -31,9 +30,9 @@ export default class ModalContent extends React.Component<Props> {
31
30
  scrollOverflow: true,
32
31
  };
33
32
 
34
- static __IS_MODAL_CONTENT__: boolean = true;
33
+ static __IS_MODAL_CONTENT__ = true;
35
34
 
36
- render(): React.Node {
35
+ render(): React.ReactElement {
37
36
  const {scrollOverflow, style, children} = this.props;
38
37
 
39
38
  return (
@@ -80,4 +79,4 @@ const styleSheets = {
80
79
  padding: `${Spacing.xLarge_32}px ${Spacing.medium_16}px`,
81
80
  },
82
81
  }),
83
- };
82
+ } as const;
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+
3
+ type ContextType = {
4
+ closeModal?: () => unknown;
5
+ };
6
+
7
+ const defaultContext: ContextType = {
8
+ closeModal: undefined,
9
+ };
10
+
11
+ export default React.createContext<ContextType>(
12
+ defaultContext,
13
+ ) as React.Context<ContextType>;