@khanacademy/wonder-blocks-clickable 2.4.5 → 2.4.7

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 (30) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/components/clickable-behavior.d.ts +248 -0
  3. package/dist/components/clickable-behavior.js.flow +296 -0
  4. package/dist/components/clickable.d.ts +150 -0
  5. package/dist/components/clickable.js.flow +176 -0
  6. package/dist/es/index.js +147 -147
  7. package/dist/index.d.ts +7 -0
  8. package/dist/index.js +169 -171
  9. package/dist/index.js.flow +18 -2
  10. package/dist/util/get-clickable-behavior.d.ts +25 -0
  11. package/dist/util/get-clickable-behavior.js.flow +19 -0
  12. package/dist/util/is-client-side-url.d.ts +7 -0
  13. package/dist/util/is-client-side-url.js.flow +14 -0
  14. package/package.json +5 -5
  15. package/src/components/__tests__/{clickable-behavior.test.js → clickable-behavior.test.tsx} +138 -82
  16. package/src/components/__tests__/{clickable.test.js → clickable.test.tsx} +27 -26
  17. package/src/components/{clickable-behavior.js → clickable-behavior.ts} +63 -78
  18. package/src/components/{clickable.js → clickable.tsx} +107 -124
  19. package/src/{index.js → index.ts} +0 -1
  20. package/src/util/__tests__/{get-clickable-behavior.test.js → get-clickable-behavior.test.tsx} +0 -1
  21. package/src/util/__tests__/{is-client-side-url.js.test.js → is-client-side-url.js.test.ts} +2 -3
  22. package/src/util/{get-clickable-behavior.js → get-clickable-behavior.ts} +9 -3
  23. package/src/util/{is-client-side-url.js → is-client-side-url.ts} +0 -1
  24. package/tsconfig.json +12 -0
  25. package/tsconfig.tsbuildinfo +1 -0
  26. package/src/components/__docs__/accessibility.stories.mdx +0 -152
  27. package/src/components/__docs__/clickable-behavior.argtypes.js +0 -64
  28. package/src/components/__docs__/clickable-behavior.stories.js +0 -178
  29. package/src/components/__docs__/clickable.argtypes.js +0 -237
  30. package/src/components/__docs__/clickable.stories.js +0 -307
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {MemoryRouter, Route, Switch} from "react-router-dom";
4
3
  import {render, screen, fireEvent, waitFor} from "@testing-library/react";
@@ -9,7 +8,9 @@ import Clickable from "../clickable";
9
8
 
10
9
  describe("Clickable", () => {
11
10
  beforeEach(() => {
11
+ // @ts-expect-error [FEI-5019] - TS2790 - The operand of a 'delete' operator must be optional.
12
12
  delete window.location;
13
+ // @ts-expect-error [FEI-5019] - TS2740 - Type '{ assign: Mock<any, any, any>; }' is missing the following properties from type 'Location': ancestorOrigins, hash, host, hostname, and 8 more.
13
14
  window.location = {assign: jest.fn()};
14
15
  });
15
16
 
@@ -19,7 +20,7 @@ describe("Clickable", () => {
19
20
  <MemoryRouter>
20
21
  <View>
21
22
  <Clickable testId="button" href="/foo">
22
- {(eventState) => <h1>Click Me!</h1>}
23
+ {(eventState: any) => <h1>Click Me!</h1>}
23
24
  </Clickable>
24
25
  <Switch>
25
26
  <Route path="/foo">
@@ -43,7 +44,7 @@ describe("Clickable", () => {
43
44
  <MemoryRouter>
44
45
  <View>
45
46
  <Clickable testId="button" href="/unknown">
46
- {(eventState) => <h1>Click Me!</h1>}
47
+ {(eventState: any) => <h1>Click Me!</h1>}
47
48
  </Clickable>
48
49
  <Switch>
49
50
  <Route path="/foo">
@@ -67,7 +68,7 @@ describe("Clickable", () => {
67
68
  <MemoryRouter>
68
69
  <View>
69
70
  <Clickable testId="button" href="/foo" skipClientNav>
70
- {(eventState) => <h1>Click Me!</h1>}
71
+ {(eventState: any) => <h1>Click Me!</h1>}
71
72
  </Clickable>
72
73
  <Switch>
73
74
  <Route path="/foo">
@@ -91,7 +92,7 @@ describe("Clickable", () => {
91
92
  <MemoryRouter>
92
93
  <View>
93
94
  <Clickable testId="button" href="/foo" disabled={true}>
94
- {(eventState) => <h1>Click Me!</h1>}
95
+ {(eventState: any) => <h1>Click Me!</h1>}
95
96
  </Clickable>
96
97
  <Switch>
97
98
  <Route path="/foo">
@@ -113,7 +114,7 @@ describe("Clickable", () => {
113
114
  // Arrange, Act
114
115
  render(
115
116
  <Clickable testId="button" href="/foo" skipClientNav={true}>
116
- {(eventState) => <h1>Click Me!</h1>}
117
+ {(eventState: any) => <h1>Click Me!</h1>}
117
118
  </Clickable>,
118
119
  );
119
120
 
@@ -127,7 +128,7 @@ describe("Clickable", () => {
127
128
  // Arrange
128
129
  render(
129
130
  <Clickable testId="button" href="/foo" skipClientNav={true}>
130
- {(eventState) => <h1>Click Me!</h1>}
131
+ {(eventState: any) => <h1>Click Me!</h1>}
131
132
  </Clickable>,
132
133
  );
133
134
 
@@ -149,7 +150,7 @@ describe("Clickable", () => {
149
150
  <Clickable
150
151
  testId="button"
151
152
  href="/foo"
152
- beforeNav={(e) => Promise.reject()}
153
+ beforeNav={() => Promise.reject()}
153
154
  >
154
155
  {() => <span>Click me!</span>}
155
156
  </Clickable>
@@ -178,7 +179,7 @@ describe("Clickable", () => {
178
179
  <Clickable
179
180
  testId="button"
180
181
  href="/foo"
181
- beforeNav={(e) => Promise.reject()}
182
+ beforeNav={() => Promise.reject()}
182
183
  safeWithNav={safeWithNavMock}
183
184
  >
184
185
  {() => <span>Click me!</span>}
@@ -207,7 +208,7 @@ describe("Clickable", () => {
207
208
  <Clickable
208
209
  testId="button"
209
210
  href="/foo"
210
- beforeNav={(e) => Promise.resolve()}
211
+ beforeNav={() => Promise.resolve()}
211
212
  >
212
213
  {() => <span>Click me!</span>}
213
214
  </Clickable>
@@ -238,7 +239,7 @@ describe("Clickable", () => {
238
239
  <Clickable
239
240
  testId="button"
240
241
  href="/foo"
241
- beforeNav={(e) => Promise.resolve()}
242
+ beforeNav={() => Promise.resolve()}
242
243
  safeWithNav={safeWithNavMock}
243
244
  >
244
245
  {() => <span>Click me!</span>}
@@ -269,7 +270,7 @@ describe("Clickable", () => {
269
270
  <Clickable
270
271
  testId="button"
271
272
  href="/foo"
272
- safeWithNav={(e) => Promise.resolve()}
273
+ safeWithNav={() => Promise.resolve()}
273
274
  skipClientNav={true}
274
275
  >
275
276
  {() => <h1>Click me!</h1>}
@@ -300,8 +301,8 @@ describe("Clickable", () => {
300
301
  <Clickable
301
302
  testId="button"
302
303
  href="/foo"
303
- beforeNav={(e) => Promise.resolve()}
304
- safeWithNav={(e) => Promise.resolve()}
304
+ beforeNav={() => Promise.resolve()}
305
+ safeWithNav={() => Promise.resolve()}
305
306
  skipClientNav={true}
306
307
  >
307
308
  {() => <h1>Click me!</h1>}
@@ -332,7 +333,7 @@ describe("Clickable", () => {
332
333
  <Clickable
333
334
  testId="button"
334
335
  href="/foo"
335
- safeWithNav={(e) => Promise.reject()}
336
+ safeWithNav={() => Promise.reject()}
336
337
  skipClientNav={true}
337
338
  >
338
339
  {() => <h1>Click me!</h1>}
@@ -432,7 +433,7 @@ describe("Clickable", () => {
432
433
  // Act
433
434
  render(
434
435
  <Clickable testId="clickable-button" disabled={true}>
435
- {(eventState) => <h1>Click Me!</h1>}
436
+ {(eventState: any) => <h1>Click Me!</h1>}
436
437
  </Clickable>,
437
438
  );
438
439
 
@@ -451,7 +452,7 @@ describe("Clickable", () => {
451
452
  testId="clickable-button"
452
453
  aria-label="clickable-button-aria-label"
453
454
  >
454
- {(eventState) => <h1>Click Me!</h1>}
455
+ {(eventState: any) => <h1>Click Me!</h1>}
455
456
  </Clickable>,
456
457
  );
457
458
 
@@ -470,7 +471,7 @@ describe("Clickable", () => {
470
471
  // Act
471
472
  render(
472
473
  <Clickable testId="clickable-button">
473
- {(eventState) => <h1>Click Me!</h1>}
474
+ {(eventState: any) => <h1>Click Me!</h1>}
474
475
  </Clickable>,
475
476
  );
476
477
 
@@ -486,7 +487,7 @@ describe("Clickable", () => {
486
487
  <div>
487
488
  <button>First focusable button</button>
488
489
  <Clickable testId="clickable-button" disabled={true}>
489
- {(eventState) => <h1>Click Me!</h1>}
490
+ {(eventState: any) => <h1>Click Me!</h1>}
490
491
  </Clickable>
491
492
  </div>,
492
493
  );
@@ -513,17 +514,17 @@ describe("Clickable", () => {
513
514
  const ClickableWrapper = ({
514
515
  children,
515
516
  ...restProps
516
- }: {|
517
- children: React.Node,
518
- onKeyDown?: (e: SyntheticKeyboardEvent<>) => mixed,
519
- onKeyUp?: (e: SyntheticKeyboardEvent<>) => mixed,
520
- |}) => {
517
+ }: {
518
+ children: React.ReactNode;
519
+ onKeyDown?: (e: React.KeyboardEvent) => unknown;
520
+ onKeyUp?: (e: React.KeyboardEvent) => unknown;
521
+ }) => {
521
522
  return <Clickable {...restProps}>{() => children}</Clickable>;
522
523
  };
523
524
 
524
525
  test("onKeyDown", () => {
525
526
  // Arrange
526
- let keyCode;
527
+ let keyCode: any;
527
528
  render(
528
529
  <ClickableWrapper onKeyDown={(e) => (keyCode = e.keyCode)}>
529
530
  Click me!
@@ -540,7 +541,7 @@ describe("Clickable", () => {
540
541
 
541
542
  test("onKeyUp", () => {
542
543
  // Arrange
543
- let keyCode;
544
+ let keyCode: any;
544
545
  render(
545
546
  <ClickableWrapper onKeyUp={(e) => (keyCode = e.keyCode)}>
546
547
  Click me!
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
 
4
3
  // NOTE: Potentially add to this as more cases come up.
@@ -13,7 +12,7 @@ export type ClickableRole =
13
12
  | "menu"
14
13
  | "tab";
15
14
 
16
- const getAppropriateTriggersForRole = (role: ?ClickableRole) => {
15
+ const getAppropriateTriggersForRole = (role?: ClickableRole | null) => {
17
16
  switch (role) {
18
17
  // Triggers on ENTER, but not SPACE
19
18
  case "link":
@@ -43,7 +42,7 @@ const getAppropriateTriggersForRole = (role: ?ClickableRole) => {
43
42
  };
44
43
 
45
44
  // TODO(FEI-5000): Convert back to conditional props after TS migration is complete.
46
- type Props = {|
45
+ type Props = {
47
46
  /**
48
47
  * A function that returns the a React `Element`.
49
48
  *
@@ -53,16 +52,14 @@ type Props = {|
53
52
  children: (
54
53
  state: ClickableState,
55
54
  childrenProps: ChildrenProps,
56
- ) => React.Node,
57
-
55
+ ) => React.ReactElement;
58
56
  /**
59
57
  * Whether the component is disabled.
60
58
  *
61
59
  * If the component is disabled, this component will return handlers
62
60
  * that do nothing.
63
61
  */
64
- disabled: boolean,
65
-
62
+ disabled: boolean;
66
63
  /**
67
64
  * A URL.
68
65
  *
@@ -72,74 +69,62 @@ type Props = {|
72
69
  * press would also navigate to this location. See the triggerOnEnter and
73
70
  * triggerOnSpace props for more details.
74
71
  */
75
- href?: string,
76
-
72
+ href?: string;
77
73
  /**
78
74
  * This should only be used by button.js.
79
75
  */
80
- type?: "submit",
81
-
76
+ type?: "submit";
82
77
  /**
83
78
  * Specifies the type of relationship between the current document and the
84
79
  * linked document. Should only be used when `href` is specified. This
85
80
  * defaults to "noopener noreferrer" when `target="_blank"`, but can be
86
81
  * overridden by setting this prop to something else.
87
82
  */
88
- rel?: string,
89
-
90
- skipClientNav?: boolean,
91
-
83
+ rel?: string;
84
+ skipClientNav?: boolean;
92
85
  /**
93
86
  * Used to indicate the tab order of an element.
94
87
  * Use 0 to make an element focusable, and use -1 to make an
95
88
  * element non-focusable via keyboard navigation.
96
89
  */
97
- tabIndex?: number,
98
-
90
+ tabIndex?: number;
99
91
  /**
100
92
  * A function to be executed `onclick`.
101
93
  */
102
- onClick?: (e: SyntheticEvent<>) => mixed,
103
-
94
+ onClick?: (e: React.SyntheticEvent) => unknown;
104
95
  /**
105
96
  * Run async code in the background while client-side navigating. If the
106
97
  * browser does a full page load navigation, the callback promise must be
107
98
  * settled before the navigation will occur. Errors are ignored so that
108
99
  * navigation is guaranteed to succeed.
109
100
  */
110
- safeWithNav?: () => Promise<mixed>,
111
-
101
+ safeWithNav?: () => Promise<unknown>;
112
102
  /**
113
103
  * Passed in by withRouter HOC.
114
104
  * @ignore
115
105
  */
116
- history?: any,
117
-
106
+ history?: any;
118
107
  /**
119
108
  * A role that encapsulates how the clickable component should behave, which
120
109
  * affects which keyboard actions trigger the component. For example, a
121
110
  * component with role="button" should be able to be clicked with both the
122
111
  * enter and space keys.
123
112
  */
124
- role?: ClickableRole,
125
-
113
+ role?: ClickableRole;
126
114
  /**
127
115
  * Respond to raw "keydown" event.
128
116
  */
129
- onKeyDown?: (e: SyntheticKeyboardEvent<>) => mixed,
130
-
117
+ onKeyDown?: (e: React.KeyboardEvent) => unknown;
131
118
  /**
132
119
  * Respond to raw "keyup" event.
133
120
  */
134
- onKeyUp?: (e: SyntheticKeyboardEvent<>) => mixed,
135
-
121
+ onKeyUp?: (e: React.KeyboardEvent) => unknown;
136
122
  /**
137
123
  * A target destination window for a link to open in. Should only be used
138
124
  * when `href` is specified.
139
125
  */
140
126
  // TODO(WB-1262): only allow this prop when `href` is also set.
141
- target?: "_blank",
142
-
127
+ target?: "_blank";
143
128
  /**
144
129
  * Run async code before navigating to the URL passed to `href`. If the
145
130
  * promise returned rejects then navigation will not occur.
@@ -153,31 +138,28 @@ type Props = {|
153
138
  * browser can't make a directly link between a user action and the
154
139
  * navigation.
155
140
  */
156
- beforeNav?: () => Promise<mixed>,
157
- |};
141
+ beforeNav?: () => Promise<unknown>;
142
+ };
158
143
 
159
- export type ClickableState = {|
144
+ export type ClickableState = {
160
145
  /**
161
146
  * Whether the component is hovered.
162
147
  *
163
148
  * See component documentation for more details.
164
149
  */
165
- hovered: boolean,
166
-
150
+ hovered: boolean;
167
151
  /**
168
152
  * Whether the component is hovered.
169
153
  *
170
154
  * See component documentation for more details.
171
155
  */
172
- focused: boolean,
173
-
156
+ focused: boolean;
174
157
  /**
175
158
  * Whether the component is hovered.
176
159
  *
177
160
  * See component documentation for more details.
178
161
  */
179
- pressed: boolean,
180
-
162
+ pressed: boolean;
181
163
  /**
182
164
  * When we're waiting for beforeNav or safeWithNav to complete an async
183
165
  * action, this will be true.
@@ -185,29 +167,29 @@ export type ClickableState = {|
185
167
  * NOTE: We only wait for safeWithNav to complete when doing a full page
186
168
  * load navigation.
187
169
  */
188
- waiting: boolean,
189
- |};
190
-
191
- type DefaultProps = {|
192
- disabled: $PropertyType<Props, "disabled">,
193
- |};
194
-
195
- export type ChildrenProps = {|
196
- onClick: (e: SyntheticMouseEvent<>) => mixed,
197
- onMouseEnter: (e: SyntheticMouseEvent<>) => mixed,
198
- onMouseLeave: () => mixed,
199
- onMouseDown: () => mixed,
200
- onMouseUp: (e: SyntheticMouseEvent<>) => mixed,
201
- onTouchStart: () => mixed,
202
- onTouchEnd: () => mixed,
203
- onTouchCancel: () => mixed,
204
- onKeyDown: (e: SyntheticKeyboardEvent<>) => mixed,
205
- onKeyUp: (e: SyntheticKeyboardEvent<>) => mixed,
206
- onFocus: (e: SyntheticFocusEvent<>) => mixed,
207
- onBlur: (e: SyntheticFocusEvent<>) => mixed,
208
- tabIndex?: number,
209
- rel?: string,
210
- |};
170
+ waiting: boolean;
171
+ };
172
+
173
+ type DefaultProps = {
174
+ disabled: Props["disabled"];
175
+ };
176
+
177
+ export type ChildrenProps = {
178
+ onClick: (e: React.SyntheticEvent) => unknown;
179
+ onMouseEnter: (e: React.MouseEvent) => unknown;
180
+ onMouseLeave: () => unknown;
181
+ onMouseDown: () => unknown;
182
+ onMouseUp: (e: React.MouseEvent) => unknown;
183
+ onTouchStart: () => unknown;
184
+ onTouchEnd: () => unknown;
185
+ onTouchCancel: () => unknown;
186
+ onKeyDown: (e: React.KeyboardEvent) => unknown;
187
+ onKeyUp: (e: React.KeyboardEvent) => unknown;
188
+ onFocus: (e: React.FocusEvent) => unknown;
189
+ onBlur: (e: React.FocusEvent) => unknown;
190
+ tabIndex?: number;
191
+ rel?: string;
192
+ };
211
193
 
212
194
  const disabledHandlers = {
213
195
  onClick: () => void 0,
@@ -220,12 +202,12 @@ const disabledHandlers = {
220
202
  onTouchCancel: () => void 0,
221
203
  onKeyDown: () => void 0,
222
204
  onKeyUp: () => void 0,
223
- };
205
+ } as const;
224
206
 
225
207
  const keyCodes = {
226
208
  enter: 13,
227
209
  space: 32,
228
- };
210
+ } as const;
229
211
 
230
212
  const startState: ClickableState = {
231
213
  hovered: false,
@@ -317,7 +299,7 @@ const startState: ClickableState = {
317
299
  */
318
300
  export default class ClickableBehavior extends React.Component<
319
301
  Props,
320
- ClickableState,
302
+ ClickableState
321
303
  > {
322
304
  waitingForClick: boolean;
323
305
  enterClick: boolean;
@@ -329,7 +311,7 @@ export default class ClickableBehavior extends React.Component<
329
311
  static getDerivedStateFromProps(
330
312
  props: Props,
331
313
  state: ClickableState,
332
- ): ?Partial<ClickableState> {
314
+ ): Partial<ClickableState> | null | undefined {
333
315
  // If new props are disabled, reset the hovered/pressed states
334
316
  if (props.disabled) {
335
317
  // Keep the focused state for enabling keyboard navigation.
@@ -375,7 +357,7 @@ export default class ClickableBehavior extends React.Component<
375
357
  }
376
358
 
377
359
  handleSafeWithNav(
378
- safeWithNav: () => Promise<mixed>,
360
+ safeWithNav: () => Promise<unknown>,
379
361
  shouldNavigate: boolean,
380
362
  ): Promise<void> {
381
363
  const {skipClientNav, history} = this.props;
@@ -416,7 +398,9 @@ export default class ClickableBehavior extends React.Component<
416
398
  }
417
399
  }
418
400
 
419
- runCallbackAndMaybeNavigate(e: SyntheticEvent<>): ?Promise<void> {
401
+ runCallbackAndMaybeNavigate(
402
+ e: React.SyntheticEvent,
403
+ ): Promise<undefined> | null | undefined {
420
404
  const {
421
405
  onClick = undefined,
422
406
  beforeNav = undefined,
@@ -457,7 +441,7 @@ export default class ClickableBehavior extends React.Component<
457
441
  // All events should be typed as SyntheticEvent<HTMLElement>.
458
442
  // Updating all of the places will take some time so I'll do
459
443
  // this later
460
- // $FlowFixMe[prop-missing]
444
+ // @ts-expect-error [FEI-5019] - TS2322 - Type 'HTMLElement | null' is not assignable to type 'EventTarget & Element'.
461
445
  target = target.parentElement;
462
446
  }
463
447
  }
@@ -477,13 +461,14 @@ export default class ClickableBehavior extends React.Component<
477
461
  })
478
462
  .catch(() => {});
479
463
  } else if (safeWithNav) {
464
+ // @ts-expect-error [FEI-5019] - TS2322 - Type 'Promise<void>' is not assignable to type 'Promise<undefined>'.
480
465
  return this.handleSafeWithNav(safeWithNav, shouldNavigate);
481
466
  } else {
482
467
  this.navigateOrReset(shouldNavigate);
483
468
  }
484
469
  }
485
470
 
486
- handleClick: (e: SyntheticMouseEvent<>) => void = (e) => {
471
+ handleClick: (e: React.SyntheticEvent) => void = (e) => {
487
472
  const {
488
473
  onClick = undefined,
489
474
  beforeNav = undefined,
@@ -501,7 +486,7 @@ export default class ClickableBehavior extends React.Component<
501
486
  this.runCallbackAndMaybeNavigate(e);
502
487
  };
503
488
 
504
- handleMouseEnter: (e: SyntheticMouseEvent<>) => void = (e) => {
489
+ handleMouseEnter: (e: React.MouseEvent) => void = (e) => {
505
490
  if (!this.waitingForClick) {
506
491
  this.setState({hovered: true});
507
492
  }
@@ -517,7 +502,7 @@ export default class ClickableBehavior extends React.Component<
517
502
  this.setState({pressed: true});
518
503
  };
519
504
 
520
- handleMouseUp: (e: SyntheticMouseEvent<>) => void = (e) => {
505
+ handleMouseUp: (e: React.MouseEvent) => void = (e) => {
521
506
  this.setState({pressed: false, focused: false});
522
507
  };
523
508
 
@@ -535,7 +520,7 @@ export default class ClickableBehavior extends React.Component<
535
520
  this.waitingForClick = true;
536
521
  };
537
522
 
538
- handleKeyDown: (e: SyntheticKeyboardEvent<>) => void = (e) => {
523
+ handleKeyDown: (e: React.KeyboardEvent) => void = (e) => {
539
524
  const {onKeyDown, role} = this.props;
540
525
  if (onKeyDown) {
541
526
  onKeyDown(e);
@@ -561,7 +546,7 @@ export default class ClickableBehavior extends React.Component<
561
546
  }
562
547
  };
563
548
 
564
- handleKeyUp: (e: SyntheticKeyboardEvent<>) => void = (e) => {
549
+ handleKeyUp: (e: React.KeyboardEvent) => void = (e) => {
565
550
  const {onKeyUp, role} = this.props;
566
551
  if (onKeyUp) {
567
552
  onKeyUp(e);
@@ -582,15 +567,15 @@ export default class ClickableBehavior extends React.Component<
582
567
  }
583
568
  };
584
569
 
585
- handleFocus: (e: SyntheticFocusEvent<>) => void = (e) => {
570
+ handleFocus: (e: React.FocusEvent) => void = (e) => {
586
571
  this.setState({focused: true});
587
572
  };
588
573
 
589
- handleBlur: (e: SyntheticFocusEvent<>) => void = (e) => {
574
+ handleBlur: (e: React.FocusEvent) => void = (e) => {
590
575
  this.setState({focused: false, pressed: false});
591
576
  };
592
577
 
593
- render(): React.Node {
578
+ render(): React.ReactElement {
594
579
  const childrenProps: ChildrenProps = this.props.disabled
595
580
  ? {
596
581
  ...disabledHandlers,