@khanacademy/perseus 14.0.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 (57) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/article-renderer.d.ts +1 -2
  3. package/dist/es/index.js +16 -468
  4. package/dist/es/index.js.map +1 -1
  5. package/dist/index.d.ts +0 -1
  6. package/dist/index.js +13 -463
  7. package/dist/index.js.map +1 -1
  8. package/dist/multi-items/item-types.d.ts +1 -1
  9. package/dist/multi-items/multi-renderer.d.ts +2 -2
  10. package/dist/perseus-api.d.ts +0 -3
  11. package/dist/server-item-renderer.d.ts +2 -15
  12. package/dist/strings.js +1 -0
  13. package/dist/styles/shared.d.ts +1 -0
  14. package/dist/types.d.ts +0 -2
  15. package/dist/util/a11y.d.ts +1 -0
  16. package/dist/widgets/expression.d.ts +0 -12
  17. package/dist/widgets/graded-group.d.ts +1 -1
  18. package/dist/widgets/label-image.d.ts +1 -1
  19. package/dist/widgets/matcher.d.ts +0 -1
  20. package/dist/widgets/passage.d.ts +1 -1
  21. package/dist/widgets/radio/widget.d.ts +1 -1
  22. package/dist/widgets/simulator.d.ts +0 -1
  23. package/dist/widgets/sorter.d.ts +0 -1
  24. package/package.json +8 -8
  25. package/src/__stories__/server-item-renderer.stories.tsx +1 -1
  26. package/src/__testdata__/server-item-renderer.testdata.ts +160 -0
  27. package/src/__tests__/server-item-renderer.test.tsx +2 -2
  28. package/src/article-renderer.tsx +13 -15
  29. package/src/components/svg-image.tsx +1 -1
  30. package/src/hints-renderer.tsx +1 -0
  31. package/src/index.ts +0 -1
  32. package/src/multi-items/item-types.ts +1 -1
  33. package/src/multi-items/multi-renderer.tsx +4 -4
  34. package/src/perseus-api.tsx +0 -6
  35. package/src/server-item-renderer.tsx +12 -13
  36. package/src/types.ts +0 -5
  37. package/src/util.ts +1 -1
  38. package/src/widgets/__stories__/expression.stories.tsx +0 -1
  39. package/src/widgets/__tests__/expression-mobile.test.tsx +0 -1
  40. package/src/widgets/__tests__/expression.test.tsx +4 -15
  41. package/src/widgets/expression.tsx +1 -5
  42. package/src/widgets/graded-group.tsx +1 -1
  43. package/src/widgets/label-image/strings.ts +3 -1
  44. package/src/widgets/label-image.tsx +2 -2
  45. package/src/widgets/passage-ref.tsx +1 -1
  46. package/src/widgets/passage.tsx +1 -1
  47. package/src/widgets/radio/widget.tsx +1 -1
  48. package/src/widgets/radio.ts +1 -1
  49. package/tsconfig-build.tsbuildinfo +1 -1
  50. package/dist/item-renderer.d.ts +0 -125
  51. package/dist/mixins/provide-keypad.d.ts +0 -39
  52. package/src/__stories__/item-renderer.stories.tsx +0 -30
  53. package/src/__testdata__/item-renderer.testdata.ts +0 -299
  54. package/src/__tests__/__snapshots__/item-renderer.test.tsx.snap +0 -224
  55. package/src/__tests__/item-renderer.test.tsx +0 -930
  56. package/src/item-renderer.tsx +0 -529
  57. package/src/mixins/provide-keypad.tsx +0 -137
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @khanacademy/perseus
2
2
 
3
+ ## 15.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#833](https://github.com/Khan/perseus/pull/833) [`3cf5ac4c`](https://github.com/Khan/perseus/commit/3cf5ac4c3f9d51dbcddc6f75bfbf0f8778b20f78) Thanks [@handeyeco](https://github.com/handeyeco)! - Remove export of ItemRenderer
8
+
9
+ ### Minor Changes
10
+
11
+ - [#794](https://github.com/Khan/perseus/pull/794) [`a91c84fe`](https://github.com/Khan/perseus/commit/a91c84fe53827ff4333220777a9918882b7fe9f0) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Removing the useV2Keypad apiOption as the V1 keypad is no longer in use.
12
+
13
+ ### Patch Changes
14
+
15
+ - [#839](https://github.com/Khan/perseus/pull/839) [`3e176246`](https://github.com/Khan/perseus/commit/3e176246025ba237682569481dd9960f7a0dabf4) Thanks [@nedredmond](https://github.com/nedredmond)! - Wrap string in internationalization function
16
+
17
+ * [#814](https://github.com/Khan/perseus/pull/814) [`105d2060`](https://github.com/Khan/perseus/commit/105d20603d935d35cff237b17f0bfb57ca751e4c) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Minor build change to how we provide Typescript type definitions (should be no change to build output).
18
+
19
+ * Updated dependencies [[`a91c84fe`](https://github.com/Khan/perseus/commit/a91c84fe53827ff4333220777a9918882b7fe9f0), [`105d2060`](https://github.com/Khan/perseus/commit/105d20603d935d35cff237b17f0bfb57ca751e4c)]:
20
+ - @khanacademy/math-input@16.1.0
21
+ - @khanacademy/perseus-core@1.4.0
22
+ - @khanacademy/kas@0.3.6
23
+ - @khanacademy/kmath@0.1.7
24
+ - @khanacademy/perseus-linter@0.3.9
25
+ - @khanacademy/pure-markdown@0.2.12
26
+ - @khanacademy/simple-markdown@0.11.1
27
+
3
28
  ## 14.0.0
4
29
 
5
30
  ### Major Changes
@@ -5,13 +5,12 @@
5
5
  import * as React from "react";
6
6
  import { DependenciesContext } from "./dependencies";
7
7
  import Renderer from "./renderer";
8
- import type { KeypadProps } from "./mixins/provide-keypad";
9
8
  import type { PerseusRenderer } from "./perseus-types";
10
9
  import type { APIOptions, PerseusDependenciesV2 } from "./types";
11
10
  import type { KeypadAPI } from "@khanacademy/math-input";
12
11
  import type { KeypadContextRendererInterface } from "@khanacademy/perseus-core";
13
12
  import type { LinterContextProps } from "@khanacademy/perseus-linter";
14
- type Props = Partial<React.ContextType<typeof DependenciesContext>> & KeypadProps & {
13
+ type Props = Partial<React.ContextType<typeof DependenciesContext>> & {
15
14
  apiOptions: APIOptions;
16
15
  json: PerseusRenderer | ReadonlyArray<PerseusRenderer>;
17
16
  /**
package/dist/es/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as KAS from '@khanacademy/kas';
2
- import { keyTranslator, CursorContext, createMathField, mathQuillInstance, getCursorContext, DesktopKeypad, KeypadInput, KeypadType, KeyArray, keypadElementPropType, MobileKeypad } from '@khanacademy/math-input';
2
+ import { keyTranslator, CursorContext, createMathField, mathQuillInstance, getCursorContext, DesktopKeypad, KeypadInput, KeypadType, KeyArray, keypadElementPropType } from '@khanacademy/math-input';
3
3
  import * as PerseusLinter from '@khanacademy/perseus-linter';
4
4
  import { linterContextDefault, Rule, linterContextProps } from '@khanacademy/perseus-linter';
5
5
  import { View, RenderStateRoot, Text } from '@khanacademy/wonder-blocks-core';
@@ -32,20 +32,17 @@ import Link from '@khanacademy/wonder-blocks-link';
32
32
  import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-core';
33
33
 
34
34
  function _extends() {
35
- _extends = Object.assign || function (target) {
35
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
36
36
  for (var i = 1; i < arguments.length; i++) {
37
37
  var source = arguments[i];
38
-
39
38
  for (var key in source) {
40
39
  if (Object.prototype.hasOwnProperty.call(source, key)) {
41
40
  target[key] = source[key];
42
41
  }
43
42
  }
44
43
  }
45
-
46
44
  return target;
47
45
  };
48
-
49
46
  return _extends.apply(this, arguments);
50
47
  }
51
48
 
@@ -54,13 +51,11 @@ function _objectWithoutPropertiesLoose(source, excluded) {
54
51
  var target = {};
55
52
  var sourceKeys = Object.keys(source);
56
53
  var key, i;
57
-
58
54
  for (i = 0; i < sourceKeys.length; i++) {
59
55
  key = sourceKeys[i];
60
56
  if (excluded.indexOf(key) >= 0) continue;
61
57
  target[key] = source[key];
62
58
  }
63
-
64
59
  return target;
65
60
  }
66
61
 
@@ -875,10 +870,6 @@ const ApiOptions = {
875
870
  nativeKeypadProxy: PropTypes.func,
876
871
  // Indicates whether or not to use mobile styling.
877
872
  isMobile: PropTypes.bool,
878
- // Whether to use v1 (Legacy) Keypad for MathInput mobile or
879
- // use the new v2 Keypad
880
- // TODO [LC-1088]: remove after v2 release
881
- useV2Keypad: PropTypes.bool,
882
873
  // A function, called with a bool indicating whether use of the
883
874
  // drawing area (scratchpad) should be allowed/disallowed.
884
875
  // Previously handled by `Khan.scratchpad.enable/disable`
@@ -917,7 +908,6 @@ const ApiOptions = {
917
908
  defaults: {
918
909
  isArticle: false,
919
910
  isMobile: false,
920
- useV2Keypad: false,
921
911
  onInputError: function () {},
922
912
  onFocusChange: function () {},
923
913
  GroupMetadataEditor: StubTagEditor,
@@ -1924,7 +1914,7 @@ const deriveKeypadVersion = apiOptions => {
1924
1914
  // a bit tricky, but this code will be relatively short-lived
1925
1915
  // as we coalesce onto the new, v2 Keypad, at which point we
1926
1916
  // can remove this `virtualKeypadVersion` field entirely.
1927
- return apiOptions.nativeKeypadProxy != null ? "REACT_NATIVE_KEYPAD" : apiOptions.customKeypad === true ? apiOptions.useV2Keypad === true ? "MATH_INPUT_KEYPAD_V2" : "MATH_INPUT_KEYPAD_V1" : "PERSEUS_MATH_INPUT";
1917
+ return apiOptions.nativeKeypadProxy != null ? "REACT_NATIVE_KEYPAD" : "MATH_INPUT_KEYPAD_V2";
1928
1918
  };
1929
1919
  // The new, MathQuill input expression widget
1930
1920
  class Expression extends React.Component {
@@ -10239,7 +10229,7 @@ const pluck = function pluck(table, subKey) {
10239
10229
  * });
10240
10230
  * {a: 2, b: 3}
10241
10231
  */
10242
- const mapObject$3 = function mapObject(obj, lambda) {
10232
+ const mapObject$2 = function mapObject(obj, lambda) {
10243
10233
  const result = {};
10244
10234
  _.each(_.keys(obj), function (key) {
10245
10235
  // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
@@ -10265,7 +10255,7 @@ const mapObjectFromArray$1 = function mapObjectFromArray(arr, lambda) {
10265
10255
  };
10266
10256
  var objective_ = {
10267
10257
  pluck: pluck,
10268
- mapObject: mapObject$3,
10258
+ mapObject: mapObject$2,
10269
10259
  mapObjectFromArray: mapObjectFromArray$1
10270
10260
  };
10271
10261
 
@@ -18874,7 +18864,7 @@ WidgetContainer.defaultProps = {
18874
18864
  };
18875
18865
 
18876
18866
  const {
18877
- mapObject: mapObject$2,
18867
+ mapObject: mapObject$1,
18878
18868
  mapObjectFromArray
18879
18869
  } = objective_;
18880
18870
  const rContainsNonWhitespace = /\S/;
@@ -18942,7 +18932,7 @@ class Renderer extends React.Component {
18942
18932
  // @ts-expect-error - TS2322 - Type '(props: Props) => Partial<Record<string, CategorizerWidget | CSProgramWidget | DefinitionWidget | DropdownWidget | ... 35 more ... | VideoWidget>>' is not assignable to type '(props: Props) => { [key: string]: PerseusWidget; }'.
18943
18933
  this._getAllWidgetsInfo = props => {
18944
18934
  // @ts-expect-error - TS2345 - Argument of type '{ [key: string]: PerseusWidget; }' is not assignable to parameter of type 'Partial<Record<string, CategorizerWidget>>'.
18945
- return mapObject$2(props.widgets, (widgetInfo, widgetId) => {
18935
+ return mapObject$1(props.widgets, (widgetInfo, widgetId) => {
18946
18936
  if (!widgetInfo.type || !widgetInfo.alignment) {
18947
18937
  const newValues = {};
18948
18938
  if (!widgetInfo.type) {
@@ -18958,7 +18948,7 @@ class Renderer extends React.Component {
18958
18948
  };
18959
18949
  this._getAllWidgetsStartProps = (allWidgetInfo, props) => {
18960
18950
  // @ts-expect-error - TS2345 - Argument of type '{ [key: string]: PerseusWidget; }' is not assignable to parameter of type 'Partial<Record<string, CategorizerWidget>>'.
18961
- return mapObject$2(allWidgetInfo, widgetInfo => {
18951
+ return mapObject$1(allWidgetInfo, widgetInfo => {
18962
18952
  return getRendererPropsForWidgetInfo(widgetInfo, props.problemNum);
18963
18953
  });
18964
18954
  };
@@ -19073,7 +19063,7 @@ class Renderer extends React.Component {
19073
19063
  * state from that instead of the current widget props.
19074
19064
  */
19075
19065
  this.getSerializedState = widgetProps => {
19076
- return mapObject$2(widgetProps || this.state.widgetProps, (props, widgetId) => {
19066
+ return mapObject$1(widgetProps || this.state.widgetProps, (props, widgetId) => {
19077
19067
  const widget = this.getWidgetInstance(widgetId);
19078
19068
  if (widget && widget.getSerializedState) {
19079
19069
  return widget.getSerializedState();
@@ -19109,7 +19099,7 @@ class Renderer extends React.Component {
19109
19099
  }
19110
19100
  };
19111
19101
  this.setState({
19112
- widgetProps: mapObject$2(serializedState, (props, widgetId) => {
19102
+ widgetProps: mapObject$1(serializedState, (props, widgetId) => {
19113
19103
  const widget = this.getWidgetInstance(widgetId);
19114
19104
  if (widget && widget.restoreSerializedState) {
19115
19105
  // Note that we probably can't call
@@ -44089,7 +44079,7 @@ const init = function init(options) {
44089
44079
 
44090
44080
  // This file is processed by a Rollup plugin (replace) to inject the production
44091
44081
  const libName = "@khanacademy/perseus";
44092
- const libVersion = "14.0.0";
44082
+ const libVersion = "15.0.0";
44093
44083
  addLibraryVersionToPerseusDebug(libName, libVersion);
44094
44084
 
44095
44085
  const apiVersion = {
@@ -44427,6 +44417,8 @@ class HintsRenderer extends React.Component {
44427
44417
  componentDidMount() {
44428
44418
  this._cacheHintImages();
44429
44419
  }
44420
+
44421
+ // eslint-disable-next-line react/no-unsafe
44430
44422
  UNSAFE_componentWillReceiveProps(nextProps) {
44431
44423
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
44432
44424
  if (nextProps.hintsVisible - this.props.hintsVisible > 1) {
@@ -44596,452 +44588,6 @@ const styles$4 = StyleSheet.create({
44596
44588
  }
44597
44589
  });
44598
44590
 
44599
- /* eslint-disable @khanacademy/ts-no-error-suppressions */
44600
-
44601
- // This represents the shape of any component that uses this ProvideKeypad
44602
- // mixin.
44603
- // NOTE: This is not a real component. It's a collection of methods used to
44604
- // create and manage a Keypad instances.
44605
- // TODO(LP-10789): replace this with a React Context object to pass information
44606
- // between Perseus and the Keypad.
44607
- const ProvideKeypad = {
44608
- getInitialState() {
44609
- const _this = this;
44610
- let keypadElement = null;
44611
- if (_this.props.apiOptions && _this.props.apiOptions.customKeypad && _this.props.apiOptions.nativeKeypadProxy) {
44612
- keypadElement = _this.props.apiOptions.nativeKeypadProxy(
44613
- // @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...'.
44614
- () => _this.blur && _this.blur());
44615
- }
44616
- return {
44617
- keypadElement
44618
- };
44619
- },
44620
- componentDidMount() {
44621
- const _this = this;
44622
- const apiOptions = _this.props.apiOptions;
44623
- if (apiOptions && apiOptions.customKeypad && !apiOptions.nativeKeypadProxy) {
44624
- var _document$body;
44625
- // TODO(charlie): Render this and the wrapped component in the same
44626
- // React tree. We may also want to add this keypad asynchronously
44627
- // or on-demand in the future.
44628
- _this._keypadContainer = document.createElement("div");
44629
- (_document$body = document.body) == null || _document$body.appendChild(_this._keypadContainer);
44630
- render( /*#__PURE__*/React.createElement(MobileKeypad, {
44631
- onElementMounted: element => {
44632
- // NOTE(kevinb): The reason why this setState works is
44633
- // b/c we're calling it manually from item-renderer.jsx
44634
- // and we're manually setting the 'this' by using 'call'
44635
- // @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...'.
44636
- _this.setState({
44637
- keypadElement: element
44638
- });
44639
- },
44640
- onDismiss: () => {
44641
- // @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...'.
44642
- _this.blur && _this.blur();
44643
- }
44644
- // @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...'.
44645
- ,
44646
- style: _this.props.keypadStyle,
44647
- onAnalyticsEvent: async () => {
44648
- // Intentionally left empty. This component is
44649
- // deprecated and so we don't want/need to instrument
44650
- // it.
44651
- }
44652
- }), _this._keypadContainer);
44653
- }
44654
- },
44655
- componentWillUnmount() {
44656
- const _this = this;
44657
- if (_this._keypadContainer) {
44658
- ReactDOM__default.unmountComponentAtNode(_this._keypadContainer);
44659
- if (_this._keypadContainer.parentNode) {
44660
- // Note ChildNode.remove() isn't available in older Android
44661
- // webviews.
44662
- _this._keypadContainer.parentNode.removeChild(_this._keypadContainer);
44663
- }
44664
- _this._keypadContainer = null;
44665
- }
44666
- },
44667
- keypadElement() {
44668
- const _this = this;
44669
- return _this.state.keypadElement;
44670
- }
44671
- };
44672
-
44673
- const {
44674
- mapObject: mapObject$1
44675
- } = objective_;
44676
- /**
44677
- * @depreciated use ServerItemRenderer
44678
- */
44679
- class ItemRenderer extends React.Component {
44680
- constructor(props) {
44681
- super(props);
44682
- // @ts-expect-error - TS2564 - Property 'questionRenderer' has no initializer and is not definitely assigned in the constructor.
44683
- this.questionRenderer = void 0;
44684
- this.hintsRenderer = void 0;
44685
- this._currentFocus = void 0;
44686
- this._handleFocusChange = (newFocus, oldFocus) => {
44687
- if (newFocus != null) {
44688
- this._setCurrentFocus(newFocus);
44689
- } else {
44690
- this._onRendererBlur(oldFocus);
44691
- }
44692
- };
44693
- // NOTE: this must remain as an arrow function because we pass it Renderer
44694
- this.handleInteractWithWidget = widgetId => {
44695
- const withRemoved = _.difference(this.state.questionHighlightedWidgets, [widgetId]);
44696
- this.setState({
44697
- questionCompleted: false,
44698
- questionHighlightedWidgets: withRemoved
44699
- });
44700
- if (this.props.apiOptions.interactionCallback) {
44701
- this.props.apiOptions.interactionCallback();
44702
- }
44703
- };
44704
- this.state = _extends({}, ProvideKeypad.getInitialState.call(this), {
44705
- hintsVisible: props.initialHintsVisible || 0,
44706
- questionCompleted: false,
44707
- questionHighlightedWidgets: []
44708
- });
44709
- }
44710
- componentDidMount() {
44711
- ProvideKeypad.componentDidMount.call(this);
44712
- if (this.props.controlPeripherals && this.props.apiOptions.setDrawingAreaAvailable) {
44713
- this.props.apiOptions.setDrawingAreaAvailable(true);
44714
- }
44715
- this._currentFocus = null;
44716
- this.update();
44717
- }
44718
- UNSAFE_componentWillReceiveProps(nextProps) {
44719
- this.setState({
44720
- questionHighlightedWidgets: []
44721
- });
44722
- }
44723
- componentDidUpdate() {
44724
- this.update();
44725
- }
44726
- componentWillUnmount() {
44727
- ProvideKeypad.componentWillUnmount.call(this);
44728
- const workArea = document.querySelector(this.props.workAreaSelector);
44729
- if (workArea != null) {
44730
- ReactDOM.unmountComponentAtNode(workArea);
44731
- }
44732
- const hintsArea = document.querySelector(this.props.hintsAreaSelector);
44733
- if (hintsArea != null) {
44734
- ReactDOM.unmountComponentAtNode(hintsArea);
44735
- }
44736
- if (this.props.controlPeripherals) {
44737
- const answerArea = this.props.item.answerArea || {};
44738
- if (answerArea.calculator) {
44739
- $("#calculator").hide();
44740
- }
44741
- if (answerArea.periodicTable) {
44742
- $(".periodic-table-info-box").hide();
44743
- }
44744
- if (answerArea.zTable) {
44745
- $(".z-table-info-box").hide();
44746
- }
44747
- if (answerArea.tTable) {
44748
- $(".t-table-info-box").hide();
44749
- }
44750
- if (answerArea.chi2Table) {
44751
- $(".chi2-table-info-box").hide();
44752
- }
44753
- }
44754
- }
44755
- keypadElement() {
44756
- return ProvideKeypad.keypadElement.call(this);
44757
- }
44758
- update() {
44759
- const apiOptions = _extends({}, ApiOptions.defaults, this.props.apiOptions, {
44760
- onFocusChange: this._handleFocusChange
44761
- });
44762
- const workArea = document.querySelector(this.props.workAreaSelector);
44763
- const hintsArea = document.querySelector(this.props.hintsAreaSelector);
44764
- if (!workArea || !hintsArea) {
44765
- return;
44766
- }
44767
-
44768
- // Since the item renderer works by rendering things into three divs
44769
- // that have completely different places in the DOM, we have to do this
44770
- // strangeness instead of relying on React's normal render() method.
44771
- // TODO(alpert): Figure out how to clean this up somehow
44772
- render( /*#__PURE__*/React.createElement(DependenciesContext.Provider, {
44773
- value: this.props.dependencies
44774
- }, /*#__PURE__*/React.createElement(Renderer, _extends({
44775
- ref: node => {
44776
- if (!node) {
44777
- return;
44778
- }
44779
- this.questionRenderer = node;
44780
-
44781
- // NOTE(jeremy): Why don't we just pass this into the
44782
- // renderer as a prop?
44783
- const {
44784
- answerableCallback
44785
- } = apiOptions;
44786
- if (answerableCallback) {
44787
- const isAnswerable = this.questionRenderer.emptyWidgets().length === 0;
44788
- answerableCallback(isAnswerable);
44789
- }
44790
- },
44791
- keypadElement: this.keypadElement(),
44792
- problemNum: this.props.problemNum,
44793
- onInteractWithWidget: this.handleInteractWithWidget,
44794
- highlightedWidgets: this.state.questionHighlightedWidgets,
44795
- apiOptions: apiOptions,
44796
- questionCompleted: this.state.questionCompleted,
44797
- reviewMode: this.props.reviewMode,
44798
- savedState: this.props.savedState,
44799
- linterContext: PerseusLinter.pushContextStack(this.props.linterContext, "question")
44800
- }, this.props.item.question, {
44801
- legacyPerseusLint: this.props.legacyPerseusLint
44802
- }))),
44803
- // @ts-expect-error - TS2345 - Argument of type 'Element' is not assignable to parameter of type 'HTMLElement'.
44804
- workArea);
44805
- render( /*#__PURE__*/React.createElement(DependenciesContext.Provider, {
44806
- value: this.props.dependencies
44807
- }, /*#__PURE__*/React.createElement(HintsRenderer, {
44808
- ref: node => this.hintsRenderer = node,
44809
- hints: this.props.item.hints,
44810
- hintsVisible: this.state.hintsVisible,
44811
- apiOptions: apiOptions,
44812
- linterContext: PerseusLinter.pushContextStack(this.props.linterContext, "hints")
44813
- })),
44814
- // @ts-expect-error - TS2345 - Argument of type 'Element' is not assignable to parameter of type 'HTMLElement'.
44815
- hintsArea);
44816
- const answerArea = this.props.item.answerArea || {};
44817
- if (this.props.controlPeripherals) {
44818
- $("#calculator").toggle(answerArea.calculator || false);
44819
- $(".periodic-table-info-box").toggle(answerArea.periodicTable || false);
44820
- $(".z-table-info-box").toggle(answerArea.zTable || false);
44821
- $(".t-table-info-box").toggle(answerArea.tTable || false);
44822
- $(".chi2-table-info-box").toggle(answerArea.chi2Table || false);
44823
- } else {
44824
- if (answerArea.calculator) {
44825
- this.props.onShowCalculator && this.props.onShowCalculator();
44826
- }
44827
- if (answerArea.periodicTable) {
44828
- this.props.onShowPeriodicTable && this.props.onShowPeriodicTable({
44829
- showKey: answerArea.periodicTableWithKey
44830
- });
44831
- }
44832
- if (answerArea.zTable) {
44833
- this.props.onShowZTable && this.props.onShowZTable();
44834
- }
44835
- if (answerArea.tTable) {
44836
- this.props.onShowTTable && this.props.onShowTTable();
44837
- }
44838
- if (answerArea.chi2Table) {
44839
- this.props.onShowChi2Table && this.props.onShowChi2Table();
44840
- }
44841
- }
44842
- }
44843
- // Sets the current focus path and element and send an onChangeFocus event
44844
- // back to our parent.
44845
- _setCurrentFocus(newFocus) {
44846
- const keypadElement = this.keypadElement();
44847
- // By the time this happens, newFocus cannot be a prefix of
44848
- // prevFocused, since we must have either been called from
44849
- // an onFocusChange within a renderer, which is only called when
44850
- // this is not a prefix, or between the question and answer areas,
44851
- // which can never prefix each other.
44852
- const prevFocus = this._currentFocus;
44853
- this._currentFocus = newFocus;
44854
-
44855
- // Determine whether the newly focused path represents an input.
44856
- const inputPaths = this.getInputPaths();
44857
- const didFocusInput = this._currentFocus && inputPaths.some(inputPath => {
44858
- return Util.inputPathsEqual(inputPath, this._currentFocus);
44859
- });
44860
- if (this.props.apiOptions.onFocusChange != null) {
44861
- this.props.apiOptions.onFocusChange(this._currentFocus, prevFocus, didFocusInput && keypadElement && keypadElement.getDOMNode());
44862
- }
44863
- if (keypadElement) {
44864
- if (didFocusInput) {
44865
- keypadElement.activate();
44866
- } else {
44867
- keypadElement.dismiss();
44868
- }
44869
- }
44870
- }
44871
- _onRendererBlur(blurPath) {
44872
- const blurringFocusPath = this._currentFocus;
44873
-
44874
- // Failsafe: abort if ID is different, because focus probably happened
44875
- // before blur.
44876
- if (!Util.inputPathsEqual(blurPath, blurringFocusPath)) {
44877
- return;
44878
- }
44879
-
44880
- // Wait until after any new focus events fire this tick before
44881
- // declaring that nothing is focused, since if there were a focus change
44882
- // across Renderers (e.g., from the HintsRenderer to the
44883
- // QuestionRenderer), we could receive the blur before the focus.
44884
- // TODO(jeff, CP-3128): Use Wonder Blocks Timing API
44885
- // eslint-disable-next-line no-restricted-syntax
44886
- setTimeout(() => {
44887
- if (Util.inputPathsEqual(this._currentFocus, blurringFocusPath)) {
44888
- this._setCurrentFocus(null);
44889
- }
44890
- });
44891
- }
44892
-
44893
- /**
44894
- * Accepts a question area widgetId, or an answer area widgetId of
44895
- * the form "answer-input-number 1", or the string "answer-area"
44896
- * for the whole answer area (if the answer area is a single widget).
44897
- */
44898
- _setWidgetProps(widgetId, newProps, callback) {
44899
- this.questionRenderer._setWidgetProps(widgetId, newProps, callback);
44900
- }
44901
-
44902
- /**
44903
- * Sets the input value into the widget found at `path`. The `focus`
44904
- * function provided is called when all affected widgets have been
44905
- * re-rendered with the new value.
44906
- */
44907
- setInputValue(path, newValue, focus) {
44908
- return this.questionRenderer.setInputValue(path, newValue, focus);
44909
- }
44910
- focusPath(path) {
44911
- return this.questionRenderer.focusPath(path);
44912
- }
44913
- blurPath(path) {
44914
- return this.questionRenderer.blurPath(path);
44915
- }
44916
- getDOMNodeForPath(path) {
44917
- return this.questionRenderer.getDOMNodeForPath(path);
44918
- }
44919
- getGrammarTypeForPath(path) {
44920
- return this.questionRenderer.getGrammarTypeForPath(path);
44921
- }
44922
- getInputPaths() {
44923
- const questionAreaInputPaths = this.questionRenderer.getInputPaths();
44924
- return questionAreaInputPaths;
44925
- }
44926
- focus() {
44927
- return this.questionRenderer.focus();
44928
- }
44929
- blur() {
44930
- if (this._currentFocus) {
44931
- this.blurPath(this._currentFocus);
44932
- }
44933
- }
44934
- showHint() {
44935
- if (this.state.hintsVisible < this.getNumHints()) {
44936
- this.setState({
44937
- hintsVisible: this.state.hintsVisible + 1
44938
- });
44939
- }
44940
- }
44941
- getNumHints() {
44942
- return this.props.item.hints.length;
44943
- }
44944
-
44945
- /**
44946
- * Grades the item.
44947
- *
44948
- * Returns a KE-style score of {
44949
- * empty: bool,
44950
- * correct: bool,
44951
- * message: string|null,
44952
- * guess: Array
44953
- * }
44954
- */
44955
- scoreInput() {
44956
- const guessAndScore = this.questionRenderer.guessAndScore();
44957
- const guess = guessAndScore[0];
44958
- const score = guessAndScore[1];
44959
-
44960
- // Continue to include an empty guess for the now defunct answer area.
44961
- // TODO(alex): Check whether we rely on the format here for
44962
- // analyzing ProblemLogs. If not, remove this layer.
44963
- const maxCompatGuess = [guess, []];
44964
- const keScore = Util.keScoreFromPerseusScore(score, maxCompatGuess, this.questionRenderer.getSerializedState());
44965
- const emptyQuestionAreaWidgets = this.questionRenderer.emptyWidgets();
44966
- this.setState({
44967
- questionCompleted: keScore.correct,
44968
- questionHighlightedWidgets: emptyQuestionAreaWidgets
44969
- });
44970
- return keScore;
44971
- }
44972
-
44973
- /**
44974
- * Returns an array of all widget IDs in the order they occur in
44975
- * the question content.
44976
- */
44977
- getWidgetIds() {
44978
- return this.questionRenderer.getWidgetIds();
44979
- }
44980
-
44981
- /**
44982
- * Returns an object mapping from widget ID to KE-style score.
44983
- * The keys of this object are the values of the array returned
44984
- * from `getWidgetIds`.
44985
- */
44986
- scoreWidgets() {
44987
- const qScore = this.questionRenderer.scoreWidgets();
44988
- const qGuess = this.questionRenderer.getUserInputForWidgets();
44989
- const state = this.questionRenderer.getSerializedState();
44990
- // @ts-expect-error - TS2322 - Type 'Partial<Record<string, KEScore>>' is not assignable to type '{ [id: string]: KEScore; }'. | TS2345 - Argument of type '{ [widgetId: string]: PerseusScore; }' is not assignable to parameter of type 'Partial<Record<string, { type: "invalid"; message?: string | null | undefined; suppressAlmostThere?: boolean | null | undefined; }>>'.
44991
- return mapObject$1(qScore, (score, id) => {
44992
- return Util.keScoreFromPerseusScore(score, qGuess[id], state[id]);
44993
- });
44994
- }
44995
-
44996
- /**
44997
- * Get a representation of the current state of the item.
44998
- */
44999
- getSerializedState() {
45000
- var _this$hintsRenderer;
45001
- return {
45002
- question: this.questionRenderer.getSerializedState(),
45003
- hints: (_this$hintsRenderer = this.hintsRenderer) == null ? void 0 : _this$hintsRenderer.getSerializedState()
45004
- };
45005
- }
45006
-
45007
- // TODO(kevinb): make the type for this state better
45008
- restoreSerializedState(state, callback) {
45009
- var _this$hintsRenderer2;
45010
- // We need to wait for both the question renderer and the hints
45011
- // renderer to finish restoring their states.
45012
- let numCallbacks = 2;
45013
- const fireCallback = () => {
45014
- --numCallbacks;
45015
- if (callback && numCallbacks === 0) {
45016
- callback();
45017
- }
45018
- };
45019
- this.questionRenderer.restoreSerializedState(state.question, fireCallback);
45020
- (_this$hintsRenderer2 = this.hintsRenderer) == null || _this$hintsRenderer2.restoreSerializedState(state.hints, fireCallback);
45021
- }
45022
- showRationalesForCurrentlySelectedChoices() {
45023
- this.questionRenderer.showRationalesForCurrentlySelectedChoices();
45024
- }
45025
- deselectIncorrectSelectedChoices() {
45026
- this.questionRenderer.deselectIncorrectSelectedChoices();
45027
- }
45028
- render() {
45029
- return /*#__PURE__*/React.createElement(DependenciesContext.Provider, {
45030
- value: this.props.dependencies
45031
- }, /*#__PURE__*/React.createElement("div", null));
45032
- }
45033
- }
45034
- ItemRenderer.defaultProps = {
45035
- apiOptions: ApiOptions.defaults,
45036
- // defaults are set in `this.update()`
45037
- controlPeripherals: true,
45038
- hintsAreaSelector: "#hintsarea",
45039
- initialHintsVisible: 0,
45040
- workAreaSelector: "#workarea",
45041
- reviewMode: false,
45042
- linterContext: PerseusLinter.linterContextDefault
45043
- };
45044
-
45045
44591
  /**
45046
44592
  * A React context for signaling when all of the components in a Perseus
45047
44593
  * renderer is fully rendered. This means that all images and math have
@@ -45107,6 +44653,8 @@ class ServerItemRenderer extends React.Component {
45107
44653
  this._currentFocus = null;
45108
44654
  this._fullyRendered = false;
45109
44655
  }
44656
+
44657
+ // eslint-disable-next-line react/no-unsafe
45110
44658
  UNSAFE_componentWillReceiveProps(nextProps) {
45111
44659
  this.setState({
45112
44660
  questionHighlightedWidgets: []
@@ -47313,5 +46861,5 @@ const EditorJsonify = {
47313
46861
  }
47314
46862
  };
47315
46863
 
47316
- export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Errors, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemRenderer, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusError, PerseusExpressionAnswerFormConsidered, PerseusMarkdown, Plotter$1 as PlotterWidget, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Transformer$1 as TransformerWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, displaySigFigs, globalConstants, globalStyles, iconPaths as icons, init, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, mediaQueries, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, traverse, violatingWidgets, allWidgets as widgets };
46864
+ export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Errors, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusError, PerseusExpressionAnswerFormConsidered, PerseusMarkdown, Plotter$1 as PlotterWidget, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Transformer$1 as TransformerWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, displaySigFigs, globalConstants, globalStyles, iconPaths as icons, init, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, mediaQueries, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, traverse, violatingWidgets, allWidgets as widgets };
47317
46865
  //# sourceMappingURL=index.js.map