@khanacademy/perseus 16.0.0 → 17.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/dist/index.js CHANGED
@@ -10260,7 +10260,7 @@ const pluck = function (table, subKey) {
10260
10260
  * });
10261
10261
  * {a: 2, b: 3}
10262
10262
  */
10263
- const mapObject$3 = function (obj, lambda) {
10263
+ const mapObject$2 = function (obj, lambda) {
10264
10264
  const result = {};
10265
10265
  ___default["default"].each(___default["default"].keys(obj), function (key) {
10266
10266
  // @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'K'.
@@ -10286,7 +10286,7 @@ const mapObjectFromArray$1 = function (arr, lambda) {
10286
10286
  };
10287
10287
  var objective_ = {
10288
10288
  pluck: pluck,
10289
- mapObject: mapObject$3,
10289
+ mapObject: mapObject$2,
10290
10290
  mapObjectFromArray: mapObjectFromArray$1
10291
10291
  };
10292
10292
 
@@ -18932,7 +18932,7 @@ class WidgetContainer extends React__namespace.Component {
18932
18932
  }
18933
18933
 
18934
18934
  const {
18935
- mapObject: mapObject$2,
18935
+ mapObject: mapObject$1,
18936
18936
  mapObjectFromArray
18937
18937
  } = objective_;
18938
18938
  const rContainsNonWhitespace = /\S/;
@@ -19159,7 +19159,7 @@ class Renderer extends React__namespace.Component {
19159
19159
  // @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; }'.
19160
19160
  _getAllWidgetsInfo = props => {
19161
19161
  // @ts-expect-error - TS2345 - Argument of type '{ [key: string]: PerseusWidget; }' is not assignable to parameter of type 'Partial<Record<string, CategorizerWidget>>'.
19162
- return mapObject$2(props.widgets, (widgetInfo, widgetId) => {
19162
+ return mapObject$1(props.widgets, (widgetInfo, widgetId) => {
19163
19163
  if (!widgetInfo.type || !widgetInfo.alignment) {
19164
19164
  const newValues = {};
19165
19165
  if (!widgetInfo.type) {
@@ -19175,7 +19175,7 @@ class Renderer extends React__namespace.Component {
19175
19175
  };
19176
19176
  _getAllWidgetsStartProps = (allWidgetInfo, props) => {
19177
19177
  // @ts-expect-error - TS2345 - Argument of type '{ [key: string]: PerseusWidget; }' is not assignable to parameter of type 'Partial<Record<string, CategorizerWidget>>'.
19178
- return mapObject$2(allWidgetInfo, widgetInfo => {
19178
+ return mapObject$1(allWidgetInfo, widgetInfo => {
19179
19179
  return getRendererPropsForWidgetInfo(widgetInfo, props.problemNum);
19180
19180
  });
19181
19181
  };
@@ -19295,7 +19295,7 @@ class Renderer extends React__namespace.Component {
19295
19295
  * state from that instead of the current widget props.
19296
19296
  */
19297
19297
  getSerializedState = widgetProps => {
19298
- return mapObject$2(widgetProps || this.state.widgetProps, (props, widgetId) => {
19298
+ return mapObject$1(widgetProps || this.state.widgetProps, (props, widgetId) => {
19299
19299
  const widget = this.getWidgetInstance(widgetId);
19300
19300
  if (widget && widget.getSerializedState) {
19301
19301
  return widget.getSerializedState();
@@ -19331,7 +19331,7 @@ class Renderer extends React__namespace.Component {
19331
19331
  }
19332
19332
  };
19333
19333
  this.setState({
19334
- widgetProps: mapObject$2(serializedState, (props, widgetId) => {
19334
+ widgetProps: mapObject$1(serializedState, (props, widgetId) => {
19335
19335
  const widget = this.getWidgetInstance(widgetId);
19336
19336
  if (widget && widget.restoreSerializedState) {
19337
19337
  // Note that we probably can't call
@@ -44216,7 +44216,7 @@ const init = function (options) {
44216
44216
 
44217
44217
  // This file is processed by a Rollup plugin (replace) to inject the production
44218
44218
  const libName = "@khanacademy/perseus";
44219
- const libVersion = "16.0.0";
44219
+ const libVersion = "17.0.0";
44220
44220
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
44221
44221
 
44222
44222
  const apiVersion = {
@@ -44726,454 +44726,6 @@ const styles$4 = aphrodite.StyleSheet.create({
44726
44726
  }
44727
44727
  });
44728
44728
 
44729
- /* eslint-disable @khanacademy/ts-no-error-suppressions */
44730
-
44731
- // This represents the shape of any component that uses this ProvideKeypad
44732
- // mixin.
44733
- // NOTE: This is not a real component. It's a collection of methods used to
44734
- // create and manage a Keypad instances.
44735
- // TODO(LP-10789): replace this with a React Context object to pass information
44736
- // between Perseus and the Keypad.
44737
- const ProvideKeypad = {
44738
- getInitialState() {
44739
- const _this = this;
44740
- let keypadElement = null;
44741
- if (_this.props.apiOptions && _this.props.apiOptions.customKeypad && _this.props.apiOptions.nativeKeypadProxy) {
44742
- keypadElement = _this.props.apiOptions.nativeKeypadProxy(
44743
- // @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...'.
44744
- () => _this.blur && _this.blur());
44745
- }
44746
- return {
44747
- keypadElement
44748
- };
44749
- },
44750
- componentDidMount() {
44751
- const _this = this;
44752
- const apiOptions = _this.props.apiOptions;
44753
- if (apiOptions && apiOptions.customKeypad && !apiOptions.nativeKeypadProxy) {
44754
- // TODO(charlie): Render this and the wrapped component in the same
44755
- // React tree. We may also want to add this keypad asynchronously
44756
- // or on-demand in the future.
44757
- _this._keypadContainer = document.createElement("div");
44758
- document.body?.appendChild(_this._keypadContainer);
44759
- render( /*#__PURE__*/React__namespace.createElement(mathInput.MobileKeypad, {
44760
- onElementMounted: element => {
44761
- // NOTE(kevinb): The reason why this setState works is
44762
- // b/c we're calling it manually from item-renderer.jsx
44763
- // and we're manually setting the 'this' by using 'call'
44764
- // @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...'.
44765
- _this.setState({
44766
- keypadElement: element
44767
- });
44768
- },
44769
- onDismiss: () => {
44770
- // @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...'.
44771
- _this.blur && _this.blur();
44772
- }
44773
- // @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...'.
44774
- ,
44775
- style: _this.props.keypadStyle,
44776
- onAnalyticsEvent: async () => {
44777
- // Intentionally left empty. This component is
44778
- // deprecated and so we don't want/need to instrument
44779
- // it.
44780
- }
44781
- }), _this._keypadContainer);
44782
- }
44783
- },
44784
- componentWillUnmount() {
44785
- const _this = this;
44786
- if (_this._keypadContainer) {
44787
- ReactDOM__default["default"].unmountComponentAtNode(_this._keypadContainer);
44788
- if (_this._keypadContainer.parentNode) {
44789
- // Note ChildNode.remove() isn't available in older Android
44790
- // webviews.
44791
- _this._keypadContainer.parentNode.removeChild(_this._keypadContainer);
44792
- }
44793
- _this._keypadContainer = null;
44794
- }
44795
- },
44796
- keypadElement() {
44797
- const _this = this;
44798
- return _this.state.keypadElement;
44799
- }
44800
- };
44801
-
44802
- const {
44803
- mapObject: mapObject$1
44804
- } = objective_;
44805
- /**
44806
- * @depreciated use ServerItemRenderer
44807
- */
44808
- class ItemRenderer extends React__namespace.Component {
44809
- // @ts-expect-error - TS2564 - Property 'questionRenderer' has no initializer and is not definitely assigned in the constructor.
44810
-
44811
- static defaultProps = {
44812
- apiOptions: ApiOptions.defaults,
44813
- // defaults are set in `this.update()`
44814
- controlPeripherals: true,
44815
- hintsAreaSelector: "#hintsarea",
44816
- initialHintsVisible: 0,
44817
- workAreaSelector: "#workarea",
44818
- reviewMode: false,
44819
- linterContext: PerseusLinter__namespace.linterContextDefault
44820
- };
44821
- constructor(props) {
44822
- super(props);
44823
- this.state = {
44824
- // NOTE: This value is used in provide-keypad.jsx which contains a
44825
- // "mixin" that this file calls methods on.
44826
- ...ProvideKeypad.getInitialState.call(this),
44827
- hintsVisible: props.initialHintsVisible || 0,
44828
- questionCompleted: false,
44829
- questionHighlightedWidgets: []
44830
- };
44831
- }
44832
- componentDidMount() {
44833
- ProvideKeypad.componentDidMount.call(this);
44834
- if (this.props.controlPeripherals && this.props.apiOptions.setDrawingAreaAvailable) {
44835
- this.props.apiOptions.setDrawingAreaAvailable(true);
44836
- }
44837
- this._currentFocus = null;
44838
- this.update();
44839
- }
44840
- UNSAFE_componentWillReceiveProps(nextProps) {
44841
- this.setState({
44842
- questionHighlightedWidgets: []
44843
- });
44844
- }
44845
- componentDidUpdate() {
44846
- this.update();
44847
- }
44848
- componentWillUnmount() {
44849
- ProvideKeypad.componentWillUnmount.call(this);
44850
- const workArea = document.querySelector(this.props.workAreaSelector);
44851
- if (workArea != null) {
44852
- ReactDOM__namespace.unmountComponentAtNode(workArea);
44853
- }
44854
- const hintsArea = document.querySelector(this.props.hintsAreaSelector);
44855
- if (hintsArea != null) {
44856
- ReactDOM__namespace.unmountComponentAtNode(hintsArea);
44857
- }
44858
- if (this.props.controlPeripherals) {
44859
- const answerArea = this.props.item.answerArea || {};
44860
- if (answerArea.calculator) {
44861
- $__default["default"]("#calculator").hide();
44862
- }
44863
- if (answerArea.periodicTable) {
44864
- $__default["default"](".periodic-table-info-box").hide();
44865
- }
44866
- if (answerArea.zTable) {
44867
- $__default["default"](".z-table-info-box").hide();
44868
- }
44869
- if (answerArea.tTable) {
44870
- $__default["default"](".t-table-info-box").hide();
44871
- }
44872
- if (answerArea.chi2Table) {
44873
- $__default["default"](".chi2-table-info-box").hide();
44874
- }
44875
- }
44876
- }
44877
- keypadElement() {
44878
- return ProvideKeypad.keypadElement.call(this);
44879
- }
44880
- update() {
44881
- const apiOptions = {
44882
- ...ApiOptions.defaults,
44883
- ...this.props.apiOptions,
44884
- onFocusChange: this._handleFocusChange
44885
- };
44886
- const workArea = document.querySelector(this.props.workAreaSelector);
44887
- const hintsArea = document.querySelector(this.props.hintsAreaSelector);
44888
- if (!workArea || !hintsArea) {
44889
- return;
44890
- }
44891
-
44892
- // Since the item renderer works by rendering things into three divs
44893
- // that have completely different places in the DOM, we have to do this
44894
- // strangeness instead of relying on React's normal render() method.
44895
- // TODO(alpert): Figure out how to clean this up somehow
44896
- render( /*#__PURE__*/React__namespace.createElement(DependenciesContext.Provider, {
44897
- value: this.props.dependencies
44898
- }, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({
44899
- ref: node => {
44900
- if (!node) {
44901
- return;
44902
- }
44903
- this.questionRenderer = node;
44904
-
44905
- // NOTE(jeremy): Why don't we just pass this into the
44906
- // renderer as a prop?
44907
- const {
44908
- answerableCallback
44909
- } = apiOptions;
44910
- if (answerableCallback) {
44911
- const isAnswerable = this.questionRenderer.emptyWidgets().length === 0;
44912
- answerableCallback(isAnswerable);
44913
- }
44914
- },
44915
- keypadElement: this.keypadElement(),
44916
- problemNum: this.props.problemNum,
44917
- onInteractWithWidget: this.handleInteractWithWidget,
44918
- highlightedWidgets: this.state.questionHighlightedWidgets,
44919
- apiOptions: apiOptions,
44920
- questionCompleted: this.state.questionCompleted,
44921
- reviewMode: this.props.reviewMode,
44922
- savedState: this.props.savedState,
44923
- linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "question")
44924
- }, this.props.item.question, {
44925
- legacyPerseusLint: this.props.legacyPerseusLint
44926
- }))),
44927
- // @ts-expect-error - TS2345 - Argument of type 'Element' is not assignable to parameter of type 'HTMLElement'.
44928
- workArea);
44929
- render( /*#__PURE__*/React__namespace.createElement(DependenciesContext.Provider, {
44930
- value: this.props.dependencies
44931
- }, /*#__PURE__*/React__namespace.createElement(HintsRenderer, {
44932
- ref: node => this.hintsRenderer = node,
44933
- hints: this.props.item.hints,
44934
- hintsVisible: this.state.hintsVisible,
44935
- apiOptions: apiOptions,
44936
- linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "hints")
44937
- })),
44938
- // @ts-expect-error - TS2345 - Argument of type 'Element' is not assignable to parameter of type 'HTMLElement'.
44939
- hintsArea);
44940
- const answerArea = this.props.item.answerArea || {};
44941
- if (this.props.controlPeripherals) {
44942
- $__default["default"]("#calculator").toggle(answerArea.calculator || false);
44943
- $__default["default"](".periodic-table-info-box").toggle(answerArea.periodicTable || false);
44944
- $__default["default"](".z-table-info-box").toggle(answerArea.zTable || false);
44945
- $__default["default"](".t-table-info-box").toggle(answerArea.tTable || false);
44946
- $__default["default"](".chi2-table-info-box").toggle(answerArea.chi2Table || false);
44947
- } else {
44948
- if (answerArea.calculator) {
44949
- this.props.onShowCalculator && this.props.onShowCalculator();
44950
- }
44951
- if (answerArea.periodicTable) {
44952
- this.props.onShowPeriodicTable && this.props.onShowPeriodicTable({
44953
- showKey: answerArea.periodicTableWithKey
44954
- });
44955
- }
44956
- if (answerArea.zTable) {
44957
- this.props.onShowZTable && this.props.onShowZTable();
44958
- }
44959
- if (answerArea.tTable) {
44960
- this.props.onShowTTable && this.props.onShowTTable();
44961
- }
44962
- if (answerArea.chi2Table) {
44963
- this.props.onShowChi2Table && this.props.onShowChi2Table();
44964
- }
44965
- }
44966
- }
44967
- _handleFocusChange = (newFocus, oldFocus) => {
44968
- if (newFocus != null) {
44969
- this._setCurrentFocus(newFocus);
44970
- } else {
44971
- this._onRendererBlur(oldFocus);
44972
- }
44973
- };
44974
-
44975
- // Sets the current focus path and element and send an onChangeFocus event
44976
- // back to our parent.
44977
- _setCurrentFocus(newFocus) {
44978
- const keypadElement = this.keypadElement();
44979
- // By the time this happens, newFocus cannot be a prefix of
44980
- // prevFocused, since we must have either been called from
44981
- // an onFocusChange within a renderer, which is only called when
44982
- // this is not a prefix, or between the question and answer areas,
44983
- // which can never prefix each other.
44984
- const prevFocus = this._currentFocus;
44985
- this._currentFocus = newFocus;
44986
-
44987
- // Determine whether the newly focused path represents an input.
44988
- const inputPaths = this.getInputPaths();
44989
- const didFocusInput = this._currentFocus && inputPaths.some(inputPath => {
44990
- return Util.inputPathsEqual(inputPath, this._currentFocus);
44991
- });
44992
- if (this.props.apiOptions.onFocusChange != null) {
44993
- this.props.apiOptions.onFocusChange(this._currentFocus, prevFocus, didFocusInput && keypadElement && keypadElement.getDOMNode());
44994
- }
44995
- if (keypadElement) {
44996
- if (didFocusInput) {
44997
- keypadElement.activate();
44998
- } else {
44999
- keypadElement.dismiss();
45000
- }
45001
- }
45002
- }
45003
- _onRendererBlur(blurPath) {
45004
- const blurringFocusPath = this._currentFocus;
45005
-
45006
- // Failsafe: abort if ID is different, because focus probably happened
45007
- // before blur.
45008
- if (!Util.inputPathsEqual(blurPath, blurringFocusPath)) {
45009
- return;
45010
- }
45011
-
45012
- // Wait until after any new focus events fire this tick before
45013
- // declaring that nothing is focused, since if there were a focus change
45014
- // across Renderers (e.g., from the HintsRenderer to the
45015
- // QuestionRenderer), we could receive the blur before the focus.
45016
- // TODO(jeff, CP-3128): Use Wonder Blocks Timing API
45017
- // eslint-disable-next-line no-restricted-syntax
45018
- setTimeout(() => {
45019
- if (Util.inputPathsEqual(this._currentFocus, blurringFocusPath)) {
45020
- this._setCurrentFocus(null);
45021
- }
45022
- });
45023
- }
45024
-
45025
- /**
45026
- * Accepts a question area widgetId, or an answer area widgetId of
45027
- * the form "answer-input-number 1", or the string "answer-area"
45028
- * for the whole answer area (if the answer area is a single widget).
45029
- */
45030
- _setWidgetProps(widgetId, newProps, callback) {
45031
- this.questionRenderer._setWidgetProps(widgetId, newProps, callback);
45032
- }
45033
-
45034
- /**
45035
- * Sets the input value into the widget found at `path`. The `focus`
45036
- * function provided is called when all affected widgets have been
45037
- * re-rendered with the new value.
45038
- */
45039
- setInputValue(path, newValue, focus) {
45040
- return this.questionRenderer.setInputValue(path, newValue, focus);
45041
- }
45042
- focusPath(path) {
45043
- return this.questionRenderer.focusPath(path);
45044
- }
45045
- blurPath(path) {
45046
- return this.questionRenderer.blurPath(path);
45047
- }
45048
- getDOMNodeForPath(path) {
45049
- return this.questionRenderer.getDOMNodeForPath(path);
45050
- }
45051
- getGrammarTypeForPath(path) {
45052
- return this.questionRenderer.getGrammarTypeForPath(path);
45053
- }
45054
- getInputPaths() {
45055
- const questionAreaInputPaths = this.questionRenderer.getInputPaths();
45056
- return questionAreaInputPaths;
45057
- }
45058
-
45059
- // NOTE: this must remain as an arrow function because we pass it Renderer
45060
- handleInteractWithWidget = widgetId => {
45061
- const withRemoved = ___default["default"].difference(this.state.questionHighlightedWidgets, [widgetId]);
45062
- this.setState({
45063
- questionCompleted: false,
45064
- questionHighlightedWidgets: withRemoved
45065
- });
45066
- if (this.props.apiOptions.interactionCallback) {
45067
- this.props.apiOptions.interactionCallback();
45068
- }
45069
- };
45070
- focus() {
45071
- return this.questionRenderer.focus();
45072
- }
45073
- blur() {
45074
- if (this._currentFocus) {
45075
- this.blurPath(this._currentFocus);
45076
- }
45077
- }
45078
- showHint() {
45079
- if (this.state.hintsVisible < this.getNumHints()) {
45080
- this.setState({
45081
- hintsVisible: this.state.hintsVisible + 1
45082
- });
45083
- }
45084
- }
45085
- getNumHints() {
45086
- return this.props.item.hints.length;
45087
- }
45088
-
45089
- /**
45090
- * Grades the item.
45091
- *
45092
- * Returns a KE-style score of {
45093
- * empty: bool,
45094
- * correct: bool,
45095
- * message: string|null,
45096
- * guess: Array
45097
- * }
45098
- */
45099
- scoreInput() {
45100
- const guessAndScore = this.questionRenderer.guessAndScore();
45101
- const guess = guessAndScore[0];
45102
- const score = guessAndScore[1];
45103
-
45104
- // Continue to include an empty guess for the now defunct answer area.
45105
- // TODO(alex): Check whether we rely on the format here for
45106
- // analyzing ProblemLogs. If not, remove this layer.
45107
- const maxCompatGuess = [guess, []];
45108
- const keScore = Util.keScoreFromPerseusScore(score, maxCompatGuess, this.questionRenderer.getSerializedState());
45109
- const emptyQuestionAreaWidgets = this.questionRenderer.emptyWidgets();
45110
- this.setState({
45111
- questionCompleted: keScore.correct,
45112
- questionHighlightedWidgets: emptyQuestionAreaWidgets
45113
- });
45114
- return keScore;
45115
- }
45116
-
45117
- /**
45118
- * Returns an array of all widget IDs in the order they occur in
45119
- * the question content.
45120
- */
45121
- getWidgetIds() {
45122
- return this.questionRenderer.getWidgetIds();
45123
- }
45124
-
45125
- /**
45126
- * Returns an object mapping from widget ID to KE-style score.
45127
- * The keys of this object are the values of the array returned
45128
- * from `getWidgetIds`.
45129
- */
45130
- scoreWidgets() {
45131
- const qScore = this.questionRenderer.scoreWidgets();
45132
- const qGuess = this.questionRenderer.getUserInputForWidgets();
45133
- const state = this.questionRenderer.getSerializedState();
45134
- // @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; }>>'.
45135
- return mapObject$1(qScore, (score, id) => {
45136
- return Util.keScoreFromPerseusScore(score, qGuess[id], state[id]);
45137
- });
45138
- }
45139
-
45140
- /**
45141
- * Get a representation of the current state of the item.
45142
- */
45143
- getSerializedState() {
45144
- return {
45145
- question: this.questionRenderer.getSerializedState(),
45146
- hints: this.hintsRenderer?.getSerializedState()
45147
- };
45148
- }
45149
-
45150
- // TODO(kevinb): make the type for this state better
45151
- restoreSerializedState(state, callback) {
45152
- // We need to wait for both the question renderer and the hints
45153
- // renderer to finish restoring their states.
45154
- let numCallbacks = 2;
45155
- const fireCallback = () => {
45156
- --numCallbacks;
45157
- if (callback && numCallbacks === 0) {
45158
- callback();
45159
- }
45160
- };
45161
- this.questionRenderer.restoreSerializedState(state.question, fireCallback);
45162
- this.hintsRenderer?.restoreSerializedState(state.hints, fireCallback);
45163
- }
45164
- showRationalesForCurrentlySelectedChoices() {
45165
- this.questionRenderer.showRationalesForCurrentlySelectedChoices();
45166
- }
45167
- deselectIncorrectSelectedChoices() {
45168
- this.questionRenderer.deselectIncorrectSelectedChoices();
45169
- }
45170
- render() {
45171
- return /*#__PURE__*/React__namespace.createElement(DependenciesContext.Provider, {
45172
- value: this.props.dependencies
45173
- }, /*#__PURE__*/React__namespace.createElement("div", null));
45174
- }
45175
- }
45176
-
45177
44729
  /**
45178
44730
  * A React context for signaling when all of the components in a Perseus
45179
44731
  * renderer is fully rendered. This means that all images and math have
@@ -45197,6 +44749,7 @@ class ServerItemRenderer extends React__namespace.Component {
45197
44749
  static defaultProps = {
45198
44750
  apiOptions: {},
45199
44751
  // a deep default is done in `this.update()`
44752
+ linterContext: PerseusLinter__namespace.linterContextDefault,
45200
44753
  onRendered: isRendered => {}
45201
44754
  };
45202
44755
  constructor(props) {
@@ -45475,13 +45028,15 @@ class ServerItemRenderer extends React__namespace.Component {
45475
45028
  },
45476
45029
  content: this.props.item.question.content,
45477
45030
  widgets: this.props.item.question.widgets,
45478
- images: this.props.item.question.images
45031
+ images: this.props.item.question.images,
45032
+ linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "question")
45479
45033
  }, this.props.dependencies)));
45480
45034
  const hintsRenderer = /*#__PURE__*/React__namespace.createElement(HintsRenderer, {
45481
45035
  hints: this.props.item.hints,
45482
45036
  hintsVisible: this.props.hintsVisible,
45483
45037
  apiOptions: apiOptions,
45484
- ref: elem => this.hintsRenderer = elem
45038
+ ref: elem => this.hintsRenderer = elem,
45039
+ linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "hints")
45485
45040
  });
45486
45041
  return /*#__PURE__*/React__namespace.createElement(DependenciesContext.Provider, {
45487
45042
  value: this.props.dependencies
@@ -45946,238 +45501,6 @@ class RangeInput extends React__namespace.Component {
45946
45501
  };
45947
45502
  }
45948
45503
 
45949
- /* eslint-disable @khanacademy/ts-no-error-suppressions */
45950
- const prettyBig = {
45951
- fontSize: "150%"
45952
- };
45953
- const slightlyBig = {
45954
- fontSize: "120%"
45955
- };
45956
- const symbStyle = {
45957
- fontSize: "130%"
45958
- };
45959
- // These are functions because we want to generate a new component for each use
45960
- // on the page rather than reusing an instance (which will cause an error).
45961
- // Also, it's useful for things which might look different depending on the
45962
- // props.
45963
- const basic = [() => [/*#__PURE__*/React__namespace.createElement("span", {
45964
- key: "plus",
45965
- style: slightlyBig
45966
- }, "+"), "PLUS", i18n__namespace._("Plus")], () => [/*#__PURE__*/React__namespace.createElement("span", {
45967
- key: "minus",
45968
- style: prettyBig
45969
- }, "-"), "MINUS", i18n__namespace._("Minus")],
45970
- // TODO(joel) - display as \cdot when appropriate
45971
- props => {
45972
- const {
45973
- TeX
45974
- } = getDependencies();
45975
- if (props.convertDotToTimes) {
45976
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
45977
- key: "times",
45978
- style: prettyBig
45979
- }, i18n__namespace.doNotTranslate("\\times")), "TIMES", i18n__namespace._("Multiply")];
45980
- }
45981
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
45982
- key: "times",
45983
- style: prettyBig
45984
- }, i18n__namespace.doNotTranslate("\\cdot")), "CDOT", i18n__namespace._("Multiply")];
45985
- }, () => {
45986
- const {
45987
- TeX
45988
- } = getDependencies();
45989
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
45990
- key: "frac",
45991
- style: prettyBig
45992
- }, i18n__namespace.doNotTranslate("\\frac{x}{y}")), "FRAC", i18n__namespace._("Fraction, excluding the current expression")];
45993
- }];
45994
- const buttonSets = {
45995
- basic,
45996
- "basic+div": basic.concat([() => {
45997
- const {
45998
- TeX
45999
- } = getDependencies();
46000
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46001
- key: "div"
46002
- }, i18n__namespace.doNotTranslate("\\div")), "DIVIDE", i18n__namespace._("Divide")];
46003
- }]),
46004
- trig: [() => {
46005
- const {
46006
- TeX
46007
- } = getDependencies();
46008
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46009
- key: "sin"
46010
- }, i18n__namespace.doNotTranslate("\\sin")), "SIN", i18n__namespace._("Sine")];
46011
- }, () => {
46012
- const {
46013
- TeX
46014
- } = getDependencies();
46015
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46016
- key: "cos"
46017
- }, i18n__namespace.doNotTranslate("\\cos")), "COS", i18n__namespace._("Cosine")];
46018
- }, () => {
46019
- const {
46020
- TeX
46021
- } = getDependencies();
46022
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46023
- key: "tan"
46024
- }, i18n__namespace.doNotTranslate("\\tan")), "TAN", i18n__namespace._("Tangent")];
46025
- }, () => {
46026
- const {
46027
- TeX
46028
- } = getDependencies();
46029
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46030
- key: "theta",
46031
- style: symbStyle
46032
- }, i18n__namespace.doNotTranslate("\\theta")), "THETA", i18n__namespace._("Theta")];
46033
- }, () => {
46034
- const {
46035
- TeX
46036
- } = getDependencies();
46037
- return [/*#__PURE__*/React__namespace.createElement("span", {
46038
- key: "phi"
46039
- }, /*#__PURE__*/React__namespace.createElement("span", {
46040
- className: "perseus-sr-only"
46041
- }, i18n__namespace.doNotTranslate("phi")), /*#__PURE__*/React__namespace.createElement(TeX, {
46042
- key: "pi",
46043
- style: symbStyle
46044
- }, i18n__namespace.doNotTranslate("\\phi"))), "PHI", i18n__namespace._("Phi")];
46045
- }],
46046
- prealgebra: [() => {
46047
- const {
46048
- TeX
46049
- } = getDependencies();
46050
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46051
- key: "sqrt"
46052
- }, i18n__namespace.doNotTranslate("\\sqrt{x}")), "SQRT", i18n__namespace._("Square root")];
46053
- },
46054
- // TODO(joel) - how does desmos do this?
46055
- () => {
46056
- const {
46057
- TeX
46058
- } = getDependencies();
46059
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46060
- key: "nthroot"
46061
- }, i18n__namespace.doNotTranslate("\\sqrt[3]{x}")), "NTHROOT3", i18n__namespace._("Cube root")];
46062
- }, () => {
46063
- const {
46064
- TeX
46065
- } = getDependencies();
46066
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46067
- key: "pow",
46068
- style: slightlyBig
46069
- }, i18n__namespace.doNotTranslate("a^b")), "POW", i18n__namespace._("Exponent")];
46070
- }, () => {
46071
- const {
46072
- TeX
46073
- } = getDependencies();
46074
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46075
- key: "pi",
46076
- style: slightlyBig
46077
- }, i18n__namespace.doNotTranslate("\\pi")), "PI", i18n__namespace._("Pi")];
46078
- }],
46079
- logarithms: [() => {
46080
- const {
46081
- TeX
46082
- } = getDependencies();
46083
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46084
- key: "log"
46085
- }, i18n__namespace.doNotTranslate("\\log")), "LOG", i18n__namespace._("Logarithm with base 10")];
46086
- }, () => {
46087
- const {
46088
- TeX
46089
- } = getDependencies();
46090
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46091
- key: "ln"
46092
- }, i18n__namespace.doNotTranslate("\\ln")), "LN", i18n__namespace._("Natural logarithm")];
46093
- }, () => {
46094
- const {
46095
- TeX
46096
- } = getDependencies();
46097
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46098
- key: "log_b"
46099
- }, i18n__namespace.doNotTranslate("\\log_b")), "LOG_B", i18n__namespace._("Logarithm with custom base")];
46100
- }],
46101
- "basic relations": [() => {
46102
- const {
46103
- TeX
46104
- } = getDependencies();
46105
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46106
- key: "eq"
46107
- }, "="), "EQUAL", i18n__namespace._("Equals sign")];
46108
- }, () => {
46109
- const {
46110
- TeX
46111
- } = getDependencies();
46112
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46113
- key: "lt"
46114
- }, i18n__namespace.doNotTranslate("\\lt")), "LT", i18n__namespace._("Less than sign")];
46115
- }, () => {
46116
- const {
46117
- TeX
46118
- } = getDependencies();
46119
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46120
- key: "gt"
46121
- }, i18n__namespace.doNotTranslate("\\gt")), "GT", i18n__namespace._("Greater than sign")];
46122
- }],
46123
- "advanced relations": [() => {
46124
- const {
46125
- TeX
46126
- } = getDependencies();
46127
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46128
- key: "neq"
46129
- }, i18n__namespace.doNotTranslate("\\neq")), "NEQ", i18n__namespace._("Not-equals sign")];
46130
- }, () => {
46131
- const {
46132
- TeX
46133
- } = getDependencies();
46134
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46135
- key: "leq"
46136
- }, i18n__namespace.doNotTranslate("\\leq")), "LEQ", i18n__namespace._("Less than or equal to sign")];
46137
- }, () => {
46138
- const {
46139
- TeX
46140
- } = getDependencies();
46141
- return [/*#__PURE__*/React__namespace.createElement(TeX, {
46142
- key: "geq"
46143
- }, i18n__namespace.doNotTranslate("\\geq")), "GEQ", i18n__namespace._("Greater than or equal to sign")];
46144
- }]
46145
- };
46146
- const buttonSetsPropType = PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOf(___default["default"](buttonSets).keys()));
46147
- class TexButtons extends React__namespace.Component {
46148
- static buttonSets = buttonSets;
46149
- static buttonSetsType = buttonSetsPropType;
46150
- render() {
46151
- // Always show buttonSets in the same order. Note: Technically it's ok
46152
- // for _.keys() to return the keys in an arbitrary order, but in
46153
- // practice, they will be ordered as listed above.
46154
- const sortedButtonSets = ___default["default"].sortBy(this.props.sets, setName => ___default["default"].keys(buttonSets).indexOf(setName));
46155
- const buttons = ___default["default"](sortedButtonSets).map(setName => buttonSets[setName]);
46156
- const buttonRows = ___default["default"](buttons).map(row => row.map(symbGen => {
46157
- // create a (component, thing we should send to mathquill) pair
46158
- const symbol = symbGen(this.props);
46159
- return /*#__PURE__*/React__namespace.createElement("button", {
46160
- onClick: () => this.props.onInsert(symbol[1]),
46161
- className: "tex-button"
46162
- // @ts-expect-error - TS2533 - Object is possibly 'null' or 'undefined'. | TS2339 - Property 'key' does not exist on type 'boolean | ReactChild | ReactFragment | ReactPortal'.
46163
- ,
46164
- key: symbol[0].key,
46165
- type: "button",
46166
- "aria-label": symbol[2]
46167
- }, symbol[0]);
46168
- }));
46169
- const buttonPopup = ___default["default"](buttonRows).map((row, i) => {
46170
- return /*#__PURE__*/React__namespace.createElement("div", {
46171
- className: "clearfix tex-button-row",
46172
- key: this.props.sets[i]
46173
- }, row);
46174
- });
46175
- return /*#__PURE__*/React__namespace.createElement("div", {
46176
- className: `${this.props.className || ""} preview-measure`
46177
- }, buttonPopup);
46178
- }
46179
- }
46180
-
46181
45504
  var components = /*#__PURE__*/Object.freeze({
46182
45505
  __proto__: null,
46183
45506
  ButtonGroup: ButtonGroup,
@@ -46194,7 +45517,6 @@ var components = /*#__PURE__*/Object.freeze({
46194
45517
  RangeInput: RangeInput,
46195
45518
  SvgImage: SvgImage,
46196
45519
  TextInput: TextInput,
46197
- TexButtons: TexButtons,
46198
45520
  TextListEditor: TextListEditor
46199
45521
  });
46200
45522
 
@@ -47457,7 +46779,6 @@ exports.HintRenderer = HintRenderer;
47457
46779
  exports.HintsRenderer = HintsRenderer;
47458
46780
  exports.InputNumber = InputNumber$1;
47459
46781
  exports.InteractiveGraphWidget = InteractiveGraph$1;
47460
- exports.ItemRenderer = ItemRenderer;
47461
46782
  exports.JiptParagraphs = JiptParagraphs;
47462
46783
  exports.KhanColors = KhanColors;
47463
46784
  exports.KhanMath = KhanMath;