@khanacademy/perseus 52.0.0 → 53.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/components/number-input.d.ts +2 -0
- package/dist/components/range-input.d.ts +1 -0
- package/dist/components/svg-image.d.ts +2 -2
- package/dist/es/index.css +0 -30
- package/dist/es/index.js +516 -1195
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +21 -13
- package/dist/es/strings.js.map +1 -1
- package/dist/index.css +0 -30
- package/dist/index.d.ts +1 -2
- package/dist/index.js +514 -1198
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +0 -1
- package/dist/renderer.d.ts +1 -1
- package/dist/strings.d.ts +1 -1
- package/dist/strings.js +21 -13
- package/dist/strings.js.map +1 -1
- package/dist/styles/constants.d.ts +0 -2
- package/dist/types.d.ts +3 -20
- package/dist/util/math-utils.d.ts +1 -0
- package/dist/util/scoring.d.ts +0 -15
- package/dist/util/test-utils.d.ts +1 -1
- package/dist/widget-ai-utils/mock-widget/prompt-utils.d.ts +1 -1
- package/dist/widget-container.d.ts +1 -1
- package/dist/widgets/categorizer/categorizer.d.ts +0 -3
- package/dist/widgets/cs-program/cs-program.d.ts +2 -3
- package/dist/widgets/definition/definition.d.ts +0 -2
- package/dist/widgets/deprecated-standin/deprecated-standin.d.ts +0 -1
- package/dist/widgets/dropdown/dropdown.d.ts +2 -4
- package/dist/widgets/explanation/explanation.d.ts +0 -2
- package/dist/widgets/expression/expression.d.ts +1 -5
- package/dist/widgets/grapher/grapher.d.ts +0 -2
- package/dist/widgets/group/group.d.ts +0 -4
- package/dist/widgets/iframe/iframe.d.ts +0 -2
- package/dist/widgets/image/image.d.ts +0 -3
- package/dist/widgets/input-number/input-number.d.ts +0 -3
- package/dist/widgets/interaction/interaction.d.ts +0 -1
- package/dist/widgets/interactive-graph.d.ts +0 -2
- package/dist/widgets/interactive-graphs/backgrounds/axis-ticks.d.ts +1 -0
- package/dist/widgets/label-image/label-image.d.ts +2 -2
- package/dist/widgets/matcher/matcher.d.ts +0 -2
- package/dist/widgets/matrix/matrix.d.ts +0 -3
- package/dist/widgets/measurer/measurer.d.ts +0 -1
- package/dist/widgets/mock-widgets/mock-widget-types.d.ts +0 -6
- package/dist/widgets/mock-widgets/mock-widget.d.ts +2 -5
- package/dist/widgets/molecule/molecule.d.ts +0 -1
- package/dist/widgets/number-line/number-line.d.ts +2 -3
- package/dist/widgets/numeric-input/numeric-input.d.ts +2 -3
- package/dist/widgets/orderer/orderer.d.ts +0 -3
- package/dist/widgets/passage/passage.d.ts +0 -1
- package/dist/widgets/passage-ref/passage-ref.d.ts +0 -2
- package/dist/widgets/passage-ref-target/passage-ref-target.d.ts +0 -2
- package/dist/widgets/plotter/plotter.d.ts +0 -3
- package/dist/widgets/radio/radio.d.ts +0 -3
- package/dist/widgets/sorter/sorter.d.ts +2 -4
- package/dist/widgets/table/table.d.ts +0 -3
- package/dist/widgets/video/video.d.ts +0 -3
- package/dist/widgets.d.ts +1 -32
- package/package.json +10 -10
- package/dist/renderer-util.d.ts +0 -14
- package/dist/widgets/__shared__/score-noop.d.ts +0 -11
- package/dist/widgets/group/score-group.d.ts +0 -4
- package/dist/widgets/group/validate-group.d.ts +0 -4
- package/dist/widgets/mock-widgets/score-mock-widget.d.ts +0 -5
- package/dist/widgets/mock-widgets/validate-mock-widget.d.ts +0 -4
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 perseusCore = require('@khanacademy/perseus-core');
|
|
8
8
|
var PerseusLinter = require('@khanacademy/perseus-linter');
|
|
9
|
-
var perseusScore = require('@khanacademy/perseus-score');
|
|
10
9
|
var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
|
|
11
10
|
var Tooltip$1 = require('@khanacademy/wonder-blocks-tooltip');
|
|
12
11
|
var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
|
|
@@ -21,6 +20,7 @@ var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
|
|
|
21
20
|
var $ = require('jquery');
|
|
22
21
|
var uuid = require('uuid');
|
|
23
22
|
var PropTypes = require('prop-types');
|
|
23
|
+
var perseusScore = require('@khanacademy/perseus-score');
|
|
24
24
|
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
25
25
|
var wonderBlocksProgressSpinner = require('@khanacademy/wonder-blocks-progress-spinner');
|
|
26
26
|
var kmath = require('@khanacademy/kmath');
|
|
@@ -109,213 +109,6 @@ function _extends() {
|
|
|
109
109
|
* The translated strings that are used to render Perseus.
|
|
110
110
|
*/
|
|
111
111
|
|
|
112
|
-
/**
|
|
113
|
-
* Untranslated strings used in Perseus. To be used by an external
|
|
114
|
-
* translator to produce translated strings, passed in as `PerseusStrings`.
|
|
115
|
-
* !! Note: Ensure that all escape sequences are double-escaped. (e.g. `\\text` -> `\\\\text`)
|
|
116
|
-
*/
|
|
117
|
-
const strings = {
|
|
118
|
-
closeKeypad: "close math keypad",
|
|
119
|
-
openKeypad: "open math keypad",
|
|
120
|
-
mathInputBox: "Math input box",
|
|
121
|
-
removeHighlight: "Remove highlight",
|
|
122
|
-
addHighlight: "Add highlight",
|
|
123
|
-
hintPos: "Hint #%(pos)s",
|
|
124
|
-
errorRendering: "Error rendering: %(error)s",
|
|
125
|
-
APPROXIMATED_PI_ERROR: "Your answer is close, but you may " + "have approximated pi. Enter your " + "answer as a multiple of pi, like " + "12 pi or " + "2/3 pi",
|
|
126
|
-
EXTRA_SYMBOLS_ERROR: "We could not understand your " + "answer. Please check your answer for extra " + "text or symbols.",
|
|
127
|
-
NEEDS_TO_BE_SIMPLFIED_ERROR: "Your answer is almost correct, " + "but it needs to be simplified.",
|
|
128
|
-
MISSING_PERCENT_ERROR: "Your answer is almost correct, " + "but it is missing a " + "<code>\\\\%</code> at the end.",
|
|
129
|
-
MULTIPLICATION_SIGN_ERROR: "I'm a computer. I only understand " + "multiplication if you use an asterisk " + "(*) as the multiplication sign.",
|
|
130
|
-
WRONG_CASE_ERROR: "Your answer includes use of a variable with the wrong case.",
|
|
131
|
-
WRONG_LETTER_ERROR: "Your answer includes a wrong variable letter.",
|
|
132
|
-
invalidSelection: "Make sure you select something for every row.",
|
|
133
|
-
ERROR_TITLE: "Oops!",
|
|
134
|
-
ERROR_MESSAGE: "Sorry, I don't understand that!",
|
|
135
|
-
hints: "Hints",
|
|
136
|
-
getAnotherHint: "Get another hint",
|
|
137
|
-
deprecatedStandin: "Sorry, this part of the question is no longer available. 😅 Don't worry, you won't be graded on this part. Keep going!",
|
|
138
|
-
keepTrying: "Keep trying",
|
|
139
|
-
tryAgain: "Try again",
|
|
140
|
-
check: "Check",
|
|
141
|
-
correctExcited: "Correct!",
|
|
142
|
-
nextQuestion: "Next question",
|
|
143
|
-
skipToTitle: "Skip to %(title)s",
|
|
144
|
-
current: "Current",
|
|
145
|
-
correct: "Correct",
|
|
146
|
-
correctSelected: "Correct (selected)",
|
|
147
|
-
correctCrossedOut: "Correct (but you crossed it out)",
|
|
148
|
-
incorrect: "Incorrect",
|
|
149
|
-
incorrectSelected: "Incorrect (selected)",
|
|
150
|
-
hideExplanation: "Hide explanation",
|
|
151
|
-
explain: "Explain",
|
|
152
|
-
INVALID_MESSAGE_PREFIX: "We couldn't grade your answer.",
|
|
153
|
-
DEFAULT_INVALID_MESSAGE_1: "It looks like you left something blank or ",
|
|
154
|
-
DEFAULT_INVALID_MESSAGE_2: "entered in an invalid answer.",
|
|
155
|
-
integerExample: "an integer, like $6$",
|
|
156
|
-
properExample: "a *proper* fraction, like $1/2$ or $6/10$",
|
|
157
|
-
simplifiedProperExample: "a *simplified proper* fraction, like $3/5$",
|
|
158
|
-
improperExample: "an *improper* fraction, like $10/7$ or $14/8$",
|
|
159
|
-
simplifiedImproperExample: "a *simplified improper* fraction, like $7/4$",
|
|
160
|
-
mixedExample: "a mixed number, like $1\\\\ 3/4$",
|
|
161
|
-
decimalExample: "an *exact* decimal, like $0.75$",
|
|
162
|
-
percentExample: "a percent, like $12.34\\\\%$",
|
|
163
|
-
piExample: "a multiple of pi, like $12$ pi or $2/3$ pi",
|
|
164
|
-
yourAnswer: "**Your answer should be** ",
|
|
165
|
-
yourAnswerLabel: "Your answer:",
|
|
166
|
-
addPoints: "Click to add points",
|
|
167
|
-
addVertices: "Click to add vertices",
|
|
168
|
-
tapMultiple: "Tap each dot on the image to select all answers that apply.",
|
|
169
|
-
tapSingle: "Tap each dot on the image to select an answer.",
|
|
170
|
-
clickMultiple: "Click each dot on the image to select all answers that apply.",
|
|
171
|
-
clickSingle: "Click each dot on the image to select an answer.",
|
|
172
|
-
choices: "Choices:",
|
|
173
|
-
answers: {
|
|
174
|
-
one: "%(num)s answer",
|
|
175
|
-
other: "%(num)s answers"
|
|
176
|
-
},
|
|
177
|
-
hideAnswersToggleLabel: "Hide answer choices",
|
|
178
|
-
moves: {
|
|
179
|
-
one: "Moves: %(num)s",
|
|
180
|
-
other: "Moves: %(num)s"
|
|
181
|
-
},
|
|
182
|
-
clickTiles: "Click on the tiles to change the lights.",
|
|
183
|
-
turnOffLights: "You must turn on all of the lights to continue.",
|
|
184
|
-
fillAllCells: "Make sure you fill in all cells in the matrix.",
|
|
185
|
-
molecularDrawing: "A molecular structure drawing. SMILES notation: %(content)s",
|
|
186
|
-
switchDirection: "Switch direction",
|
|
187
|
-
circleOpen: "Make circle open",
|
|
188
|
-
circleFilled: "Make circle filled",
|
|
189
|
-
numDivisions: "Number of divisions:",
|
|
190
|
-
divisions: "Please make sure the number of divisions is in the range %(divRangeString)s.",
|
|
191
|
-
lineRange: "lines %(lineRange)s",
|
|
192
|
-
lineNumber: "line %(lineNumber)s",
|
|
193
|
-
symbolPassage: "The symbol %(questionSymbol)s indicates that question %(questionNumber)s references this portion of the passage.",
|
|
194
|
-
symbolQuestion: " The symbol %(sentenceSymbol)s indicates that the following sentence is referenced in a question.",
|
|
195
|
-
lineLabel: {
|
|
196
|
-
context: "a label next to a reading passage to denote the line number",
|
|
197
|
-
message: "Line"
|
|
198
|
-
},
|
|
199
|
-
beginningPassage: "Beginning of reading passage.",
|
|
200
|
-
beginningFootnotes: "Beginning of reading passage footnotes.",
|
|
201
|
-
endPassage: "End of reading passage.",
|
|
202
|
-
questionMarker: "[Marker for question %(number)s]",
|
|
203
|
-
circleMarker: "[Circle marker %(number)s]",
|
|
204
|
-
sentenceMarker: "[Sentence %(number)s]",
|
|
205
|
-
dragHandles: "Drag handles to make graph",
|
|
206
|
-
tapAddPoints: "Tap to add points",
|
|
207
|
-
false: "False",
|
|
208
|
-
true: "True",
|
|
209
|
-
no: "No",
|
|
210
|
-
yes: "Yes",
|
|
211
|
-
chooseCorrectNum: "Please choose the correct number of answers.",
|
|
212
|
-
notNoneOfTheAbove: "'None of the above' may not be selected when other answers are selected.",
|
|
213
|
-
noneOfTheAbove: "None of the above",
|
|
214
|
-
chooseNumAnswers: "Choose %(numCorrect)s answers:",
|
|
215
|
-
chooseAllAnswers: "Choose all answers that apply:",
|
|
216
|
-
chooseOneAnswer: "Choose 1 answer:",
|
|
217
|
-
choiceCheckedCorrect: "(Choice %(letter)s, Checked, Correct)",
|
|
218
|
-
choiceCrossedOutCorrect: "(Choice %(letter)s, Crossed out, Correct)",
|
|
219
|
-
choiceCorrect: "(Choice %(letter)s, Correct)",
|
|
220
|
-
choiceCheckedIncorrect: "(Choice %(letter)s, Checked, Incorrect)",
|
|
221
|
-
choiceCrossedOutIncorrect: "(Choice %(letter)s, Crossed out, Incorrect)",
|
|
222
|
-
choiceIncorrect: "(Choice %(letter)s, Incorrect)",
|
|
223
|
-
choiceChecked: "(Choice %(letter)s, Checked)",
|
|
224
|
-
choiceCrossedOut: "(Choice %(letter)s, Crossed out)",
|
|
225
|
-
choice: "(Choice %(letter)s)",
|
|
226
|
-
crossOut: "Cross out",
|
|
227
|
-
crossOutOption: "Cross out option",
|
|
228
|
-
crossOutChoice: "Cross out Choice %(letter)s",
|
|
229
|
-
bringBack: "Bring back",
|
|
230
|
-
openMenuForChoice: "Open menu for Choice %(letter)s",
|
|
231
|
-
letters: {
|
|
232
|
-
context: "This is a list of single-character labels that will appear in front of multiple-choice options. For instance, a multiple-choice question with three options would display (A) first option (B) second option (C) third option. There must be spaces between each of the different characters. The characters will show up next to options in the order that they are listed here. Most multiple choice questions have 5 or fewer options.",
|
|
233
|
-
message: "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"
|
|
234
|
-
},
|
|
235
|
-
rightArrow: "Reaction arrow pointing to the right.",
|
|
236
|
-
dontUnderstandUnits: "I couldn't understand those units.",
|
|
237
|
-
checkSigFigs: "Check your significant figures.",
|
|
238
|
-
answerNumericallyIncorrect: "That answer is numerically incorrect.",
|
|
239
|
-
checkUnits: "Check your units.",
|
|
240
|
-
dontUnderstand: "I don't understand that",
|
|
241
|
-
loading: "Loading...",
|
|
242
|
-
videoTranscript: "See video transcript",
|
|
243
|
-
somethingWrong: "Something went wrong.",
|
|
244
|
-
videoWrapper: "Khan Academy video wrapper",
|
|
245
|
-
mathInputTitle: "mathematics keyboard",
|
|
246
|
-
mathInputDescription: "Use keyboard/mouse to interact with math-based input fields",
|
|
247
|
-
sin: "sin",
|
|
248
|
-
cos: "cos",
|
|
249
|
-
tan: "tan",
|
|
250
|
-
simulationLoadFail: "Sorry, this simulation cannot load.",
|
|
251
|
-
simulationLocaleWarning: "Sorry, this simulation isn't available in your language.",
|
|
252
|
-
selectAnAnswer: "Select an answer",
|
|
253
|
-
// The following strings are used for interactive graph SR descriptions.
|
|
254
|
-
addPoint: "Add Point",
|
|
255
|
-
removePoint: "Remove Point",
|
|
256
|
-
graphKeyboardPrompt: "Press Shift + Enter to interact with the graph",
|
|
257
|
-
closePolygon: "Close shape",
|
|
258
|
-
openPolygon: "Re-open shape",
|
|
259
|
-
srInteractiveElements: "Interactive elements: %(elements)s",
|
|
260
|
-
srNoInteractiveElements: "No interactive elements",
|
|
261
|
-
// TODO(LEMS-2660): The following strings are ones that will need
|
|
262
|
-
// translation tickets after all interactive graph SR strings have
|
|
263
|
-
// been finalized. Remove this comment after the tickets have been
|
|
264
|
-
// created.
|
|
265
|
-
srPointAtCoordinates: "Point %(num)s at %(x)s comma %(y)s",
|
|
266
|
-
srCircleGraph: "A circle on a coordinate plane.",
|
|
267
|
-
srCircleShape: "Circle. The center point is at %(centerX)s comma %(centerY)s.",
|
|
268
|
-
srCircleRadiusPoint: "Radius point at %(radiusPointX)s comma %(radiusPointY)s.",
|
|
269
|
-
srCircleRadius: "Circle radius is %(radius)s.",
|
|
270
|
-
srCircleOuterPoints: "Points on the circle at %(point1X)s comma %(point1Y)s, %(point2X)s comma %(point2Y)s, %(point3X)s comma %(point3Y)s, %(point4X)s comma %(point4Y)s.",
|
|
271
|
-
srLinearGraph: "A line on a coordinate plane.",
|
|
272
|
-
srLinearGraphPoints: "The line has two points, point 1 at %(point1X)s comma %(point1Y)s and point 2 at %(point2X)s comma %(point2Y)s.",
|
|
273
|
-
srLinearGraphSlopeIncreasing: "Its slope increases from left to right.",
|
|
274
|
-
srLinearGraphSlopeDecreasing: "Its slope decreases from left to right.",
|
|
275
|
-
srLinearGraphSlopeHorizontal: "Its slope is zero.",
|
|
276
|
-
srLinearGraphSlopeVertical: "Its slope is undefined.",
|
|
277
|
-
srLinearGraphXOnlyIntercept: "The line crosses the X-axis at %(xIntercept)s comma 0.",
|
|
278
|
-
srLinearGraphYOnlyIntercept: "The line crosses the Y-axis at 0 comma %(yIntercept)s.",
|
|
279
|
-
srLinearGraphBothIntercepts: "The line crosses the X-axis at %(xIntercept)s comma 0 and the Y-axis at 0 comma %(yIntercept)s.",
|
|
280
|
-
srLinearGraphOriginIntercept: "The line crosses the x and y axes at the graph's origin.",
|
|
281
|
-
srLinearGrabHandle: "Line from %(point1X)s comma %(point1Y)s to %(point2X)s comma %(point2Y)s.",
|
|
282
|
-
srAngleSideAtCoordinates: "Point %(point)s, %(side)s at %(x)s comma %(y)s",
|
|
283
|
-
srAngleVertexAtCoordinatesWithAngleMeasure: "Point 2, vertex at %(x)s comma %(y)s. Angle %(angleMeasure)s degrees",
|
|
284
|
-
srAngleGraphAriaLabel: "An angle on a coordinate plane.",
|
|
285
|
-
srAngleGraphAriaDescription: "The angle measure is %(angleMeasure)s degrees with a vertex at %(vertexX)s comma %(vertexY)s, a point on the starting side at %(startingSideX)s comma %(startingSideY)s and a point on the ending side at %(endingSideX)s comma %(endingSideY)s",
|
|
286
|
-
srSingleSegmentGraphAriaLabel: "A line segment on a coordinate plane.",
|
|
287
|
-
srMultipleSegmentGraphAriaLabel: "%(countOfSegments)s line segments on a coordinate plane.",
|
|
288
|
-
srMultipleSegmentIndividualLabel: "Segment %(indexOfSegment)s: Endpoint 1 at %(point1X)s comma %(point1Y)s. Endpoint 2 %(point2X)s comma %(point2Y)s.",
|
|
289
|
-
srSingleSegmentLabel: "Endpoint 1 at %(point1X)s comma %(point1Y)s. Endpoint 2 %(point2X)s comma %(point2Y)s.",
|
|
290
|
-
srSegmentLength: "Segment length %(length)s units.",
|
|
291
|
-
srSingleSegmentGraphEndpointAriaLabel: "Endpoint %(endpointNumber)s at %(x)s comma %(y)s.",
|
|
292
|
-
srMultipleSegmentGraphEndpointAriaLabel: "Endpoint %(endpointNumber)s on segment %(indexOfSegment)s at %(x)s comma %(y)s.",
|
|
293
|
-
srSegmentGrabHandle: "Segment from %(point1X)s comma %(point1Y)s to %(point2X)s comma %(point2Y)s.",
|
|
294
|
-
srLinearSystemGraph: "Two lines on a coordinate plane.",
|
|
295
|
-
srLinearSystemPoints: "Line %(lineNumber)s has two points, point 1 at %(point1X)s comma %(point1Y)s and point 2 at %(point2X)s comma %(point2Y)s.",
|
|
296
|
-
srLinearSystemPoint: "Point %(pointSequence)s on line %(lineNumber)s at %(x)s comma %(y)s.",
|
|
297
|
-
srRayGraph: "A ray on a coordinate plane.",
|
|
298
|
-
srRayPoints: "The endpoint is at %(point1X)s comma %(point1Y)s and the ray goes through point %(point2X)s comma %(point2Y)s.",
|
|
299
|
-
srRayGrabHandle: "Ray with endpoint %(point1X)s comma %(point1Y)s going through point %(point2X)s comma %(point2Y)s.",
|
|
300
|
-
srRayEndpoint: "Endpoint at %(x)s comma %(y)s.",
|
|
301
|
-
srRayTerminalPoint: "Through point at %(x)s comma %(y)s.",
|
|
302
|
-
srQuadraticGraph: "A parabola on a 4-quadrant coordinate plane.",
|
|
303
|
-
srQuadraticFaceUp: "The parabola opens upward.",
|
|
304
|
-
srQuadraticFaceDown: "The parabola opens downward.",
|
|
305
|
-
srQuadraticGraphVertexOrigin: "Vertex is at the origin.",
|
|
306
|
-
srQuadraticGraphVertexXAxis: "Vertex is on the X-axis.",
|
|
307
|
-
srQuadraticGraphVertexYAxis: "Vertex is on the Y-axis.",
|
|
308
|
-
srQuadraticGraphVertexQuadrant: "Vertex is in quadrant %(quadrant)s.",
|
|
309
|
-
srQuadraticTwoXIntercepts: "The X-intercepts are at %(intercept1)s comma 0 and %(intercept2)s comma 0.",
|
|
310
|
-
srQuadraticOneXIntercept: "The X-intercept is at %(intercept)s comma 0.",
|
|
311
|
-
srQuadraticYIntercept: "The Y-intercept is at 0 comma %(intercept)s.",
|
|
312
|
-
srQuadraticPointOrigin: "Point %(pointNumber)s on parabola at the origin.",
|
|
313
|
-
srQuadraticPointAxis: "Point %(pointNumber)s on parabola at %(x)s comma %(y)s.",
|
|
314
|
-
srQuadraticPointQuadrant: "Point %(pointNumber)s on parabola in quadrant %(quadrant)s at %(x)s comma %(y)s.",
|
|
315
|
-
srQuadraticInteractiveElements: "Parabola with points at %(point1X)s comma %(point1Y)s, %(point2X)s comma %(point2Y)s, and %(point3X)s comma %(point3Y)s."
|
|
316
|
-
// The above strings are used for interactive graph SR descriptions.
|
|
317
|
-
};
|
|
318
|
-
|
|
319
112
|
/**
|
|
320
113
|
* Mock strings for the Perseus package, to be used for tests and Storybook.
|
|
321
114
|
*/
|
|
@@ -883,24 +676,32 @@ const mockStrings = {
|
|
|
883
676
|
|
|
884
677
|
// This type helps us make sure all error codes are mapped to strings
|
|
885
678
|
|
|
679
|
+
/**
|
|
680
|
+
* Map an error string to a PerseusStrings key
|
|
681
|
+
* that we can use to get the translated error message
|
|
682
|
+
*/
|
|
886
683
|
const errorToString = {
|
|
887
|
-
MISSING_PERCENT_ERROR:
|
|
888
|
-
NEEDS_TO_BE_SIMPLIFIED_ERROR:
|
|
889
|
-
APPROXIMATED_PI_ERROR:
|
|
890
|
-
EXTRA_SYMBOLS_ERROR:
|
|
891
|
-
WRONG_CASE_ERROR:
|
|
892
|
-
WRONG_LETTER_ERROR:
|
|
893
|
-
MULTIPLICATION_SIGN_ERROR:
|
|
894
|
-
INVALID_SELECTION_ERROR:
|
|
895
|
-
CHOOSE_CORRECT_NUM_ERROR:
|
|
896
|
-
NOT_NONE_ABOVE_ERROR:
|
|
897
|
-
FILL_ALL_CELLS_ERROR:
|
|
898
|
-
};
|
|
899
|
-
function mapErrorToString(
|
|
684
|
+
MISSING_PERCENT_ERROR: "MISSING_PERCENT_ERROR",
|
|
685
|
+
NEEDS_TO_BE_SIMPLIFIED_ERROR: "NEEDS_TO_BE_SIMPLFIED_ERROR",
|
|
686
|
+
APPROXIMATED_PI_ERROR: "APPROXIMATED_PI_ERROR",
|
|
687
|
+
EXTRA_SYMBOLS_ERROR: "EXTRA_SYMBOLS_ERROR",
|
|
688
|
+
WRONG_CASE_ERROR: "WRONG_CASE_ERROR",
|
|
689
|
+
WRONG_LETTER_ERROR: "WRONG_LETTER_ERROR",
|
|
690
|
+
MULTIPLICATION_SIGN_ERROR: "MULTIPLICATION_SIGN_ERROR",
|
|
691
|
+
INVALID_SELECTION_ERROR: "invalidSelection",
|
|
692
|
+
CHOOSE_CORRECT_NUM_ERROR: "chooseCorrectNum",
|
|
693
|
+
NOT_NONE_ABOVE_ERROR: "notNoneOfTheAbove",
|
|
694
|
+
FILL_ALL_CELLS_ERROR: "fillAllCells"
|
|
695
|
+
};
|
|
696
|
+
function mapErrorToString(
|
|
697
|
+
// the string representing an error code
|
|
698
|
+
err,
|
|
699
|
+
// the translated Perseus strings
|
|
700
|
+
translatedStrings) {
|
|
900
701
|
if (!err) {
|
|
901
702
|
return err;
|
|
902
703
|
}
|
|
903
|
-
return errorToString[err] || err;
|
|
704
|
+
return translatedStrings[errorToString[err]] || err;
|
|
904
705
|
}
|
|
905
706
|
|
|
906
707
|
/**
|
|
@@ -1811,7 +1612,6 @@ const ClassNames = {
|
|
|
1811
1612
|
SELECTED: "perseus-radio-selected",
|
|
1812
1613
|
OPTION_CONTENT: "perseus-radio-option-content"
|
|
1813
1614
|
},
|
|
1814
|
-
INTERACTIVE: "perseus-interactive",
|
|
1815
1615
|
CORRECT: "perseus-correct",
|
|
1816
1616
|
INCORRECT: "perseus-incorrect",
|
|
1817
1617
|
UNANSWERED: "perseus-unanswered",
|
|
@@ -2067,7 +1867,6 @@ class Expression extends React__namespace.Component {
|
|
|
2067
1867
|
// eslint-disable-next-line react/no-string-refs
|
|
2068
1868
|
, {
|
|
2069
1869
|
ref: "input",
|
|
2070
|
-
className: ClassNames.INTERACTIVE,
|
|
2071
1870
|
value: this.props.value,
|
|
2072
1871
|
onChange: this.changeAndTrack,
|
|
2073
1872
|
convertDotToTimes: this.props.times,
|
|
@@ -2169,7 +1968,6 @@ var Expression$1 = {
|
|
|
2169
1968
|
name: "expression",
|
|
2170
1969
|
displayName: "Expression / Equation",
|
|
2171
1970
|
accessible: true,
|
|
2172
|
-
defaultAlignment: "inline-block",
|
|
2173
1971
|
widget: ExpressionWithDependencies,
|
|
2174
1972
|
transform: widgetOptions => {
|
|
2175
1973
|
const {
|
|
@@ -2194,12 +1992,6 @@ var Expression$1 = {
|
|
|
2194
1992
|
propUpgrades: perseusCore.expressionLogic.widgetOptionsUpgrades,
|
|
2195
1993
|
// For use by the editor
|
|
2196
1994
|
isLintable: true,
|
|
2197
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
2198
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusExpressionUserInput'.
|
|
2199
|
-
scorer: perseusScore.scoreExpression,
|
|
2200
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
2201
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusExpressionUserInput'.
|
|
2202
|
-
validator: perseusScore.validateExpression,
|
|
2203
1995
|
getPublicWidgetOptions: perseusCore.getExpressionPublicWidgetOptions,
|
|
2204
1996
|
// TODO(LEMS-2656): remove TS suppression
|
|
2205
1997
|
// @ts-expect-error: Type 'Rubric' is not assignable to type 'PerseusExpressionRubric'.
|
|
@@ -3479,10 +3271,6 @@ const pureMdMax$1 = "1023px";
|
|
|
3479
3271
|
const pureLgMax$1 = "1279px";
|
|
3480
3272
|
// @tableBackgroundAccent: #f9f9f9; // for striping
|
|
3481
3273
|
const tableBackgroundAccent = "#F9F9F9";
|
|
3482
|
-
// @zIndexAboveScratchpad: @zIndexScratchPad + 1;
|
|
3483
|
-
const zIndexAboveScratchpad$1 = 2;
|
|
3484
|
-
// @zIndexInteractiveComponent: @zIndexAboveScratchpad + 1;
|
|
3485
|
-
const zIndexInteractiveComponent$1 = 3;
|
|
3486
3274
|
// @phoneMargin: 16px;
|
|
3487
3275
|
const phoneMargin = 16;
|
|
3488
3276
|
const negativePhoneMargin = -16;
|
|
@@ -3526,8 +3314,6 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
3526
3314
|
pureMdMax: pureMdMax$1,
|
|
3527
3315
|
pureLgMax: pureLgMax$1,
|
|
3528
3316
|
tableBackgroundAccent: tableBackgroundAccent,
|
|
3529
|
-
zIndexAboveScratchpad: zIndexAboveScratchpad$1,
|
|
3530
|
-
zIndexInteractiveComponent: zIndexInteractiveComponent$1,
|
|
3531
3317
|
phoneMargin: phoneMargin,
|
|
3532
3318
|
negativePhoneMargin: negativePhoneMargin,
|
|
3533
3319
|
hintBorderWidth: hintBorderWidth,
|
|
@@ -17822,657 +17608,6 @@ class QuestionParagraph extends React__namespace.Component {
|
|
|
17822
17608
|
}
|
|
17823
17609
|
}
|
|
17824
17610
|
|
|
17825
|
-
const noScore = {
|
|
17826
|
-
type: "points",
|
|
17827
|
-
earned: 0,
|
|
17828
|
-
total: 0,
|
|
17829
|
-
message: null
|
|
17830
|
-
};
|
|
17831
|
-
|
|
17832
|
-
/**
|
|
17833
|
-
* If a widget says that it is empty once it is graded.
|
|
17834
|
-
* Trying to encapsulate references to the score format.
|
|
17835
|
-
*/
|
|
17836
|
-
function scoreIsEmpty(score) {
|
|
17837
|
-
// HACK(benkomalo): ugh. this isn't great; the Perseus score objects
|
|
17838
|
-
// overload the type "invalid" for what should probably be three
|
|
17839
|
-
// distinct cases:
|
|
17840
|
-
// - truly empty or not fully filled out
|
|
17841
|
-
// - invalid or malformed inputs
|
|
17842
|
-
// - "almost correct" like inputs where the widget wants to give
|
|
17843
|
-
// feedback (e.g. a fraction needs to be reduced, or `pi` should
|
|
17844
|
-
// be used instead of 3.14)
|
|
17845
|
-
//
|
|
17846
|
-
// Unfortunately the coercion happens all over the place, as these
|
|
17847
|
-
// Perseus style score objects are created *everywhere* (basically
|
|
17848
|
-
// in every widget), so it's hard to change now. We assume that
|
|
17849
|
-
// anything with a "message" is not truly empty, and one of the
|
|
17850
|
-
// latter two cases for now.
|
|
17851
|
-
return score.type === "invalid" && (!score.message || score.message.length === 0);
|
|
17852
|
-
}
|
|
17853
|
-
|
|
17854
|
-
/**
|
|
17855
|
-
* Combine two score objects.
|
|
17856
|
-
*
|
|
17857
|
-
* Given two score objects for two different widgets, combine them so that
|
|
17858
|
-
* if one is wrong, the total score is wrong, etc.
|
|
17859
|
-
*/
|
|
17860
|
-
function combineScores(scoreA, scoreB) {
|
|
17861
|
-
let message;
|
|
17862
|
-
if (scoreA.type === "points" && scoreB.type === "points") {
|
|
17863
|
-
if (scoreA.message && scoreB.message && scoreA.message !== scoreB.message) {
|
|
17864
|
-
// TODO(alpert): Figure out how to combine messages usefully
|
|
17865
|
-
message = null;
|
|
17866
|
-
} else {
|
|
17867
|
-
message = scoreA.message || scoreB.message;
|
|
17868
|
-
}
|
|
17869
|
-
return {
|
|
17870
|
-
type: "points",
|
|
17871
|
-
earned: scoreA.earned + scoreB.earned,
|
|
17872
|
-
total: scoreA.total + scoreB.total,
|
|
17873
|
-
message: message
|
|
17874
|
-
};
|
|
17875
|
-
}
|
|
17876
|
-
if (scoreA.type === "points" && scoreB.type === "invalid") {
|
|
17877
|
-
return scoreB;
|
|
17878
|
-
}
|
|
17879
|
-
if (scoreA.type === "invalid" && scoreB.type === "points") {
|
|
17880
|
-
return scoreA;
|
|
17881
|
-
}
|
|
17882
|
-
if (scoreA.type === "invalid" && scoreB.type === "invalid") {
|
|
17883
|
-
if (scoreA.message && scoreB.message && scoreA.message !== scoreB.message) {
|
|
17884
|
-
// TODO(alpert): Figure out how to combine messages usefully
|
|
17885
|
-
message = null;
|
|
17886
|
-
} else {
|
|
17887
|
-
message = scoreA.message || scoreB.message;
|
|
17888
|
-
}
|
|
17889
|
-
return {
|
|
17890
|
-
type: "invalid",
|
|
17891
|
-
message: message
|
|
17892
|
-
};
|
|
17893
|
-
}
|
|
17894
|
-
|
|
17895
|
-
/**
|
|
17896
|
-
* The above checks cover all combinations of score type, so if we get here
|
|
17897
|
-
* then something is amiss with our inputs.
|
|
17898
|
-
*/
|
|
17899
|
-
throw new perseusCore.PerseusError("PerseusScore with unknown type encountered", perseusCore.Errors.InvalidInput, {
|
|
17900
|
-
metadata: {
|
|
17901
|
-
scoreA: JSON.stringify(scoreA),
|
|
17902
|
-
scoreB: JSON.stringify(scoreB)
|
|
17903
|
-
}
|
|
17904
|
-
});
|
|
17905
|
-
}
|
|
17906
|
-
function flattenScores(widgetScoreMap) {
|
|
17907
|
-
return Object.values(widgetScoreMap).reduce(combineScores, noScore);
|
|
17908
|
-
}
|
|
17909
|
-
function isCorrect(score) {
|
|
17910
|
-
return score.type === "points" && score.earned >= score.total;
|
|
17911
|
-
}
|
|
17912
|
-
function keScoreFromPerseusScore(score,
|
|
17913
|
-
// It's weird, but this is what we're passing it
|
|
17914
|
-
guess, state) {
|
|
17915
|
-
if (score.type === "points") {
|
|
17916
|
-
return {
|
|
17917
|
-
empty: false,
|
|
17918
|
-
correct: isCorrect(score),
|
|
17919
|
-
message: score.message,
|
|
17920
|
-
guess: guess,
|
|
17921
|
-
state: state
|
|
17922
|
-
};
|
|
17923
|
-
}
|
|
17924
|
-
if (score.type === "invalid") {
|
|
17925
|
-
return {
|
|
17926
|
-
empty: true,
|
|
17927
|
-
correct: false,
|
|
17928
|
-
message: score.message,
|
|
17929
|
-
suppressAlmostThere: score.suppressAlmostThere,
|
|
17930
|
-
guess: guess,
|
|
17931
|
-
state: state
|
|
17932
|
-
};
|
|
17933
|
-
}
|
|
17934
|
-
throw new perseusCore.PerseusError(
|
|
17935
|
-
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
17936
|
-
"Invalid score type: " + score.type, perseusCore.Errors.InvalidInput, {
|
|
17937
|
-
metadata: {
|
|
17938
|
-
score: JSON.stringify(score),
|
|
17939
|
-
guess: JSON.stringify(guess),
|
|
17940
|
-
state: JSON.stringify(state)
|
|
17941
|
-
}
|
|
17942
|
-
});
|
|
17943
|
-
}
|
|
17944
|
-
|
|
17945
|
-
const DEFAULT_ALIGNMENT$1 = "block";
|
|
17946
|
-
// NOTE(kevinb): "default" is not one in `validAlignments`.
|
|
17947
|
-
const DEFAULT_SUPPORTED_ALIGNMENTS = ["default"];
|
|
17948
|
-
const DEFAULT_STATIC = false;
|
|
17949
|
-
const DEFAULT_TRACKING = "";
|
|
17950
|
-
const DEFAULT_LINTABLE = false;
|
|
17951
|
-
const widgets = {};
|
|
17952
|
-
const editors = {};
|
|
17953
|
-
|
|
17954
|
-
// Widgets must be registered to avoid circular dependencies with the
|
|
17955
|
-
// core Editor and Renderer components.
|
|
17956
|
-
// TODO(jeremy): The widget name is already embedded in the WidgetExports type
|
|
17957
|
-
// so could we drop the `name` parameter here?
|
|
17958
|
-
const registerWidget = (name, widget) => {
|
|
17959
|
-
widgets[name] = widget;
|
|
17960
|
-
};
|
|
17961
|
-
const registerWidgets = widgets => {
|
|
17962
|
-
widgets.forEach(widget => {
|
|
17963
|
-
registerWidget(widget.name, widget);
|
|
17964
|
-
});
|
|
17965
|
-
validateAlignments();
|
|
17966
|
-
};
|
|
17967
|
-
|
|
17968
|
-
/**
|
|
17969
|
-
*
|
|
17970
|
-
* @param name - the widget that you are trying to replace
|
|
17971
|
-
* @param replacementName - the name of the widget that takes its place
|
|
17972
|
-
*
|
|
17973
|
-
* e.g. replaceWidget("transformer", "deprecated-standin") will make it so the
|
|
17974
|
-
* transformer widget is replaced by the always correct widget
|
|
17975
|
-
*/
|
|
17976
|
-
const replaceWidget = (name, replacementName) => {
|
|
17977
|
-
const substituteWidget = widgets[replacementName];
|
|
17978
|
-
|
|
17979
|
-
// If the replacement widget isn't found, we need to throw. Otherwise after
|
|
17980
|
-
// removing the deprecated widget, we'll have data asking for a widget type
|
|
17981
|
-
// that doesn't exist at all.
|
|
17982
|
-
if (!substituteWidget) {
|
|
17983
|
-
const errorMsg = `Failed to replace ${name} with ${replacementName}`;
|
|
17984
|
-
throw new perseusCore.PerseusError(errorMsg, perseusCore.Errors.Internal);
|
|
17985
|
-
}
|
|
17986
|
-
registerWidget(name, substituteWidget);
|
|
17987
|
-
};
|
|
17988
|
-
const replaceDeprecatedWidgets = () => {
|
|
17989
|
-
replaceWidget("transformer", "deprecated-standin");
|
|
17990
|
-
replaceWidget("lights-puzzle", "deprecated-standin");
|
|
17991
|
-
replaceWidget("reaction-diagram", "deprecated-standin");
|
|
17992
|
-
replaceWidget("sequence", "deprecated-standin");
|
|
17993
|
-
replaceWidget("simulator", "deprecated-standin");
|
|
17994
|
-
replaceWidget("unit-input", "deprecated-standin");
|
|
17995
|
-
};
|
|
17996
|
-
const registerEditors = editorsToRegister => {
|
|
17997
|
-
editorsToRegister.forEach(editor => {
|
|
17998
|
-
if (!editor.widgetName) {
|
|
17999
|
-
throw new perseusCore.PerseusError(`Editor ${editor.displayName} doesn't have a widgetName property`, perseusCore.Errors.Internal);
|
|
18000
|
-
}
|
|
18001
|
-
editors[editor.widgetName] = editor;
|
|
18002
|
-
});
|
|
18003
|
-
};
|
|
18004
|
-
|
|
18005
|
-
/**
|
|
18006
|
-
*
|
|
18007
|
-
* @param name - the widget that you are trying to replace
|
|
18008
|
-
* @param replacementName - the name of the widget that takes its place
|
|
18009
|
-
*
|
|
18010
|
-
* e.g. replaceEditor("transformer", "deprecated-standin") will make it so the
|
|
18011
|
-
* transformer widget is replaced by the deprecated stand-in widget
|
|
18012
|
-
*/
|
|
18013
|
-
const replaceEditor = (name, replacementName) => {
|
|
18014
|
-
const substituteEditor = editors[replacementName];
|
|
18015
|
-
if (!substituteEditor && Log) {
|
|
18016
|
-
const errorMsg = `Failed to replace editor ${name} with ${replacementName}`;
|
|
18017
|
-
Log.error(errorMsg, perseusCore.Errors.Internal);
|
|
18018
|
-
return;
|
|
18019
|
-
}
|
|
18020
|
-
editors[name] = substituteEditor;
|
|
18021
|
-
};
|
|
18022
|
-
const replaceDeprecatedEditors = () => {
|
|
18023
|
-
replaceEditor("transformer", "deprecated-standin");
|
|
18024
|
-
replaceEditor("lights-puzzle", "deprecated-standin");
|
|
18025
|
-
replaceEditor("reaction-diagram", "deprecated-standin");
|
|
18026
|
-
replaceEditor("sequence", "deprecated-standin");
|
|
18027
|
-
replaceEditor("simulator", "deprecated-standin");
|
|
18028
|
-
replaceEditor("unit-input", "deprecated-standin");
|
|
18029
|
-
};
|
|
18030
|
-
const getWidget = name => {
|
|
18031
|
-
// TODO(alex): Consider referring to these as renderers to avoid
|
|
18032
|
-
// overloading "widget"
|
|
18033
|
-
if (!___default["default"].has(widgets, name)) {
|
|
18034
|
-
return null;
|
|
18035
|
-
}
|
|
18036
|
-
|
|
18037
|
-
// Allow widgets to specify a widget directly or via a function
|
|
18038
|
-
if (widgets[name]?.getWidget) {
|
|
18039
|
-
return widgets[name].getWidget?.();
|
|
18040
|
-
}
|
|
18041
|
-
return widgets[name].widget;
|
|
18042
|
-
};
|
|
18043
|
-
const getWidgetExport = name => {
|
|
18044
|
-
return widgets[name] ?? null;
|
|
18045
|
-
};
|
|
18046
|
-
const getWidgetValidator = name => {
|
|
18047
|
-
return widgets[name]?.validator ?? null;
|
|
18048
|
-
};
|
|
18049
|
-
const getWidgetScorer = name => {
|
|
18050
|
-
return widgets[name]?.scorer ?? null;
|
|
18051
|
-
};
|
|
18052
|
-
const getPublicWidgetOptionsFunction = name => {
|
|
18053
|
-
return widgets[name]?.getPublicWidgetOptions ?? (i => i);
|
|
18054
|
-
};
|
|
18055
|
-
const getEditor = name => {
|
|
18056
|
-
return ___default["default"].has(editors, name) ? editors[name] : null;
|
|
18057
|
-
};
|
|
18058
|
-
const getTransform = name => {
|
|
18059
|
-
return ___default["default"].has(widgets, name) ? widgets[name].transform || ___default["default"].identity : null;
|
|
18060
|
-
};
|
|
18061
|
-
const getVersion = name => {
|
|
18062
|
-
const widgetInfo = widgets[name];
|
|
18063
|
-
if (widgetInfo) {
|
|
18064
|
-
return widgets[name].version || {
|
|
18065
|
-
major: 0,
|
|
18066
|
-
minor: 0
|
|
18067
|
-
};
|
|
18068
|
-
}
|
|
18069
|
-
return;
|
|
18070
|
-
};
|
|
18071
|
-
const getVersionVector = () => {
|
|
18072
|
-
const version = {};
|
|
18073
|
-
___default["default"].each(___default["default"].keys(widgets), function (name) {
|
|
18074
|
-
version[name] = getVersion(name);
|
|
18075
|
-
});
|
|
18076
|
-
return version;
|
|
18077
|
-
};
|
|
18078
|
-
const getPublicWidgets = () => {
|
|
18079
|
-
// TODO(alex): Update underscore.js so that _.pick can take a function.
|
|
18080
|
-
// @ts-expect-error - TS2740 - Type 'Pick<{ [key: string]: Readonly<{ name: string; displayName: string; getWidget?: (() => ComponentType<any>) | undefined; accessible?: boolean | ((props: any) => boolean) | undefined; hidden?: boolean | undefined; ... 10 more ...; widget: ComponentType<...>; }>; }, string>' is missing the following properties from type 'readonly Readonly<{ name: string; displayName: string; getWidget?: (() => ComponentType<any>) | undefined; accessible?: boolean | ((props: any) => boolean) | undefined; hidden?: boolean | undefined; ... 10 more ...; widget: ComponentType<...>; }>[]': length, concat, join, slice, and 18 more.
|
|
18081
|
-
return ___default["default"].pick(widgets,
|
|
18082
|
-
// @ts-expect-error - TS2345 - Argument of type '(name: string) => boolean | undefined' is not assignable to parameter of type 'Iteratee<string[], boolean, string>'.
|
|
18083
|
-
___default["default"].reject(___default["default"].keys(widgets), function (name) {
|
|
18084
|
-
return widgets[name].hidden;
|
|
18085
|
-
}));
|
|
18086
|
-
};
|
|
18087
|
-
const isAccessible = widgetInfo => {
|
|
18088
|
-
const accessible = widgets[widgetInfo.type].accessible;
|
|
18089
|
-
if (typeof accessible === "function") {
|
|
18090
|
-
return accessible(widgetInfo.options);
|
|
18091
|
-
}
|
|
18092
|
-
return !!accessible;
|
|
18093
|
-
};
|
|
18094
|
-
const getAllWidgetTypes = () => {
|
|
18095
|
-
return ___default["default"].keys(widgets);
|
|
18096
|
-
};
|
|
18097
|
-
const upgradeWidgetInfoToLatestVersion = oldWidgetInfo => {
|
|
18098
|
-
const type = oldWidgetInfo.type;
|
|
18099
|
-
// NOTE(jeremy): This looks like it could be replaced by fixing types so
|
|
18100
|
-
// that `type` is non-optional. But we're seeing this in Sentry today so I
|
|
18101
|
-
// suspect we have legacy data (potentially unpublished) and we should
|
|
18102
|
-
// figure that out before depending solely on types.
|
|
18103
|
-
if (!___default["default"].isString(type)) {
|
|
18104
|
-
throw new perseusCore.PerseusError("widget type must be a string, but was: " + type, perseusCore.Errors.Internal);
|
|
18105
|
-
}
|
|
18106
|
-
const widgetExports = widgets[type];
|
|
18107
|
-
if (widgetExports == null) {
|
|
18108
|
-
// If we have a widget that isn't registered, we can't upgrade it
|
|
18109
|
-
// TODO(aria): Figure out what the best thing to do here would be
|
|
18110
|
-
return oldWidgetInfo;
|
|
18111
|
-
}
|
|
18112
|
-
|
|
18113
|
-
// Unversioned widgets (pre-July 2014) are all implicitly 0.0
|
|
18114
|
-
const initialVersion = oldWidgetInfo.version || {
|
|
18115
|
-
major: 0,
|
|
18116
|
-
minor: 0
|
|
18117
|
-
};
|
|
18118
|
-
const latestVersion = widgetExports.version || {
|
|
18119
|
-
major: 0,
|
|
18120
|
-
minor: 0
|
|
18121
|
-
};
|
|
18122
|
-
|
|
18123
|
-
// If the widget version is later than what we understand (major
|
|
18124
|
-
// version is higher than latest, or major versions are equal and minor
|
|
18125
|
-
// version is higher than latest), don't perform any upgrades.
|
|
18126
|
-
if (initialVersion.major > latestVersion.major || initialVersion.major === latestVersion.major && initialVersion.minor > latestVersion.minor) {
|
|
18127
|
-
return oldWidgetInfo;
|
|
18128
|
-
}
|
|
18129
|
-
|
|
18130
|
-
// We do a clone here so that it's safe to mutate the input parameter
|
|
18131
|
-
// in propUpgrades functions (which I will probably accidentally do at
|
|
18132
|
-
// some point, and we would like to not break when that happens).
|
|
18133
|
-
let newEditorProps = ___default["default"].clone(oldWidgetInfo.options) || {};
|
|
18134
|
-
const upgradePropsMap = widgetExports.propUpgrades || {};
|
|
18135
|
-
|
|
18136
|
-
// Empty props usually mean a newly created widget by the editor,
|
|
18137
|
-
// and are always considerered up-to-date.
|
|
18138
|
-
// Mostly, we'd rather not run upgrade functions on props that are
|
|
18139
|
-
// not complete.
|
|
18140
|
-
if (___default["default"].keys(newEditorProps).length !== 0) {
|
|
18141
|
-
// We loop through all the versions after the current version of
|
|
18142
|
-
// the loaded widget, up to and including the latest version of the
|
|
18143
|
-
// loaded widget, and run the upgrade function to bring our loaded
|
|
18144
|
-
// widget's props up to that version.
|
|
18145
|
-
// There is a little subtlety here in that we call
|
|
18146
|
-
// upgradePropsMap[1] to upgrade *to* version 1,
|
|
18147
|
-
// (not from version 1).
|
|
18148
|
-
for (let nextVersion = initialVersion.major + 1; nextVersion <= latestVersion.major; nextVersion++) {
|
|
18149
|
-
if (upgradePropsMap[String(nextVersion)]) {
|
|
18150
|
-
newEditorProps = upgradePropsMap[String(nextVersion)](newEditorProps);
|
|
18151
|
-
} else {
|
|
18152
|
-
// This is a Log.error because it is unlikely to be hit in
|
|
18153
|
-
// local testing, and a Log.error is slightly less scary in
|
|
18154
|
-
// prod than a `throw new Error`
|
|
18155
|
-
Log.error("No upgrade found for widget. Cannot render.", perseusCore.Errors.Internal, {
|
|
18156
|
-
loggedMetadata: {
|
|
18157
|
-
type,
|
|
18158
|
-
fromMajorVersion: nextVersion - 1,
|
|
18159
|
-
toMajorVersion: nextVersion
|
|
18160
|
-
}
|
|
18161
|
-
});
|
|
18162
|
-
// But try to keep going anyways (yolo!)
|
|
18163
|
-
// (Throwing an error here would just break the page
|
|
18164
|
-
// silently anyways, so that doesn't seem much better
|
|
18165
|
-
// than a halfhearted attempt to continue, however
|
|
18166
|
-
// shallow...)
|
|
18167
|
-
}
|
|
18168
|
-
}
|
|
18169
|
-
}
|
|
18170
|
-
|
|
18171
|
-
// Minor version upgrades (eg. new optional props) don't have
|
|
18172
|
-
// transform functions. Instead, we fill in the new props with their
|
|
18173
|
-
// defaults.
|
|
18174
|
-
const defaultProps = type in editors ? editors[type].defaultProps : {};
|
|
18175
|
-
newEditorProps = {
|
|
18176
|
-
...defaultProps,
|
|
18177
|
-
...newEditorProps
|
|
18178
|
-
};
|
|
18179
|
-
let alignment = oldWidgetInfo.alignment;
|
|
18180
|
-
|
|
18181
|
-
// Widgets that support multiple alignments will "lock in" the
|
|
18182
|
-
// alignment to the alignment that would be listed first in the
|
|
18183
|
-
// select box. If the widget only supports one alignment, the
|
|
18184
|
-
// alignment value will likely just end up as "default".
|
|
18185
|
-
if (alignment == null || alignment === "default") {
|
|
18186
|
-
alignment = getSupportedAlignments(type)[0];
|
|
18187
|
-
}
|
|
18188
|
-
let widgetStatic = oldWidgetInfo.static;
|
|
18189
|
-
if (widgetStatic == null) {
|
|
18190
|
-
widgetStatic = DEFAULT_STATIC;
|
|
18191
|
-
}
|
|
18192
|
-
return ___default["default"].extend({}, oldWidgetInfo, {
|
|
18193
|
-
// maintain other info, like type
|
|
18194
|
-
// After upgrading we guarantee that the version is up-to-date
|
|
18195
|
-
version: latestVersion,
|
|
18196
|
-
// Default graded to true (so null/undefined becomes true):
|
|
18197
|
-
graded: oldWidgetInfo.graded != null ? oldWidgetInfo.graded : true,
|
|
18198
|
-
alignment: alignment,
|
|
18199
|
-
static: widgetStatic,
|
|
18200
|
-
options: newEditorProps
|
|
18201
|
-
});
|
|
18202
|
-
};
|
|
18203
|
-
const getRendererPropsForWidgetInfo = (widgetInfo, strings, problemNum) => {
|
|
18204
|
-
const type = widgetInfo.type;
|
|
18205
|
-
const widgetExports = widgets[type];
|
|
18206
|
-
if (widgetExports == null) {
|
|
18207
|
-
// The widget is not a registered widget
|
|
18208
|
-
// It shouldn't matter what we return here, but for consistency
|
|
18209
|
-
// we return the untransformed options, as if the widget did
|
|
18210
|
-
// not have a transform defined.
|
|
18211
|
-
return widgetInfo;
|
|
18212
|
-
}
|
|
18213
|
-
let transform;
|
|
18214
|
-
if (widgetInfo.static) {
|
|
18215
|
-
// There aren't a lot of real places where we'll have to default to
|
|
18216
|
-
// _.identity, but it's theoretically possible if someone changes
|
|
18217
|
-
// the JSON manually / we have to back out static support for a
|
|
18218
|
-
// widget.
|
|
18219
|
-
transform = getStaticTransform(type) || ___default["default"].identity;
|
|
18220
|
-
} else {
|
|
18221
|
-
transform = widgetExports.transform || ___default["default"].identity;
|
|
18222
|
-
}
|
|
18223
|
-
// widgetInfo.options are the widgetEditor's props:
|
|
18224
|
-
return transform(widgetInfo.options, strings, problemNum);
|
|
18225
|
-
};
|
|
18226
|
-
const traverseChildWidgets$3 = (widgetInfo, traverseRenderer) => {
|
|
18227
|
-
if (!traverseRenderer) {
|
|
18228
|
-
throw new perseusCore.PerseusError("traverseRenderer must be provided, but was not", perseusCore.Errors.Internal);
|
|
18229
|
-
}
|
|
18230
|
-
if (!widgetInfo || !widgetInfo.type || !widgets[widgetInfo.type]) {
|
|
18231
|
-
return widgetInfo;
|
|
18232
|
-
}
|
|
18233
|
-
const widgetExports = widgets[widgetInfo.type];
|
|
18234
|
-
const props = widgetInfo.options;
|
|
18235
|
-
if (widgetExports.traverseChildWidgets && props) {
|
|
18236
|
-
const newProps = widgetExports.traverseChildWidgets(props, traverseRenderer);
|
|
18237
|
-
return ___default["default"].extend({}, widgetInfo, {
|
|
18238
|
-
options: newProps
|
|
18239
|
-
});
|
|
18240
|
-
}
|
|
18241
|
-
return widgetInfo;
|
|
18242
|
-
};
|
|
18243
|
-
|
|
18244
|
-
/**
|
|
18245
|
-
* Handling for the optional alignments for widgets
|
|
18246
|
-
* See widget-container.jsx for details on how alignments are implemented.
|
|
18247
|
-
*/
|
|
18248
|
-
|
|
18249
|
-
/**
|
|
18250
|
-
* Returns the list of supported alignments for the given (string) widget
|
|
18251
|
-
* type. This is used primarily at editing time to display the choices
|
|
18252
|
-
* for the user.
|
|
18253
|
-
*
|
|
18254
|
-
* Supported alignments are given as an array of strings in the exports of
|
|
18255
|
-
* a widget's module.
|
|
18256
|
-
*/
|
|
18257
|
-
const getSupportedAlignments = type => {
|
|
18258
|
-
const widgetExport = widgets[type];
|
|
18259
|
-
// @ts-expect-error - TS2322 - Type 'string[] | readonly Alignment[]' is not assignable to type 'readonly Alignment[]'.
|
|
18260
|
-
return widgetExport && widgetExport.supportedAlignments || DEFAULT_SUPPORTED_ALIGNMENTS;
|
|
18261
|
-
};
|
|
18262
|
-
|
|
18263
|
-
/**
|
|
18264
|
-
* For the given (string) widget type, determine the default alignment for
|
|
18265
|
-
* the widget. This is used at rendering time to go from "default" alignment
|
|
18266
|
-
* to the actual alignment displayed on the screen.
|
|
18267
|
-
*
|
|
18268
|
-
* The default alignment is given either as a string (called
|
|
18269
|
-
* `defaultAlignment`) or a function (called `getDefaultAlignment`) on
|
|
18270
|
-
* the exports of a widget's module.
|
|
18271
|
-
*/
|
|
18272
|
-
const getDefaultAlignment = type => {
|
|
18273
|
-
const widgetExports = widgets[type];
|
|
18274
|
-
let alignment;
|
|
18275
|
-
if (!widgetExports) {
|
|
18276
|
-
return DEFAULT_ALIGNMENT$1;
|
|
18277
|
-
}
|
|
18278
|
-
if (widgetExports.getDefaultAlignment) {
|
|
18279
|
-
alignment = widgetExports.getDefaultAlignment();
|
|
18280
|
-
} else {
|
|
18281
|
-
alignment = widgetExports.defaultAlignment;
|
|
18282
|
-
}
|
|
18283
|
-
return alignment || DEFAULT_ALIGNMENT$1;
|
|
18284
|
-
};
|
|
18285
|
-
const validAlignments = ["block", "inline-block", "inline", "float-left", "float-right", "full-width"];
|
|
18286
|
-
|
|
18287
|
-
/**
|
|
18288
|
-
* Used at startup to fail fast if an alignment given by a widget is
|
|
18289
|
-
* invalid.
|
|
18290
|
-
*/
|
|
18291
|
-
// TODO(alex): Change this to run as a testcase (vs. being run at runtime)
|
|
18292
|
-
// TODO(LP-10707): I think this can be completely removed because our TypeScript types
|
|
18293
|
-
// enforce this!
|
|
18294
|
-
const validateAlignments = () => {
|
|
18295
|
-
___default["default"].each(widgets, function (widgetInfo) {
|
|
18296
|
-
if (widgetInfo.defaultAlignment && !___default["default"].contains(validAlignments, widgetInfo.defaultAlignment)) {
|
|
18297
|
-
throw new perseusCore.PerseusError("Widget '" + widgetInfo.displayName + "' has an invalid defaultAlignment value: " + widgetInfo.defaultAlignment, perseusCore.Errors.InvalidInput);
|
|
18298
|
-
}
|
|
18299
|
-
if (widgetInfo.supportedAlignments) {
|
|
18300
|
-
const unknownAlignments = ___default["default"].difference(widgetInfo.supportedAlignments, validAlignments);
|
|
18301
|
-
if (unknownAlignments.length) {
|
|
18302
|
-
throw new perseusCore.PerseusError("Widget '" + widgetInfo.displayName + "' has an invalid value for supportedAlignments: " + unknownAlignments.join(" "), perseusCore.Errors.InvalidInput);
|
|
18303
|
-
}
|
|
18304
|
-
}
|
|
18305
|
-
});
|
|
18306
|
-
};
|
|
18307
|
-
|
|
18308
|
-
/**
|
|
18309
|
-
* Handling for static mode for widgets that support it.
|
|
18310
|
-
*/
|
|
18311
|
-
|
|
18312
|
-
/**
|
|
18313
|
-
* Returns true iff the widget supports static mode.
|
|
18314
|
-
* A widget implicitly supports static mode if it exports a
|
|
18315
|
-
* staticTransform function.
|
|
18316
|
-
*/
|
|
18317
|
-
const supportsStaticMode = type => {
|
|
18318
|
-
const widgetInfo = widgets[type];
|
|
18319
|
-
return widgetInfo && widgetInfo.staticTransform != null;
|
|
18320
|
-
};
|
|
18321
|
-
|
|
18322
|
-
/**
|
|
18323
|
-
* Return the staticTransform function used to convert the editorProps to
|
|
18324
|
-
* the rendered widget state.
|
|
18325
|
-
*/
|
|
18326
|
-
const getStaticTransform = type => {
|
|
18327
|
-
const widgetInfo = widgets[type];
|
|
18328
|
-
return widgetInfo && widgetInfo.staticTransform;
|
|
18329
|
-
};
|
|
18330
|
-
|
|
18331
|
-
/**
|
|
18332
|
-
* Returns the tracking option for the widget. The default is "",
|
|
18333
|
-
* which means simply to track interactions once. The other available
|
|
18334
|
-
* option is "all" which means to track all interactions.
|
|
18335
|
-
*/
|
|
18336
|
-
const getTracking = type => {
|
|
18337
|
-
const widgetExport = widgets[type];
|
|
18338
|
-
return widgetExport && widgetExport.tracking || DEFAULT_TRACKING;
|
|
18339
|
-
};
|
|
18340
|
-
|
|
18341
|
-
/**
|
|
18342
|
-
* Returns true if this widget can include lintable markdown text
|
|
18343
|
-
* and supports a highlightLint prop, or false otherwise.
|
|
18344
|
-
*/
|
|
18345
|
-
const isLintable = type => {
|
|
18346
|
-
const widgetExports = widgets[type];
|
|
18347
|
-
return widgetExports && widgetExports.isLintable || DEFAULT_LINTABLE;
|
|
18348
|
-
};
|
|
18349
|
-
|
|
18350
|
-
var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
18351
|
-
__proto__: null,
|
|
18352
|
-
registerWidget: registerWidget,
|
|
18353
|
-
registerWidgets: registerWidgets,
|
|
18354
|
-
replaceWidget: replaceWidget,
|
|
18355
|
-
replaceDeprecatedWidgets: replaceDeprecatedWidgets,
|
|
18356
|
-
registerEditors: registerEditors,
|
|
18357
|
-
replaceEditor: replaceEditor,
|
|
18358
|
-
replaceDeprecatedEditors: replaceDeprecatedEditors,
|
|
18359
|
-
getWidget: getWidget,
|
|
18360
|
-
getWidgetExport: getWidgetExport,
|
|
18361
|
-
getWidgetValidator: getWidgetValidator,
|
|
18362
|
-
getWidgetScorer: getWidgetScorer,
|
|
18363
|
-
getPublicWidgetOptionsFunction: getPublicWidgetOptionsFunction,
|
|
18364
|
-
getEditor: getEditor,
|
|
18365
|
-
getTransform: getTransform,
|
|
18366
|
-
getVersion: getVersion,
|
|
18367
|
-
getVersionVector: getVersionVector,
|
|
18368
|
-
getPublicWidgets: getPublicWidgets,
|
|
18369
|
-
isAccessible: isAccessible,
|
|
18370
|
-
getAllWidgetTypes: getAllWidgetTypes,
|
|
18371
|
-
upgradeWidgetInfoToLatestVersion: upgradeWidgetInfoToLatestVersion,
|
|
18372
|
-
getRendererPropsForWidgetInfo: getRendererPropsForWidgetInfo,
|
|
18373
|
-
traverseChildWidgets: traverseChildWidgets$3,
|
|
18374
|
-
getSupportedAlignments: getSupportedAlignments,
|
|
18375
|
-
getDefaultAlignment: getDefaultAlignment,
|
|
18376
|
-
validateAlignments: validateAlignments,
|
|
18377
|
-
supportsStaticMode: supportsStaticMode,
|
|
18378
|
-
getStaticTransform: getStaticTransform,
|
|
18379
|
-
getTracking: getTracking,
|
|
18380
|
-
isLintable: isLintable
|
|
18381
|
-
});
|
|
18382
|
-
|
|
18383
|
-
function getUpgradedWidgetOptions(oldWidgetOptions) {
|
|
18384
|
-
return perseusCore.mapObject(oldWidgetOptions, (widgetInfo, widgetId) => {
|
|
18385
|
-
if (!widgetInfo.type || !widgetInfo.alignment) {
|
|
18386
|
-
const newValues = {};
|
|
18387
|
-
if (!widgetInfo.type) {
|
|
18388
|
-
// TODO: why does widget have no type?
|
|
18389
|
-
// We don't want to derive type from widget ID
|
|
18390
|
-
// see: LEMS-1845
|
|
18391
|
-
newValues.type = widgetId.split(" ")[0];
|
|
18392
|
-
}
|
|
18393
|
-
if (!widgetInfo.alignment) {
|
|
18394
|
-
newValues.alignment = "default";
|
|
18395
|
-
}
|
|
18396
|
-
widgetInfo = {
|
|
18397
|
-
...widgetInfo,
|
|
18398
|
-
...newValues
|
|
18399
|
-
};
|
|
18400
|
-
}
|
|
18401
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
18402
|
-
return upgradeWidgetInfoToLatestVersion(widgetInfo);
|
|
18403
|
-
});
|
|
18404
|
-
}
|
|
18405
|
-
|
|
18406
|
-
/**
|
|
18407
|
-
* Checks the given user input to see if any answerable widgets have not been
|
|
18408
|
-
* "filled in" (ie. if they're empty). Another way to think about this
|
|
18409
|
-
* function is that its a check to see if we can score the provided input.
|
|
18410
|
-
*/
|
|
18411
|
-
function emptyWidgetsFunctional(widgets,
|
|
18412
|
-
// This is a port of old code, I'm not sure why
|
|
18413
|
-
// we need widgetIds vs the keys of the widgets object
|
|
18414
|
-
widgetIds, userInputMap, strings, locale) {
|
|
18415
|
-
return widgetIds.filter(id => {
|
|
18416
|
-
const widget = widgets[id];
|
|
18417
|
-
if (!widget || widget.static === true) {
|
|
18418
|
-
// Static widgets shouldn't count as empty
|
|
18419
|
-
return false;
|
|
18420
|
-
}
|
|
18421
|
-
const validator = getWidgetValidator(widget.type);
|
|
18422
|
-
const userInput = userInputMap[id];
|
|
18423
|
-
const validationData = widget.options;
|
|
18424
|
-
const score = validator?.(userInput, validationData, strings, locale);
|
|
18425
|
-
if (score) {
|
|
18426
|
-
return scoreIsEmpty(score);
|
|
18427
|
-
}
|
|
18428
|
-
});
|
|
18429
|
-
}
|
|
18430
|
-
|
|
18431
|
-
// TODO: combine scorePerseusItem with scoreWidgetsFunctional
|
|
18432
|
-
// once scorePerseusItem is the only one calling scoreWidgetsFunctional
|
|
18433
|
-
function scorePerseusItem(perseusRenderData, userInputMap,
|
|
18434
|
-
// TODO(LEMS-2461,LEMS-2391): these probably
|
|
18435
|
-
// need to be removed before we move this to the server
|
|
18436
|
-
strings, locale) {
|
|
18437
|
-
// There seems to be a chance that PerseusRenderer.widgets might include
|
|
18438
|
-
// widget data for widgets that are not in PerseusRenderer.content,
|
|
18439
|
-
// so this checks that the widgets are being used before scoring them
|
|
18440
|
-
const usedWidgetIds = perseusCore.getWidgetIdsFromContent(perseusRenderData.content);
|
|
18441
|
-
const scores = scoreWidgetsFunctional(perseusRenderData.widgets, usedWidgetIds, userInputMap, strings, locale);
|
|
18442
|
-
return flattenScores(scores);
|
|
18443
|
-
}
|
|
18444
|
-
function scoreWidgetsFunctional(widgets,
|
|
18445
|
-
// This is a port of old code, I'm not sure why
|
|
18446
|
-
// we need widgetIds vs the keys of the widgets object
|
|
18447
|
-
widgetIds, userInputMap, strings, locale) {
|
|
18448
|
-
const upgradedWidgets = getUpgradedWidgetOptions(widgets);
|
|
18449
|
-
const gradedWidgetIds = widgetIds.filter(id => {
|
|
18450
|
-
const props = upgradedWidgets[id];
|
|
18451
|
-
const widgetIsGraded = props?.graded == null || props.graded;
|
|
18452
|
-
const widgetIsStatic = !!props?.static;
|
|
18453
|
-
// Ungraded widgets or widgets set to static shouldn't be graded.
|
|
18454
|
-
return widgetIsGraded && !widgetIsStatic;
|
|
18455
|
-
});
|
|
18456
|
-
const widgetScores = {};
|
|
18457
|
-
gradedWidgetIds.forEach(id => {
|
|
18458
|
-
const widget = upgradedWidgets[id];
|
|
18459
|
-
if (!widget) {
|
|
18460
|
-
return;
|
|
18461
|
-
}
|
|
18462
|
-
const userInput = userInputMap[id];
|
|
18463
|
-
const validator = getWidgetValidator(widget.type);
|
|
18464
|
-
const scorer = getWidgetScorer(widget.type);
|
|
18465
|
-
|
|
18466
|
-
// We do validation (empty checks) first and then scoring. If
|
|
18467
|
-
// validation fails, it's result is itself a PerseusScore.
|
|
18468
|
-
const score = validator?.(userInput, widget.options, strings, locale) ?? scorer?.(userInput, widget.options, strings, locale);
|
|
18469
|
-
if (score != null) {
|
|
18470
|
-
widgetScores[id] = score;
|
|
18471
|
-
}
|
|
18472
|
-
});
|
|
18473
|
-
return widgetScores;
|
|
18474
|
-
}
|
|
18475
|
-
|
|
18476
17611
|
/**
|
|
18477
17612
|
* TranslationLinter asynchronously calls Khan Academy's poentry linter.
|
|
18478
17613
|
*
|
|
@@ -18629,6 +17764,257 @@ const getInteractiveBoxFromSizeClass = sizeClass => {
|
|
|
18629
17764
|
return [interactiveSizes.defaultBoxSize, interactiveSizes.defaultBoxSize];
|
|
18630
17765
|
};
|
|
18631
17766
|
|
|
17767
|
+
const DEFAULT_TRACKING = "";
|
|
17768
|
+
const DEFAULT_LINTABLE = false;
|
|
17769
|
+
const widgets = {};
|
|
17770
|
+
const editors = {};
|
|
17771
|
+
|
|
17772
|
+
// Widgets must be registered to avoid circular dependencies with the
|
|
17773
|
+
// core Editor and Renderer components.
|
|
17774
|
+
// TODO(jeremy): The widget name is already embedded in the WidgetExports type
|
|
17775
|
+
// so could we drop the `name` parameter here?
|
|
17776
|
+
const registerWidget = (name, widget) => {
|
|
17777
|
+
widgets[name] = widget;
|
|
17778
|
+
};
|
|
17779
|
+
const registerWidgets = widgets => {
|
|
17780
|
+
widgets.forEach(widget => {
|
|
17781
|
+
registerWidget(widget.name, widget);
|
|
17782
|
+
});
|
|
17783
|
+
};
|
|
17784
|
+
|
|
17785
|
+
/**
|
|
17786
|
+
*
|
|
17787
|
+
* @param name - the widget that you are trying to replace
|
|
17788
|
+
* @param replacementName - the name of the widget that takes its place
|
|
17789
|
+
*
|
|
17790
|
+
* e.g. replaceWidget("transformer", "deprecated-standin") will make it so the
|
|
17791
|
+
* transformer widget is replaced by the always correct widget
|
|
17792
|
+
*/
|
|
17793
|
+
const replaceWidget = (name, replacementName) => {
|
|
17794
|
+
const substituteWidget = widgets[replacementName];
|
|
17795
|
+
|
|
17796
|
+
// If the replacement widget isn't found, we need to throw. Otherwise after
|
|
17797
|
+
// removing the deprecated widget, we'll have data asking for a widget type
|
|
17798
|
+
// that doesn't exist at all.
|
|
17799
|
+
if (!substituteWidget) {
|
|
17800
|
+
const errorMsg = `Failed to replace ${name} with ${replacementName}`;
|
|
17801
|
+
throw new perseusCore.PerseusError(errorMsg, perseusCore.Errors.Internal);
|
|
17802
|
+
}
|
|
17803
|
+
registerWidget(name, substituteWidget);
|
|
17804
|
+
};
|
|
17805
|
+
const replaceDeprecatedWidgets = () => {
|
|
17806
|
+
replaceWidget("transformer", "deprecated-standin");
|
|
17807
|
+
replaceWidget("lights-puzzle", "deprecated-standin");
|
|
17808
|
+
replaceWidget("reaction-diagram", "deprecated-standin");
|
|
17809
|
+
replaceWidget("sequence", "deprecated-standin");
|
|
17810
|
+
replaceWidget("simulator", "deprecated-standin");
|
|
17811
|
+
replaceWidget("unit-input", "deprecated-standin");
|
|
17812
|
+
};
|
|
17813
|
+
const registerEditors = editorsToRegister => {
|
|
17814
|
+
editorsToRegister.forEach(editor => {
|
|
17815
|
+
if (!editor.widgetName) {
|
|
17816
|
+
throw new perseusCore.PerseusError(`Editor ${editor.displayName} doesn't have a widgetName property`, perseusCore.Errors.Internal);
|
|
17817
|
+
}
|
|
17818
|
+
editors[editor.widgetName] = editor;
|
|
17819
|
+
});
|
|
17820
|
+
};
|
|
17821
|
+
|
|
17822
|
+
/**
|
|
17823
|
+
*
|
|
17824
|
+
* @param name - the widget that you are trying to replace
|
|
17825
|
+
* @param replacementName - the name of the widget that takes its place
|
|
17826
|
+
*
|
|
17827
|
+
* e.g. replaceEditor("transformer", "deprecated-standin") will make it so the
|
|
17828
|
+
* transformer widget is replaced by the deprecated stand-in widget
|
|
17829
|
+
*/
|
|
17830
|
+
const replaceEditor = (name, replacementName) => {
|
|
17831
|
+
const substituteEditor = editors[replacementName];
|
|
17832
|
+
if (!substituteEditor && Log) {
|
|
17833
|
+
const errorMsg = `Failed to replace editor ${name} with ${replacementName}`;
|
|
17834
|
+
Log.error(errorMsg, perseusCore.Errors.Internal);
|
|
17835
|
+
return;
|
|
17836
|
+
}
|
|
17837
|
+
editors[name] = substituteEditor;
|
|
17838
|
+
};
|
|
17839
|
+
const replaceDeprecatedEditors = () => {
|
|
17840
|
+
replaceEditor("transformer", "deprecated-standin");
|
|
17841
|
+
replaceEditor("lights-puzzle", "deprecated-standin");
|
|
17842
|
+
replaceEditor("reaction-diagram", "deprecated-standin");
|
|
17843
|
+
replaceEditor("sequence", "deprecated-standin");
|
|
17844
|
+
replaceEditor("simulator", "deprecated-standin");
|
|
17845
|
+
replaceEditor("unit-input", "deprecated-standin");
|
|
17846
|
+
};
|
|
17847
|
+
const getWidget = name => {
|
|
17848
|
+
// TODO(alex): Consider referring to these as renderers to avoid
|
|
17849
|
+
// overloading "widget"
|
|
17850
|
+
if (!___default["default"].has(widgets, name)) {
|
|
17851
|
+
return null;
|
|
17852
|
+
}
|
|
17853
|
+
|
|
17854
|
+
// Allow widgets to specify a widget directly or via a function
|
|
17855
|
+
if (widgets[name]?.getWidget) {
|
|
17856
|
+
return widgets[name].getWidget?.();
|
|
17857
|
+
}
|
|
17858
|
+
return widgets[name].widget;
|
|
17859
|
+
};
|
|
17860
|
+
const getWidgetExport = name => {
|
|
17861
|
+
return widgets[name] ?? null;
|
|
17862
|
+
};
|
|
17863
|
+
const getPublicWidgetOptionsFunction = name => {
|
|
17864
|
+
return widgets[name]?.getPublicWidgetOptions ?? (i => i);
|
|
17865
|
+
};
|
|
17866
|
+
const getEditor = name => {
|
|
17867
|
+
return ___default["default"].has(editors, name) ? editors[name] : null;
|
|
17868
|
+
};
|
|
17869
|
+
const getTransform = name => {
|
|
17870
|
+
return ___default["default"].has(widgets, name) ? widgets[name].transform || ___default["default"].identity : null;
|
|
17871
|
+
};
|
|
17872
|
+
const getVersion = name => {
|
|
17873
|
+
const widgetInfo = widgets[name];
|
|
17874
|
+
if (widgetInfo) {
|
|
17875
|
+
return widgets[name].version || {
|
|
17876
|
+
major: 0,
|
|
17877
|
+
minor: 0
|
|
17878
|
+
};
|
|
17879
|
+
}
|
|
17880
|
+
return;
|
|
17881
|
+
};
|
|
17882
|
+
const getVersionVector = () => {
|
|
17883
|
+
const version = {};
|
|
17884
|
+
___default["default"].each(___default["default"].keys(widgets), function (name) {
|
|
17885
|
+
version[name] = getVersion(name);
|
|
17886
|
+
});
|
|
17887
|
+
return version;
|
|
17888
|
+
};
|
|
17889
|
+
const getPublicWidgets = () => {
|
|
17890
|
+
// TODO(alex): Update underscore.js so that _.pick can take a function.
|
|
17891
|
+
// @ts-expect-error - TS2740 - Type 'Pick<{ [key: string]: Readonly<{ name: string; displayName: string; getWidget?: (() => ComponentType<any>) | undefined; accessible?: boolean | ((props: any) => boolean) | undefined; hidden?: boolean | undefined; ... 10 more ...; widget: ComponentType<...>; }>; }, string>' is missing the following properties from type 'readonly Readonly<{ name: string; displayName: string; getWidget?: (() => ComponentType<any>) | undefined; accessible?: boolean | ((props: any) => boolean) | undefined; hidden?: boolean | undefined; ... 10 more ...; widget: ComponentType<...>; }>[]': length, concat, join, slice, and 18 more.
|
|
17892
|
+
return ___default["default"].pick(widgets,
|
|
17893
|
+
// @ts-expect-error - TS2345 - Argument of type '(name: string) => boolean | undefined' is not assignable to parameter of type 'Iteratee<string[], boolean, string>'.
|
|
17894
|
+
___default["default"].reject(___default["default"].keys(widgets), function (name) {
|
|
17895
|
+
return widgets[name].hidden;
|
|
17896
|
+
}));
|
|
17897
|
+
};
|
|
17898
|
+
const isAccessible = widgetInfo => {
|
|
17899
|
+
const accessible = widgets[widgetInfo.type].accessible;
|
|
17900
|
+
if (typeof accessible === "function") {
|
|
17901
|
+
return accessible(widgetInfo.options);
|
|
17902
|
+
}
|
|
17903
|
+
return !!accessible;
|
|
17904
|
+
};
|
|
17905
|
+
const getAllWidgetTypes = () => {
|
|
17906
|
+
return ___default["default"].keys(widgets);
|
|
17907
|
+
};
|
|
17908
|
+
const getRendererPropsForWidgetInfo = (widgetInfo, strings, problemNum) => {
|
|
17909
|
+
const type = widgetInfo.type;
|
|
17910
|
+
const widgetExports = widgets[type];
|
|
17911
|
+
if (widgetExports == null) {
|
|
17912
|
+
// The widget is not a registered widget
|
|
17913
|
+
// It shouldn't matter what we return here, but for consistency
|
|
17914
|
+
// we return the untransformed options, as if the widget did
|
|
17915
|
+
// not have a transform defined.
|
|
17916
|
+
return widgetInfo;
|
|
17917
|
+
}
|
|
17918
|
+
let transform;
|
|
17919
|
+
if (widgetInfo.static) {
|
|
17920
|
+
// There aren't a lot of real places where we'll have to default to
|
|
17921
|
+
// _.identity, but it's theoretically possible if someone changes
|
|
17922
|
+
// the JSON manually / we have to back out static support for a
|
|
17923
|
+
// widget.
|
|
17924
|
+
transform = getStaticTransform(type) || ___default["default"].identity;
|
|
17925
|
+
} else {
|
|
17926
|
+
transform = widgetExports.transform || ___default["default"].identity;
|
|
17927
|
+
}
|
|
17928
|
+
// widgetInfo.options are the widgetEditor's props:
|
|
17929
|
+
return transform(widgetInfo.options, strings, problemNum);
|
|
17930
|
+
};
|
|
17931
|
+
const traverseChildWidgets$3 = (widgetInfo, traverseRenderer) => {
|
|
17932
|
+
if (!traverseRenderer) {
|
|
17933
|
+
throw new perseusCore.PerseusError("traverseRenderer must be provided, but was not", perseusCore.Errors.Internal);
|
|
17934
|
+
}
|
|
17935
|
+
if (!widgetInfo || !widgetInfo.type || !widgets[widgetInfo.type]) {
|
|
17936
|
+
return widgetInfo;
|
|
17937
|
+
}
|
|
17938
|
+
const widgetExports = widgets[widgetInfo.type];
|
|
17939
|
+
const props = widgetInfo.options;
|
|
17940
|
+
if (widgetExports.traverseChildWidgets && props) {
|
|
17941
|
+
const newProps = widgetExports.traverseChildWidgets(props, traverseRenderer);
|
|
17942
|
+
return ___default["default"].extend({}, widgetInfo, {
|
|
17943
|
+
options: newProps
|
|
17944
|
+
});
|
|
17945
|
+
}
|
|
17946
|
+
return widgetInfo;
|
|
17947
|
+
};
|
|
17948
|
+
|
|
17949
|
+
/**
|
|
17950
|
+
* Handling for static mode for widgets that support it.
|
|
17951
|
+
*/
|
|
17952
|
+
|
|
17953
|
+
/**
|
|
17954
|
+
* Returns true iff the widget supports static mode.
|
|
17955
|
+
* A widget implicitly supports static mode if it exports a
|
|
17956
|
+
* staticTransform function.
|
|
17957
|
+
*/
|
|
17958
|
+
const supportsStaticMode = type => {
|
|
17959
|
+
const widgetInfo = widgets[type];
|
|
17960
|
+
return widgetInfo && widgetInfo.staticTransform != null;
|
|
17961
|
+
};
|
|
17962
|
+
|
|
17963
|
+
/**
|
|
17964
|
+
* Return the staticTransform function used to convert the editorProps to
|
|
17965
|
+
* the rendered widget state.
|
|
17966
|
+
*/
|
|
17967
|
+
const getStaticTransform = type => {
|
|
17968
|
+
const widgetInfo = widgets[type];
|
|
17969
|
+
return widgetInfo && widgetInfo.staticTransform;
|
|
17970
|
+
};
|
|
17971
|
+
|
|
17972
|
+
/**
|
|
17973
|
+
* Returns the tracking option for the widget. The default is "",
|
|
17974
|
+
* which means simply to track interactions once. The other available
|
|
17975
|
+
* option is "all" which means to track all interactions.
|
|
17976
|
+
*/
|
|
17977
|
+
const getTracking = type => {
|
|
17978
|
+
const widgetExport = widgets[type];
|
|
17979
|
+
return widgetExport && widgetExport.tracking || DEFAULT_TRACKING;
|
|
17980
|
+
};
|
|
17981
|
+
|
|
17982
|
+
/**
|
|
17983
|
+
* Returns true if this widget can include lintable markdown text
|
|
17984
|
+
* and supports a highlightLint prop, or false otherwise.
|
|
17985
|
+
*/
|
|
17986
|
+
const isLintable = type => {
|
|
17987
|
+
const widgetExports = widgets[type];
|
|
17988
|
+
return widgetExports && widgetExports.isLintable || DEFAULT_LINTABLE;
|
|
17989
|
+
};
|
|
17990
|
+
|
|
17991
|
+
var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
17992
|
+
__proto__: null,
|
|
17993
|
+
registerWidget: registerWidget,
|
|
17994
|
+
registerWidgets: registerWidgets,
|
|
17995
|
+
replaceWidget: replaceWidget,
|
|
17996
|
+
replaceDeprecatedWidgets: replaceDeprecatedWidgets,
|
|
17997
|
+
registerEditors: registerEditors,
|
|
17998
|
+
replaceEditor: replaceEditor,
|
|
17999
|
+
replaceDeprecatedEditors: replaceDeprecatedEditors,
|
|
18000
|
+
getWidget: getWidget,
|
|
18001
|
+
getWidgetExport: getWidgetExport,
|
|
18002
|
+
getPublicWidgetOptionsFunction: getPublicWidgetOptionsFunction,
|
|
18003
|
+
getEditor: getEditor,
|
|
18004
|
+
getTransform: getTransform,
|
|
18005
|
+
getVersion: getVersion,
|
|
18006
|
+
getVersionVector: getVersionVector,
|
|
18007
|
+
getPublicWidgets: getPublicWidgets,
|
|
18008
|
+
isAccessible: isAccessible,
|
|
18009
|
+
getAllWidgetTypes: getAllWidgetTypes,
|
|
18010
|
+
getRendererPropsForWidgetInfo: getRendererPropsForWidgetInfo,
|
|
18011
|
+
traverseChildWidgets: traverseChildWidgets$3,
|
|
18012
|
+
supportsStaticMode: supportsStaticMode,
|
|
18013
|
+
getStaticTransform: getStaticTransform,
|
|
18014
|
+
getTracking: getTracking,
|
|
18015
|
+
isLintable: isLintable
|
|
18016
|
+
});
|
|
18017
|
+
|
|
18632
18018
|
class WidgetContainer extends React__namespace.Component {
|
|
18633
18019
|
widgetRef = /*#__PURE__*/React__namespace.createRef();
|
|
18634
18020
|
static defaultProps = {
|
|
@@ -18701,7 +18087,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18701
18087
|
}
|
|
18702
18088
|
let alignment = this.state.widgetProps.alignment;
|
|
18703
18089
|
if (alignment === "default") {
|
|
18704
|
-
alignment = getDefaultAlignment(type);
|
|
18090
|
+
alignment = perseusCore.CoreWidgetRegistry.getDefaultAlignment(type);
|
|
18705
18091
|
}
|
|
18706
18092
|
className += " widget-" + alignment;
|
|
18707
18093
|
const apiOptions = this.state.widgetProps.apiOptions;
|
|
@@ -18709,6 +18095,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18709
18095
|
// Hack to prevent interaction with static widgets: we overlay a big
|
|
18710
18096
|
// div on top of the widget and overflow: hidden the container.
|
|
18711
18097
|
// Ideally widgets themselves should know how to prevent interaction.
|
|
18098
|
+
// UPDATE HTML5: `inert` on the underlying div would be better
|
|
18712
18099
|
const isStatic = this.state.widgetProps.static || apiOptions.readOnly;
|
|
18713
18100
|
const staticContainerStyles = {
|
|
18714
18101
|
position: "relative",
|
|
@@ -18720,7 +18107,7 @@ class WidgetContainer extends React__namespace.Component {
|
|
|
18720
18107
|
position: "absolute",
|
|
18721
18108
|
top: 0,
|
|
18722
18109
|
left: 0,
|
|
18723
|
-
zIndex:
|
|
18110
|
+
zIndex: 3
|
|
18724
18111
|
};
|
|
18725
18112
|
|
|
18726
18113
|
// Some widgets may include strings of markdown that we may
|
|
@@ -18986,7 +18373,7 @@ class Renderer extends React__namespace.Component {
|
|
|
18986
18373
|
};
|
|
18987
18374
|
};
|
|
18988
18375
|
_getInitialWidgetState = props => {
|
|
18989
|
-
const allWidgetInfo = getUpgradedWidgetOptions(props.widgets);
|
|
18376
|
+
const allWidgetInfo = perseusCore.getUpgradedWidgetOptions(props.widgets);
|
|
18990
18377
|
return {
|
|
18991
18378
|
widgetInfo: allWidgetInfo,
|
|
18992
18379
|
widgetProps: this._getAllWidgetsStartProps(allWidgetInfo, props)
|
|
@@ -19898,7 +19285,7 @@ class Renderer extends React__namespace.Component {
|
|
|
19898
19285
|
* empty if the graph is in the starting state.
|
|
19899
19286
|
*/
|
|
19900
19287
|
emptyWidgets() {
|
|
19901
|
-
return emptyWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.
|
|
19288
|
+
return perseusScore.emptyWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.context.locale);
|
|
19902
19289
|
}
|
|
19903
19290
|
_setWidgetProps = (id, newProps, cb, silent) => {
|
|
19904
19291
|
this.setState(prevState => {
|
|
@@ -20028,8 +19415,8 @@ class Renderer extends React__namespace.Component {
|
|
|
20028
19415
|
* @deprecated use scorePerseusItem
|
|
20029
19416
|
*/
|
|
20030
19417
|
score() {
|
|
20031
|
-
const scores = scoreWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.
|
|
20032
|
-
const combinedScore = flattenScores(scores);
|
|
19418
|
+
const scores = perseusScore.scoreWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.context.locale);
|
|
19419
|
+
const combinedScore = perseusScore.flattenScores(scores);
|
|
20033
19420
|
return combinedScore;
|
|
20034
19421
|
}
|
|
20035
19422
|
|
|
@@ -20550,7 +19937,7 @@ class InputWithExamples extends React__namespace.Component {
|
|
|
20550
19937
|
};
|
|
20551
19938
|
_getInputClassName = () => {
|
|
20552
19939
|
// Otherwise, we need to add these INPUT and FOCUSED tags here.
|
|
20553
|
-
let className = ClassNames.INPUT
|
|
19940
|
+
let className = ClassNames.INPUT;
|
|
20554
19941
|
if (this.state.focused) {
|
|
20555
19942
|
className += " " + ClassNames.FOCUSED;
|
|
20556
19943
|
}
|
|
@@ -20943,14 +20330,10 @@ const propTransform$3 = widgetOptions => {
|
|
|
20943
20330
|
var InputNumber$1 = {
|
|
20944
20331
|
name: "input-number",
|
|
20945
20332
|
displayName: "Input number (deprecated - use numeric input instead)",
|
|
20946
|
-
defaultAlignment: "inline-block",
|
|
20947
20333
|
hidden: true,
|
|
20948
20334
|
widget: InputNumber,
|
|
20949
20335
|
transform: propTransform$3,
|
|
20950
20336
|
isLintable: true,
|
|
20951
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
20952
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusInputNumberUserInput'.
|
|
20953
|
-
scorer: perseusScore.scoreInputNumber,
|
|
20954
20337
|
getOneCorrectAnswerFromRubric(rubric) {
|
|
20955
20338
|
if (rubric.value == null) {
|
|
20956
20339
|
return;
|
|
@@ -21202,14 +20585,11 @@ const propsTransform = function (widgetOptions) {
|
|
|
21202
20585
|
var NumericInput$1 = {
|
|
21203
20586
|
name: "numeric-input",
|
|
21204
20587
|
displayName: "Numeric input",
|
|
21205
|
-
defaultAlignment: "inline-block",
|
|
21206
20588
|
accessible: true,
|
|
21207
20589
|
widget: NumericInput,
|
|
21208
20590
|
transform: propsTransform,
|
|
21209
20591
|
isLintable: true,
|
|
21210
|
-
|
|
21211
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusNumericInputUserInput'.
|
|
21212
|
-
scorer: perseusScore.scoreNumericInput,
|
|
20592
|
+
getPublicWidgetOptions: perseusCore.getNumericInputPublicWidgetOptions,
|
|
21213
20593
|
// TODO(LEMS-2656): remove TS suppression
|
|
21214
20594
|
// @ts-expect-error: Type 'Rubric' is not assignable to type 'PerseusNumericInputRubric'
|
|
21215
20595
|
getOneCorrectAnswerFromRubric(rubric) {
|
|
@@ -21270,24 +20650,6 @@ const getPromptJSON$p = renderProps => {
|
|
|
21270
20650
|
};
|
|
21271
20651
|
};
|
|
21272
20652
|
|
|
21273
|
-
/**
|
|
21274
|
-
* Several widgets don't have "right"/"wrong" scoring logic,
|
|
21275
|
-
* so this just says to move on past those widgets
|
|
21276
|
-
*
|
|
21277
|
-
* TODO(LEMS-2543) widgets that use this probably shouldn't have any
|
|
21278
|
-
* scoring logic and the thing scoring an exercise
|
|
21279
|
-
* should just know to skip these
|
|
21280
|
-
*/
|
|
21281
|
-
function scoreNoop() {
|
|
21282
|
-
let points = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
21283
|
-
return {
|
|
21284
|
-
type: "points",
|
|
21285
|
-
earned: points,
|
|
21286
|
-
total: points,
|
|
21287
|
-
message: null
|
|
21288
|
-
};
|
|
21289
|
-
}
|
|
21290
|
-
|
|
21291
20653
|
/**
|
|
21292
20654
|
* Utility functions for manipulating ranges of highlightable content.
|
|
21293
20655
|
*/
|
|
@@ -23465,8 +22827,7 @@ var Passage$1 = {
|
|
|
23465
22827
|
transform: editorProps => {
|
|
23466
22828
|
return ___default["default"].pick(editorProps, "passageTitle", "passageText", "footnotes", "showLineNumbers");
|
|
23467
22829
|
},
|
|
23468
|
-
isLintable: true
|
|
23469
|
-
scorer: () => scoreNoop()
|
|
22830
|
+
isLintable: true
|
|
23470
22831
|
};
|
|
23471
22832
|
|
|
23472
22833
|
/**
|
|
@@ -23592,16 +22953,13 @@ var PassageRef$1 = {
|
|
|
23592
22953
|
name: "passage-ref",
|
|
23593
22954
|
displayName: "PassageRef (SAT only)",
|
|
23594
22955
|
hidden: true,
|
|
23595
|
-
defaultAlignment: "inline",
|
|
23596
22956
|
widget: PassageRef,
|
|
23597
22957
|
transform: widgetOptions => ({
|
|
23598
22958
|
passageNumber: widgetOptions.passageNumber,
|
|
23599
22959
|
referenceNumber: widgetOptions.referenceNumber,
|
|
23600
22960
|
summaryText: widgetOptions.summaryText
|
|
23601
22961
|
}),
|
|
23602
|
-
version: perseusCore.passageRefLogic.version
|
|
23603
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
23604
|
-
scorer: () => scoreNoop()
|
|
22962
|
+
version: perseusCore.passageRefLogic.version
|
|
23605
22963
|
};
|
|
23606
22964
|
|
|
23607
22965
|
/**
|
|
@@ -23643,109 +23001,6 @@ var mediaQueries = {
|
|
|
23643
23001
|
xlOrLarger: `@media screen and (min-width: ${pureXlMin})`
|
|
23644
23002
|
};
|
|
23645
23003
|
|
|
23646
|
-
const {
|
|
23647
|
-
zIndexAboveScratchpad,
|
|
23648
|
-
zIndexInteractiveComponent,
|
|
23649
|
-
radioBorderColor,
|
|
23650
|
-
checkedColor,
|
|
23651
|
-
circleSize,
|
|
23652
|
-
radioMarginWidth
|
|
23653
|
-
} = constants;
|
|
23654
|
-
var sharedStyles = aphrodite.StyleSheet.create({
|
|
23655
|
-
perseusInteractive: {
|
|
23656
|
-
zIndex: zIndexInteractiveComponent,
|
|
23657
|
-
position: "relative"
|
|
23658
|
-
},
|
|
23659
|
-
aboveScratchpad: {
|
|
23660
|
-
position: "relative",
|
|
23661
|
-
zIndex: zIndexAboveScratchpad
|
|
23662
|
-
},
|
|
23663
|
-
blankBackground: {
|
|
23664
|
-
// TODO(emily): Use WB colors?
|
|
23665
|
-
backgroundColor: "#FDFDFD"
|
|
23666
|
-
},
|
|
23667
|
-
perseusSrOnly: {
|
|
23668
|
-
border: 0,
|
|
23669
|
-
clip: "rect(0,0,0,0)",
|
|
23670
|
-
height: 1,
|
|
23671
|
-
margin: -1,
|
|
23672
|
-
overflow: "hidden",
|
|
23673
|
-
padding: 0,
|
|
23674
|
-
position: "absolute",
|
|
23675
|
-
width: 1
|
|
23676
|
-
},
|
|
23677
|
-
responsiveLabel: {
|
|
23678
|
-
// NOTE(charlie): The values used here should be kept in sync with the
|
|
23679
|
-
// caption text sizing in Perseus' styles.less.
|
|
23680
|
-
// TODO(charlie): Migrate the captions over to using this style.
|
|
23681
|
-
[mediaQueries.smOrSmaller]: {
|
|
23682
|
-
fontSize: 14,
|
|
23683
|
-
lineHeight: 1.3
|
|
23684
|
-
},
|
|
23685
|
-
[mediaQueries.md]: {
|
|
23686
|
-
fontSize: 17,
|
|
23687
|
-
lineHeight: 1.4
|
|
23688
|
-
},
|
|
23689
|
-
[mediaQueries.lgOrLarger]: {
|
|
23690
|
-
fontSize: 20,
|
|
23691
|
-
lineHeight: 1.4
|
|
23692
|
-
}
|
|
23693
|
-
},
|
|
23694
|
-
responsiveInput: {
|
|
23695
|
-
display: "inline-block",
|
|
23696
|
-
WebkitAppearance: "none",
|
|
23697
|
-
appearance: "none",
|
|
23698
|
-
"::-ms-check": {
|
|
23699
|
-
display: "none"
|
|
23700
|
-
},
|
|
23701
|
-
backgroundColor: "#fff",
|
|
23702
|
-
border: "2px solid #fff",
|
|
23703
|
-
boxShadow: `0 0px 0px 1px ${radioBorderColor}`,
|
|
23704
|
-
outline: "none",
|
|
23705
|
-
boxSizing: "border-box",
|
|
23706
|
-
flexShrink: 0,
|
|
23707
|
-
marginBottom: 1,
|
|
23708
|
-
marginLeft: 1,
|
|
23709
|
-
marginRight: 1,
|
|
23710
|
-
marginTop: 1,
|
|
23711
|
-
height: circleSize - 2,
|
|
23712
|
-
width: circleSize - 2
|
|
23713
|
-
},
|
|
23714
|
-
responsiveRadioInput: {
|
|
23715
|
-
borderRadius: "50%",
|
|
23716
|
-
":checked": {
|
|
23717
|
-
backgroundColor: checkedColor,
|
|
23718
|
-
border: "none",
|
|
23719
|
-
borderRadius: "50%",
|
|
23720
|
-
boxShadow: `inset 0px 0px 0px 2px white, ` + `0 0px 0px 2px ${checkedColor}`,
|
|
23721
|
-
marginTop: radioMarginWidth,
|
|
23722
|
-
marginBottom: radioMarginWidth,
|
|
23723
|
-
marginLeft: radioMarginWidth,
|
|
23724
|
-
marginRight: radioMarginWidth,
|
|
23725
|
-
height: circleSize - 2 * radioMarginWidth,
|
|
23726
|
-
width: circleSize - 2 * radioMarginWidth
|
|
23727
|
-
}
|
|
23728
|
-
},
|
|
23729
|
-
responsiveRadioInputActive: {
|
|
23730
|
-
backgroundColor: "#fff",
|
|
23731
|
-
border: "2px solid #fff",
|
|
23732
|
-
borderRadius: "50%",
|
|
23733
|
-
boxShadow: `0 0px 0px 2px ${checkedColor}`,
|
|
23734
|
-
marginTop: radioMarginWidth,
|
|
23735
|
-
marginBottom: radioMarginWidth,
|
|
23736
|
-
marginLeft: radioMarginWidth,
|
|
23737
|
-
marginRight: radioMarginWidth,
|
|
23738
|
-
height: circleSize - 2 * radioMarginWidth,
|
|
23739
|
-
width: circleSize - 2 * radioMarginWidth,
|
|
23740
|
-
":checked": {
|
|
23741
|
-
backgroundColor: "#fff"
|
|
23742
|
-
}
|
|
23743
|
-
},
|
|
23744
|
-
disableTextSelection: {
|
|
23745
|
-
userSelect: "none"
|
|
23746
|
-
}
|
|
23747
|
-
});
|
|
23748
|
-
|
|
23749
23004
|
/**
|
|
23750
23005
|
* A small collection of useful scrolling utility functions.
|
|
23751
23006
|
*/
|
|
@@ -24814,7 +24069,7 @@ const BaseRadio = function (_ref) {
|
|
|
24814
24069
|
const aphroditeClassName = checked => {
|
|
24815
24070
|
// Whether or not to show correctness borders
|
|
24816
24071
|
// for this choice and the next choice.
|
|
24817
|
-
return aphrodite.css(
|
|
24072
|
+
return aphrodite.css(styles$o.item, styles$o.responsiveItem, checked && styles$o.selectedItem, checked && choice.highlighted && styles$o.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$o.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$o.nextHighlighted);
|
|
24818
24073
|
};
|
|
24819
24074
|
|
|
24820
24075
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -25418,18 +24673,105 @@ var Radio = {
|
|
|
25418
24673
|
staticTransform: transform,
|
|
25419
24674
|
version: perseusCore.radioLogic.version,
|
|
25420
24675
|
propUpgrades: perseusCore.radioLogic.widgetOptionsUpgrades,
|
|
25421
|
-
isLintable: true
|
|
25422
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
25423
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusRadioUserInput
|
|
25424
|
-
scorer: perseusScore.scoreRadio,
|
|
25425
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
25426
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusRadioUserInput
|
|
25427
|
-
validator: perseusScore.validateRadio
|
|
24676
|
+
isLintable: true
|
|
25428
24677
|
};
|
|
25429
24678
|
|
|
25430
24679
|
/* eslint-disable import/no-named-as-default */
|
|
25431
24680
|
var basicWidgets = [Radio, InputNumber$1, NumericInput$1, Expression$1];
|
|
25432
24681
|
|
|
24682
|
+
const {
|
|
24683
|
+
radioBorderColor,
|
|
24684
|
+
checkedColor,
|
|
24685
|
+
circleSize,
|
|
24686
|
+
radioMarginWidth
|
|
24687
|
+
} = constants;
|
|
24688
|
+
var sharedStyles = aphrodite.StyleSheet.create({
|
|
24689
|
+
blankBackground: {
|
|
24690
|
+
// TODO(emily): Use WB colors?
|
|
24691
|
+
backgroundColor: "#FDFDFD"
|
|
24692
|
+
},
|
|
24693
|
+
perseusSrOnly: {
|
|
24694
|
+
border: 0,
|
|
24695
|
+
clip: "rect(0,0,0,0)",
|
|
24696
|
+
height: 1,
|
|
24697
|
+
margin: -1,
|
|
24698
|
+
overflow: "hidden",
|
|
24699
|
+
padding: 0,
|
|
24700
|
+
position: "absolute",
|
|
24701
|
+
width: 1
|
|
24702
|
+
},
|
|
24703
|
+
responsiveLabel: {
|
|
24704
|
+
// NOTE(charlie): The values used here should be kept in sync with the
|
|
24705
|
+
// caption text sizing in Perseus' styles.less.
|
|
24706
|
+
// TODO(charlie): Migrate the captions over to using this style.
|
|
24707
|
+
[mediaQueries.smOrSmaller]: {
|
|
24708
|
+
fontSize: 14,
|
|
24709
|
+
lineHeight: 1.3
|
|
24710
|
+
},
|
|
24711
|
+
[mediaQueries.md]: {
|
|
24712
|
+
fontSize: 17,
|
|
24713
|
+
lineHeight: 1.4
|
|
24714
|
+
},
|
|
24715
|
+
[mediaQueries.lgOrLarger]: {
|
|
24716
|
+
fontSize: 20,
|
|
24717
|
+
lineHeight: 1.4
|
|
24718
|
+
}
|
|
24719
|
+
},
|
|
24720
|
+
responsiveInput: {
|
|
24721
|
+
display: "inline-block",
|
|
24722
|
+
WebkitAppearance: "none",
|
|
24723
|
+
appearance: "none",
|
|
24724
|
+
"::-ms-check": {
|
|
24725
|
+
display: "none"
|
|
24726
|
+
},
|
|
24727
|
+
backgroundColor: "#fff",
|
|
24728
|
+
border: "2px solid #fff",
|
|
24729
|
+
boxShadow: `0 0px 0px 1px ${radioBorderColor}`,
|
|
24730
|
+
outline: "none",
|
|
24731
|
+
boxSizing: "border-box",
|
|
24732
|
+
flexShrink: 0,
|
|
24733
|
+
marginBottom: 1,
|
|
24734
|
+
marginLeft: 1,
|
|
24735
|
+
marginRight: 1,
|
|
24736
|
+
marginTop: 1,
|
|
24737
|
+
height: circleSize - 2,
|
|
24738
|
+
width: circleSize - 2
|
|
24739
|
+
},
|
|
24740
|
+
responsiveRadioInput: {
|
|
24741
|
+
borderRadius: "50%",
|
|
24742
|
+
":checked": {
|
|
24743
|
+
backgroundColor: checkedColor,
|
|
24744
|
+
border: "none",
|
|
24745
|
+
borderRadius: "50%",
|
|
24746
|
+
boxShadow: `inset 0px 0px 0px 2px white, ` + `0 0px 0px 2px ${checkedColor}`,
|
|
24747
|
+
marginTop: radioMarginWidth,
|
|
24748
|
+
marginBottom: radioMarginWidth,
|
|
24749
|
+
marginLeft: radioMarginWidth,
|
|
24750
|
+
marginRight: radioMarginWidth,
|
|
24751
|
+
height: circleSize - 2 * radioMarginWidth,
|
|
24752
|
+
width: circleSize - 2 * radioMarginWidth
|
|
24753
|
+
}
|
|
24754
|
+
},
|
|
24755
|
+
responsiveRadioInputActive: {
|
|
24756
|
+
backgroundColor: "#fff",
|
|
24757
|
+
border: "2px solid #fff",
|
|
24758
|
+
borderRadius: "50%",
|
|
24759
|
+
boxShadow: `0 0px 0px 2px ${checkedColor}`,
|
|
24760
|
+
marginTop: radioMarginWidth,
|
|
24761
|
+
marginBottom: radioMarginWidth,
|
|
24762
|
+
marginLeft: radioMarginWidth,
|
|
24763
|
+
marginRight: radioMarginWidth,
|
|
24764
|
+
height: circleSize - 2 * radioMarginWidth,
|
|
24765
|
+
width: circleSize - 2 * radioMarginWidth,
|
|
24766
|
+
":checked": {
|
|
24767
|
+
backgroundColor: "#fff"
|
|
24768
|
+
}
|
|
24769
|
+
},
|
|
24770
|
+
disableTextSelection: {
|
|
24771
|
+
userSelect: "none"
|
|
24772
|
+
}
|
|
24773
|
+
});
|
|
24774
|
+
|
|
25433
24775
|
const getPromptJSON$n = (renderProps, userInput) => {
|
|
25434
24776
|
return {
|
|
25435
24777
|
type: "categorizer",
|
|
@@ -25530,7 +24872,6 @@ class Categorizer extends React__namespace.Component {
|
|
|
25530
24872
|
className: "category " + aphrodite.css(styles$n.cell),
|
|
25531
24873
|
key: catNum
|
|
25532
24874
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
25533
|
-
className: ClassNames.INTERACTIVE,
|
|
25534
24875
|
role: "button",
|
|
25535
24876
|
"aria-label": catName,
|
|
25536
24877
|
onClick: () => this.onChange(itemNum, catNum)
|
|
@@ -25622,12 +24963,6 @@ var Categorizer$1 = {
|
|
|
25622
24963
|
return ___default["default"].pick(editorProps, "items", "categories", "values", "randomizeItems");
|
|
25623
24964
|
},
|
|
25624
24965
|
isLintable: true,
|
|
25625
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
25626
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusCSProgramUserInput'.
|
|
25627
|
-
scorer: perseusScore.scoreCategorizer,
|
|
25628
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
25629
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusCSProgramUserInput'.
|
|
25630
|
-
validator: perseusScore.validateCategorizer,
|
|
25631
24966
|
getPublicWidgetOptions: perseusCore.getCategorizerPublicWidgetOptions
|
|
25632
24967
|
};
|
|
25633
24968
|
|
|
@@ -25837,12 +25172,9 @@ const styles$m = aphrodite.StyleSheet.create({
|
|
|
25837
25172
|
var CSProgram$1 = {
|
|
25838
25173
|
name: "cs-program",
|
|
25839
25174
|
displayName: "CS Program",
|
|
25840
|
-
supportedAlignments: ["block", "full-width"],
|
|
25841
25175
|
widget: CSProgram,
|
|
25842
25176
|
hidden: true,
|
|
25843
|
-
|
|
25844
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusCSProgramUserInput'.
|
|
25845
|
-
scorer: perseusScore.scoreCSProgram
|
|
25177
|
+
getPublicWidgetOptions: perseusCore.getCSProgramPublicWidgetOptions
|
|
25846
25178
|
};
|
|
25847
25179
|
|
|
25848
25180
|
const getPromptJSON$l = renderProps => {
|
|
@@ -25919,11 +25251,8 @@ var Definition$1 = {
|
|
|
25919
25251
|
name: "definition",
|
|
25920
25252
|
displayName: "Definition",
|
|
25921
25253
|
accessible: true,
|
|
25922
|
-
defaultAlignment: "inline",
|
|
25923
25254
|
widget: Definition,
|
|
25924
|
-
transform: x => x
|
|
25925
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
25926
|
-
scorer: () => scoreNoop()
|
|
25255
|
+
transform: x => x
|
|
25927
25256
|
};
|
|
25928
25257
|
|
|
25929
25258
|
// There are no required props, but this component can receive props from any
|
|
@@ -25950,9 +25279,7 @@ var DeprecatedStandin$1 = {
|
|
|
25950
25279
|
name: "deprecated-standin",
|
|
25951
25280
|
displayName: "Deprecated Standin",
|
|
25952
25281
|
widget: DeprecatedStandin,
|
|
25953
|
-
hidden: true
|
|
25954
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
25955
|
-
scorer: () => scoreNoop(1)
|
|
25282
|
+
hidden: true
|
|
25956
25283
|
};
|
|
25957
25284
|
|
|
25958
25285
|
const getPromptJSON$k = (renderProps, userInput) => {
|
|
@@ -26061,16 +25388,10 @@ const optionsTransform = widgetOptions => {
|
|
|
26061
25388
|
var Dropdown$1 = {
|
|
26062
25389
|
name: "dropdown",
|
|
26063
25390
|
displayName: "Drop down",
|
|
26064
|
-
defaultAlignment: "inline-block",
|
|
26065
25391
|
accessible: true,
|
|
26066
25392
|
widget: Dropdown,
|
|
26067
25393
|
transform: optionsTransform,
|
|
26068
|
-
|
|
26069
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusDropdownUserInput'.
|
|
26070
|
-
scorer: perseusScore.scoreDropdown,
|
|
26071
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
26072
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusDropdownUserInput'.
|
|
26073
|
-
validator: perseusScore.validateDropdown
|
|
25394
|
+
getPublicWidgetOptions: perseusCore.getDropdownPublicWidgetOptions
|
|
26074
25395
|
};
|
|
26075
25396
|
|
|
26076
25397
|
const getPromptJSON$j = renderProps => {
|
|
@@ -26229,12 +25550,9 @@ var Explanation$1 = {
|
|
|
26229
25550
|
name: "explanation",
|
|
26230
25551
|
displayName: "Explanation",
|
|
26231
25552
|
accessible: true,
|
|
26232
|
-
defaultAlignment: "inline",
|
|
26233
25553
|
widget: Explanation,
|
|
26234
25554
|
transform: ___default["default"].identity,
|
|
26235
|
-
isLintable: true
|
|
26236
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
26237
|
-
scorer: () => scoreNoop()
|
|
25555
|
+
isLintable: true
|
|
26238
25556
|
};
|
|
26239
25557
|
|
|
26240
25558
|
const getPromptJSON$i = (title, rendererJSON, hintRendererJSON) => {
|
|
@@ -26442,7 +25760,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
26442
25760
|
DEFAULT_INVALID_MESSAGE_2
|
|
26443
25761
|
} = this.context.strings;
|
|
26444
25762
|
const status = score.type === "points" ? score.total === score.earned ? GRADING_STATUSES.correct : GRADING_STATUSES.incorrect : GRADING_STATUSES.invalid;
|
|
26445
|
-
const message = score.type === "points" ? score.message || "" : score.message ? `${INVALID_MESSAGE_PREFIX} ${mapErrorToString(score.message)}` : `${INVALID_MESSAGE_PREFIX} ${DEFAULT_INVALID_MESSAGE_1}${DEFAULT_INVALID_MESSAGE_2}`;
|
|
25763
|
+
const message = score.type === "points" ? score.message || "" : score.message ? `${INVALID_MESSAGE_PREFIX} ${mapErrorToString(score.message, this.context.strings)}` : `${INVALID_MESSAGE_PREFIX} ${DEFAULT_INVALID_MESSAGE_1}${DEFAULT_INVALID_MESSAGE_2}`;
|
|
26446
25764
|
this.setState({
|
|
26447
25765
|
status: status,
|
|
26448
25766
|
message: message,
|
|
@@ -27355,7 +26673,7 @@ class FunctionGrapher extends React__namespace.Component {
|
|
|
27355
26673
|
boxSizing: "initial"
|
|
27356
26674
|
}
|
|
27357
26675
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
27358
|
-
className: "graphie-container
|
|
26676
|
+
className: "graphie-container blank-background",
|
|
27359
26677
|
style: {
|
|
27360
26678
|
width: box[0],
|
|
27361
26679
|
height: box[1]
|
|
@@ -27483,8 +26801,7 @@ class Grapher extends React__namespace.Component {
|
|
|
27483
26801
|
const coords = this.props.plot.coords;
|
|
27484
26802
|
const asymptote = this.props.plot.asymptote;
|
|
27485
26803
|
const typeSelector = /*#__PURE__*/React__namespace.createElement("div", {
|
|
27486
|
-
style: typeSelectorStyle
|
|
27487
|
-
className: "above-scratchpad"
|
|
26804
|
+
style: typeSelectorStyle
|
|
27488
26805
|
}, /*#__PURE__*/React__namespace.createElement(ButtonGroup, {
|
|
27489
26806
|
value: type,
|
|
27490
26807
|
allowEmpty: true,
|
|
@@ -27566,10 +26883,7 @@ var Grapher$1 = {
|
|
|
27566
26883
|
hidden: true,
|
|
27567
26884
|
widget: Grapher,
|
|
27568
26885
|
transform: propTransform$2,
|
|
27569
|
-
staticTransform: staticTransform$4
|
|
27570
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
27571
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusGrapherUserInput'.
|
|
27572
|
-
scorer: perseusScore.scoreGrapher
|
|
26886
|
+
staticTransform: staticTransform$4
|
|
27573
26887
|
};
|
|
27574
26888
|
|
|
27575
26889
|
const getPromptJSON$f = rendererJSON => {
|
|
@@ -27586,24 +26900,6 @@ const getPromptJSON$f = rendererJSON => {
|
|
|
27586
26900
|
};
|
|
27587
26901
|
};
|
|
27588
26902
|
|
|
27589
|
-
// The `group` widget is basically a widget hosting a full Perseus system in
|
|
27590
|
-
// it. As such, scoring a group means scoring all widgets it contains.
|
|
27591
|
-
function scoreGroup(userInput, rubric, strings, locale) {
|
|
27592
|
-
const scores = scoreWidgetsFunctional(rubric.widgets, Object.keys(rubric.widgets), userInput, strings, locale);
|
|
27593
|
-
return flattenScores(scores);
|
|
27594
|
-
}
|
|
27595
|
-
|
|
27596
|
-
function validateGroup(userInput, validationData, strings, locale) {
|
|
27597
|
-
const emptyWidgets = emptyWidgetsFunctional(validationData.widgets, Object.keys(validationData.widgets), userInput, strings, locale);
|
|
27598
|
-
if (emptyWidgets.length === 0) {
|
|
27599
|
-
return null;
|
|
27600
|
-
}
|
|
27601
|
-
return {
|
|
27602
|
-
type: "invalid",
|
|
27603
|
-
message: null
|
|
27604
|
-
};
|
|
27605
|
-
}
|
|
27606
|
-
|
|
27607
26903
|
// exports has no 'transform'
|
|
27608
26904
|
|
|
27609
26905
|
class Group extends React__namespace.Component {
|
|
@@ -27755,12 +27051,6 @@ var Group$1 = {
|
|
|
27755
27051
|
displayName: "Group (SAT only)",
|
|
27756
27052
|
widget: Group,
|
|
27757
27053
|
traverseChildWidgets: traverseChildWidgets,
|
|
27758
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
27759
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusGroupUserInput'.
|
|
27760
|
-
scorer: scoreGroup,
|
|
27761
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
27762
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusGroupUserInput'.
|
|
27763
|
-
validator: validateGroup,
|
|
27764
27054
|
hidden: true,
|
|
27765
27055
|
isLintable: true
|
|
27766
27056
|
};
|
|
@@ -27900,10 +27190,7 @@ var Iframe$1 = {
|
|
|
27900
27190
|
displayName: "Iframe (deprecated)",
|
|
27901
27191
|
widget: Iframe,
|
|
27902
27192
|
// Let's not expose it to all content creators yet
|
|
27903
|
-
hidden: true
|
|
27904
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
27905
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusIframeUserInput'.
|
|
27906
|
-
scorer: perseusScore.scoreIframe
|
|
27193
|
+
hidden: true
|
|
27907
27194
|
};
|
|
27908
27195
|
|
|
27909
27196
|
const getPromptJSON$d = renderProps => {
|
|
@@ -27925,15 +27212,13 @@ const defaultBackgroundImage$2 = {
|
|
|
27925
27212
|
width: 0,
|
|
27926
27213
|
height: 0
|
|
27927
27214
|
};
|
|
27928
|
-
const editorAlignments = ["block", "full-width"];
|
|
27929
|
-
const DEFAULT_ALIGNMENT = "block";
|
|
27930
27215
|
|
|
27931
27216
|
// there is no transform as part of exports
|
|
27932
27217
|
|
|
27933
27218
|
class ImageWidget extends React__namespace.Component {
|
|
27934
27219
|
static contextType = PerseusI18nContext;
|
|
27935
27220
|
static defaultProps = {
|
|
27936
|
-
alignment:
|
|
27221
|
+
alignment: "block",
|
|
27937
27222
|
title: "",
|
|
27938
27223
|
range: [defaultRange, defaultRange],
|
|
27939
27224
|
box: [defaultBoxSize, defaultBoxSize],
|
|
@@ -28100,13 +27385,9 @@ var Image$1 = {
|
|
|
28100
27385
|
const bgImage = widgetOptions.backgroundImage;
|
|
28101
27386
|
return !(bgImage && bgImage.url && !widgetOptions.alt);
|
|
28102
27387
|
},
|
|
28103
|
-
defaultAlignment: DEFAULT_ALIGNMENT,
|
|
28104
|
-
supportedAlignments: editorAlignments,
|
|
28105
27388
|
displayName: "Image",
|
|
28106
27389
|
widget: ImageWidget,
|
|
28107
|
-
isLintable: true
|
|
28108
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
28109
|
-
scorer: () => scoreNoop()
|
|
27390
|
+
isLintable: true
|
|
28110
27391
|
};
|
|
28111
27392
|
|
|
28112
27393
|
const getPromptJSON$c = () => {
|
|
@@ -28709,9 +27990,7 @@ var Interactive = {
|
|
|
28709
27990
|
displayName: "Interaction",
|
|
28710
27991
|
widget: Interaction,
|
|
28711
27992
|
transform: ___default["default"].identity,
|
|
28712
|
-
hidden: true
|
|
28713
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
28714
|
-
scorer: () => scoreNoop()
|
|
27993
|
+
hidden: true
|
|
28715
27994
|
};
|
|
28716
27995
|
|
|
28717
27996
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -28993,7 +28272,7 @@ class Graph extends React__namespace.Component {
|
|
|
28993
28272
|
image = null;
|
|
28994
28273
|
}
|
|
28995
28274
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28996
|
-
className: "graphie-container
|
|
28275
|
+
className: "graphie-container blank-background",
|
|
28997
28276
|
style: {
|
|
28998
28277
|
width: this.props.box[0],
|
|
28999
28278
|
height: this.props.box[1]
|
|
@@ -29627,7 +28906,8 @@ const YGridTick = _ref => {
|
|
|
29627
28906
|
let {
|
|
29628
28907
|
y,
|
|
29629
28908
|
range,
|
|
29630
|
-
tickStep
|
|
28909
|
+
tickStep,
|
|
28910
|
+
showPi
|
|
29631
28911
|
} = _ref;
|
|
29632
28912
|
// If the graph requires out-of-bounds labels, we want to make sure to set the
|
|
29633
28913
|
// coordinates to the edge of the visible range of the graph. Otherwise,
|
|
@@ -29663,6 +28943,7 @@ const YGridTick = _ref => {
|
|
|
29663
28943
|
// If the graph displays both the y and x axis lines within the graph, we want
|
|
29664
28944
|
// to hide the label at -1 on the y-axis to prevent overlap with the x-axis label
|
|
29665
28945
|
const showLabel = shouldShowLabel(y, range, tickStep);
|
|
28946
|
+
const yLabel = showPi ? divideByAndShowPi(y) : y.toString();
|
|
29666
28947
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29667
28948
|
className: "tick",
|
|
29668
28949
|
"aria-hidden": true
|
|
@@ -29680,12 +28961,13 @@ const YGridTick = _ref => {
|
|
|
29680
28961
|
textAnchor: "end",
|
|
29681
28962
|
x: xPositionText,
|
|
29682
28963
|
y: yPositionText
|
|
29683
|
-
},
|
|
28964
|
+
}, yLabel));
|
|
29684
28965
|
};
|
|
29685
28966
|
const XGridTick = _ref2 => {
|
|
29686
28967
|
let {
|
|
29687
28968
|
x,
|
|
29688
|
-
range
|
|
28969
|
+
range,
|
|
28970
|
+
showPi
|
|
29689
28971
|
} = _ref2;
|
|
29690
28972
|
// If the graph requires out-of-bounds labels, we want to make sure to set the
|
|
29691
28973
|
// coordinates to the edge of the visible range of the graph. Otherwise,
|
|
@@ -29724,6 +29006,7 @@ const XGridTick = _ref2 => {
|
|
|
29724
29006
|
// Apply the adjustments to the x and y positions for the text
|
|
29725
29007
|
const xPositionText = xPosition + xAdjustment;
|
|
29726
29008
|
const yPositionText = yPosition + yAdjustment;
|
|
29009
|
+
const xLabel = showPi ? divideByAndShowPi(x) : x.toString();
|
|
29727
29010
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29728
29011
|
className: "tick",
|
|
29729
29012
|
"aria-hidden": true
|
|
@@ -29741,7 +29024,7 @@ const XGridTick = _ref2 => {
|
|
|
29741
29024
|
textAnchor: "middle",
|
|
29742
29025
|
x: xPositionText,
|
|
29743
29026
|
y: yPositionText
|
|
29744
|
-
},
|
|
29027
|
+
}, xLabel));
|
|
29745
29028
|
};
|
|
29746
29029
|
|
|
29747
29030
|
// Determines whether to show the label for the given tick
|
|
@@ -29788,6 +29071,22 @@ const countSignificantDecimals = number => {
|
|
|
29788
29071
|
}
|
|
29789
29072
|
return numStr.split(".")[1].length;
|
|
29790
29073
|
};
|
|
29074
|
+
|
|
29075
|
+
// Show the given value as a multiple of pi (already assumed to be
|
|
29076
|
+
// a multiple of pi). Exported for testing
|
|
29077
|
+
function divideByAndShowPi(value) {
|
|
29078
|
+
const dividedValue = value / Math.PI;
|
|
29079
|
+
switch (dividedValue) {
|
|
29080
|
+
case 1:
|
|
29081
|
+
return "π";
|
|
29082
|
+
case -1:
|
|
29083
|
+
return "-π";
|
|
29084
|
+
case 0:
|
|
29085
|
+
return "0";
|
|
29086
|
+
default:
|
|
29087
|
+
return dividedValue + "π";
|
|
29088
|
+
}
|
|
29089
|
+
}
|
|
29791
29090
|
const AxisTicks = () => {
|
|
29792
29091
|
const {
|
|
29793
29092
|
tickStep,
|
|
@@ -29810,6 +29109,10 @@ const AxisTicks = () => {
|
|
|
29810
29109
|
key: `y-grid-tick-${y}`,
|
|
29811
29110
|
range: range,
|
|
29812
29111
|
tickStep: tickStep[Y]
|
|
29112
|
+
// Show the tick labels as multiples of pi
|
|
29113
|
+
// if the tick step is a multiple of pi.
|
|
29114
|
+
,
|
|
29115
|
+
showPi: tickStep[Y] % Math.PI === 0
|
|
29813
29116
|
});
|
|
29814
29117
|
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
29815
29118
|
className: "x-axis-ticks"
|
|
@@ -29818,6 +29121,10 @@ const AxisTicks = () => {
|
|
|
29818
29121
|
x: x,
|
|
29819
29122
|
key: `x-grid-tick-${x}`,
|
|
29820
29123
|
range: range
|
|
29124
|
+
// Show the tick labels as multiples of pi
|
|
29125
|
+
// if the tick step is a multiple of pi.
|
|
29126
|
+
,
|
|
29127
|
+
showPi: tickStep[X] % Math.PI === 0
|
|
29821
29128
|
});
|
|
29822
29129
|
})));
|
|
29823
29130
|
};
|
|
@@ -30119,6 +29426,15 @@ const styles$d = aphrodite.StyleSheet.create({
|
|
|
30119
29426
|
}
|
|
30120
29427
|
});
|
|
30121
29428
|
|
|
29429
|
+
function isPiMultiple(value) {
|
|
29430
|
+
// Early return for integers that clearly aren't multiples
|
|
29431
|
+
// of pi to save some computation.
|
|
29432
|
+
if (Number.isInteger(value)) {
|
|
29433
|
+
return false;
|
|
29434
|
+
}
|
|
29435
|
+
return value % Math.PI === 0 || value % (Math.PI / 2) === 0 || value % (Math.PI / 3) === 0 || value % (Math.PI / 4) === 0 || value % (Math.PI / 6) === 0;
|
|
29436
|
+
}
|
|
29437
|
+
|
|
30122
29438
|
const {
|
|
30123
29439
|
firstNumericalParse,
|
|
30124
29440
|
captureScratchpadTouchStart
|
|
@@ -30156,7 +29472,8 @@ class NumberInput extends React__namespace.Component {
|
|
|
30156
29472
|
onFormatChange: PropTypes__default["default"].func,
|
|
30157
29473
|
checkValidity: PropTypes__default["default"].func,
|
|
30158
29474
|
size: PropTypes__default["default"].oneOf(["mini", "small", "normal"]),
|
|
30159
|
-
label: PropTypes__default["default"].oneOf(["put your labels outside your inputs!"])
|
|
29475
|
+
label: PropTypes__default["default"].oneOf(["put your labels outside your inputs!"]),
|
|
29476
|
+
allowPiTruncation: PropTypes__default["default"].bool
|
|
30160
29477
|
};
|
|
30161
29478
|
static defaultProps = {
|
|
30162
29479
|
value: null,
|
|
@@ -30169,6 +29486,19 @@ class NumberInput extends React__namespace.Component {
|
|
|
30169
29486
|
state = {
|
|
30170
29487
|
format: this.props.format
|
|
30171
29488
|
};
|
|
29489
|
+
componentDidMount() {
|
|
29490
|
+
// If the value is a multiple of pi, but it is not in the pi format,
|
|
29491
|
+
// then convert it to the pi format and show it as a multiple of pi.
|
|
29492
|
+
const value = this.getValue();
|
|
29493
|
+
if (this.props.allowPiTruncation && value !== null && value !== 0) {
|
|
29494
|
+
if (this.state.format !== "pi" && isPiMultiple(value)) {
|
|
29495
|
+
this._setValue(value / Math.PI, "pi");
|
|
29496
|
+
this.setState({
|
|
29497
|
+
format: "pi"
|
|
29498
|
+
});
|
|
29499
|
+
}
|
|
29500
|
+
}
|
|
29501
|
+
}
|
|
30172
29502
|
componentDidUpdate(prevProps) {
|
|
30173
29503
|
if (!kmath.number.equal(this.getValue(), this.props.value)) {
|
|
30174
29504
|
this._setValue(this.props.value, this.state.format);
|
|
@@ -30325,7 +29655,8 @@ class RangeInput extends React__namespace.Component {
|
|
|
30325
29655
|
value: PropTypes__default["default"].array.isRequired,
|
|
30326
29656
|
onChange: PropTypes__default["default"].func.isRequired,
|
|
30327
29657
|
placeholder: PropTypes__default["default"].array,
|
|
30328
|
-
checkValidity: PropTypes__default["default"].func
|
|
29658
|
+
checkValidity: PropTypes__default["default"].func,
|
|
29659
|
+
allowPiTruncation: PropTypes__default["default"].bool
|
|
30329
29660
|
};
|
|
30330
29661
|
static defaultProps = {
|
|
30331
29662
|
placeholder: [null, null]
|
|
@@ -30349,14 +29680,16 @@ class RangeInput extends React__namespace.Component {
|
|
|
30349
29680
|
// eslint-disable-next-line react/jsx-no-bind
|
|
30350
29681
|
,
|
|
30351
29682
|
onChange: this.onChange.bind(this, 0),
|
|
30352
|
-
placeholder: this.props.placeholder[0]
|
|
29683
|
+
placeholder: this.props.placeholder[0],
|
|
29684
|
+
allowPiTruncation: this.props.allowPiTruncation
|
|
30353
29685
|
})), /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
30354
29686
|
value: value[1],
|
|
30355
29687
|
checkValidity: val => checkValidity([value[0], val])
|
|
30356
29688
|
// eslint-disable-next-line react/jsx-no-bind
|
|
30357
29689
|
,
|
|
30358
29690
|
onChange: this.onChange.bind(this, 1),
|
|
30359
|
-
placeholder: this.props.placeholder[1]
|
|
29691
|
+
placeholder: this.props.placeholder[1],
|
|
29692
|
+
allowPiTruncation: this.props.allowPiTruncation
|
|
30360
29693
|
})));
|
|
30361
29694
|
}
|
|
30362
29695
|
}
|
|
@@ -37425,10 +36758,7 @@ var InteractiveGraph$1 = {
|
|
|
37425
36758
|
name: "interactive-graph",
|
|
37426
36759
|
displayName: "Interactive graph (Assessments only)",
|
|
37427
36760
|
widget: InteractiveGraph,
|
|
37428
|
-
staticTransform: staticTransform$3
|
|
37429
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
37430
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusInteractiveGraphUserInput'.
|
|
37431
|
-
scorer: perseusScore.scoreInteractiveGraph
|
|
36761
|
+
staticTransform: staticTransform$3
|
|
37432
36762
|
};
|
|
37433
36763
|
|
|
37434
36764
|
// TODO: can we use WB typography?
|
|
@@ -38386,9 +37716,7 @@ var LabelImage$1 = {
|
|
|
38386
37716
|
widget: LabelImageWithDependencies,
|
|
38387
37717
|
accessible: true,
|
|
38388
37718
|
isLintable: true,
|
|
38389
|
-
|
|
38390
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusLabelImageUserInput'.
|
|
38391
|
-
scorer: perseusScore.scoreLabelImage
|
|
37719
|
+
getPublicWidgetOptions: perseusCore.getLabelImagePublicWidgetOptions
|
|
38392
37720
|
};
|
|
38393
37721
|
|
|
38394
37722
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -38625,7 +37953,7 @@ class Draggable extends React__namespace.Component {
|
|
|
38625
37953
|
// We need to keep backwards compatbility with rules specified directly
|
|
38626
37954
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
38627
37955
|
// See sortable.less for details.
|
|
38628
|
-
let className = aphrodite.css(styles$8.card, styles$8.draggable, layout === "horizontal" && styles$8.horizontalCard, layout === "vertical" && styles$8.verticalCard, type === ItemState.DRAGGING && styles$8.dragging, type === ItemState.DISABLED && styles$8.disabled, !includePadding && styles$8.unpaddedCard) + " " +
|
|
37956
|
+
let className = aphrodite.css(styles$8.card, styles$8.draggable, layout === "horizontal" && styles$8.horizontalCard, layout === "vertical" && styles$8.verticalCard, type === ItemState.DRAGGING && styles$8.dragging, type === ItemState.DISABLED && styles$8.disabled, !includePadding && styles$8.unpaddedCard) + " " + "perseus-sortable-draggable";
|
|
38629
37957
|
if (!includePadding) {
|
|
38630
37958
|
className += " perseus-sortable-draggable-unpadded";
|
|
38631
37959
|
}
|
|
@@ -39316,10 +38644,7 @@ var Matcher$1 = {
|
|
|
39316
38644
|
name: "matcher",
|
|
39317
38645
|
displayName: "Matcher (two column)",
|
|
39318
38646
|
widget: Matcher,
|
|
39319
|
-
isLintable: true
|
|
39320
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
39321
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusMatcherUserInput'.
|
|
39322
|
-
scorer: perseusScore.scoreMatcher
|
|
38647
|
+
isLintable: true
|
|
39323
38648
|
};
|
|
39324
38649
|
|
|
39325
38650
|
const getPromptJSON$8 = (renderProps, userInput) => {
|
|
@@ -39722,13 +39047,7 @@ var Matrix$1 = {
|
|
|
39722
39047
|
widget: Matrix,
|
|
39723
39048
|
transform: propTransform$1,
|
|
39724
39049
|
staticTransform: staticTransform$2,
|
|
39725
|
-
isLintable: true
|
|
39726
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
39727
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusMatrixUserInput'.
|
|
39728
|
-
scorer: perseusScore.scoreMatrix,
|
|
39729
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
39730
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusMatrixUserInput'.
|
|
39731
|
-
validator: perseusScore.validateMatrix
|
|
39050
|
+
isLintable: true
|
|
39732
39051
|
};
|
|
39733
39052
|
|
|
39734
39053
|
const getPromptJSON$7 = () => {
|
|
@@ -39818,7 +39137,7 @@ class Measurer extends React__namespace.Component {
|
|
|
39818
39137
|
// TODO(scottgrant): This isn't a11y-friendly! We should insist on
|
|
39819
39138
|
// finding some valid alt text when this widget is used.
|
|
39820
39139
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
39821
|
-
className: "perseus-widget perseus-widget-measurer " + "graphie-container
|
|
39140
|
+
className: "perseus-widget perseus-widget-measurer " + "graphie-container blank-background",
|
|
39822
39141
|
style: {
|
|
39823
39142
|
width: this.props.box[0],
|
|
39824
39143
|
height: this.props.box[1]
|
|
@@ -39843,9 +39162,7 @@ var Measurer$1 = {
|
|
|
39843
39162
|
hidden: true,
|
|
39844
39163
|
widget: Measurer,
|
|
39845
39164
|
version: perseusCore.measurerLogic.version,
|
|
39846
|
-
propUpgrades: perseusCore.measurerLogic.widgetOptionsUpgrades
|
|
39847
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
39848
|
-
scorer: () => scoreNoop(1)
|
|
39165
|
+
propUpgrades: perseusCore.measurerLogic.widgetOptionsUpgrades
|
|
39849
39166
|
};
|
|
39850
39167
|
|
|
39851
39168
|
/**
|
|
@@ -40733,8 +40050,7 @@ var Molecule$1 = {
|
|
|
40733
40050
|
name: "molecule-renderer",
|
|
40734
40051
|
displayName: "Molecule renderer",
|
|
40735
40052
|
hidden: true,
|
|
40736
|
-
widget: MoleculeWidget
|
|
40737
|
-
scorer: () => scoreNoop()
|
|
40053
|
+
widget: MoleculeWidget
|
|
40738
40054
|
};
|
|
40739
40055
|
|
|
40740
40056
|
const getPromptJSON$6 = (renderProps, userInput) => {
|
|
@@ -41309,12 +40625,7 @@ var NumberLine$1 = {
|
|
|
41309
40625
|
widget: NumberLine,
|
|
41310
40626
|
transform: numberLineTransform,
|
|
41311
40627
|
staticTransform: staticTransform$1,
|
|
41312
|
-
|
|
41313
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusNumberLineUserInput'.
|
|
41314
|
-
scorer: perseusScore.scoreNumberLine,
|
|
41315
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
41316
|
-
// @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusNumberLineUserInput'.
|
|
41317
|
-
validator: perseusScore.validateNumberLine
|
|
40628
|
+
getPublicWidgetOptions: perseusCore.getNumberLinePublicWidgetOptions
|
|
41318
40629
|
};
|
|
41319
40630
|
|
|
41320
40631
|
const getPromptJSON$5 = (renderProps, userInput) => {
|
|
@@ -41332,7 +40643,7 @@ const getPromptJSON$5 = (renderProps, userInput) => {
|
|
|
41332
40643
|
class PlaceholderCard extends React__namespace.Component {
|
|
41333
40644
|
render() {
|
|
41334
40645
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41335
|
-
className: "card-wrap
|
|
40646
|
+
className: "card-wrap",
|
|
41336
40647
|
style: {
|
|
41337
40648
|
width: this.props.width
|
|
41338
40649
|
}
|
|
@@ -41347,7 +40658,7 @@ class PlaceholderCard extends React__namespace.Component {
|
|
|
41347
40658
|
class DragHintCard extends React__namespace.Component {
|
|
41348
40659
|
render() {
|
|
41349
40660
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41350
|
-
className: "card-wrap
|
|
40661
|
+
className: "card-wrap"
|
|
41351
40662
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
41352
40663
|
className: "card drag-hint"
|
|
41353
40664
|
}));
|
|
@@ -41482,7 +40793,7 @@ class Card extends React__namespace.Component {
|
|
|
41482
40793
|
const rendererProps = ___default["default"].pick(this.props, "content");
|
|
41483
40794
|
const onMouseDown = this.props.animating ? $__default["default"].noop : this.onMouseDown;
|
|
41484
40795
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41485
|
-
className: "card-wrap
|
|
40796
|
+
className: "card-wrap",
|
|
41486
40797
|
style: style,
|
|
41487
40798
|
onMouseDown: onMouseDown,
|
|
41488
40799
|
onTouchStart: onMouseDown,
|
|
@@ -41853,7 +41164,7 @@ class Orderer extends React__namespace.Component {
|
|
|
41853
41164
|
});
|
|
41854
41165
|
}, this));
|
|
41855
41166
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41856
|
-
className: "draggy-boxy-thing orderer " + "height-" + this.props.height + " " + "layout-" + this.props.layout + " " + "
|
|
41167
|
+
className: "draggy-boxy-thing orderer " + "height-" + this.props.height + " " + "layout-" + this.props.layout + " " + "blank-background " + "perseus-clearfix "
|
|
41857
41168
|
// eslint-disable-next-line react/no-string-refs
|
|
41858
41169
|
,
|
|
41859
41170
|
ref: "orderer"
|
|
@@ -41866,12 +41177,6 @@ var Orderer$1 = {
|
|
|
41866
41177
|
hidden: true,
|
|
41867
41178
|
widget: Orderer,
|
|
41868
41179
|
isLintable: true,
|
|
41869
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
41870
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusOrdererUserInput
|
|
41871
|
-
scorer: perseusScore.scoreOrderer,
|
|
41872
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
41873
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusOrdererUserInput
|
|
41874
|
-
validator: perseusScore.validateOrderer,
|
|
41875
41180
|
getPublicWidgetOptions: perseusCore.getOrdererPublicWidgetOptions
|
|
41876
41181
|
};
|
|
41877
41182
|
|
|
@@ -41915,15 +41220,12 @@ class PassageRefTarget extends React__namespace.Component {
|
|
|
41915
41220
|
var PassageRefTarget$1 = {
|
|
41916
41221
|
name: "passage-ref-target",
|
|
41917
41222
|
displayName: "PassageRefTarget",
|
|
41918
|
-
defaultAlignment: "inline",
|
|
41919
41223
|
widget: PassageRefTarget,
|
|
41920
41224
|
hidden: true,
|
|
41921
41225
|
transform: editorProps => {
|
|
41922
41226
|
return ___default["default"].pick(editorProps, "content");
|
|
41923
41227
|
},
|
|
41924
|
-
isLintable: true
|
|
41925
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
41926
|
-
scorer: () => scoreNoop()
|
|
41228
|
+
isLintable: true
|
|
41927
41229
|
};
|
|
41928
41230
|
|
|
41929
41231
|
const getPromptJSON$4 = () => {
|
|
@@ -42925,7 +42227,7 @@ class Plotter extends React__namespace.Component {
|
|
|
42925
42227
|
marginBottom: this.props.labels[0] ? paddingForBottomLabel : 0
|
|
42926
42228
|
};
|
|
42927
42229
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42928
|
-
className: "perseus-widget-plotter graphie
|
|
42230
|
+
className: "perseus-widget-plotter graphie"
|
|
42929
42231
|
// eslint-disable-next-line react/no-string-refs
|
|
42930
42232
|
,
|
|
42931
42233
|
ref: "graphieDiv",
|
|
@@ -42941,13 +42243,7 @@ var Plotter$1 = {
|
|
|
42941
42243
|
displayName: "Plotter",
|
|
42942
42244
|
hidden: true,
|
|
42943
42245
|
widget: Plotter,
|
|
42944
|
-
staticTransform: staticTransform
|
|
42945
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
42946
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusPlotterUserInput
|
|
42947
|
-
scorer: perseusScore.scorePlotter,
|
|
42948
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
42949
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusPlotterUserInput
|
|
42950
|
-
validator: perseusScore.validatePlotter
|
|
42246
|
+
staticTransform: staticTransform
|
|
42951
42247
|
};
|
|
42952
42248
|
|
|
42953
42249
|
const getPromptJSON$2 = () => {
|
|
@@ -43108,12 +42404,7 @@ var Sorter$1 = {
|
|
|
43108
42404
|
displayName: "Sorter",
|
|
43109
42405
|
widget: Sorter,
|
|
43110
42406
|
isLintable: true,
|
|
43111
|
-
|
|
43112
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusSorterUserInput
|
|
43113
|
-
scorer: perseusScore.scoreSorter,
|
|
43114
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
43115
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusSorterUserInput
|
|
43116
|
-
validator: perseusScore.validateSorter
|
|
42407
|
+
getPublicWidgetOptions: perseusCore.getSorterPublicWidgetOptions
|
|
43117
42408
|
};
|
|
43118
42409
|
|
|
43119
42410
|
const {
|
|
@@ -43329,13 +42620,7 @@ var Table$1 = {
|
|
|
43329
42620
|
widget: Table,
|
|
43330
42621
|
transform: propTransform,
|
|
43331
42622
|
hidden: true,
|
|
43332
|
-
isLintable: true
|
|
43333
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
43334
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusTableUserInput
|
|
43335
|
-
scorer: perseusScore.scoreTable,
|
|
43336
|
-
// TODO(LEMS-2656): remove TS suppression
|
|
43337
|
-
// @ts-expect-error: Type UserInput is not assignable to type PerseusTableUserInput
|
|
43338
|
-
validator: perseusScore.validateTable
|
|
42623
|
+
isLintable: true
|
|
43339
42624
|
};
|
|
43340
42625
|
|
|
43341
42626
|
const getPromptJSON = () => {
|
|
@@ -43497,11 +42782,7 @@ class Video extends React__namespace.Component {
|
|
|
43497
42782
|
var Video$1 = {
|
|
43498
42783
|
name: "video",
|
|
43499
42784
|
displayName: "Video",
|
|
43500
|
-
|
|
43501
|
-
supportedAlignments: ["block", "float-left", "float-right", "full-width"],
|
|
43502
|
-
widget: Video,
|
|
43503
|
-
// TODO: things that aren't interactive shouldn't need scoring functions
|
|
43504
|
-
scorer: () => scoreNoop()
|
|
42785
|
+
widget: Video
|
|
43505
42786
|
};
|
|
43506
42787
|
|
|
43507
42788
|
/* eslint-disable import/no-named-as-default */
|
|
@@ -43520,7 +42801,7 @@ const init = function () {
|
|
|
43520
42801
|
|
|
43521
42802
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43522
42803
|
const libName = "@khanacademy/perseus";
|
|
43523
|
-
const libVersion = "
|
|
42804
|
+
const libVersion = "53.0.0";
|
|
43524
42805
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43525
42806
|
|
|
43526
42807
|
const apiVersion = {
|
|
@@ -44396,6 +43677,42 @@ const ref = /*#__PURE__*/React__namespace.forwardRef((props, ref) => /*#__PURE__
|
|
|
44396
43677
|
}));
|
|
44397
43678
|
}));
|
|
44398
43679
|
|
|
43680
|
+
function isCorrect(score) {
|
|
43681
|
+
return score.type === "points" && score.earned >= score.total;
|
|
43682
|
+
}
|
|
43683
|
+
function keScoreFromPerseusScore(score,
|
|
43684
|
+
// It's weird, but this is what we're passing it
|
|
43685
|
+
guess, state) {
|
|
43686
|
+
if (score.type === "points") {
|
|
43687
|
+
return {
|
|
43688
|
+
empty: false,
|
|
43689
|
+
correct: isCorrect(score),
|
|
43690
|
+
message: score.message,
|
|
43691
|
+
guess: guess,
|
|
43692
|
+
state: state
|
|
43693
|
+
};
|
|
43694
|
+
}
|
|
43695
|
+
if (score.type === "invalid") {
|
|
43696
|
+
return {
|
|
43697
|
+
empty: true,
|
|
43698
|
+
correct: false,
|
|
43699
|
+
message: score.message,
|
|
43700
|
+
suppressAlmostThere: score.suppressAlmostThere,
|
|
43701
|
+
guess: guess,
|
|
43702
|
+
state: state
|
|
43703
|
+
};
|
|
43704
|
+
}
|
|
43705
|
+
throw new perseusCore.PerseusError(
|
|
43706
|
+
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
43707
|
+
"Invalid score type: " + score.type, perseusCore.Errors.InvalidInput, {
|
|
43708
|
+
metadata: {
|
|
43709
|
+
score: JSON.stringify(score),
|
|
43710
|
+
guess: JSON.stringify(guess),
|
|
43711
|
+
state: JSON.stringify(state)
|
|
43712
|
+
}
|
|
43713
|
+
});
|
|
43714
|
+
}
|
|
43715
|
+
|
|
44399
43716
|
/**
|
|
44400
43717
|
* Traverses a {content, widgets, images} renderer props object,
|
|
44401
43718
|
* such as `itemData.question`
|
|
@@ -44416,7 +43733,7 @@ const deepCallbackFor = function (contentCallback, widgetCallback, optionsCallba
|
|
|
44416
43733
|
// This doesn't modify the widget info if the widget info
|
|
44417
43734
|
// is at a later version than is supported, which is important
|
|
44418
43735
|
// for our latestVersion test below.
|
|
44419
|
-
const upgradedWidgetInfo = upgradeWidgetInfoToLatestVersion(widgetInfo);
|
|
43736
|
+
const upgradedWidgetInfo = perseusCore.upgradeWidgetInfoToLatestVersion(widgetInfo);
|
|
44420
43737
|
const latestVersion = getVersion(upgradedWidgetInfo.type);
|
|
44421
43738
|
|
|
44422
43739
|
// Only traverse our children if we can understand this version
|
|
@@ -44528,7 +43845,7 @@ const isRawWidgetInfoRenderableBy = function (widgetInfo, rendererContentVersion
|
|
|
44528
43845
|
|
|
44529
43846
|
// NOTE: This doesn't modify the widget info if the widget info
|
|
44530
43847
|
// is at a later version than is supported.
|
|
44531
|
-
const upgradedWidgetInfo = upgradeWidgetInfoToLatestVersion(widgetInfo);
|
|
43848
|
+
const upgradedWidgetInfo = perseusCore.upgradeWidgetInfoToLatestVersion(widgetInfo);
|
|
44532
43849
|
return isUpgradedWidgetInfoRenderableBy(upgradedWidgetInfo, rendererContentVersion[upgradedWidgetInfo.type]);
|
|
44533
43850
|
};
|
|
44534
43851
|
const isRendererContentRenderableBy = function (rendererOptions, rendererContentVersion) {
|
|
@@ -45876,7 +45193,6 @@ exports.mediaQueries = mediaQueries;
|
|
|
45876
45193
|
exports.parseDataFromJSONP = parseDataFromJSONP;
|
|
45877
45194
|
exports.preprocessTex = preprocessTex;
|
|
45878
45195
|
exports.registerAllWidgetsForTesting = registerAllWidgetsForTesting;
|
|
45879
|
-
exports.scorePerseusItem = scorePerseusItem;
|
|
45880
45196
|
exports.shouldHaveIndividualAnswer = shouldHaveIndividualAnswer;
|
|
45881
45197
|
exports.traverse = traverse;
|
|
45882
45198
|
exports.usePerseusI18n = usePerseusI18n;
|