@khanacademy/math-input 10.1.1 → 12.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.
- package/CHANGELOG.md +33 -0
- package/dist/components/input/math-input.d.ts +1 -1
- package/dist/components/input/mathquill-types.d.ts +2 -2
- package/dist/components/keypad/mobile-keypad.d.ts +2 -0
- package/dist/components/keypad-context.d.ts +6 -5
- package/dist/components/keypad-legacy/provided-keypad.d.ts +2 -0
- package/dist/components/keypad-switch.d.ts +2 -0
- package/dist/es/index.js +72 -33
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +72 -33
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/src/components/input/math-input.tsx +15 -8
- package/src/components/input/mathquill-types.ts +2 -2
- package/src/components/keypad/mobile-keypad.tsx +24 -13
- package/src/components/keypad-context.ts +8 -5
- package/src/components/keypad-legacy/keypad-container.tsx +11 -5
- package/src/components/keypad-legacy/provided-keypad.tsx +21 -3
- package/src/components/keypad-switch.tsx +5 -0
- package/src/full-math-input.stories.tsx +9 -1
- package/tsconfig-build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @khanacademy/math-input
|
|
2
2
|
|
|
3
|
+
## 12.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a383823d: Bump @khanacademy/wonder-stuff-core to v1.5.1 (which adds needed support for `isTruthy` helper function)
|
|
8
|
+
|
|
9
|
+
## 12.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- fa5f463b: Added onAnalyticsEvent prop to the LegacyKeypad (aka ProvidedKeypad). You must now pass in this prop, which is a function, to handle analytics events originating from the legacy keypad.
|
|
14
|
+
- 6d8ede65: Added `onAnalyticsEvent` prop to MobileKeypad to pipe out Perseus analytics
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- fa1bb6b4: Implemented some focus management fixes and improved the full-math-input story.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 3afc0da2: Check for ResizeObserver before using it
|
|
23
|
+
|
|
24
|
+
## 11.0.0
|
|
25
|
+
|
|
26
|
+
### Major Changes
|
|
27
|
+
|
|
28
|
+
- 2af4f9fa: Switch from using ProvideKeypad in ArticleRenderer to passing the keypad element down instead
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [2af4f9fa]
|
|
33
|
+
- @khanacademy/perseus-core@1.0.0
|
|
34
|
+
|
|
3
35
|
## 10.1.1
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
|
@@ -7,6 +39,7 @@
|
|
|
7
39
|
- 3f7be05a: Updated Keypad V2 TabbarItemType to KeypadPageType as a more accurate description.
|
|
8
40
|
- 810c7bd9: Resize letter SVGs
|
|
9
41
|
- b161d004: Ensured that the keypad is hidden from screen readers when it is closed.
|
|
42
|
+
- a99a9ca4: Fix direction types for MathQuill interface
|
|
10
43
|
|
|
11
44
|
## 10.1.0
|
|
12
45
|
|
|
@@ -50,7 +50,7 @@ declare class MathInput extends React.Component<Props, State> {
|
|
|
50
50
|
_updateCursorHandle: (arg1?: boolean) => void;
|
|
51
51
|
_hideCursorHandle: () => void;
|
|
52
52
|
_handleScroll: () => void;
|
|
53
|
-
blur: () => void;
|
|
53
|
+
blur: (callPropsOnBlur: boolean) => void;
|
|
54
54
|
focus: () => void;
|
|
55
55
|
/**
|
|
56
56
|
* Tries to determine which DOM node to place the cursor next to based on
|
|
@@ -2,6 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import ReactDOM from "react-dom";
|
|
3
3
|
import type Key from "../../data/keys";
|
|
4
4
|
import type { Cursor, KeypadConfiguration, KeyHandler, KeypadAPI } from "../../types";
|
|
5
|
+
import type { AnalyticsEventHandlerFn } from "@khanacademy/perseus-core";
|
|
5
6
|
import type { StyleType } from "@khanacademy/wonder-blocks-core";
|
|
6
7
|
/**
|
|
7
8
|
* This is the v2 equivalent of v1's ProvidedKeypad. It follows the same
|
|
@@ -17,6 +18,7 @@ type Props = {
|
|
|
17
18
|
onElementMounted?: (arg1: any) => void;
|
|
18
19
|
onDismiss?: () => void;
|
|
19
20
|
style?: StyleType;
|
|
21
|
+
onAnalyticsEvent: AnalyticsEventHandlerFn;
|
|
20
22
|
};
|
|
21
23
|
type State = {
|
|
22
24
|
active: boolean;
|
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
* ExerciseFooter.
|
|
8
8
|
*/
|
|
9
9
|
import * as React from "react";
|
|
10
|
-
import type {
|
|
10
|
+
import type { KeypadAPI } from "../types";
|
|
11
|
+
import type { KeypadContextRendererInterface } from "@khanacademy/perseus-core";
|
|
11
12
|
type KeypadContext = {
|
|
12
|
-
setKeypadElement: (keypadElement?:
|
|
13
|
-
keypadElement:
|
|
14
|
-
setRenderer: (renderer?:
|
|
15
|
-
renderer:
|
|
13
|
+
setKeypadElement: (keypadElement?: KeypadAPI) => void;
|
|
14
|
+
keypadElement: KeypadAPI | null | undefined;
|
|
15
|
+
setRenderer: (renderer?: KeypadContextRendererInterface | null | undefined) => void;
|
|
16
|
+
renderer: KeypadContextRendererInterface | null | undefined;
|
|
16
17
|
setScrollableElement: (scrollableElement?: HTMLElement | null | undefined) => void;
|
|
17
18
|
scrollableElement: HTMLElement | null | undefined;
|
|
18
19
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import ReactDOM from "react-dom";
|
|
3
3
|
import type { Cursor, KeypadConfiguration, KeyHandler, KeypadAPI } from "../../types";
|
|
4
|
+
import type { AnalyticsEventHandlerFn } from "@khanacademy/perseus-core";
|
|
4
5
|
import type { StyleType } from "@khanacademy/wonder-blocks-core";
|
|
5
6
|
type Props = {
|
|
6
7
|
onElementMounted?: (arg1: any) => void;
|
|
7
8
|
onDismiss?: () => void;
|
|
8
9
|
style?: StyleType;
|
|
10
|
+
onAnalyticsEvent: AnalyticsEventHandlerFn;
|
|
9
11
|
};
|
|
10
12
|
declare class ProvidedKeypad extends React.Component<Props> implements KeypadAPI {
|
|
11
13
|
store: any;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import type { AnalyticsEventHandlerFn } from "@khanacademy/perseus-core";
|
|
2
3
|
import type { StyleType } from "@khanacademy/wonder-blocks-core";
|
|
3
4
|
type Props = {
|
|
4
5
|
onElementMounted?: (arg1: any) => void;
|
|
5
6
|
onDismiss?: () => void;
|
|
6
7
|
style?: StyleType;
|
|
7
8
|
useV2Keypad?: boolean;
|
|
9
|
+
onAnalyticsEvent: AnalyticsEventHandlerFn;
|
|
8
10
|
};
|
|
9
11
|
declare function KeypadSwitch(props: Props): JSX.Element;
|
|
10
12
|
export default KeypadSwitch;
|
package/dist/es/index.js
CHANGED
|
@@ -1553,9 +1553,11 @@ class MathInput extends React.Component {
|
|
|
1553
1553
|
this._hideCursorHandle();
|
|
1554
1554
|
}
|
|
1555
1555
|
};
|
|
1556
|
-
this.blur =
|
|
1556
|
+
this.blur = callPropsOnBlur => {
|
|
1557
1557
|
this.mathField.blur();
|
|
1558
|
-
|
|
1558
|
+
if (callPropsOnBlur) {
|
|
1559
|
+
this.props.onBlur && this.props.onBlur();
|
|
1560
|
+
}
|
|
1559
1561
|
this.setState({
|
|
1560
1562
|
focused: false,
|
|
1561
1563
|
handle: {
|
|
@@ -1564,7 +1566,7 @@ class MathInput extends React.Component {
|
|
|
1564
1566
|
});
|
|
1565
1567
|
};
|
|
1566
1568
|
this.focus = () => {
|
|
1567
|
-
var _this$props$keypadEle2;
|
|
1569
|
+
var _this$props$keypadEle2, _this$props;
|
|
1568
1570
|
// Pass this component's handleKey method to the keypad so it can call
|
|
1569
1571
|
// it whenever it needs to trigger a keypress action.
|
|
1570
1572
|
(_this$props$keypadEle2 = this.props.keypadElement) == null ? void 0 : _this$props$keypadEle2.setKeyHandler(key => {
|
|
@@ -1590,7 +1592,7 @@ class MathInput extends React.Component {
|
|
|
1590
1592
|
return cursor;
|
|
1591
1593
|
});
|
|
1592
1594
|
this.mathField.focus();
|
|
1593
|
-
|
|
1595
|
+
(_this$props = this.props) == null ? void 0 : _this$props.onFocus();
|
|
1594
1596
|
this.setState({
|
|
1595
1597
|
focused: true
|
|
1596
1598
|
}, () => {
|
|
@@ -1600,13 +1602,14 @@ class MathInput extends React.Component {
|
|
|
1600
1602
|
// Android Browser 4.3.
|
|
1601
1603
|
setTimeout(() => {
|
|
1602
1604
|
if (this._isMounted) {
|
|
1605
|
+
var _this$props$keypadEle3;
|
|
1603
1606
|
// TODO(benkomalo): the keypad is animating at this point,
|
|
1604
1607
|
// so we can't call _cacheKeypadBounds(), even though
|
|
1605
1608
|
// it'd be nice to do so. It should probably be the case
|
|
1606
1609
|
// that the higher level controller tells us when the
|
|
1607
1610
|
// keypad is settled (then scrollIntoView wouldn't have
|
|
1608
1611
|
// to make assumptions about that either).
|
|
1609
|
-
const maybeKeypadNode = this.props.keypadElement
|
|
1612
|
+
const maybeKeypadNode = (_this$props$keypadEle3 = this.props.keypadElement) == null ? void 0 : _this$props$keypadEle3.getDOMNode();
|
|
1610
1613
|
scrollIntoView(this._container, maybeKeypadNode);
|
|
1611
1614
|
}
|
|
1612
1615
|
});
|
|
@@ -2011,7 +2014,7 @@ class MathInput extends React.Component {
|
|
|
2011
2014
|
// dismissal. This code needs to be generalized to handle
|
|
2012
2015
|
// multi-touch.
|
|
2013
2016
|
if (this.state.focused && this.didTouchOutside && !this.didScroll) {
|
|
2014
|
-
this.blur();
|
|
2017
|
+
this.blur(true);
|
|
2015
2018
|
}
|
|
2016
2019
|
this.didTouchOutside = false;
|
|
2017
2020
|
this.didScroll = false;
|
|
@@ -2087,13 +2090,18 @@ class MathInput extends React.Component {
|
|
|
2087
2090
|
role: "textbox",
|
|
2088
2091
|
ariaLabel: ariaLabel
|
|
2089
2092
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2090
|
-
className: "keypad-input"
|
|
2091
|
-
|
|
2092
|
-
,
|
|
2093
|
-
tabIndex: "0",
|
|
2093
|
+
className: "keypad-input",
|
|
2094
|
+
tabIndex: 0,
|
|
2094
2095
|
ref: node => {
|
|
2095
2096
|
this.inputRef = node;
|
|
2096
2097
|
},
|
|
2098
|
+
onFocus: () => {
|
|
2099
|
+
this.focus();
|
|
2100
|
+
},
|
|
2101
|
+
onBlur: () => {
|
|
2102
|
+
this._hideCursorHandle();
|
|
2103
|
+
this.blur(false);
|
|
2104
|
+
},
|
|
2097
2105
|
onKeyUp: this.handleKeyUp
|
|
2098
2106
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2099
2107
|
ref: node => {
|
|
@@ -5099,8 +5107,8 @@ class MobileKeypad extends React.Component {
|
|
|
5099
5107
|
this._throttleResize = false;
|
|
5100
5108
|
this.hasMounted = false;
|
|
5101
5109
|
this.state = {
|
|
5102
|
-
|
|
5103
|
-
|
|
5110
|
+
active: false,
|
|
5111
|
+
containerWidth: 0
|
|
5104
5112
|
};
|
|
5105
5113
|
this._resize = () => {
|
|
5106
5114
|
var _this$_containerRef$c;
|
|
@@ -5120,17 +5128,21 @@ class MobileKeypad extends React.Component {
|
|
|
5120
5128
|
}, 100);
|
|
5121
5129
|
};
|
|
5122
5130
|
this.activate = () => {
|
|
5123
|
-
this.
|
|
5124
|
-
|
|
5125
|
-
|
|
5131
|
+
if (!this.state.active) {
|
|
5132
|
+
this.setState({
|
|
5133
|
+
active: true
|
|
5134
|
+
});
|
|
5135
|
+
}
|
|
5126
5136
|
};
|
|
5127
5137
|
this.dismiss = () => {
|
|
5128
|
-
this.
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5138
|
+
if (this.state.active) {
|
|
5139
|
+
this.setState({
|
|
5140
|
+
active: false
|
|
5141
|
+
}, () => {
|
|
5142
|
+
var _this$props$onDismiss, _this$props;
|
|
5143
|
+
(_this$props$onDismiss = (_this$props = this.props).onDismiss) == null ? void 0 : _this$props$onDismiss.call(_this$props);
|
|
5144
|
+
});
|
|
5145
|
+
}
|
|
5134
5146
|
};
|
|
5135
5147
|
this.configure = (configuration, cb) => {
|
|
5136
5148
|
this.setState({
|
|
@@ -5166,9 +5178,14 @@ class MobileKeypad extends React.Component {
|
|
|
5166
5178
|
this._resize();
|
|
5167
5179
|
window.addEventListener("resize", this._throttleResizeHandler);
|
|
5168
5180
|
window.addEventListener("orientationchange", this._throttleResizeHandler);
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5181
|
+
|
|
5182
|
+
// LC-1213: some common older browsers (as of 2023-09-07)
|
|
5183
|
+
// don't support ResizeObserver
|
|
5184
|
+
if ("ResizeObserver" in window) {
|
|
5185
|
+
this._containerResizeObserver = new window.ResizeObserver(this._throttleResizeHandler);
|
|
5186
|
+
if (this._containerRef.current) {
|
|
5187
|
+
this._containerResizeObserver.observe(this._containerRef.current);
|
|
5188
|
+
}
|
|
5172
5189
|
}
|
|
5173
5190
|
}
|
|
5174
5191
|
componentWillUnMount() {
|
|
@@ -5226,10 +5243,8 @@ class MobileKeypad extends React.Component {
|
|
|
5226
5243
|
(_this$props$onElement = (_this$props2 = this.props).onElementMounted) == null ? void 0 : _this$props$onElement.call(_this$props2, elementWithDispatchMethods);
|
|
5227
5244
|
}
|
|
5228
5245
|
}
|
|
5229
|
-
}, /*#__PURE__*/React.createElement(Keypad$2
|
|
5230
|
-
|
|
5231
|
-
, {
|
|
5232
|
-
onAnalyticsEvent: async function () {},
|
|
5246
|
+
}, /*#__PURE__*/React.createElement(Keypad$2, {
|
|
5247
|
+
onAnalyticsEvent: this.props.onAnalyticsEvent,
|
|
5233
5248
|
extraKeys: keypadConfig == null ? void 0 : keypadConfig.extraKeys,
|
|
5234
5249
|
onClickKey: key => this._handleClickKey(key),
|
|
5235
5250
|
cursorContext: cursor == null ? void 0 : cursor.context,
|
|
@@ -8344,9 +8359,14 @@ class KeypadContainer extends React.Component {
|
|
|
8344
8359
|
// And update it on resize.
|
|
8345
8360
|
window.addEventListener("resize", this._throttleResizeHandler);
|
|
8346
8361
|
window.addEventListener("orientationchange", this._throttleResizeHandler);
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8362
|
+
|
|
8363
|
+
// LC-1213: some common older browsers (as of 2023-09-07)
|
|
8364
|
+
// don't support ResizeObserver
|
|
8365
|
+
if ("ResizeObserver" in window) {
|
|
8366
|
+
this._containerResizeObserver = new window.ResizeObserver(this._throttleResizeHandler);
|
|
8367
|
+
if (this._containerRef.current) {
|
|
8368
|
+
this._containerResizeObserver.observe(this._containerRef.current);
|
|
8369
|
+
}
|
|
8350
8370
|
}
|
|
8351
8371
|
}
|
|
8352
8372
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
@@ -9694,6 +9714,13 @@ class ProvidedKeypad extends React.Component {
|
|
|
9694
9714
|
store: this.store
|
|
9695
9715
|
}, /*#__PURE__*/React.createElement(KeypadContainer$1, {
|
|
9696
9716
|
onElementMounted: element => {
|
|
9717
|
+
this.props.onAnalyticsEvent({
|
|
9718
|
+
type: "math-input:keypad-opened",
|
|
9719
|
+
payload: {
|
|
9720
|
+
virtualKeypadVersion: "MATH_INPUT_KEYPAD_V1"
|
|
9721
|
+
}
|
|
9722
|
+
});
|
|
9723
|
+
|
|
9697
9724
|
// Append the dispatch methods that we want to expose
|
|
9698
9725
|
// externally to the returned React element.
|
|
9699
9726
|
const elementWithDispatchMethods = _extends({}, element, {
|
|
@@ -9704,9 +9731,17 @@ class ProvidedKeypad extends React.Component {
|
|
|
9704
9731
|
setKeyHandler: this.setKeyHandler,
|
|
9705
9732
|
getDOMNode: this.getDOMNode
|
|
9706
9733
|
});
|
|
9707
|
-
onElementMounted
|
|
9734
|
+
onElementMounted == null ? void 0 : onElementMounted(elementWithDispatchMethods);
|
|
9735
|
+
},
|
|
9736
|
+
onDismiss: () => {
|
|
9737
|
+
this.props.onAnalyticsEvent({
|
|
9738
|
+
type: "math-input:keypad-closed",
|
|
9739
|
+
payload: {
|
|
9740
|
+
virtualKeypadVersion: "MATH_INPUT_KEYPAD_V1"
|
|
9741
|
+
}
|
|
9742
|
+
});
|
|
9743
|
+
onDismiss == null ? void 0 : onDismiss();
|
|
9708
9744
|
},
|
|
9709
|
-
onDismiss: onDismiss,
|
|
9710
9745
|
style: style
|
|
9711
9746
|
}));
|
|
9712
9747
|
}
|
|
@@ -9719,6 +9754,10 @@ function KeypadSwitch(props) {
|
|
|
9719
9754
|
} = props,
|
|
9720
9755
|
rest = _objectWithoutPropertiesLoose(props, _excluded);
|
|
9721
9756
|
const KeypadComponent = useV2Keypad ? MobileKeypad : ProvidedKeypad;
|
|
9757
|
+
|
|
9758
|
+
// Note: Although we pass the "onAnalyticsEvent" to both keypad components,
|
|
9759
|
+
// only the current one uses it. There's no point in instrumenting the
|
|
9760
|
+
// legacy keypad given that it's on its way out the door.
|
|
9722
9761
|
return /*#__PURE__*/React.createElement(KeypadComponent, rest);
|
|
9723
9762
|
}
|
|
9724
9763
|
|