@khanacademy/perseus 17.4.0 → 17.5.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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Core Perseus API (includes renderers and widgets)",
4
4
  "author": "Khan Academy",
5
5
  "license": "MIT",
6
- "version": "17.4.0",
6
+ "version": "17.5.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -1,4 +1,5 @@
1
1
  import {KeypadContext} from "@khanacademy/math-input";
2
+ import {action} from "@storybook/addon-actions";
2
3
  import React from "react";
3
4
 
4
5
  import {storybookDependenciesV2} from "../../../../testing/test-dependencies";
@@ -67,6 +68,7 @@ export const ExpressionArticle = ({useNewStyles}): any => (
67
68
  apiOptions={{
68
69
  isMobile: true,
69
70
  customKeypad: true,
71
+ onFocusChange: action("onFocusChange"),
70
72
  }}
71
73
  keypadElement={keypadElement}
72
74
  />
@@ -326,9 +326,9 @@ describe("server item renderer", () => {
326
326
 
327
327
  // Act
328
328
  const gotFocus = renderer.focus();
329
- // We have _two_ different async processes that need to be resolved here
330
- jest.runOnlyPendingTimers();
331
- jest.runOnlyPendingTimers();
329
+
330
+ // We have some async processes that need to be resolved here
331
+ jest.runAllTimers();
332
332
 
333
333
  // Assert
334
334
  expect(gotFocus).toBeTrue();
@@ -370,9 +370,9 @@ describe("server item renderer", () => {
370
370
 
371
371
  // Act
372
372
  const gotFocus = renderer.focus();
373
- // We have _two_ different async processes that need to be resolved here
374
- jest.runOnlyPendingTimers();
375
- jest.runOnlyPendingTimers();
373
+
374
+ // We have some async processes that need to be resolved here
375
+ jest.runAllTimers();
376
376
 
377
377
  // Assert
378
378
  expect(keypadElement.activate).toHaveBeenCalled();
@@ -392,15 +392,12 @@ describe("server item renderer", () => {
392
392
  onFocusChange,
393
393
  });
394
394
  renderer.focus();
395
- // We have _two_ different async processes that need to be resolved here
396
- jest.runOnlyPendingTimers();
397
- jest.runOnlyPendingTimers();
398
395
 
399
396
  // Act
400
397
  renderer.blur();
401
- // We have _two_ different async processes that need to be resolved here
402
- jest.runOnlyPendingTimers();
403
- jest.runOnlyPendingTimers();
398
+
399
+ // We have some async processes that need to be resolved here
400
+ jest.runAllTimers();
404
401
 
405
402
  // Assert
406
403
  expect(onFocusChange).toHaveBeenCalledTimes(2);
@@ -440,15 +437,12 @@ describe("server item renderer", () => {
440
437
  {keypadElement},
441
438
  );
442
439
  renderer.focus();
443
- // We have _two_ different async processes that need to be resolved here
444
- jest.runOnlyPendingTimers();
445
- jest.runOnlyPendingTimers();
446
440
 
447
441
  // Act
448
442
  renderer.blur();
449
- // We have _two_ different async processes that need to be resolved here
450
- jest.runOnlyPendingTimers();
451
- jest.runOnlyPendingTimers();
443
+
444
+ // We have some async processes that need to be resolved here
445
+ jest.runAllTimers();
452
446
 
453
447
  // Assert
454
448
  expect(keypadElement.dismiss).toHaveBeenCalled();
@@ -471,6 +465,9 @@ describe("server item renderer", () => {
471
465
  // Act
472
466
  renderer.focusPath(["input-number 1"]);
473
467
 
468
+ // We have some async processes that need to be resolved here
469
+ jest.runAllTimers();
470
+
474
471
  // Assert
475
472
  expect(onFocusChange).toHaveBeenCalledWith(
476
473
  ["input-number 1"],
@@ -104,6 +104,26 @@ class ArticleRenderer
104
104
  );
105
105
  }
106
106
 
107
+ const {onFocusChange} = this.props.apiOptions;
108
+ if (onFocusChange) {
109
+ // Wait for the keypad to mount before getting the height
110
+ setTimeout(() => {
111
+ const keypadDomNode =
112
+ keypadElement?.getDOMNode() as HTMLElement;
113
+ const keypadHeight =
114
+ keypadDomNode && didFocusInput
115
+ ? keypadDomNode.getBoundingClientRect().height
116
+ : 0;
117
+
118
+ onFocusChange(
119
+ this._currentFocus,
120
+ prevFocusPath,
121
+ keypadHeight,
122
+ didFocusInput ? focusedInput : null,
123
+ );
124
+ }, 0);
125
+ }
126
+
107
127
  if (keypadElement && isMobile) {
108
128
  if (didFocusInput) {
109
129
  keypadElement.activate();
@@ -111,21 +131,6 @@ class ArticleRenderer
111
131
  keypadElement.dismiss();
112
132
  }
113
133
  }
114
-
115
- if (this.props.apiOptions.onFocusChange != null) {
116
- const keypadDomNode = keypadElement?.getDOMNode() as HTMLElement;
117
- const keypadHeight =
118
- keypadDomNode && didFocusInput
119
- ? keypadDomNode.getBoundingClientRect().height
120
- : 0;
121
-
122
- this.props.apiOptions.onFocusChange(
123
- this._currentFocus,
124
- prevFocusPath,
125
- keypadHeight,
126
- didFocusInput ? focusedInput : null,
127
- );
128
- }
129
134
  };
130
135
 
131
136
  _onRendererBlur: (arg1: any) => void = (blurPath) => {
@@ -180,6 +180,29 @@ export class ServerItemRenderer
180
180
  return Util.inputPathsEqual(inputPath, this._currentFocus);
181
181
  });
182
182
 
183
+ if (onFocusChange != null) {
184
+ // Wait for the keypad to mount before getting the height
185
+ setTimeout(() => {
186
+ // First, calculate the current keypad height
187
+ const keypadDomNode: HTMLElement =
188
+ keypadElement?.getDOMNode() as HTMLElement;
189
+ const keypadHeight =
190
+ keypadDomNode && didFocusInput
191
+ ? keypadDomNode.getBoundingClientRect().height
192
+ : 0;
193
+
194
+ // Then call the callback
195
+ onFocusChange(
196
+ this._currentFocus,
197
+ prevFocus,
198
+ keypadHeight,
199
+ // @ts-expect-error [FEI-5003] - TS2345 - Argument of type 'false | Element | Text | null | undefined' is not assignable to parameter of type 'HTMLElement | undefined'.
200
+ didFocusInput &&
201
+ this.questionRenderer.getDOMNodeForPath(newFocus),
202
+ );
203
+ }, 0);
204
+ }
205
+
183
206
  if (keypadElement && isMobile) {
184
207
  if (didFocusInput) {
185
208
  keypadElement.activate();
@@ -187,26 +210,6 @@ export class ServerItemRenderer
187
210
  keypadElement.dismiss();
188
211
  }
189
212
  }
190
-
191
- if (onFocusChange != null) {
192
- // First, calculate the current keypad height
193
- const keypadDomNode: HTMLElement =
194
- keypadElement?.getDOMNode() as HTMLElement;
195
- const keypadHeight =
196
- keypadDomNode && didFocusInput
197
- ? keypadDomNode.getBoundingClientRect().height
198
- : 0;
199
-
200
- // Then call the callback
201
- onFocusChange(
202
- this._currentFocus,
203
- prevFocus,
204
- keypadHeight,
205
- // @ts-expect-error [FEI-5003] - TS2345 - Argument of type 'false | Element | Text | null | undefined' is not assignable to parameter of type 'HTMLElement | undefined'.
206
- didFocusInput &&
207
- this.questionRenderer.getDOMNodeForPath(newFocus),
208
- );
209
- }
210
213
  }
211
214
 
212
215
  _onRendererBlur(blurPath: FocusPath) {
@@ -314,7 +314,7 @@
314
314
  tr:nth-child(odd) {
315
315
  // Doesn't work in IE8 :(
316
316
  td {
317
- background-color: #ededed;
317
+ background-color: @offWhite;
318
318
  }
319
319
  }
320
320
  }
@@ -15,6 +15,7 @@
15
15
  // TODO(charlie): DRY this up. How can we keep our global palette in sync across
16
16
  // repos?
17
17
  @white: #ffffff;
18
+ @offWhite: #f7f8fa;
18
19
  @gray98: #fafafa;
19
20
  @gray97: #f6f7f7;
20
21
  @gray95: #f0f1f2;