@khanacademy/perseus 21.5.0 → 22.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/article-renderer.d.ts +6 -0
- package/dist/components/highlighting/ui/highlight-set-renderer.d.ts +14 -0
- package/dist/components/highlighting/ui/highlighting-ui.d.ts +17 -0
- package/dist/components/i18n-context.d.ts +16 -0
- package/dist/components/input-with-examples.d.ts +6 -0
- package/dist/components/math-input.d.ts +22 -2
- package/dist/components/number-input.d.ts +6 -0
- package/dist/es/index.css +3 -0
- package/dist/es/index.js +953 -530
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +312 -0
- package/dist/es/strings.js.map +1 -0
- package/dist/hint-renderer.d.ts +6 -0
- package/dist/hints-renderer.d.ts +6 -0
- package/dist/index.css +3 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1175 -565
- package/dist/index.js.map +1 -1
- package/dist/multi-items/multi-renderer.d.ts +6 -0
- package/dist/perseus-api.d.ts +5 -3
- package/dist/perseus-types.d.ts +18 -8
- package/dist/renderer.d.ts +2 -0
- package/dist/server-item-renderer.d.ts +11 -3
- package/dist/strings.d.ts +190 -0
- package/dist/strings.js +395 -119
- package/dist/strings.js.map +1 -0
- package/dist/types.d.ts +10 -6
- package/dist/util/answer-types.d.ts +4 -12
- package/dist/util.d.ts +2 -1
- package/dist/widgets/categorizer.d.ts +8 -1
- package/dist/widgets/definition.d.ts +6 -0
- package/dist/widgets/deprecated-standin/index.d.ts +6 -0
- package/dist/widgets/explanation.d.ts +6 -0
- package/dist/widgets/expression.d.ts +42 -19
- package/dist/widgets/graded-group-answer-bar.d.ts +6 -0
- package/dist/widgets/graded-group.d.ts +6 -0
- package/dist/widgets/group.d.ts +6 -0
- package/dist/widgets/image.d.ts +6 -0
- package/dist/widgets/input-number.d.ts +8 -1
- package/dist/widgets/interactive-graph.d.ts +6 -0
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +21 -0
- package/dist/widgets/interactive-graphs/locked-line.d.ts +4 -0
- package/dist/widgets/interactive-graphs/locked-point.d.ts +4 -0
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +1 -0
- package/dist/widgets/interactive-graphs/reducer/use-graph-config.d.ts +1 -0
- package/dist/widgets/label-image/marker.d.ts +6 -0
- package/dist/widgets/label-image.d.ts +16 -6
- package/dist/widgets/matcher.d.ts +6 -0
- package/dist/widgets/matrix.d.ts +9 -1
- package/dist/widgets/molecule.d.ts +6 -0
- package/dist/widgets/number-line.d.ts +6 -0
- package/dist/widgets/numeric-input.d.ts +8 -1
- package/dist/widgets/passage-ref-target.d.ts +6 -0
- package/dist/widgets/passage-ref.d.ts +6 -0
- package/dist/widgets/passage.d.ts +6 -0
- package/dist/widgets/plotter.d.ts +6 -0
- package/dist/widgets/radio/choice-a11y-text.d.ts +2 -1
- package/dist/widgets/radio/radio.d.ts +8 -1
- package/dist/widgets/radio/util.d.ts +2 -1
- package/dist/widgets/table.d.ts +7 -0
- package/dist/widgets/unit.d.ts +8 -1
- package/dist/widgets/video.d.ts +6 -0
- package/dist/widgets.d.ts +2 -1
- package/package.json +50 -39
- package/dist/widgets/label-image/strings.d.ts +0 -3
package/dist/index.js
CHANGED
|
@@ -6,7 +6,6 @@ var KAS = require('@khanacademy/kas');
|
|
|
6
6
|
var mathInput = require('@khanacademy/math-input');
|
|
7
7
|
var PerseusLinter = require('@khanacademy/perseus-linter');
|
|
8
8
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
9
|
-
var i18n = require('@khanacademy/wonder-blocks-i18n');
|
|
10
9
|
var Tooltip$1 = require('@khanacademy/wonder-blocks-tooltip');
|
|
11
10
|
var classNames = require('classnames');
|
|
12
11
|
var React = require('react');
|
|
@@ -64,7 +63,6 @@ function _interopNamespace(e) {
|
|
|
64
63
|
|
|
65
64
|
var KAS__namespace = /*#__PURE__*/_interopNamespace(KAS);
|
|
66
65
|
var PerseusLinter__namespace = /*#__PURE__*/_interopNamespace(PerseusLinter);
|
|
67
|
-
var i18n__namespace = /*#__PURE__*/_interopNamespace(i18n);
|
|
68
66
|
var Tooltip__default = /*#__PURE__*/_interopDefaultLegacy(Tooltip$1);
|
|
69
67
|
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
|
|
70
68
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
@@ -102,6 +100,290 @@ function _extends() {
|
|
|
102
100
|
return _extends.apply(this, arguments);
|
|
103
101
|
}
|
|
104
102
|
|
|
103
|
+
/**
|
|
104
|
+
* The translated strings that are used to render Perseus.
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Mock strings for the Perseus package, to be used for tests and Storybook.
|
|
109
|
+
*/
|
|
110
|
+
const mockStrings = {
|
|
111
|
+
closeKeypad: "close math keypad",
|
|
112
|
+
openKeypad: "open math keypad",
|
|
113
|
+
removeHighlight: "Remove highlight",
|
|
114
|
+
addHighlight: "Add highlight",
|
|
115
|
+
hintPos: _ref => {
|
|
116
|
+
let {
|
|
117
|
+
pos
|
|
118
|
+
} = _ref;
|
|
119
|
+
return `Hint #${pos}`;
|
|
120
|
+
},
|
|
121
|
+
errorRendering: _ref2 => {
|
|
122
|
+
let {
|
|
123
|
+
error
|
|
124
|
+
} = _ref2;
|
|
125
|
+
return `Error rendering: ${error}`;
|
|
126
|
+
},
|
|
127
|
+
APPROXIMATED_PI_ERROR: "Your answer is close, but you may " + "have approximated pi. Enter your " + "answer as a multiple of pi, like " + "<code>12\\ \\text{pi}</code> or " + "<code>2/3\\ \\text{pi}</code>",
|
|
128
|
+
EXTRA_SYMBOLS_ERROR: "We could not understand your " + "answer. Please check your answer for extra " + "text or symbols.",
|
|
129
|
+
NEEDS_TO_BE_SIMPLFIED_ERROR: "Your answer is almost correct, " + "but it needs to be simplified.",
|
|
130
|
+
MISSING_PERCENT_ERROR: "Your answer is almost correct, " + "but it is missing a " + "<code>\\%</code> at the end.",
|
|
131
|
+
MULTIPLICATION_SIGN_ERROR: "I'm a computer. I only understand " + "multiplication if you use an asterisk " + "(*) as the multiplication sign.",
|
|
132
|
+
WRONG_CASE_ERROR: "Your answer includes use of a variable with the wrong case.",
|
|
133
|
+
WRONG_LETTER_ERROR: "Your answer includes a wrong variable letter.",
|
|
134
|
+
invalidSelection: "Make sure you select something for every row.",
|
|
135
|
+
ERROR_TITLE: "Oops!",
|
|
136
|
+
ERROR_MESSAGE: "Sorry, I don't understand that!",
|
|
137
|
+
hints: "Hints",
|
|
138
|
+
getAnotherHint: "Get another hint",
|
|
139
|
+
deprecatedStandin: "Sorry, this part of the question is no longer available. 😅 Don't worry, you won't be graded on this part. Keep going!",
|
|
140
|
+
keepTrying: "Keep trying",
|
|
141
|
+
tryAgain: "Try again",
|
|
142
|
+
check: "Check",
|
|
143
|
+
correctExcited: "Correct!",
|
|
144
|
+
nextQuestion: "Next question",
|
|
145
|
+
skipToTitle: _ref3 => {
|
|
146
|
+
let {
|
|
147
|
+
title
|
|
148
|
+
} = _ref3;
|
|
149
|
+
return `Skip to ${title}`;
|
|
150
|
+
},
|
|
151
|
+
current: "Current",
|
|
152
|
+
correct: "Correct",
|
|
153
|
+
correctSelected: "Correct (selected)",
|
|
154
|
+
correctCrossedOut: "Correct (but you crossed it out)",
|
|
155
|
+
incorrect: "Incorrect",
|
|
156
|
+
incorrectSelected: "Incorrect (selected)",
|
|
157
|
+
hideExplanation: "Hide explanation",
|
|
158
|
+
explain: "Explain",
|
|
159
|
+
INVALID_MESSAGE_PREFIX: "We couldn't grade your answer.",
|
|
160
|
+
DEFAULT_INVALID_MESSAGE_1: "It looks like you left something blank or ",
|
|
161
|
+
DEFAULT_INVALID_MESSAGE_2: "entered in an invalid answer.",
|
|
162
|
+
integerExample: "an integer, like $6$",
|
|
163
|
+
properExample: "a *proper* fraction, like $1/2$ or $6/10$",
|
|
164
|
+
simplifiedProperExample: "a *simplified proper* fraction, like $3/5$",
|
|
165
|
+
improperExample: "an *improper* fraction, like $10/7$ or $14/8$",
|
|
166
|
+
simplifiedImproperExample: "a *simplified improper* fraction, like $7/4$",
|
|
167
|
+
mixedExample: "a mixed number, like $1\\ 3/4$",
|
|
168
|
+
decimalExample: "an *exact* decimal, like $0.75$",
|
|
169
|
+
percentExample: "a percent, like $12.34\\%$",
|
|
170
|
+
piExample: "a multiple of pi, like $12\\ \\text{pi}$ or $2/3\\ \\text{pi}$",
|
|
171
|
+
yourAnswer: "**Your answer should be** ",
|
|
172
|
+
yourAnswerLabel: "Your answer:",
|
|
173
|
+
addPoints: "Click to add points",
|
|
174
|
+
addVertices: "Click to add vertices",
|
|
175
|
+
tapMultiple: "Tap each dot on the image to select all answers that apply.",
|
|
176
|
+
tapSingle: "Tap each dot on the image to select an answer.",
|
|
177
|
+
clickMultiple: "Click each dot on the image to select all answers that apply.",
|
|
178
|
+
clickSingle: "Click each dot on the image to select an answer.",
|
|
179
|
+
choices: "Choices:",
|
|
180
|
+
answers: _ref4 => {
|
|
181
|
+
let {
|
|
182
|
+
num
|
|
183
|
+
} = _ref4;
|
|
184
|
+
return num === 1 ? `${num} answer` : `${num} answers`;
|
|
185
|
+
},
|
|
186
|
+
hideAnswersToggleLabel: "Hide answer choices",
|
|
187
|
+
moves: _ref5 => {
|
|
188
|
+
let {
|
|
189
|
+
num
|
|
190
|
+
} = _ref5;
|
|
191
|
+
return num === 1 ? `Moves: ${num}` : `Moves: ${num}`;
|
|
192
|
+
},
|
|
193
|
+
clickTiles: "Click on the tiles to change the lights.",
|
|
194
|
+
turnOffLights: "You must turn on all of the lights to continue.",
|
|
195
|
+
fillAllCells: "Make sure you fill in all cells in the matrix.",
|
|
196
|
+
molecularDrawing: _ref6 => {
|
|
197
|
+
let {
|
|
198
|
+
content
|
|
199
|
+
} = _ref6;
|
|
200
|
+
return `A molecular structure drawing. SMILES notation: ${content}`;
|
|
201
|
+
},
|
|
202
|
+
switchDirection: "Switch direction",
|
|
203
|
+
circleOpen: "Make circle open",
|
|
204
|
+
circleFilled: "Make circle filled",
|
|
205
|
+
numDivisions: "Number of divisions:",
|
|
206
|
+
divisions: _ref7 => {
|
|
207
|
+
let {
|
|
208
|
+
divRangeString
|
|
209
|
+
} = _ref7;
|
|
210
|
+
return `Please make sure the number of divisions is in the range ${divRangeString}.`;
|
|
211
|
+
},
|
|
212
|
+
lineRange: _ref8 => {
|
|
213
|
+
let {
|
|
214
|
+
lineRange
|
|
215
|
+
} = _ref8;
|
|
216
|
+
return `lines ${lineRange}`;
|
|
217
|
+
},
|
|
218
|
+
lineNumber: _ref9 => {
|
|
219
|
+
let {
|
|
220
|
+
lineNumber
|
|
221
|
+
} = _ref9;
|
|
222
|
+
return `line ${lineNumber}`;
|
|
223
|
+
},
|
|
224
|
+
symbolPassage: _ref10 => {
|
|
225
|
+
let {
|
|
226
|
+
questionSymbol,
|
|
227
|
+
questionNumber
|
|
228
|
+
} = _ref10;
|
|
229
|
+
return `The symbol ${questionSymbol} indicates that question ${questionNumber} references this portion of the passage.`;
|
|
230
|
+
},
|
|
231
|
+
symbolQuestion: _ref11 => {
|
|
232
|
+
let {
|
|
233
|
+
sentenceSymbol
|
|
234
|
+
} = _ref11;
|
|
235
|
+
return ` The symbol ${sentenceSymbol} indicates that the following sentence is referenced in a question.`;
|
|
236
|
+
},
|
|
237
|
+
lineLabel: "Line",
|
|
238
|
+
beginningPassage: "Beginning of reading passage.",
|
|
239
|
+
beginningFootnotes: "Beginning of reading passage footnotes.",
|
|
240
|
+
endPassage: "End of reading passage.",
|
|
241
|
+
questionMarker: _ref12 => {
|
|
242
|
+
let {
|
|
243
|
+
number
|
|
244
|
+
} = _ref12;
|
|
245
|
+
return `[Marker for question ${number}]`;
|
|
246
|
+
},
|
|
247
|
+
circleMarker: _ref13 => {
|
|
248
|
+
let {
|
|
249
|
+
number
|
|
250
|
+
} = _ref13;
|
|
251
|
+
return `[Circle marker ${number}]`;
|
|
252
|
+
},
|
|
253
|
+
sentenceMarker: _ref14 => {
|
|
254
|
+
let {
|
|
255
|
+
number
|
|
256
|
+
} = _ref14;
|
|
257
|
+
return `[Sentence ${number}]`;
|
|
258
|
+
},
|
|
259
|
+
dragHandles: "Drag handles to make graph",
|
|
260
|
+
tapAddPoints: "Tap to add points",
|
|
261
|
+
false: "False",
|
|
262
|
+
true: "True",
|
|
263
|
+
no: "No",
|
|
264
|
+
yes: "Yes",
|
|
265
|
+
chooseCorrectNum: "Please choose the correct number of answers.",
|
|
266
|
+
notNoneOfTheAbove: "'None of the above' may not be selected when other answers are selected.",
|
|
267
|
+
noneOfTheAbove: "None of the above",
|
|
268
|
+
chooseNumAnswers: _ref15 => {
|
|
269
|
+
let {
|
|
270
|
+
numCorrect
|
|
271
|
+
} = _ref15;
|
|
272
|
+
return `Choose ${numCorrect} answers:`;
|
|
273
|
+
},
|
|
274
|
+
chooseAllAnswers: "Choose all answers that apply:",
|
|
275
|
+
chooseOneAnswer: "Choose 1 answer:",
|
|
276
|
+
choiceCheckedCorrect: _ref16 => {
|
|
277
|
+
let {
|
|
278
|
+
letter
|
|
279
|
+
} = _ref16;
|
|
280
|
+
return `(Choice ${letter}, Checked, Correct)`;
|
|
281
|
+
},
|
|
282
|
+
choiceCrossedOutCorrect: _ref17 => {
|
|
283
|
+
let {
|
|
284
|
+
letter
|
|
285
|
+
} = _ref17;
|
|
286
|
+
return `(Choice ${letter}, Crossed out, Correct)`;
|
|
287
|
+
},
|
|
288
|
+
choiceCorrect: _ref18 => {
|
|
289
|
+
let {
|
|
290
|
+
letter
|
|
291
|
+
} = _ref18;
|
|
292
|
+
return `(Choice ${letter}, Correct)`;
|
|
293
|
+
},
|
|
294
|
+
choiceCheckedIncorrect: _ref19 => {
|
|
295
|
+
let {
|
|
296
|
+
letter
|
|
297
|
+
} = _ref19;
|
|
298
|
+
return `(Choice ${letter}, Checked, Incorrect)`;
|
|
299
|
+
},
|
|
300
|
+
choiceCrossedOutIncorrect: _ref20 => {
|
|
301
|
+
let {
|
|
302
|
+
letter
|
|
303
|
+
} = _ref20;
|
|
304
|
+
return `(Choice ${letter}, Crossed out, Incorrect)`;
|
|
305
|
+
},
|
|
306
|
+
choiceIncorrect: _ref21 => {
|
|
307
|
+
let {
|
|
308
|
+
letter
|
|
309
|
+
} = _ref21;
|
|
310
|
+
return `(Choice ${letter}, Incorrect)`;
|
|
311
|
+
},
|
|
312
|
+
choiceChecked: _ref22 => {
|
|
313
|
+
let {
|
|
314
|
+
letter
|
|
315
|
+
} = _ref22;
|
|
316
|
+
return `(Choice ${letter}, Checked)`;
|
|
317
|
+
},
|
|
318
|
+
choiceCrossedOut: _ref23 => {
|
|
319
|
+
let {
|
|
320
|
+
letter
|
|
321
|
+
} = _ref23;
|
|
322
|
+
return `(Choice ${letter}, Crossed out)`;
|
|
323
|
+
},
|
|
324
|
+
choice: _ref24 => {
|
|
325
|
+
let {
|
|
326
|
+
letter
|
|
327
|
+
} = _ref24;
|
|
328
|
+
return `(Choice ${letter})`;
|
|
329
|
+
},
|
|
330
|
+
crossOut: "Cross out",
|
|
331
|
+
crossOutOption: "Cross out option",
|
|
332
|
+
crossOutChoice: _ref25 => {
|
|
333
|
+
let {
|
|
334
|
+
letter
|
|
335
|
+
} = _ref25;
|
|
336
|
+
return `Cross out Choice ${letter}`;
|
|
337
|
+
},
|
|
338
|
+
bringBack: "Bring back",
|
|
339
|
+
openMenuForChoice: _ref26 => {
|
|
340
|
+
let {
|
|
341
|
+
letter
|
|
342
|
+
} = _ref26;
|
|
343
|
+
return `Open menu for Choice ${letter}`;
|
|
344
|
+
},
|
|
345
|
+
letters: "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
|
|
346
|
+
rightArrow: "Reaction arrow pointing to the right.",
|
|
347
|
+
dontUnderstandUnits: "I couldn't understand those units.",
|
|
348
|
+
checkSigFigs: "Check your significant figures.",
|
|
349
|
+
answerNumericallyIncorrect: "That answer is numerically incorrect.",
|
|
350
|
+
checkUnits: "Check your units.",
|
|
351
|
+
dontUnderstand: "I don't understand that",
|
|
352
|
+
loading: "Loading...",
|
|
353
|
+
videoTranscript: "See video transcript",
|
|
354
|
+
somethingWrong: "Something went wrong.",
|
|
355
|
+
videoWrapper: "Khan Academy video wrapper"
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* PerseusI18nContext provides a way to set the strings and locale that are
|
|
360
|
+
* used inside the Perseus package.
|
|
361
|
+
*
|
|
362
|
+
*/
|
|
363
|
+
// @ts-expect-error - TS2322 - Type 'Context<{ strings: {}; locale: string; }>' is not assignable to type 'Context<I18nContextType>'.
|
|
364
|
+
const PerseusI18nContext = /*#__PURE__*/React__namespace.createContext(process.env.NODE_ENV === "test" || process.env.STORYBOOK ? {
|
|
365
|
+
strings: mockStrings,
|
|
366
|
+
locale: "en"
|
|
367
|
+
} :
|
|
368
|
+
// We want to return null here, not an empty object, so that we
|
|
369
|
+
// are will throw an error when attempting to access the
|
|
370
|
+
// undefined locale or strings, making it easier to debug.
|
|
371
|
+
null);
|
|
372
|
+
function PerseusI18nContextProvider(_ref) {
|
|
373
|
+
let {
|
|
374
|
+
children,
|
|
375
|
+
strings,
|
|
376
|
+
locale
|
|
377
|
+
} = _ref;
|
|
378
|
+
return /*#__PURE__*/React__namespace.createElement(PerseusI18nContext.Provider, {
|
|
379
|
+
value: {
|
|
380
|
+
strings,
|
|
381
|
+
locale
|
|
382
|
+
}
|
|
383
|
+
}, children);
|
|
384
|
+
}
|
|
385
|
+
const usePerseusI18n = () => React.useContext(PerseusI18nContext);
|
|
386
|
+
|
|
105
387
|
const debounce = (func, delay) => {
|
|
106
388
|
let timer = null;
|
|
107
389
|
return function () {
|
|
@@ -117,24 +399,11 @@ const debounce = (func, delay) => {
|
|
|
117
399
|
};
|
|
118
400
|
};
|
|
119
401
|
|
|
120
|
-
const customKeyTranslator = {
|
|
121
|
-
...mathInput.keyTranslator,
|
|
122
|
-
// If there's something in the input that can become part of a
|
|
123
|
-
// fraction, typing "/" puts it in the numerator. If not, typing
|
|
124
|
-
// "/" does nothing. In that case, enter a \frac.
|
|
125
|
-
FRAC: mathQuill => {
|
|
126
|
-
const contents = mathQuill.latex();
|
|
127
|
-
mathQuill.typedText("/");
|
|
128
|
-
if (mathQuill.latex() === contents) {
|
|
129
|
-
mathQuill.cmd("\\frac");
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
402
|
// A WYSIWYG math input that calls `onChange(LaTeX-string)`
|
|
135
|
-
class
|
|
403
|
+
class InnerMathInput extends React__namespace.Component {
|
|
404
|
+
static contextType = PerseusI18nContext;
|
|
136
405
|
// @ts-expect-error - TS2564 - Property 'mouseDown' has no initializer and is not definitely assigned in the constructor.
|
|
137
|
-
|
|
406
|
+
mouseDown;
|
|
138
407
|
__mathFieldWrapperRef = null;
|
|
139
408
|
__mathField = null;
|
|
140
409
|
static defaultProps = {
|
|
@@ -166,6 +435,22 @@ class MathInput extends React__namespace.Component {
|
|
|
166
435
|
}
|
|
167
436
|
insert = value => {
|
|
168
437
|
const input = this.mathField();
|
|
438
|
+
const {
|
|
439
|
+
locale
|
|
440
|
+
} = this.context;
|
|
441
|
+
const customKeyTranslator = {
|
|
442
|
+
...mathInput.getKeyTranslator(locale),
|
|
443
|
+
// If there's something in the input that can become part of a
|
|
444
|
+
// fraction, typing "/" puts it in the numerator. If not, typing
|
|
445
|
+
// "/" does nothing. In that case, enter a \frac.
|
|
446
|
+
FRAC: mathQuill => {
|
|
447
|
+
const contents = mathQuill.latex();
|
|
448
|
+
mathQuill.typedText("/");
|
|
449
|
+
if (mathQuill.latex() === contents) {
|
|
450
|
+
mathQuill.cmd("\\frac");
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
};
|
|
169
454
|
const inputModifier = customKeyTranslator[value];
|
|
170
455
|
if (inputModifier) {
|
|
171
456
|
inputModifier(input, value);
|
|
@@ -188,8 +473,11 @@ class MathInput extends React__namespace.Component {
|
|
|
188
473
|
};
|
|
189
474
|
mathField = () => {
|
|
190
475
|
if (!this.__mathField && this.__mathFieldWrapperRef) {
|
|
476
|
+
const {
|
|
477
|
+
locale
|
|
478
|
+
} = this.context;
|
|
191
479
|
// Initialize MathQuill.MathField instance
|
|
192
|
-
this.__mathField = mathInput.createMathField(this.__mathFieldWrapperRef, baseConfig => ({
|
|
480
|
+
this.__mathField = mathInput.createMathField(this.__mathFieldWrapperRef, this.props.mathInputStrings, baseConfig => ({
|
|
193
481
|
...baseConfig,
|
|
194
482
|
handlers: {
|
|
195
483
|
edit: debounce(mathField => {
|
|
@@ -206,7 +494,7 @@ class MathInput extends React__namespace.Component {
|
|
|
206
494
|
// Use the specified symbol to represent multiplication
|
|
207
495
|
// TODO(alex): Add an option to disallow variables, in
|
|
208
496
|
// which case 'x' should get converted to '\\times'
|
|
209
|
-
if (mathInput.convertDotToTimesByLocale(this.props.convertDotToTimes)) {
|
|
497
|
+
if (mathInput.convertDotToTimesByLocale(locale, this.props.convertDotToTimes)) {
|
|
210
498
|
value = value.replace(/\\cdot/g, "\\times");
|
|
211
499
|
|
|
212
500
|
// Preserve cursor position in the common case:
|
|
@@ -266,7 +554,10 @@ class MathInput extends React__namespace.Component {
|
|
|
266
554
|
focused: false
|
|
267
555
|
});
|
|
268
556
|
handleKeypadPress = (key, e) => {
|
|
269
|
-
const
|
|
557
|
+
const {
|
|
558
|
+
locale
|
|
559
|
+
} = this.context;
|
|
560
|
+
const translator = mathInput.getKeyTranslator(locale)[key];
|
|
270
561
|
const mathField = this.mathField();
|
|
271
562
|
if (mathField) {
|
|
272
563
|
if (translator) {
|
|
@@ -342,7 +633,7 @@ class MathInput extends React__namespace.Component {
|
|
|
342
633
|
focused: false,
|
|
343
634
|
active: false
|
|
344
635
|
}) : /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
345
|
-
"aria-label": this.state.keypadOpen ?
|
|
636
|
+
"aria-label": this.state.keypadOpen ? this.context.strings.closeKeypad : this.context.strings.openKeypad,
|
|
346
637
|
"aria-checked": this.state.keypadOpen,
|
|
347
638
|
role: "switch",
|
|
348
639
|
onClick: () => this.state.keypadOpen ? this.closeKeypad() : this.openKeypad()
|
|
@@ -351,6 +642,26 @@ class MathInput extends React__namespace.Component {
|
|
|
351
642
|
}, props))))));
|
|
352
643
|
}
|
|
353
644
|
}
|
|
645
|
+
|
|
646
|
+
// We need to have two contexts (one for Perseus and one for MathInput), so we
|
|
647
|
+
// add a wrapper around the MathInput component to provide the MathInput context
|
|
648
|
+
// to it.
|
|
649
|
+
class MathInput extends React__namespace.Component {
|
|
650
|
+
static contextType = mathInput.MathInputI18nContext;
|
|
651
|
+
inputRef = /*#__PURE__*/React__namespace.createRef();
|
|
652
|
+
focus() {
|
|
653
|
+
this.inputRef.current?.focus();
|
|
654
|
+
}
|
|
655
|
+
insert(value) {
|
|
656
|
+
this.inputRef.current?.insert(value);
|
|
657
|
+
}
|
|
658
|
+
render() {
|
|
659
|
+
return /*#__PURE__*/React__namespace.createElement(InnerMathInput, _extends({}, this.props, {
|
|
660
|
+
ref: this.inputRef,
|
|
661
|
+
mathInputStrings: this.context.strings
|
|
662
|
+
}));
|
|
663
|
+
}
|
|
664
|
+
}
|
|
354
665
|
const MathInputIcon = _ref => {
|
|
355
666
|
let {
|
|
356
667
|
hovered,
|
|
@@ -547,6 +858,8 @@ const Log = {
|
|
|
547
858
|
};
|
|
548
859
|
|
|
549
860
|
class PerseusError extends Error {
|
|
861
|
+
kind;
|
|
862
|
+
metadata;
|
|
550
863
|
constructor(message, kind, options) {
|
|
551
864
|
super(message);
|
|
552
865
|
this.kind = kind;
|
|
@@ -1264,16 +1577,6 @@ const MAXERROR_EPSILON = Math.pow(2, -42);
|
|
|
1264
1577
|
// TOOD(kevinb): Figure out how this relates to KEScore in
|
|
1265
1578
|
// perseus-all-package/types.js and see if there's a way to
|
|
1266
1579
|
// unify these types.
|
|
1267
|
-
const errors = {
|
|
1268
|
-
APPROXIMATED_PI_ERROR: i18n__namespace._("Your answer is close, but you may " + "have approximated pi. Enter your " + "answer as a multiple of pi, like " + "<code>12\\ \\text{pi}</code> or " + "<code>2/3\\ \\text{pi}</code>"),
|
|
1269
|
-
EXTRA_SYMBOLS_ERROR: i18n__namespace._("We could not understand your " + "answer. Please check your answer for extra " + "text or symbols."),
|
|
1270
|
-
NEEDS_TO_BE_SIMPLFIED_ERROR: i18n__namespace._("Your answer is almost correct, " + "but it needs to be simplified."),
|
|
1271
|
-
MISSING_PERCENT_ERROR: i18n__namespace._("Your answer is almost correct, " + "but it is missing a " + "<code>\\%</code> at the end."),
|
|
1272
|
-
MULTIPLICATION_SIGN_ERROR: i18n__namespace._("I'm a computer. I only understand " + "multiplication if you use an asterisk " + "(*) as the multiplication sign."),
|
|
1273
|
-
WRONG_CASE_ERROR: i18n__namespace._("Your answer includes use of a variable with the wrong case."),
|
|
1274
|
-
WRONG_LETTER_ERROR: i18n__namespace._("Your answer includes a wrong variable letter.")
|
|
1275
|
-
};
|
|
1276
|
-
|
|
1277
1580
|
/*
|
|
1278
1581
|
* Answer types
|
|
1279
1582
|
*
|
|
@@ -1346,7 +1649,7 @@ const KhanAnswerTypes = {
|
|
|
1346
1649
|
*/
|
|
1347
1650
|
predicate: {
|
|
1348
1651
|
defaultForms: "integer, proper, improper, mixed, decimal",
|
|
1349
|
-
createValidatorFunctional: function (predicate, options) {
|
|
1652
|
+
createValidatorFunctional: function (predicate, options, strings) {
|
|
1350
1653
|
// Extract the options from the given solution object
|
|
1351
1654
|
options = ___default["default"].extend({
|
|
1352
1655
|
simplify: "required",
|
|
@@ -1735,12 +2038,12 @@ const KhanAnswerTypes = {
|
|
|
1735
2038
|
} else if (form === "percent") {
|
|
1736
2039
|
// Otherwise, an error was returned
|
|
1737
2040
|
score.empty = true;
|
|
1738
|
-
score.message =
|
|
2041
|
+
score.message = strings.MISSING_PERCENT_ERROR;
|
|
1739
2042
|
} else {
|
|
1740
2043
|
if (options.simplify !== "enforced") {
|
|
1741
2044
|
score.empty = true;
|
|
1742
2045
|
}
|
|
1743
|
-
score.message =
|
|
2046
|
+
score.message = strings.NEEDS_TO_BE_SIMPLFIED_ERROR;
|
|
1744
2047
|
}
|
|
1745
2048
|
// The return false below stops the looping of the
|
|
1746
2049
|
// callback since predicate check succeeded.
|
|
@@ -1749,7 +2052,7 @@ const KhanAnswerTypes = {
|
|
|
1749
2052
|
}
|
|
1750
2053
|
if (piApprox && predicate(val, Math.abs(val * 0.001))) {
|
|
1751
2054
|
score.empty = true;
|
|
1752
|
-
score.message =
|
|
2055
|
+
score.message = strings.APPROXIMATED_PI_ERROR;
|
|
1753
2056
|
}
|
|
1754
2057
|
}
|
|
1755
2058
|
});
|
|
@@ -1765,7 +2068,7 @@ const KhanAnswerTypes = {
|
|
|
1765
2068
|
});
|
|
1766
2069
|
if (!interpretedGuess) {
|
|
1767
2070
|
score.empty = true;
|
|
1768
|
-
score.message =
|
|
2071
|
+
score.message = strings.EXTRA_SYMBOLS_ERROR;
|
|
1769
2072
|
return score;
|
|
1770
2073
|
}
|
|
1771
2074
|
}
|
|
@@ -1788,10 +2091,10 @@ const KhanAnswerTypes = {
|
|
|
1788
2091
|
type: "predicate"
|
|
1789
2092
|
})];
|
|
1790
2093
|
},
|
|
1791
|
-
createValidatorFunctional: function (correctAnswer, options) {
|
|
2094
|
+
createValidatorFunctional: function (correctAnswer, options, strings) {
|
|
1792
2095
|
return KhanAnswerTypes.predicate.createValidatorFunctional(
|
|
1793
2096
|
// @ts-expect-error - TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
|
|
1794
|
-
...KhanAnswerTypes.number.convertToPredicate(correctAnswer, options));
|
|
2097
|
+
...KhanAnswerTypes.number.convertToPredicate(correctAnswer, options), strings);
|
|
1795
2098
|
}
|
|
1796
2099
|
},
|
|
1797
2100
|
/*
|
|
@@ -1856,7 +2159,7 @@ const KhanAnswerTypes = {
|
|
|
1856
2159
|
}
|
|
1857
2160
|
return solution;
|
|
1858
2161
|
},
|
|
1859
|
-
createValidatorFunctional: function (solution, options) {
|
|
2162
|
+
createValidatorFunctional: function (solution, options, strings) {
|
|
1860
2163
|
return function (guess) {
|
|
1861
2164
|
const score = {
|
|
1862
2165
|
empty: false,
|
|
@@ -1907,7 +2210,7 @@ const KhanAnswerTypes = {
|
|
|
1907
2210
|
// @ts-expect-error - TS2540 - Cannot assign to 'ungraded' because it is a read-only property.
|
|
1908
2211
|
score.ungraded = true;
|
|
1909
2212
|
// @ts-expect-error - TS2540 - Cannot assign to 'message' because it is a read-only property.
|
|
1910
|
-
score.message = result.wrongVariableCase ?
|
|
2213
|
+
score.message = result.wrongVariableCase ? strings.WRONG_CASE_ERROR : strings.WRONG_LETTER_ERROR;
|
|
1911
2214
|
// Don't tell the use they're "almost there" in this case, that may not be true and isn't helpful.
|
|
1912
2215
|
// @ts-expect-error - TS2339 - Property 'suppressAlmostThere' does not exist on type '{ readonly empty: false; readonly correct: false; readonly message: string | null | undefined; readonly guess: any; readonly ungraded: false; }'.
|
|
1913
2216
|
score.suppressAlmostThere = true;
|
|
@@ -1933,7 +2236,7 @@ const KhanAnswerTypes = {
|
|
|
1933
2236
|
// @ts-expect-error - TS2540 - Cannot assign to 'ungraded' because it is a read-only property.
|
|
1934
2237
|
score.ungraded = true;
|
|
1935
2238
|
// @ts-expect-error - TS2540 - Cannot assign to 'message' because it is a read-only property.
|
|
1936
|
-
score.message =
|
|
2239
|
+
score.message = strings.MULTIPLICATION_SIGN_ERROR;
|
|
1937
2240
|
} else if (resultX.message) {
|
|
1938
2241
|
// TODO(aasmund): I18nize `score.message`
|
|
1939
2242
|
// @ts-expect-error - TS2540 - Cannot assign to 'message' because it is a read-only property.
|
|
@@ -1947,9 +2250,6 @@ const KhanAnswerTypes = {
|
|
|
1947
2250
|
}
|
|
1948
2251
|
};
|
|
1949
2252
|
|
|
1950
|
-
const ERROR_TITLE = i18n__namespace._("Oops!");
|
|
1951
|
-
const ERROR_MESSAGE = i18n__namespace._("Sorry, I don't understand that!");
|
|
1952
|
-
|
|
1953
2253
|
// Map of international operator names to their English equivalents
|
|
1954
2254
|
const englishOperators = {
|
|
1955
2255
|
arctg: "arctan",
|
|
@@ -1976,8 +2276,34 @@ const deriveKeypadVersion = apiOptions => {
|
|
|
1976
2276
|
// can remove this `virtualKeypadVersion` field entirely.
|
|
1977
2277
|
return apiOptions.nativeKeypadProxy != null ? "REACT_NATIVE_KEYPAD" : "MATH_INPUT_KEYPAD_V2";
|
|
1978
2278
|
};
|
|
2279
|
+
/**
|
|
2280
|
+
* Get the character used for separating decimals.
|
|
2281
|
+
*/
|
|
2282
|
+
const getDecimalSeparator = locale => {
|
|
2283
|
+
switch (locale) {
|
|
2284
|
+
// TODO(somewhatabstract): Remove this when Chrome supports the `ka`
|
|
2285
|
+
// locale properly.
|
|
2286
|
+
// https://github.com/formatjs/formatjs/issues/1526#issuecomment-559891201
|
|
2287
|
+
//
|
|
2288
|
+
// Supported locales in Chrome:
|
|
2289
|
+
// https://source.chromium.org/chromium/chromium/src/+/master:third_party/icu/scripts/chrome_ui_languages.list
|
|
2290
|
+
case "ka":
|
|
2291
|
+
return ",";
|
|
2292
|
+
default:
|
|
2293
|
+
const numberWithDecimalSeparator = 1.1;
|
|
2294
|
+
// TODO(FEI-3647): Update to use .formatToParts() once we no longer have to
|
|
2295
|
+
// support Safari 12.
|
|
2296
|
+
const match = new Intl.NumberFormat(locale).format(numberWithDecimalSeparator)
|
|
2297
|
+
// 0x661 is ARABIC-INDIC DIGIT ONE
|
|
2298
|
+
// 0x6F1 is EXTENDED ARABIC-INDIC DIGIT ONE
|
|
2299
|
+
.match(/[^\d\u0661\u06F1]/);
|
|
2300
|
+
return match?.[0] ?? ".";
|
|
2301
|
+
}
|
|
2302
|
+
};
|
|
2303
|
+
|
|
1979
2304
|
// The new, MathQuill input expression widget
|
|
1980
2305
|
class Expression extends React__namespace.Component {
|
|
2306
|
+
static contextType = PerseusI18nContext;
|
|
1981
2307
|
_isMounted = false;
|
|
1982
2308
|
|
|
1983
2309
|
//#region Previously a class extension
|
|
@@ -2001,9 +2327,11 @@ class Expression extends React__namespace.Component {
|
|
|
2001
2327
|
*/
|
|
2002
2328
|
static validate(userInput, rubric) {
|
|
2003
2329
|
let onInputError = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {};
|
|
2330
|
+
let strings = arguments.length > 3 ? arguments[3] : undefined;
|
|
2331
|
+
let locale = arguments.length > 4 ? arguments[4] : undefined;
|
|
2004
2332
|
const options = ___default["default"].clone(rubric);
|
|
2005
2333
|
___default["default"].extend(options, {
|
|
2006
|
-
decimal_separator:
|
|
2334
|
+
decimal_separator: getDecimalSeparator(locale)
|
|
2007
2335
|
});
|
|
2008
2336
|
const createValidator = answer => {
|
|
2009
2337
|
// We give options to KAS.parse here because it is parsing the
|
|
@@ -2026,7 +2354,7 @@ class Expression extends React__namespace.Component {
|
|
|
2026
2354
|
return KhanAnswerTypes.expression.createValidatorFunctional(expression.expr, ___default["default"]({}).extend(options, {
|
|
2027
2355
|
simplify: answer.simplify,
|
|
2028
2356
|
form: answer.form
|
|
2029
|
-
}));
|
|
2357
|
+
}), strings);
|
|
2030
2358
|
};
|
|
2031
2359
|
|
|
2032
2360
|
// Find the first answer form that matches the user's input and that
|
|
@@ -2173,7 +2501,7 @@ class Expression extends React__namespace.Component {
|
|
|
2173
2501
|
if (!this.parse(this.props.value, this.props).parsed) {
|
|
2174
2502
|
const apiResult = this.props.apiOptions.onInputError(null,
|
|
2175
2503
|
// reserved for some widget identifier
|
|
2176
|
-
this.props.value,
|
|
2504
|
+
this.props.value, this.context.strings.ERROR_TITLE);
|
|
2177
2505
|
if (apiResult !== false) {
|
|
2178
2506
|
this.setState({
|
|
2179
2507
|
invalid: true
|
|
@@ -2197,7 +2525,7 @@ class Expression extends React__namespace.Component {
|
|
|
2197
2525
|
scoring,
|
|
2198
2526
|
...rubric
|
|
2199
2527
|
} = _ref;
|
|
2200
|
-
const score = Expression.validate(this.getUserInput(), rubric, onInputError || function () {});
|
|
2528
|
+
const score = Expression.validate(this.getUserInput(), rubric, onInputError || function () {}, this.context.strings, this.context.locale);
|
|
2201
2529
|
|
|
2202
2530
|
// "scoring" is a flag that indicates when we are checking answers.
|
|
2203
2531
|
// otherwise, we may just be checking validity after changes.
|
|
@@ -2229,7 +2557,7 @@ class Expression extends React__namespace.Component {
|
|
|
2229
2557
|
// make it so that solution answers with ','s or '.'s work
|
|
2230
2558
|
const options = ___default["default"].pick(props || this.props, "functions");
|
|
2231
2559
|
___default["default"].extend(options, {
|
|
2232
|
-
decimal_separator:
|
|
2560
|
+
decimal_separator: getDecimalSeparator(this.context.locale)
|
|
2233
2561
|
});
|
|
2234
2562
|
return KAS__namespace.parse(normalizeTex(value), options);
|
|
2235
2563
|
};
|
|
@@ -2318,6 +2646,10 @@ class Expression extends React__namespace.Component {
|
|
|
2318
2646
|
"perseus-widget-expression": true,
|
|
2319
2647
|
"show-error-tooltip": this.state.showErrorTooltip
|
|
2320
2648
|
});
|
|
2649
|
+
const {
|
|
2650
|
+
ERROR_MESSAGE,
|
|
2651
|
+
ERROR_TITLE
|
|
2652
|
+
} = this.context.strings;
|
|
2321
2653
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
2322
2654
|
className: className,
|
|
2323
2655
|
onBlur: () => this.state.invalid && this.setState({
|
|
@@ -2744,7 +3076,7 @@ function keScoreFromPerseusScore(score, guess, state) {
|
|
|
2744
3076
|
* Return the first valid interpretation of 'text' as a number, in the form
|
|
2745
3077
|
* {value: 2.3, exact: true}.
|
|
2746
3078
|
*/
|
|
2747
|
-
function firstNumericalParse$1(text) {
|
|
3079
|
+
function firstNumericalParse$1(text, strings) {
|
|
2748
3080
|
// TODO(alpert): This is sort of hacky...
|
|
2749
3081
|
let first;
|
|
2750
3082
|
const val = KhanAnswerTypes.predicate.createValidatorFunctional(function (ans) {
|
|
@@ -2754,7 +3086,7 @@ function firstNumericalParse$1(text) {
|
|
|
2754
3086
|
simplify: "optional",
|
|
2755
3087
|
inexact: true,
|
|
2756
3088
|
forms: "integer, proper, improper, pi, log, mixed, decimal"
|
|
2757
|
-
});
|
|
3089
|
+
}, strings);
|
|
2758
3090
|
val(text);
|
|
2759
3091
|
return first;
|
|
2760
3092
|
}
|
|
@@ -8566,8 +8898,12 @@ const KhanColors = {
|
|
|
8566
8898
|
// DrawingTransform is responsible for transforming from "math coordinates"
|
|
8567
8899
|
// (on the Cartesian plane) to "canvas coordinates" in pixels.
|
|
8568
8900
|
class DrawingTransform {
|
|
8569
|
-
|
|
8901
|
+
raphael;
|
|
8570
8902
|
|
|
8903
|
+
// Scale is measured in pixels per unit on the Cartesian plane.
|
|
8904
|
+
xScale;
|
|
8905
|
+
yScale;
|
|
8906
|
+
bounds;
|
|
8571
8907
|
constructor(raphael, initialScale, bounds) {
|
|
8572
8908
|
this.raphael = raphael;
|
|
8573
8909
|
this.bounds = bounds;
|
|
@@ -8632,6 +8968,10 @@ class DrawingTransform {
|
|
|
8632
8968
|
// Defines the bounds of the visible area of a graph, in Cartesian coordinates.
|
|
8633
8969
|
// GraphBounds is immutable.
|
|
8634
8970
|
class GraphBounds {
|
|
8971
|
+
xMin;
|
|
8972
|
+
xMax;
|
|
8973
|
+
yMin;
|
|
8974
|
+
yMax;
|
|
8635
8975
|
constructor(xRange, yRange) {
|
|
8636
8976
|
this.xMin = xRange[0];
|
|
8637
8977
|
this.xMax = xRange[1];
|
|
@@ -8735,26 +9075,35 @@ function polar(r, th) {
|
|
|
8735
9075
|
return [r[0] * Math.cos(th), r[1] * Math.sin(th)];
|
|
8736
9076
|
}
|
|
8737
9077
|
class Graphie$1 {
|
|
9078
|
+
el;
|
|
8738
9079
|
#bounds;
|
|
8739
9080
|
#drawingTransform;
|
|
8740
9081
|
|
|
8741
9082
|
// The primary drawing layer
|
|
8742
|
-
|
|
9083
|
+
raphael;
|
|
8743
9084
|
// The layer that all visuals with mouse handlers are drawn into
|
|
8744
|
-
|
|
9085
|
+
mouselayer;
|
|
9086
|
+
_mouselayerWrapper;
|
|
9087
|
+
_visiblelayerWrapper;
|
|
8745
9088
|
isMobile = false;
|
|
8746
9089
|
// Set up some reasonable defaults
|
|
8747
9090
|
currentStyle = {
|
|
8748
9091
|
"stroke-width": 2,
|
|
8749
9092
|
fill: "none"
|
|
8750
9093
|
};
|
|
8751
|
-
|
|
9094
|
+
range;
|
|
9095
|
+
scale;
|
|
9096
|
+
dimensions;
|
|
8752
9097
|
// TODO(benchristel): xpixels and ypixels are never used by this class, but
|
|
8753
9098
|
// other code reaches in to access them :(
|
|
8754
9099
|
// Refactor to accessor methods that look at this.dimensions.
|
|
9100
|
+
xpixels;
|
|
9101
|
+
ypixels;
|
|
9102
|
+
|
|
8755
9103
|
// set by Movables
|
|
8756
9104
|
// TODO(benchristel): consider putting this state on the Movable instead of
|
|
8757
9105
|
// on the Graphie
|
|
9106
|
+
isDragging;
|
|
8758
9107
|
constructor(el) {
|
|
8759
9108
|
this.el = el;
|
|
8760
9109
|
$__default["default"](el).css("position", "relative");
|
|
@@ -10286,6 +10635,8 @@ const getClipPoint = function (graph, coord, angle) {
|
|
|
10286
10635
|
*/
|
|
10287
10636
|
|
|
10288
10637
|
class WrappedDrawing {
|
|
10638
|
+
graphie;
|
|
10639
|
+
initialPoint;
|
|
10289
10640
|
constructor(graphie, initialPoint) {
|
|
10290
10641
|
this.graphie = graphie;
|
|
10291
10642
|
this.initialPoint = initialPoint;
|
|
@@ -10346,6 +10697,8 @@ const DEFAULT_OPTIONS$2 = {
|
|
|
10346
10697
|
mouselayer: false
|
|
10347
10698
|
};
|
|
10348
10699
|
class WrappedPath extends WrappedDrawing {
|
|
10700
|
+
wrapper;
|
|
10701
|
+
visibleShape;
|
|
10349
10702
|
constructor(graphie, points, options) {
|
|
10350
10703
|
const initialPoint = graphie.scalePoint(___default["default"].head(points));
|
|
10351
10704
|
super(graphie, initialPoint);
|
|
@@ -10368,6 +10721,7 @@ class WrappedPath extends WrappedDrawing {
|
|
|
10368
10721
|
|
|
10369
10722
|
class Arrowhead$1 extends WrappedPath {
|
|
10370
10723
|
static scale = 1.4;
|
|
10724
|
+
center;
|
|
10371
10725
|
constructor(graphie, style) {
|
|
10372
10726
|
// Points that define the arrowhead
|
|
10373
10727
|
const center = [0.75, 0];
|
|
@@ -10413,6 +10767,9 @@ const DEFAULT_OPTIONS$1 = {
|
|
|
10413
10767
|
disableMouseEventsOnWrapper: false
|
|
10414
10768
|
};
|
|
10415
10769
|
class WrappedEllipse extends WrappedDrawing {
|
|
10770
|
+
initialPoint;
|
|
10771
|
+
wrapper;
|
|
10772
|
+
visibleShape;
|
|
10416
10773
|
constructor(graphie, center, radii, options) {
|
|
10417
10774
|
super(graphie, center);
|
|
10418
10775
|
options = ___default["default"].extend({}, DEFAULT_OPTIONS$1, options);
|
|
@@ -10460,6 +10817,9 @@ const DEFAULT_OPTIONS = {
|
|
|
10460
10817
|
mouselayer: false
|
|
10461
10818
|
};
|
|
10462
10819
|
class WrappedLine extends WrappedDrawing {
|
|
10820
|
+
initialLength;
|
|
10821
|
+
wrapper;
|
|
10822
|
+
visibleShape;
|
|
10463
10823
|
constructor(graphie, start, end, options) {
|
|
10464
10824
|
// Always make the line as large as possible and horizontal; this
|
|
10465
10825
|
// simplifies a lot of the transforms, e.g., we can rotate by exactly the
|
|
@@ -13753,6 +14113,9 @@ const DEFAULT_STATE$3 = {
|
|
|
13753
14113
|
mouseTarget: null
|
|
13754
14114
|
};
|
|
13755
14115
|
class Movable {
|
|
14116
|
+
graphie;
|
|
14117
|
+
state;
|
|
14118
|
+
prevState;
|
|
13756
14119
|
// TODO(benchristel): delete _listenerMap; it's unused
|
|
13757
14120
|
_listenerMap = {};
|
|
13758
14121
|
constructor(graphie, options) {
|
|
@@ -13878,12 +14241,12 @@ class Movable {
|
|
|
13878
14241
|
* Fire an onSomething type event to all functions in listeners
|
|
13879
14242
|
*/
|
|
13880
14243
|
_fireEvent(listeners) {
|
|
13881
|
-
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
13882
|
-
args[_key - 1] = arguments[_key];
|
|
13883
|
-
}
|
|
13884
14244
|
if (listeners == null) {
|
|
13885
14245
|
return;
|
|
13886
14246
|
}
|
|
14247
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
14248
|
+
args[_key - 1] = arguments[_key];
|
|
14249
|
+
}
|
|
13887
14250
|
for (const listener of listeners) {
|
|
13888
14251
|
listener.call(this, ...args);
|
|
13889
14252
|
}
|
|
@@ -15016,8 +15379,12 @@ const DEFAULT_STATE$1 = {
|
|
|
15016
15379
|
// tooltipResetFunctions, but never remove them.
|
|
15017
15380
|
const tooltipResetFunctions = [];
|
|
15018
15381
|
class MovablePoint$4 {
|
|
15382
|
+
graphie;
|
|
15383
|
+
movable;
|
|
15384
|
+
state;
|
|
15019
15385
|
// @ts-expect-error - TS2564: Property 'prevState' has no initializer and is not definitely assigned in the constructor.
|
|
15020
|
-
|
|
15386
|
+
prevState;
|
|
15387
|
+
_tooltip;
|
|
15021
15388
|
_listenerMap = {};
|
|
15022
15389
|
constructor(graphie, movable, options) {
|
|
15023
15390
|
this.graphie = graphie;
|
|
@@ -16706,6 +17073,7 @@ const Status = {
|
|
|
16706
17073
|
FAILED: "failed"
|
|
16707
17074
|
};
|
|
16708
17075
|
class ImageLoader extends React__namespace.Component {
|
|
17076
|
+
img;
|
|
16709
17077
|
constructor(props) {
|
|
16710
17078
|
super(props);
|
|
16711
17079
|
this.state = {
|
|
@@ -16942,6 +17310,7 @@ function defaultPreloader(dimensions) {
|
|
|
16942
17310
|
}));
|
|
16943
17311
|
}
|
|
16944
17312
|
class SvgImage extends React__namespace.Component {
|
|
17313
|
+
_isMounted;
|
|
16945
17314
|
static defaultProps = {
|
|
16946
17315
|
constrainHeight: false,
|
|
16947
17316
|
onUpdate: () => {},
|
|
@@ -17387,6 +17756,7 @@ class SvgImage extends React__namespace.Component {
|
|
|
17387
17756
|
* have been loaded. This tracking is facilitated by the AssetContext.
|
|
17388
17757
|
*/
|
|
17389
17758
|
class Tex extends React__namespace.Component {
|
|
17759
|
+
_hasRendered;
|
|
17390
17760
|
static defaultProps = {
|
|
17391
17761
|
onRender: () => {},
|
|
17392
17762
|
setAssetStatus: (src, status) => {}
|
|
@@ -17428,13 +17798,14 @@ class Tex extends React__namespace.Component {
|
|
|
17428
17798
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
17429
17799
|
class Zoomable extends React__namespace.Component {
|
|
17430
17800
|
// @ts-expect-error - TS2564 - Property '_isMounted' has no initializer and is not definitely assigned in the constructor.
|
|
17431
|
-
|
|
17801
|
+
_isMounted;
|
|
17432
17802
|
// @ts-expect-error - TS2564 - Property '_observer' has no initializer and is not definitely assigned in the constructor.
|
|
17433
|
-
|
|
17803
|
+
_observer;
|
|
17434
17804
|
// @ts-expect-error - TS2564 - Property '_measuringInitialized' has no initializer and is not definitely assigned in the constructor.
|
|
17435
|
-
|
|
17805
|
+
_measuringInitialized;
|
|
17806
|
+
_originalWidth;
|
|
17436
17807
|
// @ts-expect-error - TS2564 - Property '_node' has no initializer and is not definitely assigned in the constructor.
|
|
17437
|
-
|
|
17808
|
+
_node;
|
|
17438
17809
|
static defaultProps = {
|
|
17439
17810
|
animateHeight: false,
|
|
17440
17811
|
readyToMeasure: true,
|
|
@@ -17793,13 +18164,15 @@ function _noop() {}
|
|
|
17793
18164
|
*/
|
|
17794
18165
|
class InteractionTracker {
|
|
17795
18166
|
// @ts-expect-error - TS2564 - Property '_tracked' has no initializer and is not definitely assigned in the constructor.
|
|
17796
|
-
|
|
18167
|
+
_tracked;
|
|
17797
18168
|
// @ts-expect-error - TS2564 - Property 'setting' has no initializer and is not definitely assigned in the constructor.
|
|
17798
|
-
|
|
18169
|
+
setting;
|
|
18170
|
+
track;
|
|
18171
|
+
trackApi;
|
|
17799
18172
|
// @ts-expect-error - TS2564 - Property 'widgetID' has no initializer and is not definitely assigned in the constructor.
|
|
17800
|
-
|
|
18173
|
+
widgetID;
|
|
17801
18174
|
// @ts-expect-error - TS2564 - Property 'widgetType' has no initializer and is not definitely assigned in the constructor.
|
|
17802
|
-
|
|
18175
|
+
widgetType;
|
|
17803
18176
|
constructor(trackApi, widgetType, widgetID, setting) {
|
|
17804
18177
|
if (!trackApi) {
|
|
17805
18178
|
this.track = _noop;
|
|
@@ -17911,6 +18284,7 @@ var Severity = /*#__PURE__*/function (Severity) {
|
|
|
17911
18284
|
* to the left of where it belongs. And if there is more
|
|
17912
18285
|
**/
|
|
17913
18286
|
class Lint extends React__namespace.Component {
|
|
18287
|
+
_positionTimeout;
|
|
17914
18288
|
state = {
|
|
17915
18289
|
tooltipAbove: true
|
|
17916
18290
|
};
|
|
@@ -18367,7 +18741,7 @@ const rules$1 = {
|
|
|
18367
18741
|
// just a stub for testing.
|
|
18368
18742
|
return /*#__PURE__*/React__namespace.createElement("em", {
|
|
18369
18743
|
key: state.key
|
|
18370
|
-
},
|
|
18744
|
+
}, `[Widget: ${node.id}]`);
|
|
18371
18745
|
}
|
|
18372
18746
|
},
|
|
18373
18747
|
blockMath: {
|
|
@@ -18855,9 +19229,8 @@ const getWidget = name => {
|
|
|
18855
19229
|
}
|
|
18856
19230
|
|
|
18857
19231
|
// Allow widgets to specify a widget directly or via a function
|
|
18858
|
-
if (widgets[name]
|
|
18859
|
-
|
|
18860
|
-
return widgets[name].getWidget();
|
|
19232
|
+
if (widgets[name]?.getWidget) {
|
|
19233
|
+
return widgets[name].getWidget?.();
|
|
18861
19234
|
}
|
|
18862
19235
|
return widgets[name].widget;
|
|
18863
19236
|
};
|
|
@@ -19009,7 +19382,7 @@ const upgradeWidgetInfoToLatestVersion = oldWidgetInfo => {
|
|
|
19009
19382
|
options: newEditorProps
|
|
19010
19383
|
});
|
|
19011
19384
|
};
|
|
19012
|
-
const getRendererPropsForWidgetInfo = (widgetInfo, problemNum) => {
|
|
19385
|
+
const getRendererPropsForWidgetInfo = (widgetInfo, strings, problemNum) => {
|
|
19013
19386
|
const type = widgetInfo.type;
|
|
19014
19387
|
const widgetExports = widgets[type];
|
|
19015
19388
|
if (widgetExports == null) {
|
|
@@ -19030,7 +19403,7 @@ const getRendererPropsForWidgetInfo = (widgetInfo, problemNum) => {
|
|
|
19030
19403
|
transform = widgetExports.transform || ___default["default"].identity;
|
|
19031
19404
|
}
|
|
19032
19405
|
// widgetInfo.options are the widgetEditor's props:
|
|
19033
|
-
return transform(widgetInfo.options, problemNum);
|
|
19406
|
+
return transform(widgetInfo.options, strings, problemNum);
|
|
19034
19407
|
};
|
|
19035
19408
|
const traverseChildWidgets$3 = (widgetInfo, traverseRenderer) => {
|
|
19036
19409
|
if (!traverseRenderer) {
|
|
@@ -19374,24 +19747,26 @@ const isIdPathPrefix = function (prefixArray, wholeArray) {
|
|
|
19374
19747
|
* scoring, state serialization/deserialization, and focus management.
|
|
19375
19748
|
*/
|
|
19376
19749
|
class Renderer extends React__namespace.Component {
|
|
19750
|
+
_currentFocus;
|
|
19377
19751
|
// @ts-expect-error - TS2564 - Property '_foundTextNodes' has no initializer and is not definitely assigned in the constructor.
|
|
19378
|
-
|
|
19752
|
+
_foundTextNodes;
|
|
19379
19753
|
// @ts-expect-error - TS2564 - Property '_interactionTrackers' has no initializer and is not definitely assigned in the constructor.
|
|
19380
|
-
|
|
19754
|
+
_interactionTrackers;
|
|
19381
19755
|
// @ts-expect-error - TS2564 - Property '_isMounted' has no initializer and is not definitely assigned in the constructor.
|
|
19382
|
-
|
|
19756
|
+
_isMounted;
|
|
19383
19757
|
// @ts-expect-error - TS2564 - Property '_isTwoColumn' has no initializer and is not definitely assigned in the constructor.
|
|
19758
|
+
_isTwoColumn;
|
|
19384
19759
|
|
|
19385
19760
|
// The i18n linter.
|
|
19386
|
-
|
|
19761
|
+
_translationLinter;
|
|
19387
19762
|
_widgetContainers = new Map();
|
|
19388
|
-
|
|
19763
|
+
lastRenderedMarkdown;
|
|
19389
19764
|
// @ts-expect-error - TS2564 - Property 'reuseMarkdown' has no initializer and is not definitely assigned in the constructor.
|
|
19390
|
-
|
|
19765
|
+
reuseMarkdown;
|
|
19391
19766
|
// @ts-expect-error - TS2564 - Property 'translationIndex' has no initializer and is not definitely assigned in the constructor.
|
|
19392
|
-
|
|
19767
|
+
translationIndex;
|
|
19393
19768
|
// @ts-expect-error - TS2564 - Property 'widgetIds' has no initializer and is not definitely assigned in the constructor.
|
|
19394
|
-
|
|
19769
|
+
widgetIds;
|
|
19395
19770
|
static defaultProps = {
|
|
19396
19771
|
content: "",
|
|
19397
19772
|
widgets: {},
|
|
@@ -19590,9 +19965,12 @@ class Renderer extends React__namespace.Component {
|
|
|
19590
19965
|
problemNum
|
|
19591
19966
|
} = props;
|
|
19592
19967
|
const widgetsStartProps = {};
|
|
19968
|
+
const {
|
|
19969
|
+
strings
|
|
19970
|
+
} = this.props;
|
|
19593
19971
|
wonderStuffCore.entries(allWidgetInfo).forEach(_ref => {
|
|
19594
19972
|
let [key, widgetInfo] = _ref;
|
|
19595
|
-
widgetsStartProps[key] = getRendererPropsForWidgetInfo(widgetInfo, problemNum);
|
|
19973
|
+
widgetsStartProps[key] = getRendererPropsForWidgetInfo(widgetInfo, strings, problemNum);
|
|
19596
19974
|
});
|
|
19597
19975
|
|
|
19598
19976
|
// Call the onWidgetStartProps callback if it exists
|
|
@@ -21058,6 +21436,7 @@ class TextInput extends React__namespace.Component {
|
|
|
21058
21436
|
value: "",
|
|
21059
21437
|
disabled: false
|
|
21060
21438
|
};
|
|
21439
|
+
id;
|
|
21061
21440
|
constructor(props) {
|
|
21062
21441
|
super(props);
|
|
21063
21442
|
if (props.id) {
|
|
@@ -21383,6 +21762,7 @@ const {
|
|
|
21383
21762
|
captureScratchpadTouchStart: captureScratchpadTouchStart$2
|
|
21384
21763
|
} = Util;
|
|
21385
21764
|
class InputWithExamples extends React__namespace.Component {
|
|
21765
|
+
static contextType = PerseusI18nContext;
|
|
21386
21766
|
static defaultProps = {
|
|
21387
21767
|
type: "text",
|
|
21388
21768
|
shouldShowExamples: true,
|
|
@@ -21505,7 +21885,8 @@ class InputWithExamples extends React__namespace.Component {
|
|
|
21505
21885
|
id: this._getUniqueId()
|
|
21506
21886
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
21507
21887
|
content: examplesContent,
|
|
21508
|
-
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "input-with-examples")
|
|
21888
|
+
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "input-with-examples"),
|
|
21889
|
+
strings: this.context.strings
|
|
21509
21890
|
})));
|
|
21510
21891
|
}
|
|
21511
21892
|
_handleFocus = () => {
|
|
@@ -21653,35 +22034,36 @@ const answerTypes = {
|
|
|
21653
22034
|
}
|
|
21654
22035
|
};
|
|
21655
22036
|
const formExamples$1 = {
|
|
21656
|
-
integer: function (options) {
|
|
21657
|
-
return
|
|
22037
|
+
integer: function (options, strings) {
|
|
22038
|
+
return strings.integerExample;
|
|
21658
22039
|
},
|
|
21659
|
-
proper: function (options) {
|
|
22040
|
+
proper: function (options, strings) {
|
|
21660
22041
|
if (options.simplify === "optional") {
|
|
21661
|
-
return
|
|
22042
|
+
return strings.properExample;
|
|
21662
22043
|
}
|
|
21663
|
-
return
|
|
22044
|
+
return strings.simplifiedProperExample;
|
|
21664
22045
|
},
|
|
21665
|
-
improper: function (options) {
|
|
22046
|
+
improper: function (options, strings) {
|
|
21666
22047
|
if (options.simplify === "optional") {
|
|
21667
|
-
return
|
|
22048
|
+
return strings.improperExample;
|
|
21668
22049
|
}
|
|
21669
|
-
return
|
|
22050
|
+
return strings.simplifiedImproperExample;
|
|
21670
22051
|
},
|
|
21671
|
-
mixed: function (options) {
|
|
21672
|
-
return
|
|
22052
|
+
mixed: function (options, strings) {
|
|
22053
|
+
return strings.mixedExample;
|
|
21673
22054
|
},
|
|
21674
|
-
decimal: function (options) {
|
|
21675
|
-
return
|
|
22055
|
+
decimal: function (options, strings) {
|
|
22056
|
+
return strings.decimalExample;
|
|
21676
22057
|
},
|
|
21677
|
-
percent: function (options) {
|
|
21678
|
-
return
|
|
22058
|
+
percent: function (options, strings) {
|
|
22059
|
+
return strings.percentExample;
|
|
21679
22060
|
},
|
|
21680
|
-
pi: function (options) {
|
|
21681
|
-
return
|
|
22061
|
+
pi: function (options, strings) {
|
|
22062
|
+
return strings.piExample;
|
|
21682
22063
|
}
|
|
21683
22064
|
};
|
|
21684
22065
|
class InputNumber extends React__namespace.Component {
|
|
22066
|
+
static contextType = PerseusI18nContext;
|
|
21685
22067
|
static defaultProps = {
|
|
21686
22068
|
currentValue: "",
|
|
21687
22069
|
size: "normal",
|
|
@@ -21795,21 +22177,19 @@ class InputNumber extends React__namespace.Component {
|
|
|
21795
22177
|
};
|
|
21796
22178
|
simpleValidate = (rubric, onInputError) => {
|
|
21797
22179
|
onInputError = onInputError || function () {};
|
|
21798
|
-
return InputNumber.validate(this.getUserInput(), rubric, onInputError);
|
|
22180
|
+
return InputNumber.validate(this.getUserInput(), rubric, this.context.strings, onInputError);
|
|
21799
22181
|
};
|
|
21800
22182
|
examples = () => {
|
|
22183
|
+
const {
|
|
22184
|
+
strings
|
|
22185
|
+
} = this.context;
|
|
21801
22186
|
const type = this.props.answerType;
|
|
21802
22187
|
const forms = answerTypes[type].forms.split(/\s*,\s*/);
|
|
21803
|
-
const examples = ___default["default"].map(forms,
|
|
21804
|
-
|
|
21805
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
21806
|
-
// eslint-disable-next-line @babel/no-invalid-this
|
|
21807
|
-
return formExamples$1[form](this.props);
|
|
21808
|
-
}, this);
|
|
21809
|
-
return [i18n__namespace._("**Your answer should be** ")].concat(examples);
|
|
22188
|
+
const examples = ___default["default"].map(forms, form => formExamples$1[form](this.props, strings));
|
|
22189
|
+
return [strings.yourAnswer].concat(examples);
|
|
21810
22190
|
};
|
|
21811
|
-
static validate(state, rubric) {
|
|
21812
|
-
let onInputError = arguments.length >
|
|
22191
|
+
static validate(state, rubric, strings) {
|
|
22192
|
+
let onInputError = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : () => {};
|
|
21813
22193
|
if (rubric.answerType == null) {
|
|
21814
22194
|
rubric.answerType = "number";
|
|
21815
22195
|
}
|
|
@@ -21823,7 +22203,7 @@ class InputNumber extends React__namespace.Component {
|
|
|
21823
22203
|
inexact: rubric.inexact || undefined,
|
|
21824
22204
|
maxError: rubric.maxError,
|
|
21825
22205
|
forms: answerTypes[rubric.answerType].forms
|
|
21826
|
-
});
|
|
22206
|
+
}, strings);
|
|
21827
22207
|
|
|
21828
22208
|
// We may have received TeX; try to parse it before grading.
|
|
21829
22209
|
// If `currentValue` is not TeX, this should be a no-op.
|
|
@@ -21938,14 +22318,16 @@ const answerFormButtons = [{
|
|
|
21938
22318
|
content: "\u03C0"
|
|
21939
22319
|
}];
|
|
21940
22320
|
const formExamples = {
|
|
21941
|
-
integer: () =>
|
|
21942
|
-
proper: form => form.simplify === "optional" ?
|
|
21943
|
-
improper: form => form.simplify === "optional" ?
|
|
21944
|
-
mixed: () =>
|
|
21945
|
-
decimal: () =>
|
|
21946
|
-
pi: () =>
|
|
22321
|
+
integer: (form, strings) => strings.integerExample,
|
|
22322
|
+
proper: (form, strings) => form.simplify === "optional" ? strings.properExample : strings.simplifiedProperExample,
|
|
22323
|
+
improper: (form, strings) => form.simplify === "optional" ? strings.improperExample : strings.simplifiedImproperExample,
|
|
22324
|
+
mixed: (form, strings) => strings.mixedExample,
|
|
22325
|
+
decimal: (form, strings) => strings.decimalExample,
|
|
22326
|
+
pi: (form, strings) => strings.piExample
|
|
21947
22327
|
};
|
|
21948
22328
|
class NumericInput extends React__namespace.Component {
|
|
22329
|
+
static contextType = PerseusI18nContext;
|
|
22330
|
+
inputRef;
|
|
21949
22331
|
static defaultProps = {
|
|
21950
22332
|
currentValue: "",
|
|
21951
22333
|
size: "normal",
|
|
@@ -21989,7 +22371,7 @@ class NumericInput extends React__namespace.Component {
|
|
|
21989
22371
|
}
|
|
21990
22372
|
return answerStrings[0];
|
|
21991
22373
|
}
|
|
21992
|
-
static validate(userInput, rubric) {
|
|
22374
|
+
static validate(userInput, rubric, strings) {
|
|
21993
22375
|
const defaultAnswerForms = answerFormButtons.map(e => e["value"])
|
|
21994
22376
|
// Don't default to validating the answer as a pi answer
|
|
21995
22377
|
// if answerForm isn't set on the answer
|
|
@@ -22015,7 +22397,7 @@ class NumericInput extends React__namespace.Component {
|
|
|
22015
22397
|
// TODO(merlob) backfill / delete
|
|
22016
22398
|
maxError: answer.maxError,
|
|
22017
22399
|
forms: validatorForms
|
|
22018
|
-
});
|
|
22400
|
+
}, strings);
|
|
22019
22401
|
};
|
|
22020
22402
|
|
|
22021
22403
|
// We may have received TeX; try to parse it before grading.
|
|
@@ -22098,13 +22480,12 @@ class NumericInput extends React__namespace.Component {
|
|
|
22098
22480
|
};
|
|
22099
22481
|
});
|
|
22100
22482
|
let examples = ___default["default"].map(forms, form => {
|
|
22101
|
-
|
|
22102
|
-
return formExamples[form.name](form);
|
|
22483
|
+
return formExamples[form.name](form, this.context.strings);
|
|
22103
22484
|
});
|
|
22104
22485
|
// Ensure no duplicate tooltip text from simplified and unsimplified
|
|
22105
22486
|
// versions of the same format
|
|
22106
22487
|
examples = ___default["default"].uniq(examples);
|
|
22107
|
-
return [
|
|
22488
|
+
return [this.context.strings.yourAnswer].concat(examples);
|
|
22108
22489
|
};
|
|
22109
22490
|
shouldShowExamples = () => {
|
|
22110
22491
|
const noFormsAccepted = this.props.answerForms?.length === 0;
|
|
@@ -22116,7 +22497,7 @@ class NumericInput extends React__namespace.Component {
|
|
|
22116
22497
|
return !noFormsAccepted && !allFormsAccepted;
|
|
22117
22498
|
};
|
|
22118
22499
|
simpleValidate = rubric => {
|
|
22119
|
-
return NumericInput.validate(this.getUserInput(), rubric);
|
|
22500
|
+
return NumericInput.validate(this.getUserInput(), rubric, this.context.strings);
|
|
22120
22501
|
};
|
|
22121
22502
|
focus = () => {
|
|
22122
22503
|
this.inputRef?.focus();
|
|
@@ -22162,7 +22543,7 @@ class NumericInput extends React__namespace.Component {
|
|
|
22162
22543
|
render() {
|
|
22163
22544
|
let labelText = this.props.labelText;
|
|
22164
22545
|
if (labelText == null || labelText === "") {
|
|
22165
|
-
labelText =
|
|
22546
|
+
labelText = this.context.strings.yourAnswerLabel;
|
|
22166
22547
|
}
|
|
22167
22548
|
|
|
22168
22549
|
// To right align a custom keypad we need to wrap it.
|
|
@@ -22309,11 +22690,12 @@ var NumericInput$1 = {
|
|
|
22309
22690
|
/* eslint-disable react/sort-comp */
|
|
22310
22691
|
const EN_DASH$1 = "\u2013";
|
|
22311
22692
|
class PassageRef extends React__namespace.Component {
|
|
22693
|
+
static contextType = PerseusI18nContext;
|
|
22312
22694
|
displayName = "PassageRef";
|
|
22313
22695
|
// @ts-expect-error - TS2564 - Property '_isMounted' has no initializer and is not definitely assigned in the constructor.
|
|
22314
|
-
|
|
22696
|
+
_isMounted;
|
|
22315
22697
|
// @ts-expect-error - TS2564 - Property '_throttledUpdateRange' has no initializer and is not definitely assigned in the constructor.
|
|
22316
|
-
|
|
22698
|
+
_throttledUpdateRange;
|
|
22317
22699
|
static defaultProps = {
|
|
22318
22700
|
passageNumber: 1,
|
|
22319
22701
|
referenceNumber: 1,
|
|
@@ -22333,18 +22715,21 @@ class PassageRef extends React__namespace.Component {
|
|
|
22333
22715
|
return removeDenylistProps(this.props);
|
|
22334
22716
|
};
|
|
22335
22717
|
render() {
|
|
22718
|
+
const {
|
|
22719
|
+
strings
|
|
22720
|
+
} = this.context;
|
|
22336
22721
|
const lineRange = this.state.lineRange;
|
|
22337
22722
|
let lineRangeOutput;
|
|
22338
22723
|
if (!lineRange) {
|
|
22339
|
-
lineRangeOutput =
|
|
22724
|
+
lineRangeOutput = strings.lineRange({
|
|
22340
22725
|
lineRange: `?${EN_DASH$1}?`
|
|
22341
22726
|
});
|
|
22342
22727
|
} else if (lineRange[0] === lineRange[1]) {
|
|
22343
|
-
lineRangeOutput =
|
|
22344
|
-
lineNumber: lineRange[0]
|
|
22728
|
+
lineRangeOutput = strings.lineNumber({
|
|
22729
|
+
lineNumber: String(lineRange[0])
|
|
22345
22730
|
});
|
|
22346
22731
|
} else {
|
|
22347
|
-
lineRangeOutput =
|
|
22732
|
+
lineRangeOutput = strings.lineRange({
|
|
22348
22733
|
lineRange: lineRange[0] + EN_DASH$1 + lineRange[1]
|
|
22349
22734
|
});
|
|
22350
22735
|
}
|
|
@@ -22784,7 +23169,7 @@ class Icon extends React__namespace.Component {
|
|
|
22784
23169
|
}
|
|
22785
23170
|
}
|
|
22786
23171
|
|
|
22787
|
-
function getA11yText(letter, checked, correct, crossedOut, showCorrectness) {
|
|
23172
|
+
function getA11yText(letter, checked, correct, crossedOut, showCorrectness, strings) {
|
|
22788
23173
|
// There are two pieces of metadata we want to add to each a11yText:
|
|
22789
23174
|
// whether the answer was checked/crossed-out/neither, and whether the
|
|
22790
23175
|
// answer is correct/incorrect/not-yet-revealed.
|
|
@@ -22793,45 +23178,45 @@ function getA11yText(letter, checked, correct, crossedOut, showCorrectness) {
|
|
|
22793
23178
|
// we've just enumerated all 9 possibilities as separate strings.
|
|
22794
23179
|
if (showCorrectness && correct) {
|
|
22795
23180
|
if (checked) {
|
|
22796
|
-
return
|
|
23181
|
+
return strings.choiceCheckedCorrect({
|
|
22797
23182
|
letter
|
|
22798
23183
|
});
|
|
22799
23184
|
}
|
|
22800
23185
|
if (crossedOut) {
|
|
22801
|
-
return
|
|
23186
|
+
return strings.choiceCrossedOutCorrect({
|
|
22802
23187
|
letter
|
|
22803
23188
|
});
|
|
22804
23189
|
}
|
|
22805
|
-
return
|
|
23190
|
+
return strings.choiceCorrect({
|
|
22806
23191
|
letter
|
|
22807
23192
|
});
|
|
22808
23193
|
}
|
|
22809
23194
|
if (showCorrectness && !correct) {
|
|
22810
23195
|
if (checked) {
|
|
22811
|
-
return
|
|
23196
|
+
return strings.choiceCheckedIncorrect({
|
|
22812
23197
|
letter
|
|
22813
23198
|
});
|
|
22814
23199
|
}
|
|
22815
23200
|
if (crossedOut) {
|
|
22816
|
-
return
|
|
23201
|
+
return strings.choiceCrossedOutIncorrect({
|
|
22817
23202
|
letter
|
|
22818
23203
|
});
|
|
22819
23204
|
}
|
|
22820
|
-
return
|
|
23205
|
+
return strings.choiceIncorrect({
|
|
22821
23206
|
letter
|
|
22822
23207
|
});
|
|
22823
23208
|
}
|
|
22824
23209
|
if (checked) {
|
|
22825
|
-
return
|
|
23210
|
+
return strings.choiceChecked({
|
|
22826
23211
|
letter
|
|
22827
23212
|
});
|
|
22828
23213
|
}
|
|
22829
23214
|
if (crossedOut) {
|
|
22830
|
-
return
|
|
23215
|
+
return strings.choiceCrossedOut({
|
|
22831
23216
|
letter
|
|
22832
23217
|
});
|
|
22833
23218
|
}
|
|
22834
|
-
return
|
|
23219
|
+
return strings.choice({
|
|
22835
23220
|
letter
|
|
22836
23221
|
});
|
|
22837
23222
|
}
|
|
@@ -22853,7 +23238,7 @@ const FocusRing = function (props) {
|
|
|
22853
23238
|
borderRadius
|
|
22854
23239
|
};
|
|
22855
23240
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
22856
|
-
"data-
|
|
23241
|
+
"data-testid": "focus-ring",
|
|
22857
23242
|
className: aphrodite.css(styles$z.ring),
|
|
22858
23243
|
style: style
|
|
22859
23244
|
}, children);
|
|
@@ -22878,18 +23263,8 @@ const styles$z = aphrodite.StyleSheet.create({
|
|
|
22878
23263
|
* "choice letter". (For example, in English, `getChoiceLetter(0)` is "A",
|
|
22879
23264
|
* `getChoiceLetter(1)` is "B", etc.)
|
|
22880
23265
|
*/
|
|
22881
|
-
function getChoiceLetter(pos) {
|
|
22882
|
-
|
|
22883
|
-
* front of multiple-choice options. For instance, a multiple-choice
|
|
22884
|
-
* question with three options would display
|
|
22885
|
-
* (A) first option
|
|
22886
|
-
* (B) second option
|
|
22887
|
-
* (C) third option
|
|
22888
|
-
* There must be spaces between each of the different characters. The
|
|
22889
|
-
* characters will show up next to options in the order that they are
|
|
22890
|
-
* listed here. Most multiple choice questions have 5 or fewer options.
|
|
22891
|
-
*/
|
|
22892
|
-
const lettersString = i18n__namespace._("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z");
|
|
23266
|
+
function getChoiceLetter(pos, strings) {
|
|
23267
|
+
const lettersString = strings.letters;
|
|
22893
23268
|
const letters = lettersString.split(" ");
|
|
22894
23269
|
if (pos < letters.length) {
|
|
22895
23270
|
// If the position we need is listed in the localized string, use that.
|
|
@@ -22924,7 +23299,7 @@ const CrossOutLine = function (props) {
|
|
|
22924
23299
|
height: CROSS_OUT_LINE_SIZE,
|
|
22925
23300
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
22926
23301
|
className: aphrodite.css(styles$x.crossOutLine),
|
|
22927
|
-
"data-
|
|
23302
|
+
"data-testid": "choice-icon__cross-out-line"
|
|
22928
23303
|
}, /*#__PURE__*/React__namespace.createElement("line", {
|
|
22929
23304
|
// The line stretches from the bottom-left to top-right.
|
|
22930
23305
|
// We don't quite go to the _very_ corner, because the cute
|
|
@@ -22953,7 +23328,10 @@ function ChoiceInner(props) {
|
|
|
22953
23328
|
showCorrectness,
|
|
22954
23329
|
correct
|
|
22955
23330
|
} = props;
|
|
22956
|
-
const
|
|
23331
|
+
const {
|
|
23332
|
+
strings
|
|
23333
|
+
} = usePerseusI18n();
|
|
23334
|
+
const letter = getChoiceLetter(pos, strings);
|
|
22957
23335
|
if (!showCorrectness) {
|
|
22958
23336
|
return letter;
|
|
22959
23337
|
}
|
|
@@ -23027,7 +23405,7 @@ const ChoiceIcon = function (props) {
|
|
|
23027
23405
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
23028
23406
|
// @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
23029
23407
|
style: dynamicStyles,
|
|
23030
|
-
"data-
|
|
23408
|
+
"data-testid": "choice-icon__library-choice-icon",
|
|
23031
23409
|
className: aphrodite.css(styles$w.circle, showCorrectness && correct && styles$w.circleCorrect, showCorrectness && !correct && styles$w.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$w.circleIncorrectAnswered)
|
|
23032
23410
|
// used in BaseRadio editMode to check
|
|
23033
23411
|
// if we actually clicked on the radio icon
|
|
@@ -23099,24 +23477,24 @@ const styles$w = aphrodite.StyleSheet.create({
|
|
|
23099
23477
|
* ChoiceIcon visualizations but is meant to make the distinctions
|
|
23100
23478
|
* between the states more immediately clear to users.
|
|
23101
23479
|
*/
|
|
23102
|
-
function renderText(checked, correct, crossedOut) {
|
|
23480
|
+
function renderText(checked, correct, crossedOut, strings) {
|
|
23103
23481
|
if (correct) {
|
|
23104
23482
|
// For correct answers, we surface checked _or_ crossedOut state,
|
|
23105
23483
|
// because any interaction with the correct answer is noteworthy!
|
|
23106
23484
|
if (checked) {
|
|
23107
|
-
return
|
|
23485
|
+
return strings.correctSelected;
|
|
23108
23486
|
}
|
|
23109
23487
|
if (crossedOut) {
|
|
23110
|
-
return
|
|
23488
|
+
return strings.correctCrossedOut;
|
|
23111
23489
|
}
|
|
23112
|
-
return
|
|
23490
|
+
return strings.correct;
|
|
23113
23491
|
}
|
|
23114
23492
|
// But, for incorrect answers, we only surface checked state,
|
|
23115
23493
|
// because crossing out an incorrect answer is not noteworthy.
|
|
23116
23494
|
if (checked) {
|
|
23117
|
-
return
|
|
23495
|
+
return strings.incorrectSelected;
|
|
23118
23496
|
}
|
|
23119
|
-
return
|
|
23497
|
+
return strings.incorrect;
|
|
23120
23498
|
}
|
|
23121
23499
|
const OptionStatus = function (props) {
|
|
23122
23500
|
const {
|
|
@@ -23126,6 +23504,9 @@ const OptionStatus = function (props) {
|
|
|
23126
23504
|
previouslyAnswered,
|
|
23127
23505
|
reviewMode
|
|
23128
23506
|
} = props;
|
|
23507
|
+
const {
|
|
23508
|
+
strings
|
|
23509
|
+
} = usePerseusI18n();
|
|
23129
23510
|
|
|
23130
23511
|
// Option status is shown only in review mode, or for incorrectly
|
|
23131
23512
|
// answered items.
|
|
@@ -23145,7 +23526,7 @@ const OptionStatus = function (props) {
|
|
|
23145
23526
|
}
|
|
23146
23527
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23147
23528
|
className: aphrodite.css(styles$v.text, textStyle)
|
|
23148
|
-
}, renderText(checked, correct, crossedOut));
|
|
23529
|
+
}, renderText(checked, correct, crossedOut, strings));
|
|
23149
23530
|
};
|
|
23150
23531
|
const styles$v = aphrodite.StyleSheet.create({
|
|
23151
23532
|
text: {
|
|
@@ -23192,6 +23573,9 @@ const Choice = function (props) {
|
|
|
23192
23573
|
forwardedRef
|
|
23193
23574
|
} = props;
|
|
23194
23575
|
const [isInputFocused, setIsInputFocused] = React.useState(false);
|
|
23576
|
+
const {
|
|
23577
|
+
strings
|
|
23578
|
+
} = usePerseusI18n();
|
|
23195
23579
|
React.useEffect(() => {
|
|
23196
23580
|
if (isInputFocused && disabled) {
|
|
23197
23581
|
setIsInputFocused(false);
|
|
@@ -23220,8 +23604,8 @@ const Choice = function (props) {
|
|
|
23220
23604
|
// However, we don't want to do this when we're in review mode in the
|
|
23221
23605
|
// content library.
|
|
23222
23606
|
const showDimmed = !reviewMode && apiOptions.readOnly || crossedOut;
|
|
23223
|
-
const letter = getChoiceLetter(pos);
|
|
23224
|
-
const a11yText = getA11yText(letter, checked, correct, crossedOut, showCorrectness);
|
|
23607
|
+
const letter = getChoiceLetter(pos, strings);
|
|
23608
|
+
const a11yText = getA11yText(letter, checked, correct, crossedOut, showCorrectness, strings);
|
|
23225
23609
|
const idFactory = wonderBlocksCore.useUniqueIdWithMock(`choice`);
|
|
23226
23610
|
const choiceId = idFactory.get(letter);
|
|
23227
23611
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
@@ -23326,15 +23710,15 @@ const Choice = function (props) {
|
|
|
23326
23710
|
close
|
|
23327
23711
|
} = _ref2;
|
|
23328
23712
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContent, {
|
|
23329
|
-
title:
|
|
23330
|
-
content:
|
|
23713
|
+
title: strings.crossOut,
|
|
23714
|
+
content: strings.crossOutOption,
|
|
23331
23715
|
closeButtonVisible: true,
|
|
23332
23716
|
actions: /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksLayout.Strut, {
|
|
23333
23717
|
size: wonderBlocksTokens.spacing.medium_16
|
|
23334
23718
|
}), /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
23335
23719
|
kind: "primary",
|
|
23336
|
-
"aria-label":
|
|
23337
|
-
letter: getChoiceLetter(pos)
|
|
23720
|
+
"aria-label": strings.crossOutChoice({
|
|
23721
|
+
letter: getChoiceLetter(pos, strings)
|
|
23338
23722
|
}),
|
|
23339
23723
|
disabled: apiOptions.readOnly || reviewMode,
|
|
23340
23724
|
onClick: () => {
|
|
@@ -23354,7 +23738,7 @@ const Choice = function (props) {
|
|
|
23354
23738
|
}
|
|
23355
23739
|
close();
|
|
23356
23740
|
}
|
|
23357
|
-
}, crossedOut ?
|
|
23741
|
+
}, crossedOut ? strings.bringBack : strings.crossOut))
|
|
23358
23742
|
});
|
|
23359
23743
|
}
|
|
23360
23744
|
}, _ref3 => {
|
|
@@ -23363,8 +23747,8 @@ const Choice = function (props) {
|
|
|
23363
23747
|
} = _ref3;
|
|
23364
23748
|
return /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
23365
23749
|
onClick: open,
|
|
23366
|
-
"aria-label":
|
|
23367
|
-
letter: getChoiceLetter(pos)
|
|
23750
|
+
"aria-label": strings.openMenuForChoice({
|
|
23751
|
+
letter: getChoiceLetter(pos, strings)
|
|
23368
23752
|
}),
|
|
23369
23753
|
style: {
|
|
23370
23754
|
alignSelf: "center",
|
|
@@ -23383,7 +23767,7 @@ const Choice = function (props) {
|
|
|
23383
23767
|
});
|
|
23384
23768
|
})), showRationale && /*#__PURE__*/React__namespace.createElement("div", {
|
|
23385
23769
|
className: rationaleClassName,
|
|
23386
|
-
"data-
|
|
23770
|
+
"data-testid": `perseus-radio-rationale-content-${pos}`
|
|
23387
23771
|
}, rationale));
|
|
23388
23772
|
};
|
|
23389
23773
|
const styles$u = aphrodite.StyleSheet.create({
|
|
@@ -23414,6 +23798,9 @@ const ChoiceNoneAbove = function (props) {
|
|
|
23414
23798
|
forwardedRef,
|
|
23415
23799
|
...rest
|
|
23416
23800
|
} = props;
|
|
23801
|
+
const {
|
|
23802
|
+
strings
|
|
23803
|
+
} = usePerseusI18n();
|
|
23417
23804
|
const choiceProps = {
|
|
23418
23805
|
...rest,
|
|
23419
23806
|
content: showContent ? content :
|
|
@@ -23430,7 +23817,8 @@ const ChoiceNoneAbove = function (props) {
|
|
|
23430
23817
|
// just to render a string
|
|
23431
23818
|
React__namespace.createElement(Renderer, {
|
|
23432
23819
|
key: "noneOfTheAboveRenderer",
|
|
23433
|
-
content:
|
|
23820
|
+
content: strings.noneOfTheAbove,
|
|
23821
|
+
strings: strings
|
|
23434
23822
|
})
|
|
23435
23823
|
};
|
|
23436
23824
|
return /*#__PURE__*/React__namespace.createElement(Choice$1, _extends({}, choiceProps, {
|
|
@@ -23450,16 +23838,16 @@ const {
|
|
|
23450
23838
|
|
|
23451
23839
|
// exported for tests
|
|
23452
23840
|
|
|
23453
|
-
function getInstructionsText(multipleSelect, countChoices, numCorrect) {
|
|
23841
|
+
function getInstructionsText(multipleSelect, countChoices, numCorrect, strings) {
|
|
23454
23842
|
if (multipleSelect) {
|
|
23455
23843
|
if (countChoices) {
|
|
23456
|
-
return
|
|
23457
|
-
numCorrect: numCorrect
|
|
23844
|
+
return strings.chooseNumAnswers({
|
|
23845
|
+
numCorrect: String(numCorrect)
|
|
23458
23846
|
});
|
|
23459
23847
|
}
|
|
23460
|
-
return
|
|
23848
|
+
return strings.chooseAllAnswers;
|
|
23461
23849
|
}
|
|
23462
|
-
return
|
|
23850
|
+
return strings.chooseOneAnswer;
|
|
23463
23851
|
}
|
|
23464
23852
|
const BaseRadio = function (props) {
|
|
23465
23853
|
const {
|
|
@@ -23474,6 +23862,9 @@ const BaseRadio = function (props) {
|
|
|
23474
23862
|
isLastUsedWidget,
|
|
23475
23863
|
registerFocusFunction
|
|
23476
23864
|
} = props;
|
|
23865
|
+
const {
|
|
23866
|
+
strings
|
|
23867
|
+
} = usePerseusI18n();
|
|
23477
23868
|
|
|
23478
23869
|
// useEffect doesn't have previous props
|
|
23479
23870
|
const prevReviewModeRubric = React.useRef();
|
|
@@ -23580,7 +23971,7 @@ const BaseRadio = function (props) {
|
|
|
23580
23971
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
23581
23972
|
const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$t.radio, styles$t.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$t.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$t.radioContainerLastHighlighted));
|
|
23582
23973
|
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$t.instructions, isMobile && styles$t.instructionsMobile));
|
|
23583
|
-
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect);
|
|
23974
|
+
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
23584
23975
|
const responsiveClassName = aphrodite.css(styles$t.responsiveFieldset);
|
|
23585
23976
|
const fieldset = /*#__PURE__*/React__namespace.createElement("fieldset", {
|
|
23586
23977
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
@@ -23803,8 +24194,9 @@ const styles$t = aphrodite.StyleSheet.create({
|
|
|
23803
24194
|
// RenderProps is the return type for radio.jsx#transform
|
|
23804
24195
|
|
|
23805
24196
|
class Radio$1 extends React__namespace.Component {
|
|
24197
|
+
static contextType = PerseusI18nContext;
|
|
23806
24198
|
// @ts-expect-error - TS2564 - Property 'focusFunction' has no initializer and is not definitely assigned in the constructor.
|
|
23807
|
-
|
|
24199
|
+
focusFunction;
|
|
23808
24200
|
static defaultProps = {
|
|
23809
24201
|
choices: [],
|
|
23810
24202
|
multipleSelect: false,
|
|
@@ -23813,7 +24205,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
23813
24205
|
linterContext: PerseusLinter.linterContextDefault,
|
|
23814
24206
|
showSolutions: "none"
|
|
23815
24207
|
};
|
|
23816
|
-
static validate(userInput, rubric) {
|
|
24208
|
+
static validate(userInput, rubric, strings) {
|
|
23817
24209
|
const numSelected = userInput.choicesSelected.reduce((sum, selected) => {
|
|
23818
24210
|
return sum + (selected ? 1 : 0);
|
|
23819
24211
|
}, 0);
|
|
@@ -23826,7 +24218,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
23826
24218
|
if (userInput.numCorrect && userInput.numCorrect > 1 && numSelected !== userInput.numCorrect) {
|
|
23827
24219
|
return {
|
|
23828
24220
|
type: "invalid",
|
|
23829
|
-
message:
|
|
24221
|
+
message: strings.chooseCorrectNum
|
|
23830
24222
|
};
|
|
23831
24223
|
// If NOTA and some other answer are checked, ...
|
|
23832
24224
|
}
|
|
@@ -23834,7 +24226,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
23834
24226
|
if (userInput.noneOfTheAboveSelected && numSelected > 1) {
|
|
23835
24227
|
return {
|
|
23836
24228
|
type: "invalid",
|
|
23837
|
-
message:
|
|
24229
|
+
message: strings.notNoneOfTheAbove
|
|
23838
24230
|
};
|
|
23839
24231
|
}
|
|
23840
24232
|
const correct = userInput.choicesSelected.every((selected, i) => {
|
|
@@ -23968,7 +24360,8 @@ class Radio$1 extends React__namespace.Component {
|
|
|
23968
24360
|
..._this.props.linterContext,
|
|
23969
24361
|
// @ts-expect-error - TS2322 - Type '{ blockHighlight: true; contentType: string; highlightLint: boolean; paths: readonly string[]; stack: readonly string[]; }' is not assignable to type 'LinterContextProps'.
|
|
23970
24362
|
blockHighlight: true
|
|
23971
|
-
}
|
|
24363
|
+
},
|
|
24364
|
+
strings: _this.context.strings
|
|
23972
24365
|
});
|
|
23973
24366
|
};
|
|
23974
24367
|
})();
|
|
@@ -24041,7 +24434,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24041
24434
|
return Radio$1.getUserInputFromProps(this.props);
|
|
24042
24435
|
};
|
|
24043
24436
|
simpleValidate = rubric => {
|
|
24044
|
-
return Radio$1.validate(this.getUserInput(), rubric);
|
|
24437
|
+
return Radio$1.validate(this.getUserInput(), rubric, this.context.strings);
|
|
24045
24438
|
};
|
|
24046
24439
|
|
|
24047
24440
|
/**
|
|
@@ -24110,6 +24503,9 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24110
24503
|
const {
|
|
24111
24504
|
choices
|
|
24112
24505
|
} = this.props;
|
|
24506
|
+
const {
|
|
24507
|
+
strings
|
|
24508
|
+
} = this.context;
|
|
24113
24509
|
let choiceStates;
|
|
24114
24510
|
if (this.props.static) {
|
|
24115
24511
|
choiceStates = choices.map(choice => ({
|
|
@@ -24164,11 +24560,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24164
24560
|
}));
|
|
24165
24561
|
}
|
|
24166
24562
|
const choicesProp = choices.map((choice, i) => {
|
|
24167
|
-
const content = choice.isNoneOfTheAbove && !choice.content ?
|
|
24168
|
-
// we use i18n._ instead of $_ here because the content
|
|
24169
|
-
// sent to a renderer needs to be a string, not a react
|
|
24170
|
-
// node (/renderable/fragment).
|
|
24171
|
-
i18n__namespace._("None of the above") : choice.content;
|
|
24563
|
+
const content = choice.isNoneOfTheAbove && !choice.content ? strings.noneOfTheAbove : choice.content;
|
|
24172
24564
|
const {
|
|
24173
24565
|
selected,
|
|
24174
24566
|
crossedOut,
|
|
@@ -24226,14 +24618,8 @@ const {
|
|
|
24226
24618
|
random
|
|
24227
24619
|
} = Util;
|
|
24228
24620
|
|
|
24229
|
-
// Represents choices that we automatically re-order if encountered.
|
|
24230
|
-
// Note: these are in the reversed (incorrect) order that we will swap, if
|
|
24231
|
-
// found.
|
|
24232
|
-
// Note 2: these are internationalized when compared later on.
|
|
24233
|
-
const ReversedChoices = [[i18n__namespace._("False"), i18n__namespace._("True")], [i18n__namespace._("No"), i18n__namespace._("Yes")]];
|
|
24234
|
-
|
|
24235
24621
|
// Transforms the choices for display.
|
|
24236
|
-
const _choiceTransform = (widgetOptions, problemNum) => {
|
|
24622
|
+
const _choiceTransform = (widgetOptions, strings, problemNum) => {
|
|
24237
24623
|
const _maybeRandomize = function (array) {
|
|
24238
24624
|
const randomSeed = problemNum === undefined ? random : problemNum;
|
|
24239
24625
|
// NOTE: `problemNum` will only be set when the radio widget is
|
|
@@ -24262,6 +24648,11 @@ const _choiceTransform = (widgetOptions, problemNum) => {
|
|
|
24262
24648
|
return newChoices;
|
|
24263
24649
|
};
|
|
24264
24650
|
const enforceOrdering = choices => {
|
|
24651
|
+
// Represents choices that we automatically re-order if encountered.
|
|
24652
|
+
// Note: these are in the reversed (incorrect) order that we will swap, if
|
|
24653
|
+
// found.
|
|
24654
|
+
// Note 2: these are internationalized when compared later on.
|
|
24655
|
+
const ReversedChoices = [[strings.false, strings.true], [strings.no, strings.yes]];
|
|
24265
24656
|
const content = choices.map(c => c.content);
|
|
24266
24657
|
if (ReversedChoices.some(reversed => ___default["default"].isEqual(content, reversed))) {
|
|
24267
24658
|
return [choices[1], choices[0]];
|
|
@@ -24288,8 +24679,8 @@ const _choiceTransform = (widgetOptions, problemNum) => {
|
|
|
24288
24679
|
// 1) we randomize the order first
|
|
24289
24680
|
_maybeRandomize(choices)));
|
|
24290
24681
|
};
|
|
24291
|
-
const transform = (widgetOptions, problemNum) => {
|
|
24292
|
-
const choices = _choiceTransform(widgetOptions, problemNum);
|
|
24682
|
+
const transform = (widgetOptions, strings, problemNum) => {
|
|
24683
|
+
const choices = _choiceTransform(widgetOptions, strings, problemNum);
|
|
24293
24684
|
const numCorrect = ___default["default"].reduce(widgetOptions.choices, function (memo, choice) {
|
|
24294
24685
|
return choice.correct ? memo + 1 : memo;
|
|
24295
24686
|
}, 0);
|
|
@@ -24362,6 +24753,7 @@ const WidgetJsonifyDeprecated = {
|
|
|
24362
24753
|
|
|
24363
24754
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
24364
24755
|
class Categorizer extends React__namespace.Component {
|
|
24756
|
+
static contextType = PerseusI18nContext;
|
|
24365
24757
|
static defaultProps = {
|
|
24366
24758
|
items: [],
|
|
24367
24759
|
categories: [],
|
|
@@ -24410,7 +24802,8 @@ class Categorizer extends React__namespace.Component {
|
|
|
24410
24802
|
key: i
|
|
24411
24803
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
24412
24804
|
content: category,
|
|
24413
|
-
linterContext: this.props.linterContext
|
|
24805
|
+
linterContext: this.props.linterContext,
|
|
24806
|
+
strings: this.context.strings
|
|
24414
24807
|
}));
|
|
24415
24808
|
}))), /*#__PURE__*/React__namespace.createElement("tbody", null, indexedItems.map(indexedItem => {
|
|
24416
24809
|
const item = indexedItem[0];
|
|
@@ -24422,7 +24815,8 @@ class Categorizer extends React__namespace.Component {
|
|
|
24422
24815
|
// @ts-expect-error - TS2322 - Type 'string | number' is not assignable to type 'string | undefined'.
|
|
24423
24816
|
, {
|
|
24424
24817
|
content: item,
|
|
24425
|
-
linterContext: this.props.linterContext
|
|
24818
|
+
linterContext: this.props.linterContext,
|
|
24819
|
+
strings: this.context.strings
|
|
24426
24820
|
})), self.props.categories.map((catName, catNum) => {
|
|
24427
24821
|
const selected = self.props.values[itemNum] === catNum;
|
|
24428
24822
|
return /*#__PURE__*/React__namespace.createElement("td", {
|
|
@@ -24466,9 +24860,9 @@ class Categorizer extends React__namespace.Component {
|
|
|
24466
24860
|
this.props.trackInteraction();
|
|
24467
24861
|
}
|
|
24468
24862
|
simpleValidate = rubric => {
|
|
24469
|
-
return Categorizer.validate(this.getUserInput(), rubric);
|
|
24863
|
+
return Categorizer.validate(this.getUserInput(), rubric, this.context.strings);
|
|
24470
24864
|
};
|
|
24471
|
-
static validate(userInput, rubric) {
|
|
24865
|
+
static validate(userInput, rubric, strings) {
|
|
24472
24866
|
let completed = true;
|
|
24473
24867
|
let allCorrect = true;
|
|
24474
24868
|
rubric.values.forEach((value, i) => {
|
|
@@ -24482,7 +24876,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24482
24876
|
if (!completed) {
|
|
24483
24877
|
return {
|
|
24484
24878
|
type: "invalid",
|
|
24485
|
-
message:
|
|
24879
|
+
message: strings.invalidSelection
|
|
24486
24880
|
};
|
|
24487
24881
|
}
|
|
24488
24882
|
return {
|
|
@@ -24796,6 +25190,7 @@ var CSProgram$1 = {
|
|
|
24796
25190
|
// TODO(FEI-5054): Figure out how to get global .d.ts files working with monorepos
|
|
24797
25191
|
|
|
24798
25192
|
class Definition extends React__namespace.Component {
|
|
25193
|
+
static contextType = PerseusI18nContext;
|
|
24799
25194
|
static defaultProps = {
|
|
24800
25195
|
togglePrompt: "define me",
|
|
24801
25196
|
definition: "definition goes here"
|
|
@@ -24828,7 +25223,8 @@ class Definition extends React__namespace.Component {
|
|
|
24828
25223
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
24829
25224
|
apiOptions: this.props.apiOptions,
|
|
24830
25225
|
content: this.props.definition,
|
|
24831
|
-
widgets: this.props.widgets
|
|
25226
|
+
widgets: this.props.widgets,
|
|
25227
|
+
strings: this.context.strings
|
|
24832
25228
|
})),
|
|
24833
25229
|
opened: activeDefinitionId === this.props.widgetId,
|
|
24834
25230
|
onClose: () => setActiveDefinitionId(null),
|
|
@@ -24874,6 +25270,7 @@ var Definition$1 = {
|
|
|
24874
25270
|
// The props are type `any` on purpose so that this can receive props
|
|
24875
25271
|
// from any deprecated widget
|
|
24876
25272
|
class DeprecatedStandin extends React__default["default"].Component {
|
|
25273
|
+
static contextType = PerseusI18nContext;
|
|
24877
25274
|
static validate(userInput, rubric) {
|
|
24878
25275
|
// Since this mean to replace an existing widget the learner
|
|
24879
25276
|
// WILL earn points for this widget
|
|
@@ -24897,7 +25294,7 @@ class DeprecatedStandin extends React__default["default"].Component {
|
|
|
24897
25294
|
paddingBottom: 8
|
|
24898
25295
|
}
|
|
24899
25296
|
}, /*#__PURE__*/React__default["default"].createElement(Banner__default["default"], {
|
|
24900
|
-
text:
|
|
25297
|
+
text: this.context.strings.deprecatedStandin,
|
|
24901
25298
|
kind: "info",
|
|
24902
25299
|
layout: "full-width"
|
|
24903
25300
|
}));
|
|
@@ -25014,6 +25411,7 @@ function mediaQueryIsMatched(mediaQuery) {
|
|
|
25014
25411
|
return window.matchMedia(mediaQuery).matches;
|
|
25015
25412
|
}
|
|
25016
25413
|
class Explanation extends React__namespace.Component {
|
|
25414
|
+
static contextType = PerseusI18nContext;
|
|
25017
25415
|
static defaultProps = {
|
|
25018
25416
|
showPrompt: "Explain",
|
|
25019
25417
|
hidePrompt: "Hide explanation",
|
|
@@ -25098,7 +25496,8 @@ class Explanation extends React__namespace.Component {
|
|
|
25098
25496
|
apiOptions: this.props.apiOptions,
|
|
25099
25497
|
content: this.props.explanation,
|
|
25100
25498
|
widgets: this.props.widgets,
|
|
25101
|
-
linterContext: this.props.linterContext
|
|
25499
|
+
linterContext: this.props.linterContext,
|
|
25500
|
+
strings: this.context.strings
|
|
25102
25501
|
})))));
|
|
25103
25502
|
}
|
|
25104
25503
|
getUserInput = () => {
|
|
@@ -25161,6 +25560,7 @@ var Explanation$1 = {
|
|
|
25161
25560
|
};
|
|
25162
25561
|
|
|
25163
25562
|
class GradedGroupAnswerBar extends React__namespace.Component {
|
|
25563
|
+
static contextType = PerseusI18nContext;
|
|
25164
25564
|
render() {
|
|
25165
25565
|
const {
|
|
25166
25566
|
apiOptions,
|
|
@@ -25168,6 +25568,13 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25168
25568
|
onCheckAnswer,
|
|
25169
25569
|
onNextQuestion
|
|
25170
25570
|
} = this.props;
|
|
25571
|
+
const {
|
|
25572
|
+
keepTrying,
|
|
25573
|
+
tryAgain,
|
|
25574
|
+
check,
|
|
25575
|
+
correctExcited,
|
|
25576
|
+
nextQuestion
|
|
25577
|
+
} = this.context.strings;
|
|
25171
25578
|
const answerBarStyle = {
|
|
25172
25579
|
...styles$o.answerBar,
|
|
25173
25580
|
backgroundColor: answerBarState === "CORRECT" ? wonderBlocksTokens.color.offWhite : "white",
|
|
@@ -25182,10 +25589,10 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25182
25589
|
style: {
|
|
25183
25590
|
marginLeft: 8
|
|
25184
25591
|
}
|
|
25185
|
-
},
|
|
25592
|
+
}, keepTrying)) : /*#__PURE__*/React__namespace.createElement("span", null); // empty span keeps the button on the right side
|
|
25186
25593
|
|
|
25187
25594
|
if (answerBarState !== "CORRECT") {
|
|
25188
|
-
const buttonLabel = answerBarState === "INCORRECT" ?
|
|
25595
|
+
const buttonLabel = answerBarState === "INCORRECT" ? tryAgain : check;
|
|
25189
25596
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25190
25597
|
style: answerBarStyle
|
|
25191
25598
|
}, message, /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
@@ -25208,13 +25615,13 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
25208
25615
|
}
|
|
25209
25616
|
}))), /*#__PURE__*/React__namespace.createElement("span", {
|
|
25210
25617
|
role: "alert",
|
|
25211
|
-
"aria-label":
|
|
25618
|
+
"aria-label": correctExcited,
|
|
25212
25619
|
style: {
|
|
25213
25620
|
marginLeft: 8
|
|
25214
25621
|
}
|
|
25215
|
-
},
|
|
25622
|
+
}, correctExcited)), onNextQuestion && /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
25216
25623
|
onClick: onNextQuestion
|
|
25217
|
-
},
|
|
25624
|
+
}, nextQuestion));
|
|
25218
25625
|
}
|
|
25219
25626
|
}
|
|
25220
25627
|
const fontSize = 17;
|
|
@@ -25270,10 +25677,6 @@ const getNextState = (currentState, answerable) => {
|
|
|
25270
25677
|
}
|
|
25271
25678
|
};
|
|
25272
25679
|
|
|
25273
|
-
// Prepended to all invalid messages to make the widget messages a bit clearer
|
|
25274
|
-
const INVALID_MESSAGE_PREFIX = i18n__namespace._("We couldn't grade your answer.");
|
|
25275
|
-
const DEFAULT_INVALID_MESSAGE = i18n__namespace._("It looks like you left something blank or ") + i18n__namespace._("entered in an invalid answer.");
|
|
25276
|
-
|
|
25277
25680
|
// exports has no 'transform'
|
|
25278
25681
|
|
|
25279
25682
|
// A Graded Group is more or less a Group widget that displays a check
|
|
@@ -25281,6 +25684,7 @@ const DEFAULT_INVALID_MESSAGE = i18n__namespace._("It looks like you left someth
|
|
|
25281
25684
|
// the stuff inside and displays feedback about whether the inputted answer was
|
|
25282
25685
|
// correct or not.
|
|
25283
25686
|
class GradedGroup extends React__namespace.Component {
|
|
25687
|
+
static contextType = PerseusI18nContext;
|
|
25284
25688
|
static defaultProps = {
|
|
25285
25689
|
title: "",
|
|
25286
25690
|
content: "",
|
|
@@ -25342,8 +25746,13 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25342
25746
|
// eslint-disable-next-line react/no-string-refs
|
|
25343
25747
|
// @ts-expect-error - TS2339 - Property 'score' does not exist on type 'ReactInstance'.
|
|
25344
25748
|
const score = this.refs.renderer.score();
|
|
25749
|
+
const {
|
|
25750
|
+
INVALID_MESSAGE_PREFIX,
|
|
25751
|
+
DEFAULT_INVALID_MESSAGE_1,
|
|
25752
|
+
DEFAULT_INVALID_MESSAGE_2
|
|
25753
|
+
} = this.context.strings;
|
|
25345
25754
|
const status = score.type === "points" ? score.total === score.earned ? GRADING_STATUSES.correct : GRADING_STATUSES.incorrect : GRADING_STATUSES.invalid;
|
|
25346
|
-
const message = score.type === "points" ? score.message || "" : score.message ? `${INVALID_MESSAGE_PREFIX} ${score.message}` : `${INVALID_MESSAGE_PREFIX} ${
|
|
25755
|
+
const message = score.type === "points" ? score.message || "" : score.message ? `${INVALID_MESSAGE_PREFIX} ${score.message}` : `${INVALID_MESSAGE_PREFIX} ${DEFAULT_INVALID_MESSAGE_1}${DEFAULT_INVALID_MESSAGE_2}`;
|
|
25347
25756
|
this.setState({
|
|
25348
25757
|
status: status,
|
|
25349
25758
|
message: message,
|
|
@@ -25405,8 +25814,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25405
25814
|
color: "#526f03"
|
|
25406
25815
|
}
|
|
25407
25816
|
}));
|
|
25408
|
-
|
|
25409
|
-
gradeStatus = i18n__namespace._("Correct");
|
|
25817
|
+
gradeStatus = this.context.strings.correct;
|
|
25410
25818
|
} else if (this.state.status === GRADING_STATUSES.incorrect) {
|
|
25411
25819
|
// TODO(jeremy): update to a WB colour
|
|
25412
25820
|
// @ts-expect-error - TS2322 - Type 'Element' is not assignable to type 'null'.
|
|
@@ -25415,8 +25823,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25415
25823
|
color: "#ff5454"
|
|
25416
25824
|
}
|
|
25417
25825
|
}));
|
|
25418
|
-
|
|
25419
|
-
gradeStatus = i18n__namespace._("Incorrect");
|
|
25826
|
+
gradeStatus = this.context.strings.incorrect;
|
|
25420
25827
|
}
|
|
25421
25828
|
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$n.gradedGroupInSet) : aphrodite.css(styles$n.gradedGroup);
|
|
25422
25829
|
const classes = classNames__default["default"]({
|
|
@@ -25446,7 +25853,8 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25446
25853
|
readOnly
|
|
25447
25854
|
},
|
|
25448
25855
|
onInteractWithWidget: this._onInteractWithWidget,
|
|
25449
|
-
linterContext: this.props.linterContext
|
|
25856
|
+
linterContext: this.props.linterContext,
|
|
25857
|
+
strings: this.context.strings
|
|
25450
25858
|
})), !apiOptions.isMobile && icon && /*#__PURE__*/React__namespace.createElement("div", {
|
|
25451
25859
|
className: "group-icon"
|
|
25452
25860
|
}, icon), !apiOptions.isMobile && gradeStatus && /*#__PURE__*/React__namespace.createElement("div", {
|
|
@@ -25460,14 +25868,14 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25460
25868
|
kind: "secondary",
|
|
25461
25869
|
disabled: this.props.apiOptions.readOnly,
|
|
25462
25870
|
onClick: this._checkAnswer
|
|
25463
|
-
},
|
|
25871
|
+
}, this.context.strings.check), !apiOptions.isMobile && isCorrect && this.props.onNextQuestion && /*#__PURE__*/React__namespace.createElement(Button__default["default"], {
|
|
25464
25872
|
kind: "secondary",
|
|
25465
25873
|
disabled: this.props.apiOptions.readOnly,
|
|
25466
25874
|
onClick: this.props.onNextQuestion,
|
|
25467
25875
|
style: {
|
|
25468
25876
|
marginLeft: 5
|
|
25469
25877
|
}
|
|
25470
|
-
},
|
|
25878
|
+
}, this.context.strings.nextQuestion), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("button", {
|
|
25471
25879
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
25472
25880
|
tabIndex: "0",
|
|
25473
25881
|
className: aphrodite.css(styles$n.explanationTitle),
|
|
@@ -25481,11 +25889,12 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25481
25889
|
showHint: false
|
|
25482
25890
|
});
|
|
25483
25891
|
}
|
|
25484
|
-
},
|
|
25892
|
+
}, this.context.strings.hideExplanation), /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, this.props.hint, {
|
|
25485
25893
|
// eslint-disable-next-line react/no-string-refs
|
|
25486
25894
|
ref: "hints-renderer",
|
|
25487
25895
|
apiOptions: apiOptions,
|
|
25488
|
-
linterContext: this.props.linterContext
|
|
25896
|
+
linterContext: this.props.linterContext,
|
|
25897
|
+
strings: this.context.strings
|
|
25489
25898
|
}))) :
|
|
25490
25899
|
/*#__PURE__*/
|
|
25491
25900
|
// Not using Button here bc the styles won't work.
|
|
@@ -25503,7 +25912,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25503
25912
|
});
|
|
25504
25913
|
},
|
|
25505
25914
|
className: aphrodite.css(styles$n.showHintLink)
|
|
25506
|
-
},
|
|
25915
|
+
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React__namespace.createElement(GradedGroupAnswerBar, {
|
|
25507
25916
|
apiOptions: apiOptions,
|
|
25508
25917
|
answerBarState: answerBarState,
|
|
25509
25918
|
onCheckAnswer: this._checkAnswer,
|
|
@@ -25575,6 +25984,7 @@ var GradedGroup$1 = {
|
|
|
25575
25984
|
};
|
|
25576
25985
|
|
|
25577
25986
|
class Indicators extends React__namespace.Component {
|
|
25987
|
+
static contextType = PerseusI18nContext;
|
|
25578
25988
|
handleKeyDown = (e, i) => {
|
|
25579
25989
|
if (e.key === "Enter" || e.key === " ") {
|
|
25580
25990
|
this.props.onChangeCurrentGroup(i);
|
|
@@ -25594,7 +26004,7 @@ class Indicators extends React__namespace.Component {
|
|
|
25594
26004
|
key: title
|
|
25595
26005
|
}, /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
25596
26006
|
role: "button",
|
|
25597
|
-
"aria-label":
|
|
26007
|
+
"aria-label": this.context.strings.skipToTitle({
|
|
25598
26008
|
title
|
|
25599
26009
|
}),
|
|
25600
26010
|
style: styles$m.indicatorButton,
|
|
@@ -25612,7 +26022,7 @@ class Indicators extends React__namespace.Component {
|
|
|
25612
26022
|
style: styles$m.indicatorDotActive
|
|
25613
26023
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25614
26024
|
className: aphrodite.css(a11y.srOnly)
|
|
25615
|
-
},
|
|
26025
|
+
}, this.context.strings.current)));
|
|
25616
26026
|
}));
|
|
25617
26027
|
}));
|
|
25618
26028
|
}
|
|
@@ -25624,7 +26034,7 @@ class Indicators extends React__namespace.Component {
|
|
|
25624
26034
|
// are currently a little confusing.
|
|
25625
26035
|
class GradedGroupSet extends React__namespace.Component {
|
|
25626
26036
|
// @ts-expect-error - TS2564 - Property '_childGroup' has no initializer and is not definitely assigned in the constructor.
|
|
25627
|
-
|
|
26037
|
+
_childGroup;
|
|
25628
26038
|
static defaultProps = {
|
|
25629
26039
|
gradedGroups: [],
|
|
25630
26040
|
linterContext: PerseusLinter.linterContextDefault
|
|
@@ -25703,7 +26113,7 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
25703
26113
|
}
|
|
25704
26114
|
const currentGroup = this.props.gradedGroups[this.state.currentGroup];
|
|
25705
26115
|
if (!currentGroup) {
|
|
25706
|
-
return /*#__PURE__*/React__namespace.createElement("span", null,
|
|
26116
|
+
return /*#__PURE__*/React__namespace.createElement("span", null, "No current group...");
|
|
25707
26117
|
}
|
|
25708
26118
|
const numGroups = this.props.gradedGroups.length;
|
|
25709
26119
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
@@ -25826,6 +26236,7 @@ const styles$m = aphrodite.StyleSheet.create({
|
|
|
25826
26236
|
* ButtonGroup is an aesthetically pleasing group of buttons.
|
|
25827
26237
|
*/
|
|
25828
26238
|
class ButtonGroup extends React__namespace.Component {
|
|
26239
|
+
container;
|
|
25829
26240
|
static defaultProps = {
|
|
25830
26241
|
value: null,
|
|
25831
26242
|
allowEmpty: true
|
|
@@ -26675,6 +27086,8 @@ class FunctionGrapher extends React__namespace.Component {
|
|
|
26675
27086
|
|
|
26676
27087
|
/* Widget and editor. */
|
|
26677
27088
|
class Grapher extends React__namespace.Component {
|
|
27089
|
+
horizHairline;
|
|
27090
|
+
vertHairline;
|
|
26678
27091
|
static defaultProps = DEFAULT_GRAPHER_PROPS;
|
|
26679
27092
|
render() {
|
|
26680
27093
|
const type = this.props.plot.type;
|
|
@@ -26881,6 +27294,8 @@ var Grapher$1 = {
|
|
|
26881
27294
|
// exports has no 'transform'
|
|
26882
27295
|
|
|
26883
27296
|
class Group extends React__namespace.Component {
|
|
27297
|
+
static contextType = PerseusI18nContext;
|
|
27298
|
+
rendererRef;
|
|
26884
27299
|
static defaultProps = {
|
|
26885
27300
|
content: "",
|
|
26886
27301
|
widgets: {},
|
|
@@ -26997,7 +27412,8 @@ class Group extends React__namespace.Component {
|
|
|
26997
27412
|
findExternalWidgets: this.props.findWidgets,
|
|
26998
27413
|
reviewMode: !!this.props.reviewModeRubric,
|
|
26999
27414
|
onInteractWithWidget: onInteractWithWidget,
|
|
27000
|
-
linterContext: this.props.linterContext
|
|
27415
|
+
linterContext: this.props.linterContext,
|
|
27416
|
+
strings: this.context.strings
|
|
27001
27417
|
}), this.props.icon &&
|
|
27002
27418
|
/*#__PURE__*/
|
|
27003
27419
|
// @ts-expect-error - TS2339 - Property 'icon' does not exist on type 'Readonly<Props> & Readonly<{ children?: ReactNode; }>'.
|
|
@@ -27202,6 +27618,7 @@ const DEFAULT_ALIGNMENT = "block";
|
|
|
27202
27618
|
// there is no transform as part of exports
|
|
27203
27619
|
|
|
27204
27620
|
class ImageWidget extends React__namespace.Component {
|
|
27621
|
+
static contextType = PerseusI18nContext;
|
|
27205
27622
|
static defaultProps = {
|
|
27206
27623
|
alignment: DEFAULT_ALIGNMENT,
|
|
27207
27624
|
title: "",
|
|
@@ -27290,7 +27707,8 @@ class ImageWidget extends React__namespace.Component {
|
|
|
27290
27707
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27291
27708
|
content: this.props.alt,
|
|
27292
27709
|
apiOptions: apiOptions,
|
|
27293
|
-
linterContext: this.props.linterContext
|
|
27710
|
+
linterContext: this.props.linterContext,
|
|
27711
|
+
strings: this.context.strings
|
|
27294
27712
|
}));
|
|
27295
27713
|
}
|
|
27296
27714
|
|
|
@@ -27350,7 +27768,8 @@ class ImageWidget extends React__namespace.Component {
|
|
|
27350
27768
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27351
27769
|
content: title + this.props.caption,
|
|
27352
27770
|
apiOptions: apiOptions,
|
|
27353
|
-
linterContext: this.props.linterContext
|
|
27771
|
+
linterContext: this.props.linterContext,
|
|
27772
|
+
strings: this.context.strings
|
|
27354
27773
|
})));
|
|
27355
27774
|
}
|
|
27356
27775
|
return /*#__PURE__*/React__namespace.createElement("figure", {
|
|
@@ -27368,7 +27787,8 @@ class ImageWidget extends React__namespace.Component {
|
|
|
27368
27787
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27369
27788
|
content: this.props.title,
|
|
27370
27789
|
apiOptions: apiOptions,
|
|
27371
|
-
linterContext: this.props.linterContext
|
|
27790
|
+
linterContext: this.props.linterContext,
|
|
27791
|
+
strings: this.context.strings
|
|
27372
27792
|
}));
|
|
27373
27793
|
}
|
|
27374
27794
|
if (this.props.caption) {
|
|
@@ -27380,7 +27800,8 @@ class ImageWidget extends React__namespace.Component {
|
|
|
27380
27800
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27381
27801
|
content: this.props.caption,
|
|
27382
27802
|
apiOptions: apiOptions,
|
|
27383
|
-
linterContext: this.props.linterContext
|
|
27803
|
+
linterContext: this.props.linterContext,
|
|
27804
|
+
strings: this.context.strings
|
|
27384
27805
|
}));
|
|
27385
27806
|
}
|
|
27386
27807
|
return /*#__PURE__*/React__namespace.createElement("figure", {
|
|
@@ -28050,10 +28471,13 @@ function numSteps$1(range, step) {
|
|
|
28050
28471
|
return Math.floor((range[1] - range[0]) / step);
|
|
28051
28472
|
}
|
|
28052
28473
|
class Graph extends React__namespace.Component {
|
|
28474
|
+
protractor;
|
|
28475
|
+
ruler;
|
|
28476
|
+
_graphie;
|
|
28053
28477
|
// @ts-expect-error - TS2564 - Property '_hasSetupGraphieThisUpdate' has no initializer and is not definitely assigned in the constructor.
|
|
28054
|
-
|
|
28478
|
+
_hasSetupGraphieThisUpdate;
|
|
28055
28479
|
// @ts-expect-error - TS2564 - Property '_shouldSetupGraphie' has no initializer and is not definitely assigned in the constructor.
|
|
28056
|
-
|
|
28480
|
+
_shouldSetupGraphie;
|
|
28057
28481
|
static defaultProps = {
|
|
28058
28482
|
labels: ["x", "y"],
|
|
28059
28483
|
range: [[-10, 10], [-10, 10]],
|
|
@@ -28322,44 +28746,216 @@ class Graph extends React__namespace.Component {
|
|
|
28322
28746
|
}
|
|
28323
28747
|
}
|
|
28324
28748
|
|
|
28325
|
-
|
|
28326
|
-
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
|
|
28330
|
-
|
|
28331
|
-
|
|
28332
|
-
|
|
28333
|
-
|
|
28334
|
-
|
|
28335
|
-
|
|
28336
|
-
|
|
28749
|
+
// TODO(FEI-4010): Remove `Perseus` prefix for all types here
|
|
28750
|
+
// TODO(FEI-4011): Use types generated by https://github.com/jaredly/generate-perseus-flowtypes
|
|
28751
|
+
|
|
28752
|
+
// Range is replaced within this file with Interval, but it is used elsewhere
|
|
28753
|
+
// and exported from the package, so we need to keep it around.
|
|
28754
|
+
// TODO(FEI-5054): Figure out how to get global .d.ts files working with monorepos
|
|
28755
|
+
const ItemExtras = [
|
|
28756
|
+
// The user might benefit from using a Scientific Calculator. Provided on Khan Academy when true
|
|
28757
|
+
"calculator",
|
|
28758
|
+
// The user might benefit from using a statistics Chi Squared Table like https://people.richland.edu/james/lecture/m170/tbl-chi.html
|
|
28759
|
+
"chi2Table",
|
|
28760
|
+
// The user might benefit from a monthly payments calculator. Provided on Khan Academy when true
|
|
28761
|
+
"financialCalculatorMonthlyPayment",
|
|
28762
|
+
// The user might benefit from a total amount calculator. Provided on Khan Academy when true
|
|
28763
|
+
"financialCalculatorTotalAmount",
|
|
28764
|
+
// The user might benefit from a time to pay off calculator. Provided on Khan Academy when true
|
|
28765
|
+
"financialCalculatorTimeToPayOff",
|
|
28766
|
+
// The user might benefit from using a Periodic Table of Elements. Provided on Khan Academy when true
|
|
28767
|
+
"periodicTable",
|
|
28768
|
+
// The user might benefit from using a Periodic Table of Elements with key. Provided on Khan Academy when true
|
|
28769
|
+
"periodicTableWithKey",
|
|
28770
|
+
// The user might benefit from using a statistics T Table like https://www.statisticshowto.com/tables/t-distribution-table/
|
|
28771
|
+
"tTable",
|
|
28772
|
+
// The user might benefit from using a statistics Z Table like https://www.ztable.net/
|
|
28773
|
+
"zTable"];
|
|
28774
|
+
|
|
28775
|
+
// prettier-ignore
|
|
28776
|
+
|
|
28777
|
+
// prettier-ignore
|
|
28778
|
+
|
|
28779
|
+
// prettier-ignore
|
|
28780
|
+
|
|
28781
|
+
// prettier-ignore
|
|
28782
|
+
|
|
28783
|
+
// prettier-ignore
|
|
28784
|
+
|
|
28785
|
+
// prettier-ignore
|
|
28786
|
+
|
|
28787
|
+
// prettier-ignore
|
|
28788
|
+
|
|
28789
|
+
// prettier-ignore
|
|
28790
|
+
|
|
28791
|
+
// prettier-ignore
|
|
28792
|
+
|
|
28793
|
+
// prettier-ignore
|
|
28794
|
+
|
|
28795
|
+
// prettier-ignore
|
|
28796
|
+
|
|
28797
|
+
// prettier-ignore
|
|
28798
|
+
|
|
28799
|
+
// prettier-ignore
|
|
28800
|
+
|
|
28801
|
+
// prettier-ignore
|
|
28802
|
+
|
|
28803
|
+
// prettier-ignore
|
|
28804
|
+
|
|
28805
|
+
// prettier-ignore
|
|
28806
|
+
|
|
28807
|
+
// prettier-ignore
|
|
28808
|
+
|
|
28809
|
+
// prettier-ignore
|
|
28810
|
+
|
|
28811
|
+
// prettier-ignore
|
|
28812
|
+
|
|
28813
|
+
// prettier-ignore
|
|
28814
|
+
|
|
28815
|
+
// prettier-ignore
|
|
28816
|
+
|
|
28817
|
+
// prettier-ignore
|
|
28818
|
+
|
|
28819
|
+
// prettier-ignore
|
|
28820
|
+
|
|
28821
|
+
// prettier-ignore
|
|
28822
|
+
|
|
28823
|
+
// prettier-ignore
|
|
28824
|
+
|
|
28825
|
+
// prettier-ignore
|
|
28826
|
+
|
|
28827
|
+
// prettier-ignore
|
|
28828
|
+
|
|
28829
|
+
// prettier-ignore
|
|
28830
|
+
|
|
28831
|
+
// prettier-ignore
|
|
28832
|
+
|
|
28833
|
+
// prettier-ignore
|
|
28834
|
+
|
|
28835
|
+
// prettier-ignore
|
|
28836
|
+
|
|
28837
|
+
// prettier-ignore
|
|
28838
|
+
|
|
28839
|
+
// prettier-ignore
|
|
28840
|
+
|
|
28841
|
+
// prettier-ignore
|
|
28842
|
+
|
|
28843
|
+
// prettier-ignore
|
|
28844
|
+
|
|
28845
|
+
// prettier-ignore
|
|
28846
|
+
|
|
28847
|
+
//prettier-ignore
|
|
28848
|
+
|
|
28849
|
+
// A background image applied to various widgets.
|
|
28850
|
+
|
|
28851
|
+
const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
|
|
28852
|
+
const lockedFigureColors = {
|
|
28853
|
+
blue: "#3D7586",
|
|
28854
|
+
green: "#447A53",
|
|
28855
|
+
gray: "#5D5F66",
|
|
28856
|
+
grayH: "#3B3D45",
|
|
28857
|
+
grayI: "#21242C",
|
|
28858
|
+
purple: "#594094",
|
|
28859
|
+
purpleD: "#8351E8",
|
|
28860
|
+
pink: "#B25071",
|
|
28861
|
+
orange: "#946700",
|
|
28862
|
+
red: "#D92916"
|
|
28863
|
+
};
|
|
28864
|
+
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
28865
|
+
|
|
28866
|
+
const LockedLine = props => {
|
|
28867
|
+
const {
|
|
28868
|
+
color,
|
|
28869
|
+
lineStyle,
|
|
28870
|
+
kind,
|
|
28871
|
+
points,
|
|
28872
|
+
showStartPoint,
|
|
28873
|
+
showEndPoint
|
|
28874
|
+
} = props;
|
|
28875
|
+
const [point1, point2] = points;
|
|
28876
|
+
let line;
|
|
28877
|
+
if (kind === "line" || kind === "segment") {
|
|
28878
|
+
const LineType = kind === "segment" ? mafs.Line.Segment : mafs.Line.ThroughPoints;
|
|
28879
|
+
line = /*#__PURE__*/React__namespace.createElement(LineType, {
|
|
28880
|
+
point1: point1.coord,
|
|
28881
|
+
point2: point2.coord,
|
|
28882
|
+
color: lockedFigureColors[color],
|
|
28883
|
+
style: lineStyle
|
|
28884
|
+
});
|
|
28885
|
+
} else {
|
|
28886
|
+
// TODO(LEMS-1928): Implement rays
|
|
28887
|
+
return null;
|
|
28888
|
+
}
|
|
28889
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
28890
|
+
className: "locked-line"
|
|
28891
|
+
}, line, showStartPoint && /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
28892
|
+
x: point1.coord[0],
|
|
28893
|
+
y: point1.coord[1],
|
|
28894
|
+
svgCircleProps: {
|
|
28895
|
+
style: {
|
|
28896
|
+
fill: point1.filled ? lockedFigureColors[point1.color] : wonderBlocksTokens.color.white,
|
|
28897
|
+
stroke: lockedFigureColors[point1.color],
|
|
28898
|
+
strokeWidth: wonderBlocksTokens.spacing.xxxxSmall_2
|
|
28899
|
+
}
|
|
28900
|
+
}
|
|
28901
|
+
}), showEndPoint && /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
28902
|
+
x: point2.coord[0],
|
|
28903
|
+
y: point2.coord[1],
|
|
28904
|
+
svgCircleProps: {
|
|
28905
|
+
style: {
|
|
28906
|
+
fill: point2.filled ? lockedFigureColors[point2.color] : wonderBlocksTokens.color.white,
|
|
28907
|
+
stroke: lockedFigureColors[point2.color],
|
|
28908
|
+
strokeWidth: wonderBlocksTokens.spacing.xxxxSmall_2
|
|
28909
|
+
}
|
|
28910
|
+
}
|
|
28911
|
+
}));
|
|
28912
|
+
};
|
|
28913
|
+
|
|
28914
|
+
const LockedPoint = props => {
|
|
28915
|
+
const {
|
|
28916
|
+
color,
|
|
28917
|
+
coord,
|
|
28918
|
+
filled
|
|
28919
|
+
} = props;
|
|
28920
|
+
const [x, y] = coord;
|
|
28921
|
+
return /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
28922
|
+
x: x,
|
|
28923
|
+
y: y,
|
|
28924
|
+
svgCircleProps: {
|
|
28925
|
+
style: {
|
|
28926
|
+
fill: filled ? lockedFigureColors[color] : wonderBlocksTokens.color.white,
|
|
28927
|
+
stroke: lockedFigureColors[color],
|
|
28928
|
+
strokeWidth: wonderBlocksTokens.spacing.xxxxSmall_2
|
|
28929
|
+
}
|
|
28930
|
+
}
|
|
28931
|
+
});
|
|
28932
|
+
};
|
|
28933
|
+
|
|
28337
28934
|
const GraphLockedLayer = props => {
|
|
28338
28935
|
const {
|
|
28339
28936
|
lockedFigures
|
|
28340
28937
|
} = props;
|
|
28341
28938
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lockedFigures.map((figure, index) => {
|
|
28939
|
+
let Figure;
|
|
28342
28940
|
switch (figure.type) {
|
|
28343
28941
|
case "point":
|
|
28344
|
-
|
|
28345
|
-
|
|
28346
|
-
|
|
28347
|
-
|
|
28348
|
-
|
|
28349
|
-
|
|
28350
|
-
|
|
28351
|
-
|
|
28352
|
-
|
|
28353
|
-
|
|
28354
|
-
|
|
28355
|
-
|
|
28356
|
-
|
|
28357
|
-
|
|
28358
|
-
|
|
28359
|
-
|
|
28360
|
-
|
|
28361
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28362
|
-
throw new wonderStuffCore.UnreachableCaseError(figure.type);
|
|
28942
|
+
Figure = LockedPoint;
|
|
28943
|
+
break;
|
|
28944
|
+
case "line":
|
|
28945
|
+
Figure = LockedLine;
|
|
28946
|
+
break;
|
|
28947
|
+
default:
|
|
28948
|
+
/**
|
|
28949
|
+
* Devlopment-time future-proofing: This should
|
|
28950
|
+
* fail during type-checking if we add a new locked
|
|
28951
|
+
* shape type and forget to handle it in any other
|
|
28952
|
+
* switch case here.
|
|
28953
|
+
*/
|
|
28954
|
+
throw new wonderStuffCore.UnreachableCaseError(figure);
|
|
28955
|
+
}
|
|
28956
|
+
return /*#__PURE__*/React__namespace.createElement(Figure, _extends({
|
|
28957
|
+
key: `${figure.type}-${index}`
|
|
28958
|
+
}, figure));
|
|
28363
28959
|
}));
|
|
28364
28960
|
};
|
|
28365
28961
|
|
|
@@ -28511,7 +29107,7 @@ function SVGLine(props) {
|
|
|
28511
29107
|
y2: end[1],
|
|
28512
29108
|
style: style,
|
|
28513
29109
|
className: `${className}`,
|
|
28514
|
-
"data-
|
|
29110
|
+
"data-testid": testId
|
|
28515
29111
|
});
|
|
28516
29112
|
}
|
|
28517
29113
|
|
|
@@ -28640,7 +29236,7 @@ const MovableLine = props => {
|
|
|
28640
29236
|
ref: line,
|
|
28641
29237
|
tabIndex: 0,
|
|
28642
29238
|
className: "movable-line",
|
|
28643
|
-
"data-
|
|
29239
|
+
"data-testid": "movable-line",
|
|
28644
29240
|
style: {
|
|
28645
29241
|
cursor: dragging ? "grabbing" : "grab"
|
|
28646
29242
|
}
|
|
@@ -28684,7 +29280,8 @@ const MovableLine = props => {
|
|
|
28684
29280
|
const defaultGraphConfig = {
|
|
28685
29281
|
range: [[0, 1], [0, 1]],
|
|
28686
29282
|
snapStep: [1, 1],
|
|
28687
|
-
markings: "none"
|
|
29283
|
+
markings: "none",
|
|
29284
|
+
showTooltips: false
|
|
28688
29285
|
};
|
|
28689
29286
|
const GraphConfigContext = /*#__PURE__*/React.createContext(defaultGraphConfig);
|
|
28690
29287
|
function useGraphConfig() {
|
|
@@ -28698,7 +29295,8 @@ const StyledMovablePoint = props => {
|
|
|
28698
29295
|
const {
|
|
28699
29296
|
range,
|
|
28700
29297
|
snapStep,
|
|
28701
|
-
markings
|
|
29298
|
+
markings,
|
|
29299
|
+
showTooltips
|
|
28702
29300
|
} = useGraphConfig();
|
|
28703
29301
|
const hitboxRef = React.useRef(null);
|
|
28704
29302
|
const {
|
|
@@ -28706,6 +29304,13 @@ const StyledMovablePoint = props => {
|
|
|
28706
29304
|
onMove,
|
|
28707
29305
|
color = wonderBlocksTokens.color.blue
|
|
28708
29306
|
} = props;
|
|
29307
|
+
|
|
29308
|
+
// WB Tooltip requires a color name for the background color.
|
|
29309
|
+
// Since the color in props is a hex value, a reverse lookup is needed.
|
|
29310
|
+
const wbColorName = Object.entries(wonderBlocksTokens.color).find(_ref => {
|
|
29311
|
+
let [_, value] = _ref;
|
|
29312
|
+
return value === color;
|
|
29313
|
+
})?.[0] ?? "blue";
|
|
28709
29314
|
const {
|
|
28710
29315
|
dragging
|
|
28711
29316
|
} = mafs.useMovable({
|
|
@@ -28723,26 +29328,27 @@ const StyledMovablePoint = props => {
|
|
|
28723
29328
|
const [[_, horizontalStartY]] = useTransform([0, yMin]);
|
|
28724
29329
|
const [[__, horizontalEndY]] = useTransform([0, yMax]);
|
|
28725
29330
|
const showHairlines = dragging && markings !== "none";
|
|
28726
|
-
|
|
29331
|
+
const hairlines = /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
28727
29332
|
x1: verticalStartX,
|
|
28728
29333
|
y1: y,
|
|
28729
29334
|
x2: verticalEndX,
|
|
28730
29335
|
y2: y,
|
|
28731
|
-
stroke:
|
|
29336
|
+
stroke: color
|
|
28732
29337
|
}), /*#__PURE__*/React__namespace.createElement("line", {
|
|
28733
29338
|
x1: x,
|
|
28734
29339
|
y1: horizontalStartY,
|
|
28735
29340
|
x2: x,
|
|
28736
29341
|
y2: horizontalEndY,
|
|
28737
|
-
stroke:
|
|
28738
|
-
}))
|
|
29342
|
+
stroke: color
|
|
29343
|
+
}));
|
|
29344
|
+
const svgForPoint = /*#__PURE__*/React__namespace.createElement("g", {
|
|
28739
29345
|
ref: hitboxRef,
|
|
28740
29346
|
className: pointClasses,
|
|
28741
29347
|
tabIndex: 0,
|
|
28742
29348
|
style: {
|
|
28743
29349
|
"--movable-point-color": color
|
|
28744
29350
|
},
|
|
28745
|
-
"data-
|
|
29351
|
+
"data-testid": "movable-point"
|
|
28746
29352
|
}, /*#__PURE__*/React__namespace.createElement("circle", {
|
|
28747
29353
|
className: "movable-point-hitbox",
|
|
28748
29354
|
r: hitboxSizePx / 2,
|
|
@@ -28767,8 +29373,16 @@ const StyledMovablePoint = props => {
|
|
|
28767
29373
|
style: {
|
|
28768
29374
|
fill: color
|
|
28769
29375
|
},
|
|
28770
|
-
"data-
|
|
28771
|
-
}))
|
|
29376
|
+
"data-testid": "movable-point__center"
|
|
29377
|
+
}));
|
|
29378
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && hairlines, showTooltips ? /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
29379
|
+
autoUpdate: true,
|
|
29380
|
+
backgroundColor: wbColorName,
|
|
29381
|
+
content: `(${point[0]}, ${point[1]})`,
|
|
29382
|
+
contentStyle: {
|
|
29383
|
+
color: "white"
|
|
29384
|
+
}
|
|
29385
|
+
}, svgForPoint) : svgForPoint);
|
|
28772
29386
|
};
|
|
28773
29387
|
|
|
28774
29388
|
const SegmentGraph = props => {
|
|
@@ -28786,8 +29400,7 @@ const SegmentGraph = props => {
|
|
|
28786
29400
|
},
|
|
28787
29401
|
onMovePoint: (endpointIndex, destination) => {
|
|
28788
29402
|
dispatch(moveControlPoint(endpointIndex, destination, i));
|
|
28789
|
-
}
|
|
28790
|
-
"data-testid": "segment" + i
|
|
29403
|
+
}
|
|
28791
29404
|
})));
|
|
28792
29405
|
};
|
|
28793
29406
|
const SegmentView = props => {
|
|
@@ -28817,8 +29430,7 @@ const LinearGraph = props => {
|
|
|
28817
29430
|
dispatch
|
|
28818
29431
|
} = props;
|
|
28819
29432
|
const {
|
|
28820
|
-
coords: lines
|
|
28821
|
-
type
|
|
29433
|
+
coords: lines
|
|
28822
29434
|
} = props.graphState;
|
|
28823
29435
|
const colors = ["var(--movable-line-stroke-color)", "var(--mafs-violet)"];
|
|
28824
29436
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lines?.map((line, i) => /*#__PURE__*/React__namespace.createElement(LineView, {
|
|
@@ -28827,10 +29439,7 @@ const LinearGraph = props => {
|
|
|
28827
29439
|
onMoveLine: delta => {
|
|
28828
29440
|
dispatch(moveLine(i, delta));
|
|
28829
29441
|
},
|
|
28830
|
-
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i))
|
|
28831
|
-
// "linear" or "linear-system" + index
|
|
28832
|
-
,
|
|
28833
|
-
"data-testid": type + i,
|
|
29442
|
+
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i)),
|
|
28834
29443
|
stroke: colors[i]
|
|
28835
29444
|
})));
|
|
28836
29445
|
};
|
|
@@ -29077,7 +29686,6 @@ const PolygonGraph = props => {
|
|
|
29077
29686
|
} = props;
|
|
29078
29687
|
const {
|
|
29079
29688
|
coords,
|
|
29080
|
-
type,
|
|
29081
29689
|
showAngles,
|
|
29082
29690
|
showSides,
|
|
29083
29691
|
range,
|
|
@@ -29149,8 +29757,7 @@ const PolygonGraph = props => {
|
|
|
29149
29757
|
}), points.map((point, i) => /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
29150
29758
|
key: "point-" + i,
|
|
29151
29759
|
point: point,
|
|
29152
|
-
onMove: destination => dispatch(movePoint(i, destination))
|
|
29153
|
-
"data-testid": type + i
|
|
29760
|
+
onMove: destination => dispatch(movePoint(i, destination))
|
|
29154
29761
|
})));
|
|
29155
29762
|
};
|
|
29156
29763
|
|
|
@@ -29679,6 +30286,7 @@ const getNumericFormat = KhanMath.getNumericFormat;
|
|
|
29679
30286
|
* Optionally takes a size ("mini", "small", "normal")
|
|
29680
30287
|
*/
|
|
29681
30288
|
class NumberInput extends React__namespace.Component {
|
|
30289
|
+
static contextType = PerseusI18nContext;
|
|
29682
30290
|
static propTypes = {
|
|
29683
30291
|
value: PropTypes__default["default"].number,
|
|
29684
30292
|
format: PropTypes__default["default"].string,
|
|
@@ -29765,7 +30373,7 @@ class NumberInput extends React__namespace.Component {
|
|
|
29765
30373
|
const placeholder = this.props.placeholder;
|
|
29766
30374
|
return ___default["default"].isFinite(placeholder) ? +placeholder : null;
|
|
29767
30375
|
}
|
|
29768
|
-
const result = firstNumericalParse(value);
|
|
30376
|
+
const result = firstNumericalParse(value, this.context.strings);
|
|
29769
30377
|
return ___default["default"].isFinite(result) ? result : this.props.value;
|
|
29770
30378
|
};
|
|
29771
30379
|
|
|
@@ -29796,7 +30404,7 @@ class NumberInput extends React__namespace.Component {
|
|
|
29796
30404
|
if (value == null) {
|
|
29797
30405
|
return true;
|
|
29798
30406
|
}
|
|
29799
|
-
const val = firstNumericalParse(value);
|
|
30407
|
+
const val = firstNumericalParse(value, this.context.strings);
|
|
29800
30408
|
const checkValidity = this.props.checkValidity;
|
|
29801
30409
|
return ___default["default"].isFinite(val) && checkValidity(val);
|
|
29802
30410
|
};
|
|
@@ -30595,7 +31203,8 @@ const MafsGraph = props => {
|
|
|
30595
31203
|
value: {
|
|
30596
31204
|
range: state.range,
|
|
30597
31205
|
snapStep: state.snapStep,
|
|
30598
|
-
markings: props.markings
|
|
31206
|
+
markings: props.markings,
|
|
31207
|
+
showTooltips: !!props.showTooltips
|
|
30599
31208
|
}
|
|
30600
31209
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30601
31210
|
style: {
|
|
@@ -30696,10 +31305,25 @@ const makeInvalidTypeError = (functionName, graphType) => {
|
|
|
30696
31305
|
// There's no transform function in exports
|
|
30697
31306
|
|
|
30698
31307
|
class LegacyInteractiveGraph extends React__namespace.Component {
|
|
31308
|
+
static contextType = PerseusI18nContext;
|
|
31309
|
+
angle;
|
|
31310
|
+
circle;
|
|
31311
|
+
graphie;
|
|
31312
|
+
horizHairline;
|
|
31313
|
+
line;
|
|
31314
|
+
lines;
|
|
31315
|
+
parabola;
|
|
31316
|
+
pointA;
|
|
31317
|
+
pointB;
|
|
31318
|
+
pointC;
|
|
30699
31319
|
// @ts-expect-error - TS2564 - Property 'points' has no initializer and is not definitely assigned in the constructor.
|
|
30700
|
-
|
|
31320
|
+
points;
|
|
31321
|
+
polygon;
|
|
30701
31322
|
// @ts-expect-error - TS2564 - Property 'shouldResetGraphie' has no initializer and is not definitely assigned in the constructor.
|
|
30702
|
-
|
|
31323
|
+
shouldResetGraphie;
|
|
31324
|
+
sinusoid;
|
|
31325
|
+
trashCan;
|
|
31326
|
+
vertHairline;
|
|
30703
31327
|
static defaultProps = {
|
|
30704
31328
|
labels: ["x", "y"],
|
|
30705
31329
|
range: [[-10, 10], [-10, 10]],
|
|
@@ -31837,9 +32461,9 @@ class LegacyInteractiveGraph extends React__namespace.Component {
|
|
|
31837
32461
|
// isClickToAddPoints() only applies to points and polygons
|
|
31838
32462
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
31839
32463
|
if (this.props.graph.type === "point") {
|
|
31840
|
-
instructions =
|
|
32464
|
+
instructions = this.context.strings.addPoints;
|
|
31841
32465
|
} else if (this.props.graph.type === "polygon") {
|
|
31842
|
-
instructions =
|
|
32466
|
+
instructions = this.context.strings.addVertices;
|
|
31843
32467
|
}
|
|
31844
32468
|
} else {
|
|
31845
32469
|
instructions = undefined;
|
|
@@ -31917,7 +32541,8 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
31917
32541
|
ref: this.mafsRef,
|
|
31918
32542
|
gridStep: gridStep,
|
|
31919
32543
|
snapStep: snapStep,
|
|
31920
|
-
box: box
|
|
32544
|
+
box: box,
|
|
32545
|
+
showTooltips: !!this.props.showTooltips
|
|
31921
32546
|
}));
|
|
31922
32547
|
}
|
|
31923
32548
|
return /*#__PURE__*/React__namespace.createElement(LegacyInteractiveGraph, _extends({
|
|
@@ -33444,6 +34069,9 @@ var globalStyles = /*#__PURE__*/Object.freeze({
|
|
|
33444
34069
|
});
|
|
33445
34070
|
|
|
33446
34071
|
const AnswerChoices = props => {
|
|
34072
|
+
const {
|
|
34073
|
+
strings
|
|
34074
|
+
} = usePerseusI18n();
|
|
33447
34075
|
const onAnswerChange = selected => {
|
|
33448
34076
|
const {
|
|
33449
34077
|
choices,
|
|
@@ -33463,6 +34091,7 @@ const AnswerChoices = props => {
|
|
|
33463
34091
|
value: content,
|
|
33464
34092
|
label: /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33465
34093
|
content: content,
|
|
34094
|
+
strings: strings,
|
|
33466
34095
|
inline: true
|
|
33467
34096
|
})
|
|
33468
34097
|
});
|
|
@@ -33493,14 +34122,13 @@ const AnswerChoices = props => {
|
|
|
33493
34122
|
}));
|
|
33494
34123
|
};
|
|
33495
34124
|
|
|
33496
|
-
const strings = {
|
|
33497
|
-
hideAnswersToggleLabel: i18n__namespace._("Hide answer choices")
|
|
33498
|
-
};
|
|
33499
|
-
|
|
33500
34125
|
const HideAnswersToggle = props => {
|
|
33501
34126
|
const idFactory = wonderBlocksCore.useUniqueIdWithMock();
|
|
33502
34127
|
const switchId = idFactory.get("hide-answers-toggle");
|
|
33503
34128
|
const labelId = idFactory.get("hide-answers-label");
|
|
34129
|
+
const {
|
|
34130
|
+
strings
|
|
34131
|
+
} = usePerseusI18n();
|
|
33504
34132
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
33505
34133
|
style: styles$g.switchWrapper
|
|
33506
34134
|
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
@@ -33541,9 +34169,12 @@ const AnswerPill = props => {
|
|
|
33541
34169
|
hovered
|
|
33542
34170
|
} = props;
|
|
33543
34171
|
const idFactory = wonderBlocksCore.useUniqueIdWithMock();
|
|
33544
|
-
const
|
|
33545
|
-
|
|
33546
|
-
|
|
34172
|
+
const {
|
|
34173
|
+
strings
|
|
34174
|
+
} = usePerseusI18n();
|
|
34175
|
+
const answerString = selectedAnswers.length > 1 ? strings.answers({
|
|
34176
|
+
num: selectedAnswers.length
|
|
34177
|
+
}) : selectedAnswers[0];
|
|
33547
34178
|
|
|
33548
34179
|
// It should no longer be possible to interact with an answer after it
|
|
33549
34180
|
// has been labeled (answered) correctly.
|
|
@@ -33572,6 +34203,7 @@ const AnswerPill = props => {
|
|
|
33572
34203
|
style: [style, popperStyle, styles$f.pill, correct && styles$f.correct, incorrect && styles$f.incorrect, (focused || hovered) && BringToFront]
|
|
33573
34204
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33574
34205
|
content: answerString,
|
|
34206
|
+
strings: strings,
|
|
33575
34207
|
inline: true
|
|
33576
34208
|
}));
|
|
33577
34209
|
});
|
|
@@ -33598,8 +34230,9 @@ function shouldReduceMotion() {
|
|
|
33598
34230
|
}
|
|
33599
34231
|
const MARKER_SIZE = 24;
|
|
33600
34232
|
class Marker extends React__namespace.Component {
|
|
34233
|
+
static contextType = PerseusI18nContext;
|
|
33601
34234
|
// The marker icon element.
|
|
33602
|
-
|
|
34235
|
+
_icon;
|
|
33603
34236
|
static defaultProps = {
|
|
33604
34237
|
selected: []
|
|
33605
34238
|
};
|
|
@@ -33669,10 +34302,8 @@ class Marker extends React__namespace.Component {
|
|
|
33669
34302
|
const markerDisabled = showCorrectness === "correct";
|
|
33670
34303
|
const active = hovered || focused;
|
|
33671
34304
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
33672
|
-
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive]
|
|
33673
|
-
|
|
33674
|
-
,
|
|
33675
|
-
"aria-label": markerDisabled ? i18n__namespace._("Correct!") : label
|
|
34305
|
+
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive],
|
|
34306
|
+
"aria-label": markerDisabled ? this.context.strings.correctExcited : label
|
|
33676
34307
|
}, this.renderIcon()), !!selected && showAnswer && /*#__PURE__*/React__namespace.createElement(AnswerPill, {
|
|
33677
34308
|
selectedAnswers: selected,
|
|
33678
34309
|
showCorrectness: showCorrectness,
|
|
@@ -33772,8 +34403,9 @@ const styles$e = aphrodite.StyleSheet.create({
|
|
|
33772
34403
|
*/
|
|
33773
34404
|
|
|
33774
34405
|
class LabelImage extends React__namespace.Component {
|
|
34406
|
+
static contextType = PerseusI18nContext;
|
|
33775
34407
|
// The rendered markers on the question image for labeling.
|
|
33776
|
-
|
|
34408
|
+
_markers;
|
|
33777
34409
|
static gradeMarker(marker) {
|
|
33778
34410
|
const score = {
|
|
33779
34411
|
hasAnswers: false,
|
|
@@ -34259,8 +34891,11 @@ class LabelImage extends React__namespace.Component {
|
|
|
34259
34891
|
multipleAnswers,
|
|
34260
34892
|
hideChoicesFromInstructions: hideChoices
|
|
34261
34893
|
} = this.props;
|
|
34262
|
-
const
|
|
34263
|
-
|
|
34894
|
+
const {
|
|
34895
|
+
strings
|
|
34896
|
+
} = this.context;
|
|
34897
|
+
const promptString = isMobile ? multipleAnswers ? strings.tapMultiple : strings.tapSingle : multipleAnswers ? strings.clickMultiple : strings.clickSingle;
|
|
34898
|
+
const choicesString = strings.choices;
|
|
34264
34899
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
34265
34900
|
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$d.instructions))
|
|
34266
34901
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
@@ -34271,7 +34906,8 @@ class LabelImage extends React__namespace.Component {
|
|
|
34271
34906
|
className: aphrodite.css(styles$d.instructionsChoice),
|
|
34272
34907
|
key: index
|
|
34273
34908
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
34274
|
-
content: choice
|
|
34909
|
+
content: choice,
|
|
34910
|
+
strings: strings
|
|
34275
34911
|
})))));
|
|
34276
34912
|
}
|
|
34277
34913
|
render() {
|
|
@@ -34446,12 +35082,13 @@ class Placeholder extends React__namespace.Component {
|
|
|
34446
35082
|
// Usual flow: Static -> Dragging -> Animating -> Static
|
|
34447
35083
|
// [Dis|en]abling: Static|Dragging|Animating -> Disabled -> Static
|
|
34448
35084
|
class Draggable extends React__namespace.Component {
|
|
35085
|
+
static contextType = PerseusI18nContext;
|
|
34449
35086
|
// Handler returned by requestAnimationFrame.
|
|
34450
35087
|
animationFrameRequest = null;
|
|
34451
35088
|
// @ts-expect-error - TS2564 - Property 'isMouseMoveUpBound' has no initializer and is not definitely assigned in the constructor.
|
|
34452
|
-
|
|
35089
|
+
isMouseMoveUpBound;
|
|
34453
35090
|
// @ts-expect-error - TS2564 - Property '_mounted' has no initializer and is not definitely assigned in the constructor.
|
|
34454
|
-
|
|
35091
|
+
_mounted;
|
|
34455
35092
|
static defaultProps = {
|
|
34456
35093
|
includePadding: true,
|
|
34457
35094
|
type: ItemState.STATIC,
|
|
@@ -34554,7 +35191,8 @@ class Draggable extends React__namespace.Component {
|
|
|
34554
35191
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
34555
35192
|
content: this.props.content,
|
|
34556
35193
|
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "draggable"),
|
|
34557
|
-
onRender: this.props.onRender
|
|
35194
|
+
onRender: this.props.onRender,
|
|
35195
|
+
strings: this.context.strings
|
|
34558
35196
|
}));
|
|
34559
35197
|
}
|
|
34560
35198
|
componentDidUpdate(prevProps) {
|
|
@@ -35108,6 +35746,7 @@ const {
|
|
|
35108
35746
|
} = Util;
|
|
35109
35747
|
const HACKY_CSS_CLASSNAME = "perseus-widget-matcher";
|
|
35110
35748
|
class Matcher extends React__namespace.Component {
|
|
35749
|
+
static contextType = PerseusI18nContext;
|
|
35111
35750
|
static propTypes = {
|
|
35112
35751
|
apiOptions: ApiOptions.propTypes,
|
|
35113
35752
|
labels: PropTypes__default["default"].array,
|
|
@@ -35187,12 +35826,14 @@ class Matcher extends React__namespace.Component {
|
|
|
35187
35826
|
className: aphrodite.css(styles$b.column, styles$b.columnLabel)
|
|
35188
35827
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
35189
35828
|
content: this.props.labels[0] || "...",
|
|
35190
|
-
linterContext: this.props.linterContext
|
|
35829
|
+
linterContext: this.props.linterContext,
|
|
35830
|
+
strings: this.context.strings
|
|
35191
35831
|
})), /*#__PURE__*/React__namespace.createElement("th", {
|
|
35192
35832
|
className: aphrodite.css(styles$b.column, styles$b.columnRight, styles$b.columnLabel)
|
|
35193
35833
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
35194
35834
|
content: this.props.labels[1] || "...",
|
|
35195
|
-
linterContext: this.props.linterContext
|
|
35835
|
+
linterContext: this.props.linterContext,
|
|
35836
|
+
strings: this.context.strings
|
|
35196
35837
|
}))), /*#__PURE__*/React__namespace.createElement("tr", {
|
|
35197
35838
|
className: aphrodite.css(styles$b.row)
|
|
35198
35839
|
}, /*#__PURE__*/React__namespace.createElement("td", {
|
|
@@ -35404,8 +36045,9 @@ const getMatrixSize = function (matrix) {
|
|
|
35404
36045
|
return matrixSize;
|
|
35405
36046
|
};
|
|
35406
36047
|
class Matrix extends React__namespace.Component {
|
|
36048
|
+
static contextType = PerseusI18nContext;
|
|
35407
36049
|
// @ts-expect-error - TS2564 - Property 'cursorPosition' has no initializer and is not definitely assigned in the constructor.
|
|
35408
|
-
|
|
36050
|
+
cursorPosition;
|
|
35409
36051
|
static defaultProps = {
|
|
35410
36052
|
matrixBoardSize: [3, 3],
|
|
35411
36053
|
answers: [[]],
|
|
@@ -35415,6 +36057,57 @@ class Matrix extends React__namespace.Component {
|
|
|
35415
36057
|
apiOptions: ApiOptions.defaults,
|
|
35416
36058
|
linterContext: PerseusLinter.linterContextDefault
|
|
35417
36059
|
};
|
|
36060
|
+
static validate(state, rubric, strings) {
|
|
36061
|
+
const solution = rubric.answers;
|
|
36062
|
+
const supplied = state.answers;
|
|
36063
|
+
const solutionSize = getMatrixSize(solution);
|
|
36064
|
+
const suppliedSize = getMatrixSize(supplied);
|
|
36065
|
+
const incorrectSize = solutionSize[0] !== suppliedSize[0] || solutionSize[1] !== suppliedSize[1];
|
|
36066
|
+
const createValidator = KhanAnswerTypes.number.createValidatorFunctional;
|
|
36067
|
+
let message = null;
|
|
36068
|
+
let hasEmptyCell = false;
|
|
36069
|
+
let incorrect = false;
|
|
36070
|
+
___default["default"](suppliedSize[0]).times(row => {
|
|
36071
|
+
___default["default"](suppliedSize[1]).times(col => {
|
|
36072
|
+
if (supplied[row][col] == null || supplied[row][col].toString().length === 0) {
|
|
36073
|
+
hasEmptyCell = true;
|
|
36074
|
+
}
|
|
36075
|
+
if (!incorrectSize) {
|
|
36076
|
+
const validator = createValidator(solution[row][col], {
|
|
36077
|
+
simplify: true
|
|
36078
|
+
}, strings);
|
|
36079
|
+
const result = validator(supplied[row][col]);
|
|
36080
|
+
if (result.message) {
|
|
36081
|
+
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
|
|
36082
|
+
message = result.message;
|
|
36083
|
+
}
|
|
36084
|
+
if (!result.correct) {
|
|
36085
|
+
incorrect = true;
|
|
36086
|
+
}
|
|
36087
|
+
}
|
|
36088
|
+
});
|
|
36089
|
+
});
|
|
36090
|
+
if (hasEmptyCell) {
|
|
36091
|
+
return {
|
|
36092
|
+
type: "invalid",
|
|
36093
|
+
message: strings.fillAllCells
|
|
36094
|
+
};
|
|
36095
|
+
}
|
|
36096
|
+
if (incorrectSize) {
|
|
36097
|
+
return {
|
|
36098
|
+
type: "points",
|
|
36099
|
+
earned: 0,
|
|
36100
|
+
total: 1,
|
|
36101
|
+
message: null
|
|
36102
|
+
};
|
|
36103
|
+
}
|
|
36104
|
+
return {
|
|
36105
|
+
type: "points",
|
|
36106
|
+
earned: incorrect ? 0 : 1,
|
|
36107
|
+
total: 1,
|
|
36108
|
+
message: message
|
|
36109
|
+
};
|
|
36110
|
+
}
|
|
35418
36111
|
state = {
|
|
35419
36112
|
enterTheMatrix: 0
|
|
35420
36113
|
};
|
|
@@ -35457,7 +36150,8 @@ class Matrix extends React__namespace.Component {
|
|
|
35457
36150
|
className: "matrix-prefix"
|
|
35458
36151
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
35459
36152
|
content: this.props.prefix,
|
|
35460
|
-
linterContext: this.props.linterContext
|
|
36153
|
+
linterContext: this.props.linterContext,
|
|
36154
|
+
strings: this.context.strings
|
|
35461
36155
|
})), /*#__PURE__*/React__namespace.createElement("div", {
|
|
35462
36156
|
className: "matrix-input"
|
|
35463
36157
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
@@ -35572,7 +36266,8 @@ class Matrix extends React__namespace.Component {
|
|
|
35572
36266
|
className: "matrix-suffix"
|
|
35573
36267
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
35574
36268
|
content: this.props.suffix,
|
|
35575
|
-
linterContext: this.props.linterContext
|
|
36269
|
+
linterContext: this.props.linterContext,
|
|
36270
|
+
strings: this.context.strings
|
|
35576
36271
|
})));
|
|
35577
36272
|
}
|
|
35578
36273
|
getInputPaths = () => {
|
|
@@ -35711,63 +36406,9 @@ class Matrix extends React__namespace.Component {
|
|
|
35711
36406
|
};
|
|
35712
36407
|
};
|
|
35713
36408
|
simpleValidate = rubric => {
|
|
35714
|
-
|
|
35715
|
-
return Matrix.validate(this.getUserInput(), rubric);
|
|
36409
|
+
return Matrix.validate(this.getUserInput(), rubric, this.context.strings);
|
|
35716
36410
|
};
|
|
35717
36411
|
}
|
|
35718
|
-
___default["default"].extend(Matrix, {
|
|
35719
|
-
validate: function (state, rubric) {
|
|
35720
|
-
const solution = rubric.answers;
|
|
35721
|
-
const supplied = state.answers;
|
|
35722
|
-
const solutionSize = getMatrixSize(solution);
|
|
35723
|
-
const suppliedSize = getMatrixSize(supplied);
|
|
35724
|
-
const incorrectSize = solutionSize[0] !== suppliedSize[0] || solutionSize[1] !== suppliedSize[1];
|
|
35725
|
-
const createValidator = KhanAnswerTypes.number.createValidatorFunctional;
|
|
35726
|
-
let message = null;
|
|
35727
|
-
let hasEmptyCell = false;
|
|
35728
|
-
let incorrect = false;
|
|
35729
|
-
___default["default"](suppliedSize[0]).times(row => {
|
|
35730
|
-
___default["default"](suppliedSize[1]).times(col => {
|
|
35731
|
-
if (supplied[row][col] == null || supplied[row][col].toString().length === 0) {
|
|
35732
|
-
hasEmptyCell = true;
|
|
35733
|
-
}
|
|
35734
|
-
if (!incorrectSize) {
|
|
35735
|
-
const validator = createValidator(solution[row][col], {
|
|
35736
|
-
simplify: true
|
|
35737
|
-
});
|
|
35738
|
-
const result = validator(supplied[row][col]);
|
|
35739
|
-
if (result.message) {
|
|
35740
|
-
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
|
|
35741
|
-
message = result.message;
|
|
35742
|
-
}
|
|
35743
|
-
if (!result.correct) {
|
|
35744
|
-
incorrect = true;
|
|
35745
|
-
}
|
|
35746
|
-
}
|
|
35747
|
-
});
|
|
35748
|
-
});
|
|
35749
|
-
if (hasEmptyCell) {
|
|
35750
|
-
return {
|
|
35751
|
-
type: "invalid",
|
|
35752
|
-
message: i18n__namespace._("Make sure you fill in all cells in the matrix.")
|
|
35753
|
-
};
|
|
35754
|
-
}
|
|
35755
|
-
if (incorrectSize) {
|
|
35756
|
-
return {
|
|
35757
|
-
type: "points",
|
|
35758
|
-
earned: 0,
|
|
35759
|
-
total: 1,
|
|
35760
|
-
message: null
|
|
35761
|
-
};
|
|
35762
|
-
}
|
|
35763
|
-
return {
|
|
35764
|
-
type: "points",
|
|
35765
|
-
earned: incorrect ? 0 : 1,
|
|
35766
|
-
total: 1,
|
|
35767
|
-
message: message
|
|
35768
|
-
};
|
|
35769
|
-
}
|
|
35770
|
-
});
|
|
35771
36412
|
const propTransform$1 = editorProps => {
|
|
35772
36413
|
// Remove answers before passing to widget
|
|
35773
36414
|
const blankAnswers = ___default["default"](editorProps.matrixBoardSize[0]).times(function () {
|
|
@@ -36731,6 +37372,7 @@ const parse$1 = SmilesParser.parse;
|
|
|
36731
37372
|
const ParseError = SmilesParser.ParseError;
|
|
36732
37373
|
const borderSize = 30;
|
|
36733
37374
|
class Molecule extends React__namespace.Component {
|
|
37375
|
+
static contextType = PerseusI18nContext;
|
|
36734
37376
|
state = {
|
|
36735
37377
|
parsedSmiles: null,
|
|
36736
37378
|
error: null
|
|
@@ -36807,8 +37449,8 @@ class Molecule extends React__namespace.Component {
|
|
|
36807
37449
|
// eslint-disable-next-line react/no-string-refs
|
|
36808
37450
|
,
|
|
36809
37451
|
ref: "canvas"
|
|
36810
|
-
},
|
|
36811
|
-
content: this.props.smiles
|
|
37452
|
+
}, this.context.strings.molecularDrawing({
|
|
37453
|
+
content: this.props.smiles || ""
|
|
36812
37454
|
}));
|
|
36813
37455
|
if (this.state.error) {
|
|
36814
37456
|
content = /*#__PURE__*/React__namespace.createElement("div", {
|
|
@@ -36987,6 +37629,7 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
|
|
|
36987
37629
|
return results;
|
|
36988
37630
|
});
|
|
36989
37631
|
class NumberLine extends React__namespace.Component {
|
|
37632
|
+
static contextType = PerseusI18nContext;
|
|
36990
37633
|
static defaultProps = {
|
|
36991
37634
|
range: [0, 10],
|
|
36992
37635
|
labelStyle: "decimal",
|
|
@@ -37299,18 +37942,21 @@ class NumberLine extends React__namespace.Component {
|
|
|
37299
37942
|
return NumberLine.validate(this.getUserInput(), rubric);
|
|
37300
37943
|
};
|
|
37301
37944
|
render() {
|
|
37945
|
+
const {
|
|
37946
|
+
strings
|
|
37947
|
+
} = this.context;
|
|
37302
37948
|
const divisionRange = this.props.divisionRange;
|
|
37303
37949
|
const divRangeString = divisionRange[0] + EN_DASH + divisionRange[1];
|
|
37304
37950
|
const invalidNumDivisions = this.props.numDivisions < divisionRange[0] || this.props.numDivisions > divisionRange[1];
|
|
37305
37951
|
const inequalityControls = /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("input", {
|
|
37306
37952
|
type: "button",
|
|
37307
37953
|
className: "simple-button",
|
|
37308
|
-
value:
|
|
37954
|
+
value: strings.switchDirection,
|
|
37309
37955
|
onClick: this.handleReverse
|
|
37310
37956
|
}), /*#__PURE__*/React__namespace.createElement("input", {
|
|
37311
37957
|
type: "button",
|
|
37312
37958
|
className: "simple-button",
|
|
37313
|
-
value: ___default["default"](["le", "ge"]).contains(this.props.rel) ?
|
|
37959
|
+
value: ___default["default"](["le", "ge"]).contains(this.props.rel) ? strings.circleOpen : strings.circleFilled,
|
|
37314
37960
|
onClick: this.handleToggleStrict
|
|
37315
37961
|
}));
|
|
37316
37962
|
let tickCtrl;
|
|
@@ -37321,7 +37967,7 @@ class NumberLine extends React__namespace.Component {
|
|
|
37321
37967
|
} else {
|
|
37322
37968
|
Input = NumberInput;
|
|
37323
37969
|
}
|
|
37324
|
-
tickCtrl = /*#__PURE__*/React__namespace.createElement("label", null,
|
|
37970
|
+
tickCtrl = /*#__PURE__*/React__namespace.createElement("label", null, strings.numDivisions, " ", /*#__PURE__*/React__namespace.createElement(Input
|
|
37325
37971
|
// eslint-disable-next-line react/no-string-refs
|
|
37326
37972
|
, {
|
|
37327
37973
|
ref: "tick-ctrl",
|
|
@@ -37338,9 +37984,9 @@ class NumberLine extends React__namespace.Component {
|
|
|
37338
37984
|
className: "perseus-widget " + "perseus-widget-interactive-number-line"
|
|
37339
37985
|
}, tickCtrl, !this.isValid() ? /*#__PURE__*/React__namespace.createElement("div", {
|
|
37340
37986
|
className: "perseus-error"
|
|
37341
|
-
},
|
|
37987
|
+
}, "Invalid number line configuration.") : this.props.isTickCtrl && invalidNumDivisions ? /*#__PURE__*/React__namespace.createElement("div", {
|
|
37342
37988
|
className: "perseus-error"
|
|
37343
|
-
},
|
|
37989
|
+
}, strings.divisions({
|
|
37344
37990
|
divRangeString: divRangeString
|
|
37345
37991
|
})) : this._renderGraphie(), !this.props.static && this.props.isInequality && inequalityControls);
|
|
37346
37992
|
}
|
|
@@ -37472,8 +38118,9 @@ const PropTypePosition = PropTypes__default["default"].shape({
|
|
|
37472
38118
|
top: PropTypes__default["default"].number
|
|
37473
38119
|
});
|
|
37474
38120
|
class Card extends React__namespace.Component {
|
|
38121
|
+
static contextType = PerseusI18nContext;
|
|
37475
38122
|
// @ts-expect-error - TS2564 - Property 'mouseMoveUpBound' has no initializer and is not definitely assigned in the constructor.
|
|
37476
|
-
|
|
38123
|
+
mouseMoveUpBound;
|
|
37477
38124
|
static propTypes = {
|
|
37478
38125
|
floating: PropTypes__default["default"].bool.isRequired,
|
|
37479
38126
|
animating: PropTypes__default["default"].bool,
|
|
@@ -37532,7 +38179,8 @@ class Card extends React__namespace.Component {
|
|
|
37532
38179
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
37533
38180
|
className: className.join(" ")
|
|
37534
38181
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, rendererProps, {
|
|
37535
|
-
linterContext: this.props.linterContext
|
|
38182
|
+
linterContext: this.props.linterContext,
|
|
38183
|
+
strings: this.context.strings
|
|
37536
38184
|
}))));
|
|
37537
38185
|
}
|
|
37538
38186
|
shouldComponentUpdate(nextProps, nextState) {
|
|
@@ -38805,6 +39453,7 @@ const styles$8 = aphrodite.StyleSheet.create({
|
|
|
38805
39453
|
|
|
38806
39454
|
/* eslint-disable react/no-unsafe */
|
|
38807
39455
|
class HighlightSetRenderer extends React__namespace.PureComponent {
|
|
39456
|
+
static contextType = PerseusI18nContext;
|
|
38808
39457
|
state = {
|
|
38809
39458
|
hoveredHighlightKey: null,
|
|
38810
39459
|
hoveringTooltipFor: null
|
|
@@ -38894,7 +39543,7 @@ class HighlightSetRenderer extends React__namespace.PureComponent {
|
|
|
38894
39543
|
}
|
|
38895
39544
|
const hoveredHighlight = this.props.highlights[hoveredHighlightKey];
|
|
38896
39545
|
return /*#__PURE__*/React__namespace.createElement(HighlightTooltip, {
|
|
38897
|
-
label:
|
|
39546
|
+
label: this.context.strings.removeHighlight,
|
|
38898
39547
|
focusNode: hoveredHighlight.domRange.endContainer,
|
|
38899
39548
|
focusOffset: hoveredHighlight.domRange.endOffset,
|
|
38900
39549
|
offsetParent: this.props.offsetParent,
|
|
@@ -39065,6 +39714,7 @@ class SelectionTracker extends React__namespace.PureComponent {
|
|
|
39065
39714
|
* `HighlightingUI`.
|
|
39066
39715
|
*/
|
|
39067
39716
|
class HighlightingUI extends React__namespace.PureComponent {
|
|
39717
|
+
static contextType = PerseusI18nContext;
|
|
39068
39718
|
_handleAddHighlight(highlightToAdd) {
|
|
39069
39719
|
this.props.onAddHighlight(highlightToAdd);
|
|
39070
39720
|
|
|
@@ -39121,7 +39771,7 @@ class HighlightingUI extends React__namespace.PureComponent {
|
|
|
39121
39771
|
onRemoveHighlight: this.props.onRemoveHighlight,
|
|
39122
39772
|
zIndexes: this.props.zIndexes
|
|
39123
39773
|
}), this._selectionIsValid(trackedSelection) && !userIsMouseSelecting && /*#__PURE__*/React__namespace.createElement(HighlightTooltip, {
|
|
39124
|
-
label:
|
|
39774
|
+
label: this.context.strings.addHighlight,
|
|
39125
39775
|
onClick: () => this._handleAddHighlight(trackedSelection.proposedHighlight),
|
|
39126
39776
|
focusNode: trackedSelection.focusNode,
|
|
39127
39777
|
focusOffset: trackedSelection.focusOffset,
|
|
@@ -39144,6 +39794,7 @@ class HighlightingUI extends React__namespace.PureComponent {
|
|
|
39144
39794
|
* them amenable to binary search - see `findBoundaryWordIndex` in ranges.js.
|
|
39145
39795
|
*/
|
|
39146
39796
|
class WordIndexer extends React__namespace.PureComponent {
|
|
39797
|
+
_container;
|
|
39147
39798
|
/* eslint-enable react/sort-comp */
|
|
39148
39799
|
|
|
39149
39800
|
componentDidMount() {
|
|
@@ -39263,7 +39914,8 @@ class WordIndexer extends React__namespace.PureComponent {
|
|
|
39263
39914
|
*/
|
|
39264
39915
|
class HighlightableContent extends React__namespace.PureComponent {
|
|
39265
39916
|
// References to the mounted container and content divs.
|
|
39266
|
-
|
|
39917
|
+
_container;
|
|
39918
|
+
_content;
|
|
39267
39919
|
state = {
|
|
39268
39920
|
wordRanges: []
|
|
39269
39921
|
};
|
|
@@ -39424,7 +40076,7 @@ class RefStart extends React__namespace.Component {
|
|
|
39424
40076
|
render() {
|
|
39425
40077
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
39426
40078
|
style: REF_STYLE
|
|
39427
|
-
},
|
|
40079
|
+
}, "_");
|
|
39428
40080
|
}
|
|
39429
40081
|
|
|
39430
40082
|
// @ts-expect-error - TS2322 - Type '() => React.ReactNode' is not assignable to type '() => ReactElement<any, string | JSXElementConstructor<any>>'.
|
|
@@ -39436,9 +40088,24 @@ class RefEnd extends React__namespace.Component {
|
|
|
39436
40088
|
render() {
|
|
39437
40089
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
39438
40090
|
style: REF_STYLE
|
|
39439
|
-
},
|
|
40091
|
+
}, "_");
|
|
39440
40092
|
}
|
|
39441
40093
|
}
|
|
40094
|
+
const AltText = _ref => {
|
|
40095
|
+
let {
|
|
40096
|
+
id,
|
|
40097
|
+
number
|
|
40098
|
+
} = _ref;
|
|
40099
|
+
const {
|
|
40100
|
+
strings
|
|
40101
|
+
} = usePerseusI18n();
|
|
40102
|
+
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
40103
|
+
key: "alt-text",
|
|
40104
|
+
className: "perseus-sr-only"
|
|
40105
|
+
}, strings[id]({
|
|
40106
|
+
number
|
|
40107
|
+
}));
|
|
40108
|
+
};
|
|
39442
40109
|
const rules = {
|
|
39443
40110
|
newline: SimpleMarkdown__default["default"].defaultRules.newline,
|
|
39444
40111
|
paragraph: SimpleMarkdown__default["default"].defaultRules.paragraph,
|
|
@@ -39607,12 +40274,10 @@ const rules = {
|
|
|
39607
40274
|
"aria-hidden": "true"
|
|
39608
40275
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
39609
40276
|
style: SQUARE_LABEL_STYLE
|
|
39610
|
-
}, node.content)), /*#__PURE__*/React__namespace.createElement(
|
|
39611
|
-
|
|
39612
|
-
className: "perseus-sr-only"
|
|
39613
|
-
}, i18n__namespace.$_("[Marker for question %(number)s]", {
|
|
40277
|
+
}, node.content)), /*#__PURE__*/React__namespace.createElement(AltText, {
|
|
40278
|
+
id: "questionMarker",
|
|
39614
40279
|
number: node.content
|
|
39615
|
-
})
|
|
40280
|
+
}), node.space ? "\u00A0" : null];
|
|
39616
40281
|
}
|
|
39617
40282
|
},
|
|
39618
40283
|
circleLabel: {
|
|
@@ -39633,12 +40298,10 @@ const rules = {
|
|
|
39633
40298
|
"aria-hidden": true
|
|
39634
40299
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
39635
40300
|
style: CIRCLE_LABEL_STYLE
|
|
39636
|
-
}, node.content)), /*#__PURE__*/React__namespace.createElement(
|
|
39637
|
-
|
|
39638
|
-
className: "perseus-sr-only"
|
|
39639
|
-
}, i18n__namespace.$_("[Circle marker %(number)s]", {
|
|
40301
|
+
}, node.content)), /*#__PURE__*/React__namespace.createElement(AltText, {
|
|
40302
|
+
id: "circleMarker",
|
|
39640
40303
|
number: node.content
|
|
39641
|
-
})
|
|
40304
|
+
}), node.space ? "\u00A0" : null];
|
|
39642
40305
|
}
|
|
39643
40306
|
},
|
|
39644
40307
|
squareBracketRef: {
|
|
@@ -39658,12 +40321,10 @@ const rules = {
|
|
|
39658
40321
|
key: "visual-brackets",
|
|
39659
40322
|
className: "perseus-passage-bracket-label",
|
|
39660
40323
|
"aria-hidden": "true"
|
|
39661
|
-
}, "[", node.content, "]"), /*#__PURE__*/React__namespace.createElement(
|
|
39662
|
-
|
|
39663
|
-
className: "perseus-sr-only"
|
|
39664
|
-
}, i18n__namespace.$_("[Sentence %(number)s]", {
|
|
40324
|
+
}, "[", node.content, "]"), /*#__PURE__*/React__namespace.createElement(AltText, {
|
|
40325
|
+
id: "sentenceMarker",
|
|
39665
40326
|
number: node.content
|
|
39666
|
-
})
|
|
40327
|
+
}), node.space ? "\u00A0" : null];
|
|
39667
40328
|
}
|
|
39668
40329
|
},
|
|
39669
40330
|
highlight: {
|
|
@@ -39763,6 +40424,7 @@ var PassageMarkdown = {
|
|
|
39763
40424
|
// A fake paragraph to measure the line height of the passage,
|
|
39764
40425
|
// so we can adapt to browser zoom
|
|
39765
40426
|
class LineHeightMeasurer extends React__namespace.Component {
|
|
40427
|
+
_line;
|
|
39766
40428
|
measureLineHeight() {
|
|
39767
40429
|
if (!this._line) {
|
|
39768
40430
|
return 0;
|
|
@@ -39795,10 +40457,13 @@ const styles$6 = aphrodite.StyleSheet.create({
|
|
|
39795
40457
|
// Information about a passage reference, used in inter-widgets.
|
|
39796
40458
|
|
|
39797
40459
|
class Passage extends React__namespace.Component {
|
|
40460
|
+
static contextType = PerseusI18nContext;
|
|
40461
|
+
_contentRef;
|
|
40462
|
+
_lineHeightMeasurerRef;
|
|
39798
40463
|
// @ts-expect-error - TS2564 - Property '_onResize' has no initializer and is not definitely assigned in the constructor.
|
|
39799
|
-
|
|
40464
|
+
_onResize;
|
|
39800
40465
|
// @ts-expect-error - TS2564 - Property '_stylesAppiedTimer' has no initializer and is not definitely assigned in the constructor.
|
|
39801
|
-
|
|
40466
|
+
_stylesAppiedTimer;
|
|
39802
40467
|
static defaultProps = {
|
|
39803
40468
|
passageTitle: "",
|
|
39804
40469
|
passageText: "",
|
|
@@ -40053,15 +40718,18 @@ class Passage extends React__namespace.Component {
|
|
|
40053
40718
|
_renderInstructions(parseState) {
|
|
40054
40719
|
const firstQuestionNumber = parseState.firstQuestionRef;
|
|
40055
40720
|
const firstSentenceRef = parseState.firstSentenceRef;
|
|
40721
|
+
const {
|
|
40722
|
+
strings
|
|
40723
|
+
} = this.context;
|
|
40056
40724
|
let instructions = "";
|
|
40057
40725
|
if (firstQuestionNumber) {
|
|
40058
|
-
instructions +=
|
|
40726
|
+
instructions += strings.symbolPassage({
|
|
40059
40727
|
questionSymbol: "[[" + firstQuestionNumber + "]]",
|
|
40060
40728
|
questionNumber: firstQuestionNumber
|
|
40061
40729
|
});
|
|
40062
40730
|
}
|
|
40063
40731
|
if (firstSentenceRef) {
|
|
40064
|
-
instructions +=
|
|
40732
|
+
instructions += strings.symbolQuestion({
|
|
40065
40733
|
sentenceSymbol: "[" + firstSentenceRef + "]"
|
|
40066
40734
|
});
|
|
40067
40735
|
}
|
|
@@ -40107,6 +40775,9 @@ class Passage extends React__namespace.Component {
|
|
|
40107
40775
|
return PassageMarkdown.output(parsed);
|
|
40108
40776
|
}
|
|
40109
40777
|
render() {
|
|
40778
|
+
const {
|
|
40779
|
+
strings
|
|
40780
|
+
} = this.context;
|
|
40110
40781
|
let lineNumbers;
|
|
40111
40782
|
const nLines = this.state.nLines;
|
|
40112
40783
|
if (this.props.showLineNumbers && nLines) {
|
|
@@ -40115,9 +40786,7 @@ class Passage extends React__namespace.Component {
|
|
|
40115
40786
|
lineNumbers = ___default["default"].range(1, nLines + 1).map(lineN => {
|
|
40116
40787
|
const lineAt = lineN + this.state.startLineNumbersAfter;
|
|
40117
40788
|
if (lineAt === 4) {
|
|
40118
|
-
|
|
40119
|
-
// I18N: a label next to a reading passage to denote the line number
|
|
40120
|
-
const translatedLine = i18n__namespace._("Line ");
|
|
40789
|
+
const translatedLine = strings.lineLabel;
|
|
40121
40790
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
40122
40791
|
key: "line-marker",
|
|
40123
40792
|
className: "line-marker"
|
|
@@ -40147,13 +40816,14 @@ class Passage extends React__namespace.Component {
|
|
|
40147
40816
|
className: "passage-title"
|
|
40148
40817
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
40149
40818
|
content: this.props.passageTitle,
|
|
40150
|
-
linterContext: this.props.linterContext
|
|
40819
|
+
linterContext: this.props.linterContext,
|
|
40820
|
+
strings: strings
|
|
40151
40821
|
})), lineNumbers && /*#__PURE__*/React__namespace.createElement("div", {
|
|
40152
40822
|
className: "line-numbers",
|
|
40153
40823
|
"aria-hidden": true
|
|
40154
40824
|
}, lineNumbers), !hasTitle && /*#__PURE__*/React__namespace.createElement("h3", {
|
|
40155
40825
|
className: "perseus-sr-only"
|
|
40156
|
-
},
|
|
40826
|
+
}, strings.beginningPassage), /*#__PURE__*/React__namespace.createElement("div", {
|
|
40157
40827
|
className: "passage-text"
|
|
40158
40828
|
}, this.shouldRenderJipt() ?
|
|
40159
40829
|
/*#__PURE__*/
|
|
@@ -40161,16 +40831,17 @@ class Passage extends React__namespace.Component {
|
|
|
40161
40831
|
// content to a <Renderer /> which knows how
|
|
40162
40832
|
// to handle rendering JIPT text.
|
|
40163
40833
|
React__namespace.createElement(Renderer, {
|
|
40164
|
-
content: this.props.passageText
|
|
40834
|
+
content: this.props.passageText,
|
|
40835
|
+
strings: strings
|
|
40165
40836
|
}) : this._renderContent(parsedContent)), this._hasFootnotes() && [/*#__PURE__*/React__namespace.createElement("h4", {
|
|
40166
40837
|
key: "footnote-start",
|
|
40167
40838
|
className: "perseus-sr-only"
|
|
40168
|
-
},
|
|
40839
|
+
}, strings.beginningFootnotes), /*#__PURE__*/React__namespace.createElement("div", {
|
|
40169
40840
|
key: "footnotes",
|
|
40170
40841
|
className: "footnotes"
|
|
40171
40842
|
}, this._renderFootnotes())], /*#__PURE__*/React__namespace.createElement("div", {
|
|
40172
40843
|
className: "perseus-sr-only"
|
|
40173
|
-
},
|
|
40844
|
+
}, strings.endPassage))));
|
|
40174
40845
|
}
|
|
40175
40846
|
}
|
|
40176
40847
|
var Passage$1 = {
|
|
@@ -40185,6 +40856,7 @@ var Passage$1 = {
|
|
|
40185
40856
|
|
|
40186
40857
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
40187
40858
|
class PassageRefTarget extends React__namespace.Component {
|
|
40859
|
+
static contextType = PerseusI18nContext;
|
|
40188
40860
|
static defaultProps = {
|
|
40189
40861
|
content: "",
|
|
40190
40862
|
linterContext: PerseusLinter.linterContextDefault
|
|
@@ -40222,7 +40894,8 @@ class PassageRefTarget extends React__namespace.Component {
|
|
|
40222
40894
|
// inline={true}
|
|
40223
40895
|
,
|
|
40224
40896
|
apiOptions: this.props.apiOptions,
|
|
40225
|
-
linterContext: this.props.linterContext
|
|
40897
|
+
linterContext: this.props.linterContext,
|
|
40898
|
+
strings: this.context.strings
|
|
40226
40899
|
});
|
|
40227
40900
|
}
|
|
40228
40901
|
}
|
|
@@ -40247,9 +40920,13 @@ const {
|
|
|
40247
40920
|
deepEq
|
|
40248
40921
|
} = Util;
|
|
40249
40922
|
class Plotter extends React__namespace.Component {
|
|
40923
|
+
static contextType = PerseusI18nContext;
|
|
40250
40924
|
// @ts-expect-error - TS2564 - Property 'shouldSetupGraphie' has no initializer and is not definitely assigned in the constructor.
|
|
40251
|
-
|
|
40925
|
+
shouldSetupGraphie;
|
|
40252
40926
|
_isMounted = false;
|
|
40927
|
+
horizHairline;
|
|
40928
|
+
hairlineRange;
|
|
40929
|
+
graphie;
|
|
40253
40930
|
static defaultProps = {
|
|
40254
40931
|
type: "bar",
|
|
40255
40932
|
labels: ["", ""],
|
|
@@ -40436,11 +41113,11 @@ class Plotter extends React__namespace.Component {
|
|
|
40436
41113
|
}
|
|
40437
41114
|
}
|
|
40438
41115
|
if ((isBar || isLine) && isMobile && !this.props.static) {
|
|
40439
|
-
self.graphie.dragPrompt = graphie.label([c.dimX / 2, c.dimY / 2],
|
|
41116
|
+
self.graphie.dragPrompt = graphie.label([c.dimX / 2, c.dimY / 2], this.context.strings.dragHandles, "center", false).css("font-weight", "bold").css("color", KhanColors.KA_GREEN).css("display", "none");
|
|
40440
41117
|
}
|
|
40441
41118
|
self.setupCategories(config);
|
|
40442
41119
|
if (isTiledPlot && isMobile) {
|
|
40443
|
-
self.graphie.dotPrompt = graphie.label([c.dimX / 2, c.dimY / 2],
|
|
41120
|
+
self.graphie.dotPrompt = graphie.label([c.dimX / 2, c.dimY / 2], this.context.strings.tapAddPoints, "center", false).css("font-weight", "bold").css("color", KhanColors.KA_GREEN).css("display", "none");
|
|
40444
41121
|
}
|
|
40445
41122
|
if (isTiledPlot) {
|
|
40446
41123
|
self.drawPicHeights(self.state.values, prevState.values);
|
|
@@ -41115,7 +41792,7 @@ const HORIZONTAL = "horizontal";
|
|
|
41115
41792
|
const VERTICAL = "vertical";
|
|
41116
41793
|
class Sorter extends React__namespace.Component {
|
|
41117
41794
|
// @ts-expect-error - TS2564 - Property '_isMounted' has no initializer and is not definitely assigned in the constructor.
|
|
41118
|
-
|
|
41795
|
+
_isMounted;
|
|
41119
41796
|
static propTypes = {
|
|
41120
41797
|
apiOptions: ApiOptions.propTypes,
|
|
41121
41798
|
// eslint-disable-next-line react/forbid-prop-types
|
|
@@ -41258,6 +41935,7 @@ const getRefForPath = function (path) {
|
|
|
41258
41935
|
return "answer" + row + "," + column;
|
|
41259
41936
|
};
|
|
41260
41937
|
class Table extends React__namespace.Component {
|
|
41938
|
+
static contextType = PerseusI18nContext;
|
|
41261
41939
|
static propTypes = {
|
|
41262
41940
|
answers: PropTypes__default["default"].arrayOf(PropTypes__default["default"].arrayOf(PropTypes__default["default"].string)),
|
|
41263
41941
|
editableHeaders: PropTypes__default["default"].bool,
|
|
@@ -41327,7 +42005,8 @@ class Table extends React__namespace.Component {
|
|
|
41327
42005
|
key: i
|
|
41328
42006
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
41329
42007
|
content: header,
|
|
41330
|
-
linterContext: this.props.linterContext
|
|
42008
|
+
linterContext: this.props.linterContext,
|
|
42009
|
+
strings: this.context.strings
|
|
41331
42010
|
}));
|
|
41332
42011
|
}))), /*#__PURE__*/React__namespace.createElement("tbody", null, ___default["default"](rows).times(r => {
|
|
41333
42012
|
return /*#__PURE__*/React__namespace.createElement("tr", {
|
|
@@ -41372,7 +42051,7 @@ class Table extends React__namespace.Component {
|
|
|
41372
42051
|
};
|
|
41373
42052
|
simpleValidate = rubric => {
|
|
41374
42053
|
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type 'typeof Table'.
|
|
41375
|
-
return Table.validate(this.getUserInput(), rubric);
|
|
42054
|
+
return Table.validate(this.getUserInput(), rubric, this.context.strings);
|
|
41376
42055
|
};
|
|
41377
42056
|
_handleFocus = inputPath => {
|
|
41378
42057
|
this.props.onFocus(inputPath);
|
|
@@ -41441,7 +42120,7 @@ class Table extends React__namespace.Component {
|
|
|
41441
42120
|
};
|
|
41442
42121
|
}
|
|
41443
42122
|
___default["default"].extend(Table, {
|
|
41444
|
-
validate: function (state, rubric) {
|
|
42123
|
+
validate: function (state, rubric, strings) {
|
|
41445
42124
|
const filterNonEmpty = function (table) {
|
|
41446
42125
|
return ___default["default"].filter(table, function (row) {
|
|
41447
42126
|
// Check if row has a cell that is nonempty
|
|
@@ -41479,7 +42158,7 @@ ___default["default"].extend(Table, {
|
|
|
41479
42158
|
const cellSolution = rowSolution[i];
|
|
41480
42159
|
const validator = createValidator(cellSolution, {
|
|
41481
42160
|
simplify: true
|
|
41482
|
-
});
|
|
42161
|
+
}, strings);
|
|
41483
42162
|
const result = validator(cellSupplied);
|
|
41484
42163
|
if (result.message) {
|
|
41485
42164
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
|
|
@@ -41766,6 +42445,11 @@ const str = {
|
|
|
41766
42445
|
* @param s A string representation of a floating point.
|
|
41767
42446
|
*/
|
|
41768
42447
|
class SignificantFigures {
|
|
42448
|
+
order;
|
|
42449
|
+
mantissa;
|
|
42450
|
+
positive;
|
|
42451
|
+
sigFigs;
|
|
42452
|
+
sigDecs;
|
|
41769
42453
|
constructor(s) {
|
|
41770
42454
|
this.order = parseOrder(s);
|
|
41771
42455
|
this.mantissa = parseMantissa(s);
|
|
@@ -42174,17 +42858,19 @@ const countSigfigs = function (value) {
|
|
|
42174
42858
|
* rolling two second delay, but hidden immediately on further typing.
|
|
42175
42859
|
*/
|
|
42176
42860
|
class OldUnitInput extends React__namespace.Component {
|
|
42861
|
+
static contextType = PerseusI18nContext;
|
|
42862
|
+
_errorTimeout;
|
|
42177
42863
|
static defaultProps = {
|
|
42178
42864
|
apiOptions: ApiOptions.defaults,
|
|
42179
42865
|
value: ""
|
|
42180
42866
|
};
|
|
42181
|
-
static validate(userInput, rubric) {
|
|
42867
|
+
static validate(userInput, rubric, strings) {
|
|
42182
42868
|
const answer = KAS__namespace.unitParse(rubric.value).expr;
|
|
42183
42869
|
const guess = KAS__namespace.unitParse(userInput);
|
|
42184
42870
|
if (!guess.parsed) {
|
|
42185
42871
|
return {
|
|
42186
42872
|
type: "invalid",
|
|
42187
|
-
message:
|
|
42873
|
+
message: strings.dontUnderstandUnits
|
|
42188
42874
|
};
|
|
42189
42875
|
}
|
|
42190
42876
|
|
|
@@ -42199,8 +42885,7 @@ class OldUnitInput extends React__namespace.Component {
|
|
|
42199
42885
|
const sigfigs = rubric.sigfigs;
|
|
42200
42886
|
const sigfigsCorrect = countSigfigs(guess.coefficient) === sigfigs;
|
|
42201
42887
|
if (!sigfigsCorrect) {
|
|
42202
|
-
|
|
42203
|
-
message = i18n__namespace._("Check your significant figures.");
|
|
42888
|
+
message = strings.checkSigFigs;
|
|
42204
42889
|
}
|
|
42205
42890
|
|
|
42206
42891
|
// now we need to check that the answer is correct to the precision we
|
|
@@ -42219,8 +42904,7 @@ class OldUnitInput extends React__namespace.Component {
|
|
|
42219
42904
|
numericallyCorrect = false;
|
|
42220
42905
|
}
|
|
42221
42906
|
if (!numericallyCorrect) {
|
|
42222
|
-
|
|
42223
|
-
message = i18n__namespace._("That answer is numerically incorrect.");
|
|
42907
|
+
message = strings.answerNumericallyIncorrect;
|
|
42224
42908
|
}
|
|
42225
42909
|
let kasCorrect;
|
|
42226
42910
|
const guessUnit = primUnits(guess.expr.simplify());
|
|
@@ -42240,8 +42924,7 @@ class OldUnitInput extends React__namespace.Component {
|
|
|
42240
42924
|
});
|
|
42241
42925
|
}
|
|
42242
42926
|
if (!kasCorrect) {
|
|
42243
|
-
|
|
42244
|
-
message = i18n__namespace._("Check your units.");
|
|
42927
|
+
message = strings.checkUnits;
|
|
42245
42928
|
}
|
|
42246
42929
|
const correct = kasCorrect && numericallyCorrect && sigfigsCorrect;
|
|
42247
42930
|
return {
|
|
@@ -42337,7 +43020,7 @@ class OldUnitInput extends React__namespace.Component {
|
|
|
42337
43020
|
});
|
|
42338
43021
|
};
|
|
42339
43022
|
simpleValidate = (rubric, onInputError) => {
|
|
42340
|
-
return OldUnitInput.validate(this.getUserInput(), rubric);
|
|
43023
|
+
return OldUnitInput.validate(this.getUserInput(), rubric, this.context.strings);
|
|
42341
43024
|
};
|
|
42342
43025
|
getUserInput = () => {
|
|
42343
43026
|
return this.props.value;
|
|
@@ -42412,7 +43095,7 @@ class OldUnitInput extends React__namespace.Component {
|
|
|
42412
43095
|
style: {
|
|
42413
43096
|
display: "none"
|
|
42414
43097
|
}
|
|
42415
|
-
},
|
|
43098
|
+
}, this.context.strings.dontUnderstand));
|
|
42416
43099
|
}
|
|
42417
43100
|
}
|
|
42418
43101
|
|
|
@@ -42464,9 +43147,12 @@ const VideoTranscriptLink = props => {
|
|
|
42464
43147
|
// which is used by our GraphQL framework.
|
|
42465
43148
|
// @ts-expect-error - TS2345 - Argument of type 'string' is not assignable to parameter of type 'VideoKind'.
|
|
42466
43149
|
const result = useVideo(id, kind);
|
|
43150
|
+
const {
|
|
43151
|
+
strings
|
|
43152
|
+
} = usePerseusI18n();
|
|
42467
43153
|
switch (result.status) {
|
|
42468
43154
|
case "loading":
|
|
42469
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null,
|
|
43155
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, strings.loading);
|
|
42470
43156
|
case "success":
|
|
42471
43157
|
{
|
|
42472
43158
|
const video = result.data?.video;
|
|
@@ -42478,14 +43164,14 @@ const VideoTranscriptLink = props => {
|
|
|
42478
43164
|
href: "/transcript/" + (video?.contentId || "videoNotFound"),
|
|
42479
43165
|
target: "_blank",
|
|
42480
43166
|
className: "visited-no-recolor"
|
|
42481
|
-
},
|
|
43167
|
+
}, strings.videoTranscript));
|
|
42482
43168
|
}
|
|
42483
43169
|
case "error":
|
|
42484
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null,
|
|
43170
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, strings.somethingWrong);
|
|
42485
43171
|
case "aborted":
|
|
42486
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null,
|
|
43172
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, strings.somethingWrong);
|
|
42487
43173
|
default:
|
|
42488
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null,
|
|
43174
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, strings.somethingWrong);
|
|
42489
43175
|
}
|
|
42490
43176
|
};
|
|
42491
43177
|
const styles$4 = aphrodite.StyleSheet.create({
|
|
@@ -42513,6 +43199,7 @@ const IS_VIMEO = /(vimeo\.com)/;
|
|
|
42513
43199
|
* Video renderer.
|
|
42514
43200
|
*/
|
|
42515
43201
|
class Video extends React__namespace.Component {
|
|
43202
|
+
static contextType = PerseusI18nContext;
|
|
42516
43203
|
/**
|
|
42517
43204
|
* This is the widget's grading function.
|
|
42518
43205
|
* Points for videos are tallied by the embedded video itself, in the case
|
|
@@ -42580,7 +43267,7 @@ class Video extends React__namespace.Component {
|
|
|
42580
43267
|
key: location + this.props.alignment
|
|
42581
43268
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
42582
43269
|
style: a11y.srOnly
|
|
42583
|
-
},
|
|
43270
|
+
}, this.context.strings.videoWrapper), /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
42584
43271
|
// TODO(joshuan): Consider not using iframes when we're
|
|
42585
43272
|
// loading this from webapp. This iframe is problematic
|
|
42586
43273
|
// for screenreaders.
|
|
@@ -42644,7 +43331,7 @@ const init = function (options) {
|
|
|
42644
43331
|
|
|
42645
43332
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
42646
43333
|
const libName = "@khanacademy/perseus";
|
|
42647
|
-
const libVersion = "
|
|
43334
|
+
const libVersion = "22.0.0";
|
|
42648
43335
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
42649
43336
|
|
|
42650
43337
|
const apiVersion = {
|
|
@@ -42663,6 +43350,8 @@ const ItemVersion = getVersionVector();
|
|
|
42663
43350
|
ItemVersion["::renderer::"] = itemDataVersion;
|
|
42664
43351
|
|
|
42665
43352
|
class ArticleRenderer extends React__namespace.Component {
|
|
43353
|
+
static contextType = PerseusI18nContext;
|
|
43354
|
+
_currentFocus;
|
|
42666
43355
|
sectionRenderers = [];
|
|
42667
43356
|
static defaultProps = {
|
|
42668
43357
|
apiOptions: ApiOptions.defaults,
|
|
@@ -42818,8 +43507,9 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
42818
43507
|
}
|
|
42819
43508
|
},
|
|
42820
43509
|
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "article"),
|
|
42821
|
-
legacyPerseusLint: this.props.legacyPerseusLint
|
|
42822
|
-
|
|
43510
|
+
legacyPerseusLint: this.props.legacyPerseusLint,
|
|
43511
|
+
strings: this.context.strings
|
|
43512
|
+
})));
|
|
42823
43513
|
});
|
|
42824
43514
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42825
43515
|
className: classes
|
|
@@ -42831,6 +43521,7 @@ class ArticleRenderer extends React__namespace.Component {
|
|
|
42831
43521
|
|
|
42832
43522
|
/* Renders just a hint preview */
|
|
42833
43523
|
class HintRenderer extends React__namespace.Component {
|
|
43524
|
+
static contextType = PerseusI18nContext;
|
|
42834
43525
|
static defaultProps = {
|
|
42835
43526
|
linterContext: PerseusLinter__namespace.linterContextDefault
|
|
42836
43527
|
};
|
|
@@ -42876,7 +43567,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
42876
43567
|
tabIndex: "-1"
|
|
42877
43568
|
}, !apiOptions.isMobile && /*#__PURE__*/React__namespace.createElement("span", {
|
|
42878
43569
|
className: "perseus-sr-only"
|
|
42879
|
-
},
|
|
43570
|
+
}, this.context.strings.hintPos({
|
|
42880
43571
|
pos: pos + 1
|
|
42881
43572
|
})), !apiOptions.isMobile && totalHints != null && pos != null && /*#__PURE__*/React__namespace.createElement("span", {
|
|
42882
43573
|
className: "perseus-hint-label",
|
|
@@ -42893,7 +43584,8 @@ class HintRenderer extends React__namespace.Component {
|
|
|
42893
43584
|
images: hint.images,
|
|
42894
43585
|
apiOptions: rendererApiOptions,
|
|
42895
43586
|
findExternalWidgets: this.props.findExternalWidgets,
|
|
42896
|
-
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "hint")
|
|
43587
|
+
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "hint"),
|
|
43588
|
+
strings: this.context.strings
|
|
42897
43589
|
}))
|
|
42898
43590
|
);
|
|
42899
43591
|
}
|
|
@@ -42928,6 +43620,7 @@ const styles$3 = aphrodite.StyleSheet.create({
|
|
|
42928
43620
|
// Use of UNSAFE_componentWillReceiveProps:
|
|
42929
43621
|
// eslint-disable-next-line react/no-unsafe
|
|
42930
43622
|
class HintsRenderer extends React__namespace.Component {
|
|
43623
|
+
static contextType = PerseusI18nContext;
|
|
42931
43624
|
static defaultProps = {
|
|
42932
43625
|
linterContext: PerseusLinter__namespace.linterContextDefault
|
|
42933
43626
|
};
|
|
@@ -43080,7 +43773,7 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
43080
43773
|
className: classNames
|
|
43081
43774
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React__namespace.createElement("div", {
|
|
43082
43775
|
className: aphrodite.css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
43083
|
-
},
|
|
43776
|
+
}, this.context.strings.hints), hints, showGetAnotherHint && /*#__PURE__*/React__namespace.createElement("button", {
|
|
43084
43777
|
// @ts-expect-error - TS2322 - Type '{ children: Element[]; rel: string; className: string; onClick: (evt: MouseEvent<HTMLButtonElement, MouseEvent>) => void; }' is not assignable to type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'.
|
|
43085
43778
|
rel: "button",
|
|
43086
43779
|
className: aphrodite.css(styles$2.linkButton, styles$2.getAnotherHintButton, apiOptions.isMobile && styles$2.mobileHintStylesGetAnotherHintButton),
|
|
@@ -43095,7 +43788,7 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
43095
43788
|
className: aphrodite.css(styles$2.plusText, apiOptions.isMobile && styles$2.mobileHintStylesPlusText)
|
|
43096
43789
|
}, "+"), /*#__PURE__*/React__namespace.createElement("span", {
|
|
43097
43790
|
className: aphrodite.css(styles$2.getAnotherHintText)
|
|
43098
|
-
},
|
|
43791
|
+
}, this.context.strings.getAnotherHint, " ", hintRatioCopy)));
|
|
43099
43792
|
}
|
|
43100
43793
|
}
|
|
43101
43794
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
@@ -43198,8 +43891,13 @@ const {
|
|
|
43198
43891
|
} = objective_;
|
|
43199
43892
|
/* eslint-disable-next-line react/no-unsafe */
|
|
43200
43893
|
class ServerItemRenderer extends React__namespace.Component {
|
|
43894
|
+
static contextType = PerseusI18nContext;
|
|
43201
43895
|
// @ts-expect-error - TS2564 - Property 'questionRenderer' has no initializer and is not definitely assigned in the constructor.
|
|
43202
|
-
|
|
43896
|
+
questionRenderer;
|
|
43897
|
+
hintsRenderer;
|
|
43898
|
+
_currentFocus;
|
|
43899
|
+
_fullyRendered;
|
|
43900
|
+
blurTimeoutID;
|
|
43203
43901
|
static defaultProps = {
|
|
43204
43902
|
apiOptions: {},
|
|
43205
43903
|
// a deep default is done in `this.update()`
|
|
@@ -43491,14 +44189,16 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
43491
44189
|
content: this.props.item.question.content,
|
|
43492
44190
|
widgets: this.props.item.question.widgets,
|
|
43493
44191
|
images: this.props.item.question.images,
|
|
43494
|
-
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "question")
|
|
44192
|
+
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "question"),
|
|
44193
|
+
strings: this.context.strings
|
|
43495
44194
|
}, this.props.dependencies)));
|
|
43496
44195
|
const hintsRenderer = /*#__PURE__*/React__namespace.createElement(HintsRenderer, {
|
|
43497
44196
|
hints: this.props.item.hints,
|
|
43498
44197
|
hintsVisible: this.props.hintsVisible,
|
|
43499
44198
|
apiOptions: apiOptions,
|
|
43500
44199
|
ref: elem => this.hintsRenderer = elem,
|
|
43501
|
-
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "hints")
|
|
44200
|
+
linterContext: PerseusLinter__namespace.pushContextStack(this.props.linterContext, "hints"),
|
|
44201
|
+
strings: this.context.strings
|
|
43502
44202
|
});
|
|
43503
44203
|
return /*#__PURE__*/React__namespace.createElement(DependenciesContext.Provider, {
|
|
43504
44204
|
value: this.props.dependencies
|
|
@@ -43671,114 +44371,6 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
43671
44371
|
perseusFrameBorderWidth: perseusFrameBorderWidth
|
|
43672
44372
|
});
|
|
43673
44373
|
|
|
43674
|
-
// TODO(FEI-4010): Remove `Perseus` prefix for all types here
|
|
43675
|
-
// TODO(FEI-4011): Use types generated by https://github.com/jaredly/generate-perseus-flowtypes
|
|
43676
|
-
|
|
43677
|
-
// Range is replaced within this file with Interval, but it is used elsewhere
|
|
43678
|
-
// and exported from the package, so we need to keep it around.
|
|
43679
|
-
// TODO(FEI-5054): Figure out how to get global .d.ts files working with monorepos
|
|
43680
|
-
const ItemExtras = [
|
|
43681
|
-
// The user might benefit from using a Scientific Calculator. Provided on Khan Academy when true
|
|
43682
|
-
"calculator",
|
|
43683
|
-
// The user might benefit from using a statistics Chi Squared Table like https://people.richland.edu/james/lecture/m170/tbl-chi.html
|
|
43684
|
-
"chi2Table",
|
|
43685
|
-
// The user might benefit from a monthly payments calculator. Provided on Khan Academy when true
|
|
43686
|
-
"financialCalculatorMonthlyPayment",
|
|
43687
|
-
// The user might benefit from a total amount calculator. Provided on Khan Academy when true
|
|
43688
|
-
"financialCalculatorTotalAmount",
|
|
43689
|
-
// The user might benefit from a time to pay off calculator. Provided on Khan Academy when true
|
|
43690
|
-
"financialCalculatorTimeToPayOff",
|
|
43691
|
-
// The user might benefit from using a Periodic Table of Elements. Provided on Khan Academy when true
|
|
43692
|
-
"periodicTable",
|
|
43693
|
-
// The user might benefit from using a Periodic Table of Elements with key. Provided on Khan Academy when true
|
|
43694
|
-
"periodicTableWithKey",
|
|
43695
|
-
// The user might benefit from using a statistics T Table like https://www.statisticshowto.com/tables/t-distribution-table/
|
|
43696
|
-
"tTable",
|
|
43697
|
-
// The user might benefit from using a statistics Z Table like https://www.ztable.net/
|
|
43698
|
-
"zTable"];
|
|
43699
|
-
|
|
43700
|
-
// prettier-ignore
|
|
43701
|
-
|
|
43702
|
-
// prettier-ignore
|
|
43703
|
-
|
|
43704
|
-
// prettier-ignore
|
|
43705
|
-
|
|
43706
|
-
// prettier-ignore
|
|
43707
|
-
|
|
43708
|
-
// prettier-ignore
|
|
43709
|
-
|
|
43710
|
-
// prettier-ignore
|
|
43711
|
-
|
|
43712
|
-
// prettier-ignore
|
|
43713
|
-
|
|
43714
|
-
// prettier-ignore
|
|
43715
|
-
|
|
43716
|
-
// prettier-ignore
|
|
43717
|
-
|
|
43718
|
-
// prettier-ignore
|
|
43719
|
-
|
|
43720
|
-
// prettier-ignore
|
|
43721
|
-
|
|
43722
|
-
// prettier-ignore
|
|
43723
|
-
|
|
43724
|
-
// prettier-ignore
|
|
43725
|
-
|
|
43726
|
-
// prettier-ignore
|
|
43727
|
-
|
|
43728
|
-
// prettier-ignore
|
|
43729
|
-
|
|
43730
|
-
// prettier-ignore
|
|
43731
|
-
|
|
43732
|
-
// prettier-ignore
|
|
43733
|
-
|
|
43734
|
-
// prettier-ignore
|
|
43735
|
-
|
|
43736
|
-
// prettier-ignore
|
|
43737
|
-
|
|
43738
|
-
// prettier-ignore
|
|
43739
|
-
|
|
43740
|
-
// prettier-ignore
|
|
43741
|
-
|
|
43742
|
-
// prettier-ignore
|
|
43743
|
-
|
|
43744
|
-
// prettier-ignore
|
|
43745
|
-
|
|
43746
|
-
// prettier-ignore
|
|
43747
|
-
|
|
43748
|
-
// prettier-ignore
|
|
43749
|
-
|
|
43750
|
-
// prettier-ignore
|
|
43751
|
-
|
|
43752
|
-
// prettier-ignore
|
|
43753
|
-
|
|
43754
|
-
// prettier-ignore
|
|
43755
|
-
|
|
43756
|
-
// prettier-ignore
|
|
43757
|
-
|
|
43758
|
-
// prettier-ignore
|
|
43759
|
-
|
|
43760
|
-
// prettier-ignore
|
|
43761
|
-
|
|
43762
|
-
// prettier-ignore
|
|
43763
|
-
|
|
43764
|
-
// prettier-ignore
|
|
43765
|
-
|
|
43766
|
-
// prettier-ignore
|
|
43767
|
-
|
|
43768
|
-
// prettier-ignore
|
|
43769
|
-
|
|
43770
|
-
// prettier-ignore
|
|
43771
|
-
|
|
43772
|
-
//prettier-ignore
|
|
43773
|
-
|
|
43774
|
-
// A background image applied to various widgets.
|
|
43775
|
-
|
|
43776
|
-
const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
|
|
43777
|
-
|
|
43778
|
-
// 2D range: xMin, xMax, yMin, yMax
|
|
43779
|
-
|
|
43780
|
-
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
43781
|
-
|
|
43782
44374
|
/**
|
|
43783
44375
|
* Traverses a {content, widgets, images} renderer props object,
|
|
43784
44376
|
* such as `itemData.question`
|
|
@@ -44019,6 +44611,10 @@ var shapes = {
|
|
|
44019
44611
|
* TreeMapperForLeavesAndCollections.
|
|
44020
44612
|
*/
|
|
44021
44613
|
class TreeMapperJustForLeaves {
|
|
44614
|
+
content;
|
|
44615
|
+
hint;
|
|
44616
|
+
tags;
|
|
44617
|
+
array;
|
|
44022
44618
|
constructor(content, hint, tags) {
|
|
44023
44619
|
this.content = content;
|
|
44024
44620
|
this.hint = hint;
|
|
@@ -44049,6 +44645,10 @@ class TreeMapperJustForLeaves {
|
|
|
44049
44645
|
* ContentMapper and HintMapper are now locked in.
|
|
44050
44646
|
*/
|
|
44051
44647
|
class TreeMapperForLeavesAndCollections {
|
|
44648
|
+
content;
|
|
44649
|
+
hint;
|
|
44650
|
+
tags;
|
|
44651
|
+
array;
|
|
44052
44652
|
constructor(content, hint, tags, array) {
|
|
44053
44653
|
this.content = content;
|
|
44054
44654
|
this.hint = hint;
|
|
@@ -44307,6 +44907,9 @@ function treeToItem(node) {
|
|
|
44307
44907
|
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
44308
44908
|
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
44309
44909
|
class MultiRenderer extends React__namespace.Component {
|
|
44910
|
+
static contextType = PerseusI18nContext;
|
|
44911
|
+
rendererDataTreeMapper;
|
|
44912
|
+
getRenderersMapper;
|
|
44310
44913
|
constructor(props) {
|
|
44311
44914
|
super(props);
|
|
44312
44915
|
this.rendererDataTreeMapper = buildMapper()
|
|
@@ -44381,7 +44984,10 @@ class MultiRenderer extends React__namespace.Component {
|
|
|
44381
44984
|
onSerializedStateUpdated: _____,
|
|
44382
44985
|
...otherProps
|
|
44383
44986
|
} = this.props;
|
|
44384
|
-
return
|
|
44987
|
+
return {
|
|
44988
|
+
...otherProps,
|
|
44989
|
+
strings: this.context.strings
|
|
44990
|
+
};
|
|
44385
44991
|
}
|
|
44386
44992
|
|
|
44387
44993
|
/**
|
|
@@ -44630,7 +45236,7 @@ class MultiRenderer extends React__namespace.Component {
|
|
|
44630
45236
|
if (this.state.renderError) {
|
|
44631
45237
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
44632
45238
|
className: aphrodite.css(styles.error)
|
|
44633
|
-
},
|
|
45239
|
+
}, this.context.strings.errorRendering({
|
|
44634
45240
|
error: String(this.state.renderError)
|
|
44635
45241
|
}));
|
|
44636
45242
|
}
|
|
@@ -45772,6 +46378,8 @@ exports.MultiItems = MultiItems;
|
|
|
45772
46378
|
exports.NumericInput = NumericInput$1;
|
|
45773
46379
|
exports.PerseusError = PerseusError;
|
|
45774
46380
|
exports.PerseusExpressionAnswerFormConsidered = PerseusExpressionAnswerFormConsidered;
|
|
46381
|
+
exports.PerseusI18nContext = PerseusI18nContext;
|
|
46382
|
+
exports.PerseusI18nContextProvider = PerseusI18nContextProvider;
|
|
45775
46383
|
exports.PerseusMarkdown = PerseusMarkdown;
|
|
45776
46384
|
exports.PlotterWidget = Plotter$1;
|
|
45777
46385
|
exports.QUESTION_WIDGETS = QUESTION_WIDGETS;
|
|
@@ -45823,6 +46431,7 @@ exports.itemDataVersion = itemDataVersion;
|
|
|
45823
46431
|
exports.itemToTree = itemToTree;
|
|
45824
46432
|
exports.itemVersion = ItemVersion;
|
|
45825
46433
|
exports.libVersion = libVersion;
|
|
46434
|
+
exports.lockedFigureColors = lockedFigureColors;
|
|
45826
46435
|
exports.mediaQueries = mediaQueries;
|
|
45827
46436
|
exports.parsePerseusItem = parsePerseusItem;
|
|
45828
46437
|
exports.plotterPlotTypes = plotterPlotTypes;
|
|
@@ -45831,6 +46440,7 @@ exports.registerAllWidgetsForTesting = registerAllWidgetsForTesting;
|
|
|
45831
46440
|
exports.shapes = shapes;
|
|
45832
46441
|
exports.shouldHaveIndividualAnswer = shouldHaveIndividualAnswer;
|
|
45833
46442
|
exports.traverse = traverse;
|
|
46443
|
+
exports.usePerseusI18n = usePerseusI18n;
|
|
45834
46444
|
exports.violatingWidgets = violatingWidgets;
|
|
45835
46445
|
exports.widgets = allWidgets;
|
|
45836
46446
|
//# sourceMappingURL=index.js.map
|