@khanacademy/perseus 13.2.0 → 15.0.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/article-renderer.d.ts +1 -2
  3. package/dist/components/svg-image.d.ts +10 -9
  4. package/dist/es/index.js +51 -498
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/index.d.ts +0 -1
  7. package/dist/index.js +72 -511
  8. package/dist/index.js.map +1 -1
  9. package/dist/multi-items/item-types.d.ts +1 -1
  10. package/dist/multi-items/multi-renderer.d.ts +2 -2
  11. package/dist/perseus-api.d.ts +0 -3
  12. package/dist/server-item-renderer.d.ts +2 -15
  13. package/dist/strings.js +1 -0
  14. package/dist/styles/shared.d.ts +1 -0
  15. package/dist/types.d.ts +0 -2
  16. package/dist/util/a11y.d.ts +1 -0
  17. package/dist/widgets/expression.d.ts +0 -12
  18. package/dist/widgets/graded-group.d.ts +1 -1
  19. package/dist/widgets/label-image.d.ts +1 -1
  20. package/dist/widgets/matcher.d.ts +0 -1
  21. package/dist/widgets/passage.d.ts +1 -1
  22. package/dist/widgets/radio/widget.d.ts +1 -1
  23. package/dist/widgets/simulator.d.ts +0 -1
  24. package/dist/widgets/sorter.d.ts +0 -1
  25. package/package.json +8 -8
  26. package/src/__stories__/server-item-renderer.stories.tsx +1 -1
  27. package/src/__testdata__/server-item-renderer.testdata.ts +160 -0
  28. package/src/__tests__/article-renderer.test.tsx +2 -3
  29. package/src/__tests__/server-item-renderer.test.tsx +2 -2
  30. package/src/article-renderer.tsx +13 -15
  31. package/src/components/graph.tsx +14 -8
  32. package/src/components/svg-image.tsx +14 -12
  33. package/src/hints-renderer.tsx +1 -0
  34. package/src/index.ts +0 -1
  35. package/src/multi-items/item-types.ts +1 -1
  36. package/src/multi-items/multi-renderer.tsx +4 -4
  37. package/src/perseus-api.tsx +0 -6
  38. package/src/perseus-types.ts +8 -3
  39. package/src/server-item-renderer.tsx +12 -13
  40. package/src/types.ts +0 -5
  41. package/src/util.ts +1 -1
  42. package/src/widgets/__stories__/expression.stories.tsx +0 -1
  43. package/src/widgets/__stories__/random-widgets.stories.tsx +59 -0
  44. package/src/widgets/__stories__/test-keypad-context-wrapper.tsx +0 -1
  45. package/src/widgets/__testdata__/categorizer.testdata.ts +40 -0
  46. package/src/widgets/__testdata__/dropdown.testdata.ts +38 -0
  47. package/src/widgets/__testdata__/explanation.testdata.ts +30 -0
  48. package/src/widgets/__testdata__/expression.testdata.ts +82 -0
  49. package/src/widgets/__testdata__/interactive-graph-random.testdata.ts +269 -0
  50. package/src/widgets/__testdata__/radio.testdata.ts +63 -0
  51. package/src/widgets/__testdata__/randomizers.ts +51 -0
  52. package/src/widgets/__tests__/expression-mobile.test.tsx +0 -2
  53. package/src/widgets/__tests__/expression.test.tsx +4 -15
  54. package/src/widgets/__tests__/randomizers.test.ts +53 -0
  55. package/src/widgets/expression.tsx +1 -5
  56. package/src/widgets/graded-group.tsx +1 -1
  57. package/src/widgets/image.tsx +27 -20
  58. package/src/widgets/label-image/strings.ts +3 -1
  59. package/src/widgets/label-image.tsx +2 -2
  60. package/src/widgets/passage-ref.tsx +1 -1
  61. package/src/widgets/passage.tsx +1 -1
  62. package/src/widgets/radio/widget.tsx +1 -1
  63. package/src/widgets/radio.ts +1 -1
  64. package/tsconfig-build.tsbuildinfo +1 -1
  65. package/dist/item-renderer.d.ts +0 -125
  66. package/dist/mixins/provide-keypad.d.ts +0 -39
  67. package/src/__stories__/item-renderer.stories.tsx +0 -30
  68. package/src/__testdata__/item-renderer.testdata.ts +0 -299
  69. package/src/__tests__/__snapshots__/item-renderer.test.tsx.snap +0 -224
  70. package/src/__tests__/item-renderer.test.tsx +0 -930
  71. package/src/item-renderer.tsx +0 -529
  72. package/src/mixins/provide-keypad.tsx +0 -138
@@ -8,8 +8,8 @@
8
8
  * interface, so it's compatible with our tree traversal functions.
9
9
  * - And the various types of nodes that compose a tree.
10
10
  */
11
- import type { WidgetDict, ImageDict } from "../types";
12
11
  import type { Tree, ArrayNode, ObjectNode } from "./tree-types";
12
+ import type { WidgetDict, ImageDict } from "../types";
13
13
  export type ContentNode = {
14
14
  __type: "content" | "item";
15
15
  content?: string | null | undefined;
@@ -1,11 +1,11 @@
1
1
  import * as React from "react";
2
2
  import Renderer from "../renderer";
3
- import type { Widget } from "../renderer";
4
- import type { APIOptions, FilterCriterion, PerseusDependenciesV2 } from "../types";
5
3
  import type { Item, ContentNode, HintNode, TagsNode } from "./item-types";
6
4
  import type { Shape, ArrayShape } from "./shape-types";
7
5
  import type { Tree } from "./tree-types";
8
6
  import type { TreeMapper, ContentMapper, HintMapper, Path } from "./trees";
7
+ import type { Widget } from "../renderer";
8
+ import type { APIOptions, FilterCriterion, PerseusDependenciesV2 } from "../types";
9
9
  import type { PropsFor } from "@khanacademy/wonder-blocks-core";
10
10
  type Hint = any;
11
11
  type Score = any;
@@ -53,7 +53,6 @@ export declare const ApiOptions: {
53
53
  customKeypad: PropTypes.Requireable<boolean>;
54
54
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>;
55
55
  isMobile: PropTypes.Requireable<boolean>;
56
- useV2Keypad: PropTypes.Requireable<boolean>;
57
56
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
58
57
  useDraftEditor: PropTypes.Requireable<boolean>;
59
58
  hintProgressColor: PropTypes.Requireable<string>;
@@ -85,7 +84,6 @@ export declare const ApiOptions: {
85
84
  correct?: boolean | undefined;
86
85
  } & Partial<import("./types").TrackingGradedGroupExtraArguments> & Partial<import("./types").TrackingSequenceExtraArguments>) => void) | undefined;
87
86
  customKeypad?: boolean | undefined;
88
- useV2Keypad?: boolean | undefined;
89
87
  nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
90
88
  isMobile?: boolean | undefined;
91
89
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -107,7 +105,6 @@ export declare const ApiOptions: {
107
105
  inModal: NonNullable<boolean | undefined>;
108
106
  isArticle: NonNullable<boolean | undefined>;
109
107
  isMobile: NonNullable<boolean | undefined>;
110
- useV2Keypad: NonNullable<boolean | undefined>;
111
108
  onFocusChange: (newFocusPath: import("./types").FocusPath, oldFocusPath: import("./types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown;
112
109
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
113
110
  readOnly: NonNullable<boolean | undefined>;
@@ -8,12 +8,10 @@
8
8
  */
9
9
  import * as React from "react";
10
10
  import Renderer from "./renderer";
11
- import type { KeypadProps } from "./mixins/provide-keypad";
12
11
  import type { APIOptions, FocusPath, PerseusDependenciesV2 } from "./types";
13
12
  import type { KeypadAPI } from "@khanacademy/math-input";
14
13
  import type { KeypadContextRendererInterface, RendererInterface, KEScore } from "@khanacademy/perseus-core";
15
- type OwnProps = // These props are used by the ProvideKeypad mixin.
16
- KeypadProps & {
14
+ type OwnProps = {
17
15
  apiOptions: APIOptions;
18
16
  hintsVisible?: number;
19
17
  item: {
@@ -102,16 +100,5 @@ export declare class ServerItemRenderer extends React.Component<Props, State> im
102
100
  setAssetStatus: (assetKey: string, status: boolean) => void;
103
101
  render(): React.ReactNode;
104
102
  }
105
- declare const ref: React.ForwardRefExoticComponent<Omit<KeypadProps & {
106
- apiOptions: APIOptions;
107
- hintsVisible?: number | undefined;
108
- item: {
109
- hints: ReadonlyArray<any>;
110
- question: any;
111
- };
112
- problemNum?: number | undefined;
113
- reviewMode?: boolean | undefined;
114
- keypadElement?: KeypadAPI | null | undefined;
115
- dependencies: PerseusDependenciesV2;
116
- } & HOCProps, "onRendered"> & React.RefAttributes<ServerItemRenderer>>;
103
+ declare const ref: React.ForwardRefExoticComponent<Omit<OwnProps & HOCProps, "onRendered"> & React.RefAttributes<ServerItemRenderer>>;
117
104
  export default ref;
package/dist/strings.js CHANGED
@@ -75,6 +75,7 @@ module.exports = [
75
75
  i18n._("Get another hint", {}),
76
76
  i18n._("Greater than or equal to sign", {}),
77
77
  i18n._("Greater than sign", {}),
78
+ i18n._("Hide answer choices", {}),
78
79
  i18n._("Hide explanation", {}),
79
80
  i18n._("Hint #%(pos)s", {}),
80
81
  i18n._("Hints", {}),
@@ -1,2 +1,3 @@
1
+ import type { StyleDeclaration } from "aphrodite";
1
2
  declare const _default: StyleDeclaration;
2
3
  export default _default;
package/dist/types.d.ts CHANGED
@@ -102,7 +102,6 @@ export type APIOptions = Readonly<{
102
102
  imagePreloader?: (dimensions: Dimensions) => React.ReactNode;
103
103
  trackInteraction?: (args: TrackInteractionArgs) => void;
104
104
  customKeypad?: boolean;
105
- useV2Keypad?: boolean;
106
105
  nativeKeypadProxy?: (blur: () => void) => KeypadAPI;
107
106
  isMobile?: boolean;
108
107
  setDrawingAreaAvailable?: (arg1: boolean) => unknown;
@@ -196,7 +195,6 @@ export type APIOptionsWithDefaults = Readonly<APIOptions & {
196
195
  inModal: NonNullable<APIOptions["inModal"]>;
197
196
  isArticle: NonNullable<APIOptions["isArticle"]>;
198
197
  isMobile: NonNullable<APIOptions["isMobile"]>;
199
- useV2Keypad: NonNullable<APIOptions["useV2Keypad"]>;
200
198
  onFocusChange: NonNullable<APIOptions["onFocusChange"]>;
201
199
  onInputError: NonNullable<APIOptions["onInputError"]>;
202
200
  readOnly: NonNullable<APIOptions["readOnly"]>;
@@ -1,2 +1,3 @@
1
+ import type { StyleDeclaration } from "aphrodite";
1
2
  declare const _default: StyleDeclaration;
2
3
  export default _default;
@@ -112,7 +112,6 @@ declare const _default: Readonly<{
112
112
  correct?: boolean | undefined;
113
113
  } & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
114
114
  customKeypad?: boolean | undefined;
115
- useV2Keypad?: boolean | undefined;
116
115
  nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
117
116
  isMobile?: boolean | undefined;
118
117
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -134,7 +133,6 @@ declare const _default: Readonly<{
134
133
  inModal: NonNullable<boolean | undefined>;
135
134
  isArticle: NonNullable<boolean | undefined>;
136
135
  isMobile: NonNullable<boolean | undefined>;
137
- useV2Keypad: NonNullable<boolean | undefined>;
138
136
  onFocusChange: (newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown;
139
137
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
140
138
  readOnly: NonNullable<boolean | undefined>;
@@ -177,7 +175,6 @@ declare const _default: Readonly<{
177
175
  correct?: boolean | undefined;
178
176
  } & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
179
177
  customKeypad?: boolean | undefined;
180
- useV2Keypad?: boolean | undefined;
181
178
  nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
182
179
  isMobile?: boolean | undefined;
183
180
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -199,7 +196,6 @@ declare const _default: Readonly<{
199
196
  inModal: NonNullable<boolean | undefined>;
200
197
  isArticle: NonNullable<boolean | undefined>;
201
198
  isMobile: NonNullable<boolean | undefined>;
202
- useV2Keypad: NonNullable<boolean | undefined>;
203
199
  onFocusChange: (newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown;
204
200
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
205
201
  readOnly: NonNullable<boolean | undefined>;
@@ -242,7 +238,6 @@ declare const _default: Readonly<{
242
238
  correct?: boolean | undefined;
243
239
  } & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
244
240
  customKeypad?: boolean | undefined;
245
- useV2Keypad?: boolean | undefined;
246
241
  nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
247
242
  isMobile?: boolean | undefined;
248
243
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -264,7 +259,6 @@ declare const _default: Readonly<{
264
259
  inModal: NonNullable<boolean | undefined>;
265
260
  isArticle: NonNullable<boolean | undefined>;
266
261
  isMobile: NonNullable<boolean | undefined>;
267
- useV2Keypad: NonNullable<boolean | undefined>;
268
262
  onFocusChange: (newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown;
269
263
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
270
264
  readOnly: NonNullable<boolean | undefined>;
@@ -318,7 +312,6 @@ declare const _default: Readonly<{
318
312
  correct?: boolean | undefined;
319
313
  } & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
320
314
  customKeypad?: boolean | undefined;
321
- useV2Keypad?: boolean | undefined;
322
315
  nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
323
316
  isMobile?: boolean | undefined;
324
317
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -340,7 +333,6 @@ declare const _default: Readonly<{
340
333
  inModal: NonNullable<boolean | undefined>;
341
334
  isArticle: NonNullable<boolean | undefined>;
342
335
  isMobile: NonNullable<boolean | undefined>;
343
- useV2Keypad: NonNullable<boolean | undefined>;
344
336
  onFocusChange: (newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown;
345
337
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
346
338
  readOnly: NonNullable<boolean | undefined>;
@@ -383,7 +375,6 @@ declare const _default: Readonly<{
383
375
  correct?: boolean | undefined;
384
376
  } & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
385
377
  customKeypad?: boolean | undefined;
386
- useV2Keypad?: boolean | undefined;
387
378
  nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
388
379
  isMobile?: boolean | undefined;
389
380
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -405,7 +396,6 @@ declare const _default: Readonly<{
405
396
  inModal: NonNullable<boolean | undefined>;
406
397
  isArticle: NonNullable<boolean | undefined>;
407
398
  isMobile: NonNullable<boolean | undefined>;
408
- useV2Keypad: NonNullable<boolean | undefined>;
409
399
  onFocusChange: (newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown;
410
400
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
411
401
  readOnly: NonNullable<boolean | undefined>;
@@ -448,7 +438,6 @@ declare const _default: Readonly<{
448
438
  correct?: boolean | undefined;
449
439
  } & Partial<import("../types").TrackingGradedGroupExtraArguments> & Partial<import("../types").TrackingSequenceExtraArguments>) => void) | undefined;
450
440
  customKeypad?: boolean | undefined;
451
- useV2Keypad?: boolean | undefined;
452
441
  nativeKeypadProxy?: ((blur: () => void) => import("@khanacademy/math-input").KeypadAPI) | undefined;
453
442
  isMobile?: boolean | undefined;
454
443
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -470,7 +459,6 @@ declare const _default: Readonly<{
470
459
  inModal: NonNullable<boolean | undefined>;
471
460
  isArticle: NonNullable<boolean | undefined>;
472
461
  isMobile: NonNullable<boolean | undefined>;
473
- useV2Keypad: NonNullable<boolean | undefined>;
474
462
  onFocusChange: (newFocusPath: import("../types").FocusPath, oldFocusPath: import("../types").FocusPath, keypadElement?: Element | Text | null | undefined, focusedElement?: HTMLElement | undefined) => unknown;
475
463
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
476
464
  readOnly: NonNullable<boolean | undefined>;
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
+ import type { ANSWER_BAR_STATES } from "./graded-group-answer-bar";
2
3
  import type { PerseusGradedGroupWidgetOptions } from "../perseus-types";
3
4
  import type { TrackingGradedGroupExtraArguments, WidgetProps } from "../types";
4
- import type { ANSWER_BAR_STATES } from "./graded-group-answer-bar";
5
5
  declare const GRADING_STATUSES: {
6
6
  readonly ungraded: "ungraded";
7
7
  readonly correct: "correct";
@@ -9,9 +9,9 @@ import { Popover } from "@khanacademy/wonder-blocks-popover";
9
9
  import * as React from "react";
10
10
  import AnswerChoices from "./label-image/answer-choices";
11
11
  import Marker from "./label-image/marker";
12
+ import type { InteractiveMarkerType, InteractiveMarkerScore } from "./label-image/types";
12
13
  import type { ChangeableProps } from "../mixins/changeable";
13
14
  import type { APIOptions, PerseusScore } from "../types";
14
- import type { InteractiveMarkerType, InteractiveMarkerScore } from "./label-image/types";
15
15
  type MarkersState = {
16
16
  markers: ReadonlyArray<InteractiveMarkerType>;
17
17
  };
@@ -29,7 +29,6 @@ export declare class Matcher extends React.Component<any, any> {
29
29
  customKeypad: PropTypes.Requireable<boolean>;
30
30
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>;
31
31
  isMobile: PropTypes.Requireable<boolean>;
32
- useV2Keypad: PropTypes.Requireable<boolean>;
33
32
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
34
33
  useDraftEditor: PropTypes.Requireable<boolean>;
35
34
  hintProgressColor: PropTypes.Requireable<string>;
@@ -1,9 +1,9 @@
1
1
  import * as React from "react";
2
+ import type { ParseState } from "./passage/passage-markdown";
2
3
  import type { SerializedHighlightSet } from "../components/highlighting/types";
3
4
  import type { ChangeableProps } from "../mixins/changeable";
4
5
  import type { PerseusPassageWidgetOptions } from "../perseus-types";
5
6
  import type { PerseusScore, WidgetInfo, WidgetProps } from "../types";
6
- import type { ParseState } from "./passage/passage-markdown";
7
7
  import type { SingleASTNode } from "@khanacademy/simple-markdown";
8
8
  export declare class LineHeightMeasurer extends React.Component<Record<any, any>> {
9
9
  _line: HTMLDivElement | null | undefined;
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
+ import type { FocusFunction } from "./base-radio";
2
3
  import type { PerseusRadioChoice, PerseusRadioWidgetOptions } from "../../perseus-types";
3
4
  import type { PerseusScore, WidgetProps, ChoiceState } from "../../types";
4
- import type { FocusFunction } from "./base-radio";
5
5
  export type RenderProps = {
6
6
  numCorrect: number;
7
7
  hasNoneOfTheAbove?: boolean;
@@ -24,7 +24,6 @@ declare class Simulator extends React.Component<any, any> {
24
24
  customKeypad: PropTypes.Requireable<boolean>;
25
25
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>;
26
26
  isMobile: PropTypes.Requireable<boolean>;
27
- useV2Keypad: PropTypes.Requireable<boolean>;
28
27
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
29
28
  useDraftEditor: PropTypes.Requireable<boolean>;
30
29
  hintProgressColor: PropTypes.Requireable<string>;
@@ -25,7 +25,6 @@ declare class Sorter extends React.Component<any, any> {
25
25
  customKeypad: PropTypes.Requireable<boolean>;
26
26
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>;
27
27
  isMobile: PropTypes.Requireable<boolean>;
28
- useV2Keypad: PropTypes.Requireable<boolean>;
29
28
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
30
29
  useDraftEditor: PropTypes.Requireable<boolean>;
31
30
  hintProgressColor: PropTypes.Requireable<string>;
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": "13.2.0",
6
+ "version": "15.0.0",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -22,13 +22,13 @@
22
22
  "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'"
23
23
  },
24
24
  "dependencies": {
25
- "@khanacademy/kas": "^0.3.5",
26
- "@khanacademy/kmath": "^0.1.6",
27
- "@khanacademy/math-input": "^15.1.0",
28
- "@khanacademy/perseus-core": "1.3.0",
29
- "@khanacademy/perseus-linter": "^0.3.8",
30
- "@khanacademy/pure-markdown": "^0.2.11",
31
- "@khanacademy/simple-markdown": "^0.11.0"
25
+ "@khanacademy/kas": "^0.3.6",
26
+ "@khanacademy/kmath": "^0.1.7",
27
+ "@khanacademy/math-input": "^16.1.0",
28
+ "@khanacademy/perseus-core": "1.4.0",
29
+ "@khanacademy/perseus-linter": "^0.3.9",
30
+ "@khanacademy/pure-markdown": "^0.2.12",
31
+ "@khanacademy/simple-markdown": "^0.11.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@khanacademy/wonder-blocks-button": "^6.2.2",
@@ -4,7 +4,7 @@ import {ServerItemRendererWithDebugUI} from "../../../../testing/server-item-ren
4
4
  import {
5
5
  itemWithInput,
6
6
  labelImageItem,
7
- } from "../__testdata__/item-renderer.testdata";
7
+ } from "../__testdata__/server-item-renderer.testdata";
8
8
 
9
9
  type StoryArgs = Record<any, any>;
10
10
 
@@ -0,0 +1,160 @@
1
+ import type {
2
+ InputNumberWidget,
3
+ LabelImageWidget,
4
+ PerseusItem,
5
+ PerseusRenderer,
6
+ } from "../perseus-types";
7
+
8
+ export const itemWithInput: PerseusItem = {
9
+ question: {
10
+ content:
11
+ "Enter the number $$-42$$ in the box: [[\u2603 input-number 1]]",
12
+ images: {},
13
+ widgets: {
14
+ "input-number 1": {
15
+ type: "input-number",
16
+ graded: true,
17
+ options: {
18
+ answerType: "number",
19
+ value: "-42",
20
+ simplify: "required",
21
+ size: "normal",
22
+ inexact: false,
23
+ maxError: 0.1,
24
+ },
25
+ } as InputNumberWidget,
26
+ },
27
+ },
28
+ hints: [
29
+ {content: "Hint #1", images: {}, widgets: {}},
30
+ {content: "Hint #2", images: {}, widgets: {}},
31
+ {content: "Hint #3", images: {}, widgets: {}},
32
+ ],
33
+ answerArea: null,
34
+ _multi: null,
35
+ itemDataVersion: {major: 0, minor: 0},
36
+ answer: null,
37
+ };
38
+
39
+ export const labelImageItem: PerseusItem = {
40
+ answerArea: {
41
+ calculator: false,
42
+ chi2Table: false,
43
+ periodicTable: false,
44
+ tTable: false,
45
+ zTable: false,
46
+ },
47
+ _multi: null,
48
+ answer: null,
49
+ hints: [],
50
+ itemDataVersion: {major: 0, minor: 1},
51
+ question: {
52
+ content:
53
+ "Catherine created a chart and a bar graph to show how many dogs of each breed the animal shelter placed into good homes last year. \n\nDog breed | Number of dogs \n:- | :-: \nBulldog | $32$ \nGreyhound | $72$ \nMastiff | $56$ \nCollie | $40$ \n\n**Label each bar on the bar graph.**\n\n[[☃ label-image 1]]\n\n\n\n",
54
+ images: {
55
+ "web+graphie://ka-perseus-graphie.s3.amazonaws.com/2f60b533892fe6cb9351f704ffdada8ae4bc655c":
56
+ {height: 365, width: 503},
57
+ "web+graphie://ka-perseus-graphie.s3.amazonaws.com/75f937c6ea133d655dd9f698a58182efd6cc85d4":
58
+ {height: 293, width: 331},
59
+ },
60
+ widgets: {
61
+ "label-image 1": {
62
+ alignment: "default",
63
+ graded: true,
64
+ static: false,
65
+ type: "label-image",
66
+ version: {major: 0, minor: 0},
67
+ options: {
68
+ choices: ["Bulldog", "Greyhound", "Mastiff", "Collie"],
69
+ hideChoicesFromInstructions: true,
70
+ imageAlt:
71
+ "A bar graph with four bar lines shows the horizontal axis labeled Dog breed and the vertical axis labeled Number of dogs. The vertical axis is labeled from the bottom of the axis to the top of the axis as follows: 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, and 80. The horizontal axis has, from left to right, four unlabeled bar lines as follows: the first unlabeled bar line extends to 56, the second unlabeled bar line extends to 72, the third unlabeled bar line extends to 40, and the fourth unlabeled bar line extends to 32.",
72
+ imageHeight: 293,
73
+ imageUrl:
74
+ "web+graphie://ka-perseus-graphie.s3.amazonaws.com/64ace45942546183c3dc842cb0e9e4f64a312727",
75
+ imageWidth: 331,
76
+ markers: [
77
+ {
78
+ answers: ["Bulldog"],
79
+ label: "The fourth unlabeled bar line.",
80
+ x: 87.3,
81
+ y: 90.2,
82
+ },
83
+ {
84
+ answers: ["Collie"],
85
+ label: "The third unlabeled bar line.",
86
+ x: 67.7,
87
+ y: 90.5,
88
+ },
89
+ {
90
+ answers: ["Greyhound"],
91
+ label: "The second unlabeled bar line.",
92
+ x: 47.7,
93
+ y: 90.2,
94
+ },
95
+ {
96
+ answers: ["Mastiff"],
97
+ label: "The first unlabeled bar line.",
98
+ x: 27.8,
99
+ y: 90.5,
100
+ },
101
+ ],
102
+ multipleAnswers: false,
103
+ static: false,
104
+ },
105
+ } as LabelImageWidget,
106
+ },
107
+ },
108
+ };
109
+
110
+ // Note that if this item is used, you _must_ first register the MockWidget
111
+ export const mockedItem: PerseusItem = {
112
+ // The mock widget type is not part of the PerseusWidget type union (and
113
+ // we don't want to make it such to avoid polluting our production types
114
+ // for test purposes) so we force TypeScript to accept it here.
115
+ // @ts-expect-error - TS2352 - Conversion of type '{ content: string; images: {}; widgets: { "mock-widget 1": { graded: true; version: { major: number; minor: number; }; static: false; type: "mock-widget"; options: { static: false; smiling: boolean; }; alignment: string; }; "mock-widget 2": { ...; }; "mock-widget 3": { ...; }; "mock-widget 4": { ...; }; }; }' to type 'PerseusRenderer' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
116
+ question: {
117
+ content:
118
+ "Mock widget ==> [[\u2603 mock-widget 1]] [[\u2603 mock-widget 2]] [[\u2603 mock-widget 3]] [[\u2603 mock-widget 4]]",
119
+ images: {},
120
+ widgets: {
121
+ "mock-widget 1": {
122
+ graded: true,
123
+ version: {major: 0, minor: 0},
124
+ static: false,
125
+ type: "mock-widget",
126
+ options: {static: false, smiling: true},
127
+ alignment: "default",
128
+ },
129
+ "mock-widget 2": {
130
+ graded: true,
131
+ version: {major: 0, minor: 0},
132
+ static: false,
133
+ type: "mock-widget",
134
+ options: {static: false, smiling: false},
135
+ alignment: "default",
136
+ },
137
+ "mock-widget 3": {
138
+ graded: true,
139
+ version: {major: 0, minor: 0},
140
+ static: false,
141
+ type: "mock-widget",
142
+ options: {static: false, smiling: true},
143
+ alignment: "default",
144
+ },
145
+ "mock-widget 4": {
146
+ graded: true,
147
+ version: {major: 0, minor: 0},
148
+ static: false,
149
+ type: "mock-widget",
150
+ options: {static: false, smiling: false},
151
+ alignment: "default",
152
+ },
153
+ },
154
+ } as PerseusRenderer,
155
+ hints: [],
156
+ answerArea: null,
157
+ _multi: null,
158
+ itemDataVersion: {major: 0, minor: 0},
159
+ answer: null,
160
+ };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  StatefulKeypadContextProvider,
3
3
  KeypadContext,
4
+ MobileKeypad,
4
5
  } from "@khanacademy/math-input";
5
6
  import {RenderStateRoot} from "@khanacademy/wonder-blocks-core";
6
7
  import {screen, render, fireEvent, waitFor} from "@testing-library/react";
@@ -11,7 +12,6 @@ import {
11
12
  testDependencies,
12
13
  testDependenciesV2,
13
14
  } from "../../../../testing/test-dependencies";
14
- import KeypadSwitch from "../../../math-input/src/components/keypad-switch";
15
15
  import {articleWithExpression} from "../__testdata__/article-renderer.testdata";
16
16
  import ArticleRenderer from "../article-renderer";
17
17
  import * as Dependencies from "../dependencies";
@@ -24,11 +24,10 @@ function KeypadWithContext() {
24
24
  <KeypadContext.Consumer>
25
25
  {({setKeypadElement}) => {
26
26
  return (
27
- <KeypadSwitch
27
+ <MobileKeypad
28
28
  onElementMounted={setKeypadElement}
29
29
  onDismiss={() => {}}
30
30
  onAnalyticsEvent={async () => {}}
31
- useV2Keypad
32
31
  />
33
32
  );
34
33
  }}
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  itemWithInput,
13
13
  mockedItem,
14
- } from "../__testdata__/item-renderer.testdata";
14
+ } from "../__testdata__/server-item-renderer.testdata";
15
15
  import * as Dependencies from "../dependencies";
16
16
  import WrappedServerItemRenderer, {
17
17
  ServerItemRenderer,
@@ -25,9 +25,9 @@ import MockAssetLoadingWidgetExport, {
25
25
  } from "./mock-asset-loading-widget";
26
26
  import MockWidgetExport from "./mock-widget";
27
27
 
28
+ import type {MockAssetLoadingWidget} from "./mock-asset-loading-widget";
28
29
  import type {PerseusItem} from "../perseus-types";
29
30
  import type {APIOptions} from "../types";
30
- import type {MockAssetLoadingWidget} from "./mock-asset-loading-widget";
31
31
  import type {KeypadAPI} from "@khanacademy/math-input";
32
32
  import type {PropsFor} from "@khanacademy/wonder-blocks-core";
33
33
 
@@ -12,27 +12,25 @@ import {ClassNames as ApiClassNames, ApiOptions} from "./perseus-api";
12
12
  import Renderer from "./renderer";
13
13
  import Util from "./util";
14
14
 
15
- import type {KeypadProps} from "./mixins/provide-keypad";
16
15
  import type {PerseusRenderer} from "./perseus-types";
17
16
  import type {APIOptions, PerseusDependenciesV2} from "./types";
18
17
  import type {KeypadAPI} from "@khanacademy/math-input";
19
18
  import type {KeypadContextRendererInterface} from "@khanacademy/perseus-core";
20
19
  import type {LinterContextProps} from "@khanacademy/perseus-linter";
21
20
 
22
- type Props = Partial<React.ContextType<typeof DependenciesContext>> &
23
- KeypadProps & {
24
- apiOptions: APIOptions;
25
- json: PerseusRenderer | ReadonlyArray<PerseusRenderer>;
26
- // Whether to use the new Bibliotron styles for articles
27
- /**
28
- * @deprecated Does nothing
29
- */
30
- useNewStyles: boolean;
31
- linterContext: LinterContextProps;
32
- legacyPerseusLint?: ReadonlyArray<string>;
33
- keypadElement?: KeypadAPI | null | undefined;
34
- dependencies: PerseusDependenciesV2;
35
- };
21
+ type Props = Partial<React.ContextType<typeof DependenciesContext>> & {
22
+ apiOptions: APIOptions;
23
+ json: PerseusRenderer | ReadonlyArray<PerseusRenderer>;
24
+ // Whether to use the new Bibliotron styles for articles
25
+ /**
26
+ * @deprecated Does nothing
27
+ */
28
+ useNewStyles: boolean;
29
+ linterContext: LinterContextProps;
30
+ legacyPerseusLint?: ReadonlyArray<string>;
31
+ keypadElement?: KeypadAPI | null | undefined;
32
+ dependencies: PerseusDependenciesV2;
33
+ };
36
34
 
37
35
  type DefaultProps = {
38
36
  apiOptions: Props["apiOptions"];
@@ -5,6 +5,7 @@ import * as React from "react";
5
5
  import ReactDOM from "react-dom";
6
6
  import _ from "underscore";
7
7
 
8
+ import AssetContext from "../asset-context";
8
9
  import {interactiveSizes} from "../styles/constants";
9
10
  import Util from "../util";
10
11
  import GraphUtils from "../util/graph-utils";
@@ -395,14 +396,19 @@ class Graph extends React.Component<Props> {
395
396
  if (imageData.url) {
396
397
  const scale = this.props.box[0] / interactiveSizes.defaultBoxSize;
397
398
  image = (
398
- // @ts-expect-error - TS2741 - Property 'alt' is missing in type '{ src: any; width: any; height: any; scale: number; responsive: false; }' but required in type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "children" | "height" | "width" | "title" | "alt" | "trackInteraction" | "preloader" | "allowFullBleed" | "extraGraphie" | "overrideAriaHidden">'.
399
- <SvgImage
400
- src={imageData.url}
401
- width={imageData.width}
402
- height={imageData.height}
403
- scale={scale}
404
- responsive={false}
405
- />
399
+ <AssetContext.Consumer>
400
+ {({setAssetStatus}) => (
401
+ <SvgImage
402
+ // @ts-expect-error - TS2741 - Property 'alt' is missing in type '{ src: any; width: any; height: any; scale: number; responsive: false; }' but required in type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "children" | "height" | "width" | "title" | "alt" | "trackInteraction" | "preloader" | "allowFullBleed" | "extraGraphie" | "overrideAriaHidden">'.
403
+ src={imageData.url}
404
+ width={imageData.width}
405
+ height={imageData.height}
406
+ scale={scale}
407
+ responsive={false}
408
+ setAssetStatus={setAssetStatus}
409
+ />
410
+ )}
411
+ </AssetContext.Consumer>
406
412
  );
407
413
  } else {
408
414
  image = null;