@khanacademy/perseus 10.1.0 → 11.1.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 +20 -0
- package/dist/article-renderer.d.ts +5 -7
- package/dist/es/index.js +83 -90
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +83 -90
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +2 -2
- package/dist/server-item-renderer.d.ts +5 -4
- package/dist/types.d.ts +2 -1
- package/dist/widgets/expression.d.ts +12 -12
- package/package.json +5 -4
- package/src/__stories__/article-renderer.stories.tsx +22 -0
- package/src/__testdata__/article-renderer.testdata.ts +28 -0
- package/src/__tests__/server-item-renderer.test.tsx +12 -4
- package/src/article-renderer.tsx +14 -27
- package/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap +5 -5
- package/src/server-item-renderer.tsx +10 -7
- package/src/types.ts +2 -4
- package/src/widgets/__stories__/expression.stories.tsx +3 -3
- package/src/widgets/__tests__/__snapshots__/group.test.tsx.snap +5 -5
- package/src/widgets/__tests__/__snapshots__/radio.test.ts.snap +28 -28
- package/src/widgets/radio/choice.tsx +2 -1
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/index.js
CHANGED
|
@@ -22825,7 +22825,8 @@ const Choice = function (props) {
|
|
|
22825
22825
|
display: "flex",
|
|
22826
22826
|
flexDirection: "row",
|
|
22827
22827
|
opacity: showDimmed ? 0.5 : 1.0,
|
|
22828
|
-
|
|
22828
|
+
overflowX: "auto",
|
|
22829
|
+
overflowY: "hidden"
|
|
22829
22830
|
}
|
|
22830
22831
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
22831
22832
|
className: "perseus-sr-only"
|
|
@@ -44146,80 +44147,10 @@ registerWidgets(allWidgets);
|
|
|
44146
44147
|
const ItemVersion = getVersionVector();
|
|
44147
44148
|
ItemVersion["::renderer::"] = version.itemDataVersion;
|
|
44148
44149
|
|
|
44149
|
-
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
44150
|
-
// NOTE: This is not a real component. It's a collection of methods used to
|
|
44151
|
-
// create and manage a Keypad instances.
|
|
44152
|
-
// TODO(LP-10789): replace this with a React Context object to pass information
|
|
44153
|
-
// between Perseus and the Keypad.
|
|
44154
|
-
const ProvideKeypad = {
|
|
44155
|
-
getInitialState() {
|
|
44156
|
-
const _this = this;
|
|
44157
|
-
let keypadElement = null;
|
|
44158
|
-
if (_this.props.apiOptions && _this.props.apiOptions.customKeypad && _this.props.apiOptions.nativeKeypadProxy) {
|
|
44159
|
-
keypadElement = _this.props.apiOptions.nativeKeypadProxy(
|
|
44160
|
-
// @ts-expect-error - TS2339 - Property 'blur' 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...'. | TS2339 - Property 'blur' 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...'.
|
|
44161
|
-
() => _this.blur && _this.blur());
|
|
44162
|
-
}
|
|
44163
|
-
return {
|
|
44164
|
-
keypadElement
|
|
44165
|
-
};
|
|
44166
|
-
},
|
|
44167
|
-
componentDidMount() {
|
|
44168
|
-
const _this = this;
|
|
44169
|
-
const apiOptions = _this.props.apiOptions;
|
|
44170
|
-
if (apiOptions && apiOptions.customKeypad && !apiOptions.nativeKeypadProxy) {
|
|
44171
|
-
var _document$body;
|
|
44172
|
-
// TODO(charlie): Render this and the wrapped component in the same
|
|
44173
|
-
// React tree. We may also want to add this keypad asynchronously
|
|
44174
|
-
// or on-demand in the future.
|
|
44175
|
-
_this._keypadContainer = document.createElement("div");
|
|
44176
|
-
(_document$body = document.body) === null || _document$body === void 0 ? void 0 : _document$body.appendChild(_this._keypadContainer);
|
|
44177
|
-
render( /*#__PURE__*/React__namespace.createElement(mathInput.MobileKeypad, {
|
|
44178
|
-
onElementMounted: element => {
|
|
44179
|
-
// NOTE(kevinb): The reason why this setState works is
|
|
44180
|
-
// b/c we're calling it manually from item-renderer.jsx
|
|
44181
|
-
// and we're manually setting the 'this' by using 'call'
|
|
44182
|
-
// @ts-expect-error - TS2339 - Property 'setState' 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...'.
|
|
44183
|
-
_this.setState({
|
|
44184
|
-
keypadElement: element
|
|
44185
|
-
});
|
|
44186
|
-
},
|
|
44187
|
-
onDismiss: () => {
|
|
44188
|
-
// @ts-expect-error - TS2339 - Property 'blur' 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...'. | TS2339 - Property 'blur' 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...'.
|
|
44189
|
-
_this.blur && _this.blur();
|
|
44190
|
-
}
|
|
44191
|
-
// @ts-expect-error - 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...'.
|
|
44192
|
-
,
|
|
44193
|
-
style: _this.props.keypadStyle,
|
|
44194
|
-
useV2Keypad: apiOptions.useV2Keypad
|
|
44195
|
-
}), _this._keypadContainer);
|
|
44196
|
-
}
|
|
44197
|
-
},
|
|
44198
|
-
componentWillUnmount() {
|
|
44199
|
-
const _this = this;
|
|
44200
|
-
if (_this._keypadContainer) {
|
|
44201
|
-
ReactDOM__default["default"].unmountComponentAtNode(_this._keypadContainer);
|
|
44202
|
-
if (_this._keypadContainer.parentNode) {
|
|
44203
|
-
// Note ChildNode.remove() isn't available in older Android
|
|
44204
|
-
// webviews.
|
|
44205
|
-
_this._keypadContainer.parentNode.removeChild(_this._keypadContainer);
|
|
44206
|
-
}
|
|
44207
|
-
_this._keypadContainer = null;
|
|
44208
|
-
}
|
|
44209
|
-
},
|
|
44210
|
-
keypadElement() {
|
|
44211
|
-
const _this = this;
|
|
44212
|
-
return _this.state.keypadElement;
|
|
44213
|
-
}
|
|
44214
|
-
};
|
|
44215
|
-
|
|
44216
44150
|
class ArticleRenderer extends React__namespace.Component {
|
|
44217
44151
|
constructor(props) {
|
|
44218
44152
|
super(props);
|
|
44219
44153
|
_defineProperty(this, "_currentFocus", void 0);
|
|
44220
|
-
_defineProperty(this, "keypadElement", () => {
|
|
44221
|
-
return ProvideKeypad.keypadElement.call(this);
|
|
44222
|
-
});
|
|
44223
44154
|
_defineProperty(this, "_handleFocusChange", (newFocusPath, oldFocusPath) => {
|
|
44224
44155
|
// TODO(charlie): DRY this up--some of this logic is repeated in
|
|
44225
44156
|
// ItemRenderer.
|
|
@@ -44230,7 +44161,13 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44230
44161
|
}
|
|
44231
44162
|
});
|
|
44232
44163
|
_defineProperty(this, "_setCurrentFocus", newFocusPath => {
|
|
44233
|
-
const
|
|
44164
|
+
const {
|
|
44165
|
+
keypadElement,
|
|
44166
|
+
apiOptions
|
|
44167
|
+
} = this.props;
|
|
44168
|
+
const {
|
|
44169
|
+
isMobile
|
|
44170
|
+
} = apiOptions;
|
|
44234
44171
|
const prevFocusPath = this._currentFocus;
|
|
44235
44172
|
this._currentFocus = newFocusPath;
|
|
44236
44173
|
|
|
@@ -44248,18 +44185,12 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44248
44185
|
});
|
|
44249
44186
|
}
|
|
44250
44187
|
if (this.props.apiOptions.onFocusChange != null) {
|
|
44251
|
-
this.props.apiOptions.onFocusChange(this._currentFocus, prevFocusPath,
|
|
44252
|
-
// @ts-expect-error - TS2339 - Property 'getDOMNode' does not exist on type 'never'.
|
|
44253
|
-
didFocusInput && keypadElement && keypadElement.getDOMNode());
|
|
44188
|
+
this.props.apiOptions.onFocusChange(this._currentFocus, prevFocusPath, didFocusInput ? keypadElement === null || keypadElement === void 0 ? void 0 : keypadElement.getDOMNode() : null);
|
|
44254
44189
|
}
|
|
44255
|
-
|
|
44256
|
-
// @ts-expect-error - TS1345 - An expression of type 'void' cannot be tested for truthiness.
|
|
44257
|
-
if (keypadElement) {
|
|
44190
|
+
if (keypadElement && isMobile) {
|
|
44258
44191
|
if (didFocusInput) {
|
|
44259
|
-
// @ts-expect-error - TS2339 - Property 'activate' does not exist on type 'never'.
|
|
44260
44192
|
keypadElement.activate();
|
|
44261
44193
|
} else {
|
|
44262
|
-
// @ts-expect-error - TS2339 - Property 'dismiss' does not exist on type 'never'.
|
|
44263
44194
|
keypadElement.dismiss();
|
|
44264
44195
|
}
|
|
44265
44196
|
}
|
|
@@ -44295,17 +44226,12 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44295
44226
|
_defineProperty(this, "_sections", () => {
|
|
44296
44227
|
return Array.isArray(this.props.json) ? this.props.json : [this.props.json];
|
|
44297
44228
|
});
|
|
44298
|
-
this.state = ProvideKeypad.getInitialState.call(this);
|
|
44299
44229
|
}
|
|
44300
44230
|
componentDidMount() {
|
|
44301
|
-
ProvideKeypad.componentDidMount.call(this);
|
|
44302
44231
|
this._currentFocus = null;
|
|
44303
44232
|
}
|
|
44304
|
-
shouldComponentUpdate(nextProps
|
|
44305
|
-
return nextProps !== this.props
|
|
44306
|
-
}
|
|
44307
|
-
componentWillUnmount() {
|
|
44308
|
-
ProvideKeypad.componentWillUnmount.call(this);
|
|
44233
|
+
shouldComponentUpdate(nextProps) {
|
|
44234
|
+
return nextProps !== this.props;
|
|
44309
44235
|
}
|
|
44310
44236
|
render() {
|
|
44311
44237
|
const apiOptions = {
|
|
@@ -44333,7 +44259,7 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
44333
44259
|
ref: refForSection,
|
|
44334
44260
|
key: i,
|
|
44335
44261
|
key_: i,
|
|
44336
|
-
keypadElement: this.keypadElement
|
|
44262
|
+
keypadElement: this.props.keypadElement,
|
|
44337
44263
|
apiOptions: {
|
|
44338
44264
|
...apiOptions,
|
|
44339
44265
|
onFocusChange: (newFocusPath, oldFocusPath) => {
|
|
@@ -44705,6 +44631,73 @@ const styles$4 = aphrodite.StyleSheet.create({
|
|
|
44705
44631
|
}
|
|
44706
44632
|
});
|
|
44707
44633
|
|
|
44634
|
+
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
44635
|
+
// NOTE: This is not a real component. It's a collection of methods used to
|
|
44636
|
+
// create and manage a Keypad instances.
|
|
44637
|
+
// TODO(LP-10789): replace this with a React Context object to pass information
|
|
44638
|
+
// between Perseus and the Keypad.
|
|
44639
|
+
const ProvideKeypad = {
|
|
44640
|
+
getInitialState() {
|
|
44641
|
+
const _this = this;
|
|
44642
|
+
let keypadElement = null;
|
|
44643
|
+
if (_this.props.apiOptions && _this.props.apiOptions.customKeypad && _this.props.apiOptions.nativeKeypadProxy) {
|
|
44644
|
+
keypadElement = _this.props.apiOptions.nativeKeypadProxy(
|
|
44645
|
+
// @ts-expect-error - TS2339 - Property 'blur' 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...'. | TS2339 - Property 'blur' 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...'.
|
|
44646
|
+
() => _this.blur && _this.blur());
|
|
44647
|
+
}
|
|
44648
|
+
return {
|
|
44649
|
+
keypadElement
|
|
44650
|
+
};
|
|
44651
|
+
},
|
|
44652
|
+
componentDidMount() {
|
|
44653
|
+
const _this = this;
|
|
44654
|
+
const apiOptions = _this.props.apiOptions;
|
|
44655
|
+
if (apiOptions && apiOptions.customKeypad && !apiOptions.nativeKeypadProxy) {
|
|
44656
|
+
var _document$body;
|
|
44657
|
+
// TODO(charlie): Render this and the wrapped component in the same
|
|
44658
|
+
// React tree. We may also want to add this keypad asynchronously
|
|
44659
|
+
// or on-demand in the future.
|
|
44660
|
+
_this._keypadContainer = document.createElement("div");
|
|
44661
|
+
(_document$body = document.body) === null || _document$body === void 0 ? void 0 : _document$body.appendChild(_this._keypadContainer);
|
|
44662
|
+
render( /*#__PURE__*/React__namespace.createElement(mathInput.MobileKeypad, {
|
|
44663
|
+
onElementMounted: element => {
|
|
44664
|
+
// NOTE(kevinb): The reason why this setState works is
|
|
44665
|
+
// b/c we're calling it manually from item-renderer.jsx
|
|
44666
|
+
// and we're manually setting the 'this' by using 'call'
|
|
44667
|
+
// @ts-expect-error - TS2339 - Property 'setState' 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...'.
|
|
44668
|
+
_this.setState({
|
|
44669
|
+
keypadElement: element
|
|
44670
|
+
});
|
|
44671
|
+
},
|
|
44672
|
+
onDismiss: () => {
|
|
44673
|
+
// @ts-expect-error - TS2339 - Property 'blur' 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...'. | TS2339 - Property 'blur' 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...'.
|
|
44674
|
+
_this.blur && _this.blur();
|
|
44675
|
+
}
|
|
44676
|
+
// @ts-expect-error - 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...'.
|
|
44677
|
+
,
|
|
44678
|
+
style: _this.props.keypadStyle,
|
|
44679
|
+
useV2Keypad: apiOptions.useV2Keypad
|
|
44680
|
+
}), _this._keypadContainer);
|
|
44681
|
+
}
|
|
44682
|
+
},
|
|
44683
|
+
componentWillUnmount() {
|
|
44684
|
+
const _this = this;
|
|
44685
|
+
if (_this._keypadContainer) {
|
|
44686
|
+
ReactDOM__default["default"].unmountComponentAtNode(_this._keypadContainer);
|
|
44687
|
+
if (_this._keypadContainer.parentNode) {
|
|
44688
|
+
// Note ChildNode.remove() isn't available in older Android
|
|
44689
|
+
// webviews.
|
|
44690
|
+
_this._keypadContainer.parentNode.removeChild(_this._keypadContainer);
|
|
44691
|
+
}
|
|
44692
|
+
_this._keypadContainer = null;
|
|
44693
|
+
}
|
|
44694
|
+
},
|
|
44695
|
+
keypadElement() {
|
|
44696
|
+
const _this = this;
|
|
44697
|
+
return _this.state.keypadElement;
|
|
44698
|
+
}
|
|
44699
|
+
};
|
|
44700
|
+
|
|
44708
44701
|
const {
|
|
44709
44702
|
mapObject: mapObject$1
|
|
44710
44703
|
} = objective_;
|
|
@@ -45201,8 +45194,8 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
45201
45194
|
return Util.inputPathsEqual(inputPath, this._currentFocus);
|
|
45202
45195
|
});
|
|
45203
45196
|
if (onFocusChange != null) {
|
|
45204
|
-
onFocusChange(this._currentFocus, prevFocus, didFocusInput
|
|
45205
|
-
// @ts-expect-error - TS2345 - Argument of type 'false | Element | Text | null | undefined' is not assignable to parameter of type 'HTMLElement | undefined'.
|
|
45197
|
+
onFocusChange(this._currentFocus, prevFocus, didFocusInput ? keypadElement === null || keypadElement === void 0 ? void 0 : keypadElement.getDOMNode() : null,
|
|
45198
|
+
// @ts-expect-error [FEI-5003] - TS2345 - Argument of type 'false | Element | Text | null | undefined' is not assignable to parameter of type 'HTMLElement | undefined'.
|
|
45206
45199
|
didFocusInput && this.questionRenderer.getDOMNodeForPath(newFocus));
|
|
45207
45200
|
}
|
|
45208
45201
|
if (keypadElement && isMobile) {
|