@khanacademy/math-input 13.1.0 → 14.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.
- package/CHANGELOG.md +7 -0
- package/dist/components/keypad/mobile-keypad.d.ts +2 -1
- package/dist/components/keypad-context.d.ts +10 -16
- package/dist/components/keypad-legacy/provided-keypad.d.ts +3 -0
- package/dist/es/index.js +73 -45
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +74 -44
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/package.json +1 -1
- package/src/components/__tests__/integration.test.tsx +4 -18
- package/src/components/keypad/mobile-keypad.tsx +10 -12
- package/src/components/keypad-context.tsx +61 -0
- package/src/components/keypad-legacy/provided-keypad.tsx +14 -2
- package/src/components/keypad-switch.tsx +14 -1
- package/src/full-mobile-input.stories.tsx +23 -20
- package/src/index.ts +4 -1
- package/src/types.ts +16 -0
- package/tsconfig-build.tsbuildinfo +1 -1
- package/src/components/keypad-context.ts +0 -37
package/CHANGELOG.md
CHANGED
|
@@ -19,9 +19,10 @@ type Props = {
|
|
|
19
19
|
onDismiss?: () => void;
|
|
20
20
|
style?: StyleType;
|
|
21
21
|
onAnalyticsEvent: AnalyticsEventHandlerFn;
|
|
22
|
+
setKeypadActive: (keypadActive: boolean) => void;
|
|
23
|
+
keypadActive: boolean;
|
|
22
24
|
};
|
|
23
25
|
type State = {
|
|
24
|
-
active: boolean;
|
|
25
26
|
containerWidth: number;
|
|
26
27
|
hasBeenActivated: boolean;
|
|
27
28
|
keypadConfig?: KeypadConfiguration;
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* KeypadContext provides a way to the Keypad and
|
|
2
|
+
* KeypadContext provides a way to the Keypad and Perseus Renderers to
|
|
3
3
|
* communicate.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The StatefulKeypadContextProvider wraps the application
|
|
6
|
+
* while KeypadContext.Consumer wraps things that need this state:
|
|
7
|
+
* - mobile keypad usages
|
|
8
|
+
* - Perseus Renderers (Server/Item/Article)
|
|
8
9
|
*/
|
|
9
10
|
import * as React from "react";
|
|
10
|
-
import type {
|
|
11
|
-
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
setRenderer: (renderer?: KeypadContextRendererInterface | null | undefined) => void;
|
|
16
|
-
renderer: KeypadContextRendererInterface | null | undefined;
|
|
17
|
-
setScrollableElement: (scrollableElement?: HTMLElement | null | undefined) => void;
|
|
18
|
-
scrollableElement: HTMLElement | null | undefined;
|
|
19
|
-
};
|
|
20
|
-
declare const context: React.Context<KeypadContext>;
|
|
21
|
-
export default context;
|
|
11
|
+
import type { KeypadContextType } from "../types";
|
|
12
|
+
export declare const KeypadContext: React.Context<KeypadContextType>;
|
|
13
|
+
type Props = React.PropsWithChildren<unknown>;
|
|
14
|
+
export declare function StatefulKeypadContextProvider(props: Props): JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -4,6 +4,8 @@ import type { Cursor, KeypadConfiguration, KeyHandler, KeypadAPI } from "../../t
|
|
|
4
4
|
import type { AnalyticsEventHandlerFn } from "@khanacademy/perseus-core";
|
|
5
5
|
import type { StyleType } from "@khanacademy/wonder-blocks-core";
|
|
6
6
|
type Props = {
|
|
7
|
+
setKeypadActive: (keypadActive: boolean) => void;
|
|
8
|
+
keypadActive: boolean;
|
|
7
9
|
onElementMounted?: (arg1: any) => void;
|
|
8
10
|
onDismiss?: () => void;
|
|
9
11
|
style?: StyleType;
|
|
@@ -12,6 +14,7 @@ type Props = {
|
|
|
12
14
|
declare class ProvidedKeypad extends React.Component<Props> implements KeypadAPI {
|
|
13
15
|
store: any;
|
|
14
16
|
constructor(props: any);
|
|
17
|
+
componentDidUpdate(prevProps: any): void;
|
|
15
18
|
activate: () => void;
|
|
16
19
|
dismiss: () => void;
|
|
17
20
|
configure: (configuration: KeypadConfiguration, cb: () => void) => void;
|
package/dist/es/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { getDecimalSeparator } from '@khanacademy/wonder-blocks-i18n';
|
|
|
4
4
|
import { entries } from '@khanacademy/wonder-stuff-core';
|
|
5
5
|
import { StyleSheet, css } from 'aphrodite';
|
|
6
6
|
import * as React from 'react';
|
|
7
|
-
import { useEffect } from 'react';
|
|
7
|
+
import { useEffect, useState } from 'react';
|
|
8
8
|
import ReactDOM from 'react-dom';
|
|
9
9
|
import $ from 'jquery';
|
|
10
10
|
import MathQuill from 'mathquill';
|
|
@@ -5085,17 +5085,6 @@ const styles$d = StyleSheet.create({
|
|
|
5085
5085
|
}
|
|
5086
5086
|
});
|
|
5087
5087
|
|
|
5088
|
-
/**
|
|
5089
|
-
* This is the v2 equivalent of v1's ProvidedKeypad. It follows the same
|
|
5090
|
-
* external API so that it can be hot-swapped with the v1 keypad and
|
|
5091
|
-
* is responsible for connecting the keypad with MathInput and the Renderer.
|
|
5092
|
-
*
|
|
5093
|
-
* Ideally this strategy of attaching methods on the class component for
|
|
5094
|
-
* other components to call will be replaced props/callbacks since React
|
|
5095
|
-
* doesn't support this type of code anymore (functional components
|
|
5096
|
-
* can't have methods attached to them).
|
|
5097
|
-
*/
|
|
5098
|
-
|
|
5099
5088
|
class MobileKeypad extends React.Component {
|
|
5100
5089
|
constructor(...args) {
|
|
5101
5090
|
super(...args);
|
|
@@ -5104,7 +5093,6 @@ class MobileKeypad extends React.Component {
|
|
|
5104
5093
|
this._throttleResize = false;
|
|
5105
5094
|
this.hasMounted = false;
|
|
5106
5095
|
this.state = {
|
|
5107
|
-
active: false,
|
|
5108
5096
|
containerWidth: 0,
|
|
5109
5097
|
hasBeenActivated: false
|
|
5110
5098
|
};
|
|
@@ -5126,18 +5114,15 @@ class MobileKeypad extends React.Component {
|
|
|
5126
5114
|
}, 100);
|
|
5127
5115
|
};
|
|
5128
5116
|
this.activate = () => {
|
|
5117
|
+
this.props.setKeypadActive(true);
|
|
5129
5118
|
this.setState({
|
|
5130
|
-
active: true,
|
|
5131
5119
|
hasBeenActivated: true
|
|
5132
5120
|
});
|
|
5133
5121
|
};
|
|
5134
5122
|
this.dismiss = () => {
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
var _this$props$onDismiss, _this$props;
|
|
5139
|
-
(_this$props$onDismiss = (_this$props = this.props).onDismiss) == null ? void 0 : _this$props$onDismiss.call(_this$props);
|
|
5140
|
-
});
|
|
5123
|
+
var _this$props$onDismiss, _this$props;
|
|
5124
|
+
this.props.setKeypadActive(false);
|
|
5125
|
+
(_this$props$onDismiss = (_this$props = this.props).onDismiss) == null ? void 0 : _this$props$onDismiss.call(_this$props);
|
|
5141
5126
|
};
|
|
5142
5127
|
this.configure = (configuration, cb) => {
|
|
5143
5128
|
this.setState({
|
|
@@ -5202,10 +5187,10 @@ class MobileKeypad extends React.Component {
|
|
|
5202
5187
|
}
|
|
5203
5188
|
render() {
|
|
5204
5189
|
const {
|
|
5190
|
+
keypadActive,
|
|
5205
5191
|
style
|
|
5206
5192
|
} = this.props;
|
|
5207
5193
|
const {
|
|
5208
|
-
active,
|
|
5209
5194
|
hasBeenActivated,
|
|
5210
5195
|
containerWidth,
|
|
5211
5196
|
cursor,
|
|
@@ -5213,7 +5198,7 @@ class MobileKeypad extends React.Component {
|
|
|
5213
5198
|
} = this.state;
|
|
5214
5199
|
const containerStyle = [
|
|
5215
5200
|
// internal styles
|
|
5216
|
-
styles$c.keypadContainer,
|
|
5201
|
+
styles$c.keypadContainer, keypadActive && styles$c.activeKeypadContainer,
|
|
5217
5202
|
// styles passed as props
|
|
5218
5203
|
...(Array.isArray(style) ? style : [style])];
|
|
5219
5204
|
|
|
@@ -5222,7 +5207,7 @@ class MobileKeypad extends React.Component {
|
|
|
5222
5207
|
// during the initial render.
|
|
5223
5208
|
// Done inline (dynamicStyle) since stylesheets might not be loaded yet.
|
|
5224
5209
|
let dynamicStyle = {};
|
|
5225
|
-
if (!
|
|
5210
|
+
if (!keypadActive && !hasBeenActivated) {
|
|
5226
5211
|
dynamicStyle = {
|
|
5227
5212
|
visibility: "hidden"
|
|
5228
5213
|
};
|
|
@@ -5287,6 +5272,51 @@ const styles$c = StyleSheet.create({
|
|
|
5287
5272
|
}
|
|
5288
5273
|
});
|
|
5289
5274
|
|
|
5275
|
+
/**
|
|
5276
|
+
* KeypadContext provides a way to the Keypad and Perseus Renderers to
|
|
5277
|
+
* communicate.
|
|
5278
|
+
*
|
|
5279
|
+
* The StatefulKeypadContextProvider wraps the application
|
|
5280
|
+
* while KeypadContext.Consumer wraps things that need this state:
|
|
5281
|
+
* - mobile keypad usages
|
|
5282
|
+
* - Perseus Renderers (Server/Item/Article)
|
|
5283
|
+
*/
|
|
5284
|
+
// @ts-expect-error - TS2322 - Type 'Context<{ setKeypadElement: (keypadElement: HTMLElement | null | undefined) => void; keypadElement: null; setRenderer: (renderer: RendererInterface | null | undefined) => void; renderer: null; setScrollableElement: (scrollableElement: HTMLElement | ... 1 more ... | undefined) => void; scrollableElement: null; }>' is not assignable to type 'Context<KeypadContext>'.
|
|
5285
|
+
const KeypadContext = /*#__PURE__*/React.createContext({
|
|
5286
|
+
setKeypadActive: keypadActive => {},
|
|
5287
|
+
keypadActive: false,
|
|
5288
|
+
setKeypadElement: keypadElement => {},
|
|
5289
|
+
keypadElement: null,
|
|
5290
|
+
setRenderer: renderer => {},
|
|
5291
|
+
renderer: null,
|
|
5292
|
+
setScrollableElement: scrollableElement => {},
|
|
5293
|
+
scrollableElement: null
|
|
5294
|
+
});
|
|
5295
|
+
function StatefulKeypadContextProvider(props) {
|
|
5296
|
+
// whether or not to display the keypad
|
|
5297
|
+
const [keypadActive, setKeypadActive] = useState(false);
|
|
5298
|
+
// used to communicate between the keypad and the Renderer
|
|
5299
|
+
const [keypadElement, setKeypadElement] = useState();
|
|
5300
|
+
// this is a KeypadContextRendererInterface from Perseus
|
|
5301
|
+
const [renderer, setRenderer] = useState();
|
|
5302
|
+
const [scrollableElement, setScrollableElement] = useState();
|
|
5303
|
+
return /*#__PURE__*/React.createElement(KeypadContext.Provider, {
|
|
5304
|
+
value: {
|
|
5305
|
+
setKeypadActive,
|
|
5306
|
+
keypadActive,
|
|
5307
|
+
setKeypadElement,
|
|
5308
|
+
keypadElement,
|
|
5309
|
+
setRenderer,
|
|
5310
|
+
renderer,
|
|
5311
|
+
// The scrollableElement options can likely be removed after
|
|
5312
|
+
// the exercises-package is officially deprecated. They don't appear
|
|
5313
|
+
// to be used anywhere except for the exercises-package and tests.
|
|
5314
|
+
setScrollableElement,
|
|
5315
|
+
scrollableElement
|
|
5316
|
+
}
|
|
5317
|
+
}, props.children);
|
|
5318
|
+
}
|
|
5319
|
+
|
|
5290
5320
|
/**
|
|
5291
5321
|
* A small triangular decal to sit in the corner of a parent component.
|
|
5292
5322
|
*/
|
|
@@ -9685,10 +9715,10 @@ class ProvidedKeypad extends React.Component {
|
|
|
9685
9715
|
super(props);
|
|
9686
9716
|
this.store = void 0;
|
|
9687
9717
|
this.activate = () => {
|
|
9688
|
-
this.
|
|
9718
|
+
this.props.setKeypadActive(true);
|
|
9689
9719
|
};
|
|
9690
9720
|
this.dismiss = () => {
|
|
9691
|
-
this.
|
|
9721
|
+
this.props.setKeypadActive(false);
|
|
9692
9722
|
};
|
|
9693
9723
|
this.configure = (configuration, cb) => {
|
|
9694
9724
|
this.store.dispatch(configureKeypad(configuration));
|
|
@@ -9713,6 +9743,14 @@ class ProvidedKeypad extends React.Component {
|
|
|
9713
9743
|
};
|
|
9714
9744
|
this.store = createStore();
|
|
9715
9745
|
}
|
|
9746
|
+
componentDidUpdate(prevProps) {
|
|
9747
|
+
if (this.props.keypadActive && !prevProps.keypadActive) {
|
|
9748
|
+
this.store.dispatch(activateKeypad());
|
|
9749
|
+
}
|
|
9750
|
+
if (!this.props.keypadActive && prevProps.keypadActive) {
|
|
9751
|
+
this.store.dispatch(dismissKeypad());
|
|
9752
|
+
}
|
|
9753
|
+
}
|
|
9716
9754
|
render() {
|
|
9717
9755
|
const {
|
|
9718
9756
|
onElementMounted,
|
|
@@ -9767,27 +9805,17 @@ function KeypadSwitch(props) {
|
|
|
9767
9805
|
// Note: Although we pass the "onAnalyticsEvent" to both keypad components,
|
|
9768
9806
|
// only the current one uses it. There's no point in instrumenting the
|
|
9769
9807
|
// legacy keypad given that it's on its way out the door.
|
|
9770
|
-
return /*#__PURE__*/React.createElement(
|
|
9808
|
+
return /*#__PURE__*/React.createElement(KeypadContext.Consumer, null, ({
|
|
9809
|
+
setKeypadActive,
|
|
9810
|
+
keypadActive
|
|
9811
|
+
}) => {
|
|
9812
|
+
return /*#__PURE__*/React.createElement(KeypadComponent, _extends({}, rest, {
|
|
9813
|
+
keypadActive: keypadActive,
|
|
9814
|
+
setKeypadActive: setKeypadActive
|
|
9815
|
+
}));
|
|
9816
|
+
});
|
|
9771
9817
|
}
|
|
9772
9818
|
|
|
9773
|
-
/**
|
|
9774
|
-
* KeypadContext provides a way to the Keypad and (Server)ItemRenderer to
|
|
9775
|
-
* communicate.
|
|
9776
|
-
*
|
|
9777
|
-
* The KeypadContext.Provider wraps the ExerciseFooter while KeypadContext.Consumer
|
|
9778
|
-
* wraps each (Server)ItemRenderer render site and the Keypad rendered in the
|
|
9779
|
-
* ExerciseFooter.
|
|
9780
|
-
*/
|
|
9781
|
-
// @ts-expect-error - TS2322 - Type 'Context<{ setKeypadElement: (keypadElement: HTMLElement | null | undefined) => void; keypadElement: null; setRenderer: (renderer: RendererInterface | null | undefined) => void; renderer: null; setScrollableElement: (scrollableElement: HTMLElement | ... 1 more ... | undefined) => void; scrollableElement: null; }>' is not assignable to type 'Context<KeypadContext>'.
|
|
9782
|
-
const context = /*#__PURE__*/React.createContext({
|
|
9783
|
-
setKeypadElement: keypadElement => {},
|
|
9784
|
-
keypadElement: null,
|
|
9785
|
-
setRenderer: renderer => {},
|
|
9786
|
-
renderer: null,
|
|
9787
|
-
setScrollableElement: scrollableElement => {},
|
|
9788
|
-
scrollableElement: null
|
|
9789
|
-
});
|
|
9790
|
-
|
|
9791
9819
|
/**
|
|
9792
9820
|
* React PropTypes that may be shared between components.
|
|
9793
9821
|
*/
|
|
@@ -9803,5 +9831,5 @@ const keypadElementPropType = PropTypes.shape({
|
|
|
9803
9831
|
getDOMNode: PropTypes.func.isRequired
|
|
9804
9832
|
});
|
|
9805
9833
|
|
|
9806
|
-
export { CursorContext, Keypad$2 as DesktopKeypad, KeyConfigs,
|
|
9834
|
+
export { CursorContext, Keypad$2 as DesktopKeypad, KeyConfigs, KeypadContext, MathInput as KeypadInput, KeypadType, KeypadSwitch as MobileKeypad, StatefulKeypadContextProvider, createMathField, getCursorContext, keyToMathquillMap as keyTranslator, keypadElementPropType, mathQuillInstance };
|
|
9807
9835
|
//# sourceMappingURL=index.js.map
|