@khanacademy/perseus 6.7.0 → 7.0.1

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.
@@ -3,7 +3,8 @@ import HintsRenderer from "./hints-renderer";
3
3
  import Renderer from "./renderer";
4
4
  import type { KeypadProps } from "./mixins/provide-keypad";
5
5
  import type { PerseusItem } from "./perseus-types";
6
- import type { APIOptions, FocusPath, KEScore, LinterContextProps } from "./types";
6
+ import type { APIOptions, FocusPath, LinterContextProps } from "./types";
7
+ import type { KEScore } from "@khanacademy/perseus-core";
7
8
  type Props = // These props are used by the ProvideKeypad mixin.
8
9
  KeypadProps & {
9
10
  apiOptions: APIOptions;
@@ -9,12 +9,8 @@ import HintsRenderer from "./hints-renderer";
9
9
  import Renderer from "./renderer";
10
10
  import type { KeypadProps } from "./mixins/provide-keypad";
11
11
  import type { PerseusItem } from "./perseus-types";
12
- import type {
13
- APIOptions,
14
- FocusPath,
15
- KEScore,
16
- LinterContextProps,
17
- } from "./types";
12
+ import type { APIOptions, FocusPath, LinterContextProps } from "./types";
13
+ import type { KEScore } from "@khanacademy/perseus-core";
18
14
  declare type Props = {|
19
15
  ...KeypadProps,
20
16
  ...{|
@@ -53,6 +53,7 @@ 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>;
56
57
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
57
58
  useDraftEditor: PropTypes.Requireable<boolean>;
58
59
  hintProgressColor: PropTypes.Requireable<string>;
@@ -84,6 +85,7 @@ export declare const ApiOptions: {
84
85
  correct?: boolean | undefined;
85
86
  } & Record<string, unknown>) => void) | undefined;
86
87
  customKeypad?: boolean | undefined;
88
+ useV2Keypad?: boolean | undefined;
87
89
  nativeKeypadProxy?: (() => unknown) | undefined;
88
90
  isMobile?: boolean | undefined;
89
91
  setDrawingAreaAvailable?: ((arg1: boolean) => unknown) | undefined;
@@ -105,6 +107,7 @@ export declare const ApiOptions: {
105
107
  inModal: NonNullable<boolean | undefined>;
106
108
  isArticle: NonNullable<boolean | undefined>;
107
109
  isMobile: NonNullable<boolean | undefined>;
110
+ useV2Keypad: NonNullable<boolean | undefined>;
108
111
  onFocusChange: (newFocusPath: import("./types").FocusPath, oldFocusPath: import("./types").FocusPath, keypadElement?: HTMLElement | undefined, focusedElement?: HTMLElement | undefined) => unknown;
109
112
  onInputError: (widgetId: any, value: string, message?: string | null | undefined) => unknown;
110
113
  readOnly: NonNullable<boolean | undefined>;
@@ -33,6 +33,7 @@ declare export var ApiOptions: {|
33
33
  customKeypad: PropTypes.Requireable<boolean>,
34
34
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>,
35
35
  isMobile: PropTypes.Requireable<boolean>,
36
+ useV2Keypad: PropTypes.Requireable<boolean>,
36
37
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>,
37
38
  useDraftEditor: PropTypes.Requireable<boolean>,
38
39
  hintProgressColor: PropTypes.Requireable<string>,
@@ -89,6 +90,7 @@ declare export var ApiOptions: {|
89
90
  |}) => void)
90
91
  | void,
91
92
  customKeypad?: boolean | void,
93
+ useV2Keypad?: boolean | void,
92
94
  nativeKeypadProxy?: (() => mixed) | void,
93
95
  isMobile?: boolean | void,
94
96
  setDrawingAreaAvailable?: ((arg1: boolean) => mixed) | void,
@@ -111,6 +113,7 @@ declare export var ApiOptions: {|
111
113
  inModal: $NonMaybeType<boolean | void>,
112
114
  isArticle: $NonMaybeType<boolean | void>,
113
115
  isMobile: $NonMaybeType<boolean | void>,
116
+ useV2Keypad: $NonMaybeType<boolean | void>,
114
117
  onFocusChange: (
115
118
  newFocusPath: $Flowgen$Import$_2e__2f_types.FocusPath,
116
119
  oldFocusPath: $Flowgen$Import$_2e__2f_types.FocusPath,
@@ -9,7 +9,8 @@
9
9
  import * as React from "react";
10
10
  import Renderer from "./renderer";
11
11
  import type { KeypadProps } from "./mixins/provide-keypad";
12
- import type { APIOptions, KEScore, FocusPath, RendererInterface } from "./types";
12
+ import type { APIOptions, FocusPath } from "./types";
13
+ import type { RendererInterface, KEScore } from "@khanacademy/perseus-core";
13
14
  type OwnProps = // These props are used by the ProvideKeypad mixin.
14
15
  KeypadProps & {
15
16
  apiOptions: APIOptions;
@@ -7,12 +7,8 @@
7
7
  import * as React from "react";
8
8
  import Renderer from "./renderer";
9
9
  import type { KeypadProps } from "./mixins/provide-keypad";
10
- import type {
11
- APIOptions,
12
- KEScore,
13
- FocusPath,
14
- RendererInterface,
15
- } from "./types";
10
+ import type { APIOptions, FocusPath } from "./types";
11
+ import type { RendererInterface, KEScore } from "@khanacademy/perseus-core";
16
12
  declare type OwnProps = {|
17
13
  ...KeypadProps,
18
14
  ...{|
package/dist/types.d.ts CHANGED
@@ -7,15 +7,6 @@ import type { SizeClass } from "./util/sizing-utils";
7
7
  import type { SendEventFn } from "@khanacademy/perseus-core";
8
8
  import type { Result } from "@khanacademy/wonder-blocks-data";
9
9
  export type FocusPath = ReadonlyArray<string> | null | undefined;
10
- type State = any;
11
- export interface RendererInterface {
12
- getSerializedState(): State;
13
- restoreSerializedState(state: State, callback?: () => void): void;
14
- scoreInput(): KEScore;
15
- blur(): void;
16
- focus(): boolean | null | undefined;
17
- props: any;
18
- }
19
10
  export type Dimensions = {
20
11
  width?: number;
21
12
  height?: number;
@@ -38,14 +29,6 @@ export type PerseusScore = {
38
29
  total: number;
39
30
  message?: string | null | undefined;
40
31
  };
41
- export type KEScore = {
42
- empty: boolean;
43
- correct: boolean;
44
- message?: string | null | undefined;
45
- suppressAlmostThere?: boolean | null | undefined;
46
- guess: any;
47
- state: any;
48
- };
49
32
  export type Hint = {
50
33
  widgets: WidgetDict;
51
34
  content: string;
@@ -114,6 +97,7 @@ export type APIOptions = Readonly<{
114
97
  correct?: boolean;
115
98
  } & Record<string, unknown>) => void;
116
99
  customKeypad?: boolean;
100
+ useV2Keypad?: boolean;
117
101
  nativeKeypadProxy?: () => unknown;
118
102
  isMobile?: boolean;
119
103
  setDrawingAreaAvailable?: (arg1: boolean) => unknown;
@@ -195,6 +179,7 @@ export type APIOptionsWithDefaults = Readonly<APIOptions & {
195
179
  inModal: NonNullable<APIOptions["inModal"]>;
196
180
  isArticle: NonNullable<APIOptions["isArticle"]>;
197
181
  isMobile: NonNullable<APIOptions["isMobile"]>;
182
+ useV2Keypad: NonNullable<APIOptions["useV2Keypad"]>;
198
183
  onFocusChange: NonNullable<APIOptions["onFocusChange"]>;
199
184
  onInputError: NonNullable<APIOptions["onInputError"]>;
200
185
  readOnly: NonNullable<APIOptions["readOnly"]>;
@@ -13,15 +13,6 @@ import type { SizeClass } from "./util/sizing-utils";
13
13
  import type { SendEventFn } from "@khanacademy/perseus-core";
14
14
  import type { Result } from "@khanacademy/wonder-blocks-data";
15
15
  export type FocusPath = $ReadOnlyArray<string> | null | void;
16
- declare type State = any;
17
- export interface RendererInterface {
18
- getSerializedState(): State;
19
- restoreSerializedState(state: State, callback?: () => void): void;
20
- scoreInput(): KEScore;
21
- blur(): void;
22
- focus(): boolean | null | void;
23
- props: any;
24
- }
25
16
  export type Dimensions = {|
26
17
  width?: number,
27
18
  height?: number,
@@ -46,14 +37,6 @@ export type PerseusScore =
46
37
  total: number,
47
38
  message?: string | null | void,
48
39
  |};
49
- export type KEScore = {|
50
- empty: boolean,
51
- correct: boolean,
52
- message?: string | null | void,
53
- suppressAlmostThere?: boolean | null | void,
54
- guess: any,
55
- state: any,
56
- |};
57
40
  export type Hint = {|
58
41
  widgets: WidgetDict,
59
42
  content: string,
@@ -141,6 +124,7 @@ export type APIOptions = $ReadOnly<{|
141
124
  ...{ [key: string]: mixed },
142
125
  |}) => void,
143
126
  customKeypad?: boolean,
127
+ useV2Keypad?: boolean,
144
128
  nativeKeypadProxy?: () => mixed,
145
129
  isMobile?: boolean,
146
130
  setDrawingAreaAvailable?: (arg1: boolean) => mixed,
@@ -239,6 +223,7 @@ export type APIOptionsWithDefaults = $ReadOnly<{|
239
223
  inModal: $NonMaybeType<$PropertyType<APIOptions, "inModal">>,
240
224
  isArticle: $NonMaybeType<$PropertyType<APIOptions, "isArticle">>,
241
225
  isMobile: $NonMaybeType<$PropertyType<APIOptions, "isMobile">>,
226
+ useV2Keypad: $NonMaybeType<$PropertyType<APIOptions, "useV2Keypad">>,
242
227
  onFocusChange: $NonMaybeType<$PropertyType<APIOptions, "onFocusChange">>,
243
228
  onInputError: $NonMaybeType<$PropertyType<APIOptions, "onInputError">>,
244
229
  readOnly: $NonMaybeType<$PropertyType<APIOptions, "readOnly">>,
package/dist/util.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Range } from "./perseus-types";
2
- import type { Widget, PerseusScore, KEScore } from "./types";
2
+ import type { Widget, PerseusScore } from "./types";
3
+ import type { KEScore } from "@khanacademy/perseus-core";
3
4
  type WordPosition = {
4
5
  start: number;
5
6
  end: number;
@@ -170,7 +171,8 @@ declare function extractPointerLocation(event: any): Position | null | undefined
170
171
  * avoid sending the touch to the mobile scratchpad
171
172
  */
172
173
  declare function captureScratchpadTouchStart(e: TouchEvent): void;
173
- declare function getImageSize(url: string, callback: (arg1: number, arg2: number) => void): void;
174
+ declare function getImageSizeModern(url: string): Promise<[number, number]>;
175
+ declare function getImageSize(url: string, callback: (width: number, height: number) => void): void;
174
176
  declare function getRealImageUrl(url: string): string;
175
177
  declare function isLabeledSVG(url: string): boolean;
176
178
  declare function getBaseUrl(url: string): string;
@@ -232,6 +234,7 @@ declare const Util: {
232
234
  readonly supportsPassiveEvents: () => boolean;
233
235
  readonly captureScratchpadTouchStart: typeof captureScratchpadTouchStart;
234
236
  readonly getImageSize: typeof getImageSize;
237
+ readonly getImageSizeModern: typeof getImageSizeModern;
235
238
  readonly getRealImageUrl: typeof getRealImageUrl;
236
239
  readonly isLabeledSVG: typeof isLabeledSVG;
237
240
  readonly getBaseUrl: typeof getBaseUrl;
package/dist/util.js.flow CHANGED
@@ -5,7 +5,8 @@
5
5
  * @flow
6
6
  */
7
7
  import type { Range } from "./perseus-types";
8
- import type { Widget, PerseusScore, KEScore } from "./types";
8
+ import type { Widget, PerseusScore } from "./types";
9
+ import type { KEScore } from "@khanacademy/perseus-core";
9
10
  declare type WordPosition = {|
10
11
  start: number,
11
12
  end: number,
@@ -235,9 +236,10 @@ declare function extractPointerLocation(event: any): Position | null | void;
235
236
  * avoid sending the touch to the mobile scratchpad
236
237
  */
237
238
  declare function captureScratchpadTouchStart(e: TouchEvent): void;
239
+ declare function getImageSizeModern(url: string): Promise<[number, number]>;
238
240
  declare function getImageSize(
239
241
  url: string,
240
- callback: (arg1: number, arg2: number) => void
242
+ callback: (width: number, height: number) => void
241
243
  ): void;
242
244
  declare function getRealImageUrl(url: string): string;
243
245
  declare function isLabeledSVG(url: string): boolean;
@@ -306,6 +308,7 @@ declare var Util: {|
306
308
  +supportsPassiveEvents: () => boolean,
307
309
  +captureScratchpadTouchStart: typeof captureScratchpadTouchStart,
308
310
  +getImageSize: typeof getImageSize,
311
+ +getImageSizeModern: typeof getImageSizeModern,
309
312
  +getRealImageUrl: typeof getRealImageUrl,
310
313
  +isLabeledSVG: typeof isLabeledSVG,
311
314
  +getBaseUrl: typeof getBaseUrl,
@@ -29,6 +29,7 @@ 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>;
32
33
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
33
34
  useDraftEditor: PropTypes.Requireable<boolean>;
34
35
  hintProgressColor: PropTypes.Requireable<string>;
@@ -40,6 +40,7 @@ declare class Matcher extends React.Component<any, any> {
40
40
  customKeypad: PropTypes.Requireable<boolean>,
41
41
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>,
42
42
  isMobile: PropTypes.Requireable<boolean>,
43
+ useV2Keypad: PropTypes.Requireable<boolean>,
43
44
  setDrawingAreaAvailable: PropTypes.Requireable<
44
45
  (...args: any[]) => any
45
46
  >,
@@ -24,6 +24,7 @@ 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>;
27
28
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
28
29
  useDraftEditor: PropTypes.Requireable<boolean>;
29
30
  hintProgressColor: PropTypes.Requireable<string>;
@@ -35,6 +35,7 @@ declare class Simulator extends React.Component<any, any> {
35
35
  customKeypad: PropTypes.Requireable<boolean>,
36
36
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>,
37
37
  isMobile: PropTypes.Requireable<boolean>,
38
+ useV2Keypad: PropTypes.Requireable<boolean>,
38
39
  setDrawingAreaAvailable: PropTypes.Requireable<
39
40
  (...args: any[]) => any
40
41
  >,
@@ -25,6 +25,7 @@ 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>;
28
29
  setDrawingAreaAvailable: PropTypes.Requireable<(...args: any[]) => any>;
29
30
  useDraftEditor: PropTypes.Requireable<boolean>;
30
31
  hintProgressColor: PropTypes.Requireable<string>;
@@ -36,6 +36,7 @@ declare class Sorter extends React.Component<any, any> {
36
36
  customKeypad: PropTypes.Requireable<boolean>,
37
37
  nativeKeypadProxy: PropTypes.Requireable<(...args: any[]) => any>,
38
38
  isMobile: PropTypes.Requireable<boolean>,
39
+ useV2Keypad: PropTypes.Requireable<boolean>,
39
40
  setDrawingAreaAvailable: PropTypes.Requireable<
40
41
  (...args: any[]) => any
41
42
  >,
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": "6.7.0",
6
+ "version": "7.0.1",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -23,8 +23,8 @@
23
23
  "dependencies": {
24
24
  "@khanacademy/kas": "^0.3.1",
25
25
  "@khanacademy/kmath": "^0.1.1",
26
- "@khanacademy/math-input": "^7.0.0",
27
- "@khanacademy/perseus-core": "0.0.2",
26
+ "@khanacademy/math-input": "^8.1.0",
27
+ "@khanacademy/perseus-core": "0.1.0",
28
28
  "@khanacademy/perseus-linter": "^0.3.1",
29
29
  "@khanacademy/pure-markdown": "^0.2.3",
30
30
  "@khanacademy/simple-markdown": "^0.9.3"
package/src/index.ts CHANGED
@@ -60,7 +60,6 @@ export * as Dependencies from "./dependencies";
60
60
  export {Errors, Log} from "./logging/log";
61
61
  export {PerseusError} from "./perseus-error";
62
62
  export {default as JiptParagraphs} from "./jipt-paragraphs";
63
- export {default as KeypadContext} from "./keypad-context";
64
63
  export {default as KhanMath} from "./util/math";
65
64
  export {default as LoadingContext} from "./loading-context";
66
65
  export {default as mediaQueries} from "./styles/media-queries";
@@ -109,11 +108,9 @@ export type {
109
108
  ImageUploader,
110
109
  JiptLabelStore,
111
110
  JiptRenderer,
112
- KEScore,
113
111
  LinterContextProps,
114
112
  PerseusDependencies,
115
113
  PerseusScore,
116
- RendererInterface,
117
114
  Version,
118
115
  VideoData,
119
116
  VideoKind,
@@ -15,7 +15,8 @@ import reactRender from "./util/react-render";
15
15
 
16
16
  import type {KeypadProps} from "./mixins/provide-keypad";
17
17
  import type {PerseusItem} from "./perseus-types";
18
- import type {APIOptions, FocusPath, KEScore, LinterContextProps} from "./types";
18
+ import type {APIOptions, FocusPath, LinterContextProps} from "./types";
19
+ import type {KEScore} from "@khanacademy/perseus-core";
19
20
 
20
21
  const {mapObject} = Objective;
21
22
 
@@ -10,13 +10,14 @@
10
10
  * extend a `ProvideKeypad` component instead of using this mixin.
11
11
  */
12
12
 
13
- import {LegacyKeypad} from "@khanacademy/math-input";
13
+ import {MobileKeypad} from "@khanacademy/math-input";
14
14
  import PropTypes from "prop-types";
15
15
  import * as React from "react";
16
16
  import ReactDOM from "react-dom";
17
17
 
18
18
  import reactRender from "../util/react-render";
19
19
 
20
+ import type {APIOptions} from "../types";
20
21
  import type {CSSProperties} from "aphrodite";
21
22
 
22
23
  export type KeypadProps = {
@@ -73,13 +74,13 @@ const ProvideKeypad = {
73
74
 
74
75
  componentDidMount() {
75
76
  const _this = this;
77
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'props' does not exist on type '{ readonly propTypes: { readonly apiOptions: React.PropType<{ customKeypad?: boolean | undefined; nativeKeypadProxy?: ((...a: readonly any[]) => unknown) | undefined; }>; readonly keypadStyle: Requireable<any>; }; readonly getInitialState: () => { ...; }; readonly componentDidMount: () => void; readonly componentWil...'.
78
+ const apiOptions: APIOptions = _this.props.apiOptions;
79
+
76
80
  if (
77
- // @ts-expect-error [FEI-5003] - TS2339 - Property 'props' does not exist on type '{ readonly propTypes: { readonly apiOptions: React.PropType<{ customKeypad?: boolean | undefined; nativeKeypadProxy?: ((...a: readonly any[]) => unknown) | undefined; }>; readonly keypadStyle: Requireable<any>; }; readonly getInitialState: () => { ...; }; readonly componentDidMount: () => void; readonly componentWil...'.
78
- _this.props.apiOptions &&
79
- // @ts-expect-error [FEI-5003] - TS2339 - Property 'props' does not exist on type '{ readonly propTypes: { readonly apiOptions: React.PropType<{ customKeypad?: boolean | undefined; nativeKeypadProxy?: ((...a: readonly any[]) => unknown) | undefined; }>; readonly keypadStyle: Requireable<any>; }; readonly getInitialState: () => { ...; }; readonly componentDidMount: () => void; readonly componentWil...'.
80
- _this.props.apiOptions.customKeypad &&
81
- // @ts-expect-error [FEI-5003] - TS2339 - Property 'props' does not exist on type '{ readonly propTypes: { readonly apiOptions: React.PropType<{ customKeypad?: boolean | undefined; nativeKeypadProxy?: ((...a: readonly any[]) => unknown) | undefined; }>; readonly keypadStyle: Requireable<any>; }; readonly getInitialState: () => { ...; }; readonly componentDidMount: () => void; readonly componentWil...'.
82
- !_this.props.apiOptions.nativeKeypadProxy
81
+ apiOptions &&
82
+ apiOptions.customKeypad &&
83
+ !apiOptions.nativeKeypadProxy
83
84
  ) {
84
85
  // TODO(charlie): Render this and the wrapped component in the same
85
86
  // React tree. We may also want to add this keypad asynchronously
@@ -90,7 +91,7 @@ const ProvideKeypad = {
90
91
  document.body?.appendChild(_this._keypadContainer);
91
92
 
92
93
  reactRender(
93
- <LegacyKeypad
94
+ <MobileKeypad
94
95
  onElementMounted={(element) => {
95
96
  // NOTE(kevinb): The reason why this setState works is
96
97
  // b/c we're calling it manually from item-renderer.jsx
@@ -106,6 +107,7 @@ const ProvideKeypad = {
106
107
  }}
107
108
  // @ts-expect-error [FEI-5003] - TS2339 - Property 'props' does not exist on type '{ readonly propTypes: { readonly apiOptions: React.PropType<{ customKeypad?: boolean | undefined; nativeKeypadProxy?: ((...a: readonly any[]) => unknown) | undefined; }>; readonly keypadStyle: Requireable<any>; }; readonly getInitialState: () => { ...; }; readonly componentDidMount: () => void; readonly componentWil...'.
108
109
  style={_this.props.keypadStyle}
110
+ useV2Keypad={apiOptions.useV2Keypad}
109
111
  />,
110
112
  // @ts-expect-error [FEI-5003] - TS2339 - Property '_keypadContainer' does not exist on type '{ readonly propTypes: { readonly apiOptions: React.PropType<{ customKeypad?: boolean | undefined; nativeKeypadProxy?: ((...a: readonly any[]) => unknown) | undefined; }>; readonly keypadStyle: Requireable<any>; }; readonly getInitialState: () => { ...; }; readonly componentDidMount: () => void; readonly componentWil...'.
111
113
  _this._keypadContainer,
@@ -100,6 +100,11 @@ export const ApiOptions = {
100
100
  // Indicates whether or not to use mobile styling.
101
101
  isMobile: PropTypes.bool,
102
102
 
103
+ // Whether to use v1 (Legacy) Keypad for MathInput mobile or
104
+ // use the new v2 Keypad
105
+ // TODO [LC-1088]: remove after v2 release
106
+ useV2Keypad: PropTypes.bool,
107
+
103
108
  // A function, called with a bool indicating whether use of the
104
109
  // drawing area (scratchpad) should be allowed/disallowed.
105
110
  // Previously handled by `Khan.scratchpad.enable/disable`
@@ -145,6 +150,7 @@ export const ApiOptions = {
145
150
  defaults: {
146
151
  isArticle: false,
147
152
  isMobile: false,
153
+ useV2Keypad: false,
148
154
  onInputError: function () {},
149
155
  onFocusChange: function () {},
150
156
  GroupMetadataEditor: StubTagEditor,
@@ -19,7 +19,8 @@ import Renderer from "./renderer";
19
19
  import Util from "./util";
20
20
 
21
21
  import type {KeypadProps} from "./mixins/provide-keypad";
22
- import type {APIOptions, KEScore, FocusPath, RendererInterface} from "./types";
22
+ import type {APIOptions, FocusPath} from "./types";
23
+ import type {RendererInterface, KEScore} from "@khanacademy/perseus-core";
23
24
 
24
25
  const {mapObject} = Objective;
25
26
 
package/src/types.ts CHANGED
@@ -10,17 +10,6 @@ import type {Result} from "@khanacademy/wonder-blocks-data";
10
10
 
11
11
  export type FocusPath = ReadonlyArray<string> | null | undefined;
12
12
 
13
- type State = any;
14
-
15
- export interface RendererInterface {
16
- getSerializedState(): State;
17
- restoreSerializedState(state: State, callback?: () => void): void;
18
- scoreInput(): KEScore;
19
- blur(): void;
20
- focus(): boolean | null | undefined;
21
- props: any;
22
- }
23
-
24
13
  export type Dimensions = {
25
14
  width?: number;
26
15
  height?: number;
@@ -51,15 +40,6 @@ export type PerseusScore =
51
40
  message?: string | null | undefined;
52
41
  };
53
42
 
54
- export type KEScore = {
55
- empty: boolean;
56
- correct: boolean;
57
- message?: string | null | undefined;
58
- suppressAlmostThere?: boolean | null | undefined;
59
- guess: any;
60
- state: any;
61
- };
62
-
63
43
  export type Hint = {
64
44
  widgets: WidgetDict;
65
45
  content: string; // JSON string,
@@ -197,6 +177,10 @@ export type APIOptions = Readonly<{
197
177
  // from the math-input repo instead of the existing perseus math
198
178
  // input components.
199
179
  customKeypad?: boolean;
180
+ // Whether to use v1 (Legacy) Keypad for MathInput mobile or
181
+ // use the new v2 Keypad
182
+ // TODO [LC-1088]: remove after v2 release
183
+ useV2Keypad?: boolean;
200
184
  // If this is provided, it is called instead of appending an instance
201
185
  // of `math-input`'s keypad to the body. This is used by the native
202
186
  // apps so they can have the keypad be defined on the native side.
@@ -359,6 +343,7 @@ export type APIOptionsWithDefaults = Readonly<
359
343
  inModal: NonNullable<APIOptions["inModal"]>;
360
344
  isArticle: NonNullable<APIOptions["isArticle"]>;
361
345
  isMobile: NonNullable<APIOptions["isMobile"]>;
346
+ useV2Keypad: NonNullable<APIOptions["useV2Keypad"]>;
362
347
  onFocusChange: NonNullable<APIOptions["onFocusChange"]>;
363
348
  onInputError: NonNullable<APIOptions["onInputError"]>;
364
349
  readOnly: NonNullable<APIOptions["readOnly"]>;
package/src/util.ts CHANGED
@@ -6,7 +6,8 @@ import {PerseusError} from "./perseus-error";
6
6
  import KhanAnswerTypes from "./util/answer-types";
7
7
 
8
8
  import type {Range} from "./perseus-types";
9
- import type {Widget, PerseusScore, KEScore} from "./types";
9
+ import type {Widget, PerseusScore} from "./types";
10
+ import type {KEScore} from "@khanacademy/perseus-core";
10
11
 
11
12
  type WordPosition = {
12
13
  start: number;
@@ -838,9 +839,26 @@ function captureScratchpadTouchStart(e: TouchEvent) {
838
839
  e.stopPropagation();
839
840
  }
840
841
 
842
+ async function getImageSizeModern(url: string): Promise<[number, number]> {
843
+ const image = new Image();
844
+
845
+ return new Promise((resolve, reject) => {
846
+ // Handle the success case
847
+ image.onload = () => {
848
+ resolve([image.naturalWidth, image.naturalHeight]);
849
+ };
850
+
851
+ // Handle the error case
852
+ image.onerror = reject;
853
+
854
+ // Kick off the loading
855
+ image.src = url;
856
+ });
857
+ }
858
+
841
859
  function getImageSize(
842
860
  url: string,
843
- callback: (arg1: number, arg2: number) => void,
861
+ callback: (width: number, height: number) => void,
844
862
  ): void {
845
863
  const img = new Image();
846
864
  img.onload = function () {
@@ -989,6 +1007,7 @@ const Util = {
989
1007
  supportsPassiveEvents,
990
1008
  captureScratchpadTouchStart,
991
1009
  getImageSize,
1010
+ getImageSizeModern,
992
1011
  getRealImageUrl,
993
1012
  isLabeledSVG,
994
1013
  getBaseUrl,
@@ -1,7 +1,7 @@
1
+ import {KeypadContext} from "@khanacademy/math-input";
1
2
  import * as React from "react";
2
3
 
3
4
  import {ItemRendererWithDebugUI} from "../../../../../testing/item-renderer-with-debug-ui";
4
- import KeypadContext from "../../keypad-context";
5
5
  import {
6
6
  expressionItem2,
7
7
  expressionItem3,
@@ -1,16 +1,14 @@
1
- import {LegacyKeypad} from "@khanacademy/math-input";
1
+ import {KeypadContext, MobileKeypad} from "@khanacademy/math-input";
2
2
  import {View} from "@khanacademy/wonder-blocks-core";
3
3
  import {StyleSheet} from "aphrodite";
4
4
  import * as React from "react";
5
5
 
6
- import KeypadContext from "../../keypad-context";
7
-
8
6
  const Footer = (): React.ReactElement => {
9
7
  return (
10
8
  <View style={styles.keypadContainer}>
11
9
  <KeypadContext.Consumer>
12
- {({keypadElement, setKeypadElement, renderer}) => (
13
- <LegacyKeypad
10
+ {({setKeypadElement, renderer}) => (
11
+ <MobileKeypad
14
12
  onElementMounted={setKeypadElement}
15
13
  onDismiss={() => renderer && renderer.blur()}
16
14
  style={styles.keypad}