@khanacademy/perseus 61.2.1 → 63.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/components/scrollable-view.d.ts +17 -0
  2. package/dist/es/index.css +1 -1
  3. package/dist/es/index.js +62 -47
  4. package/dist/es/index.js.map +1 -1
  5. package/dist/es/strings.js +1 -1
  6. package/dist/es/strings.js.map +1 -1
  7. package/dist/index.css +1 -1
  8. package/dist/index.js +61 -42
  9. package/dist/index.js.map +1 -1
  10. package/dist/server-item-renderer.d.ts +1 -0
  11. package/dist/strings.d.ts +16 -0
  12. package/dist/strings.js +1 -1
  13. package/dist/strings.js.map +1 -1
  14. package/dist/types.d.ts +3 -0
  15. package/dist/util/widget-enum-utils.d.ts +1 -1
  16. package/dist/widgets/expression/expression.d.ts +2 -0
  17. package/dist/widgets/free-response/free-response.d.ts +28 -0
  18. package/dist/widgets/free-response/index.d.ts +1 -0
  19. package/dist/widgets/grapher/grapher.d.ts +1 -2
  20. package/dist/widgets/numeric-input/numeric-input.d.ts +2 -0
  21. package/dist/widgets/phet-simulation/phet-simulation.d.ts +20 -0
  22. package/dist/widgets/radio/base-radio.new.d.ts +1 -3
  23. package/dist/widgets/radio/choice-icon/choice-icon-styles.d.ts +9 -0
  24. package/dist/widgets/radio/choice-none-above.new.d.ts +12 -4
  25. package/dist/widgets/radio/choice.new.d.ts +9 -2
  26. package/dist/widgets/radio/option-status.new.d.ts +1 -1
  27. package/dist/widgets/radio/{radio-component.new.d.ts → radio.class.new.d.ts} +9 -22
  28. package/dist/widgets/radio/radio.ff.d.ts +1 -2
  29. package/dist/widgets/radio/radio.new.d.ts +30 -0
  30. package/dist/widgets/radio/utils/general-utils.d.ts +35 -0
  31. package/dist/widgets/radio/utils/string-utils.d.ts +72 -0
  32. package/dist/widgets.d.ts +15 -15
  33. package/package.json +13 -11
  34. package/dist/widgets/radio/choice-a11y-text.new.d.ts +0 -14
package/dist/es/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { PerseusError, Errors, expressionLogic, getDecimalSeparator, approximateDeepEqual, pluck, CoreWidgetRegistry, getUpgradedWidgetOptions, mapObject, passageRefLogic, usesNumCorrect, radioLogic, shuffle, random, GrapherUtil as GrapherUtil$1, deepClone, lockedFigureColors, lockedFigureFillStyles, approximateEqual, shuffleMatcher, getMatrixSize, measurerLogic, registerCoreWidgets, upgradeWidgetInfoToLatestVersion, getWidgetIdsFromContentByType } from '@khanacademy/perseus-core';
1
+ import { PerseusError, Errors, expressionLogic, getDecimalSeparator, approximateDeepEqual, pluck, Registry, CoreWidgetRegistry, getUpgradedWidgetOptions, mapObject, passageRefLogic, usesNumCorrect, radioLogic, shuffle, random, GrapherUtil as GrapherUtil$1, deepClone, lockedFigureColors, lockedFigureFillStyles, approximateEqual, shuffleMatcher, getMatrixSize, measurerLogic, shuffleSorter, registerCoreWidgets, upgradeWidgetInfoToLatestVersion, getWidgetIdsFromContentByType } from '@khanacademy/perseus-core';
2
2
  export { isFailure, isSuccess, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem } from '@khanacademy/perseus-core';
3
3
  import * as React from 'react';
4
4
  import React__default, { useContext, forwardRef, useId, useImperativeHandle, useRef, useState, useEffect, createElement, createContext, useLayoutEffect } from 'react';
@@ -6,7 +6,7 @@ import * as KAS from '@khanacademy/kas';
6
6
  import { MathInputI18nContext, DesktopKeypad, getCursorContext, CursorContext, getKeyTranslator, createMathField, convertDotToTimesByLocale, mathQuillInstance, KeypadInput, keypadElementPropType } from '@khanacademy/math-input';
7
7
  import * as PerseusLinter from '@khanacademy/perseus-linter';
8
8
  import { linterContextDefault, Rule } from '@khanacademy/perseus-linter';
9
- import { View, RenderStateRoot, Id, useOnMountEffect, useLatestRef, Text as Text$2 } from '@khanacademy/wonder-blocks-core';
9
+ import { View, RenderStateRoot, Id, Text as Text$1, useOnMountEffect, useLatestRef } from '@khanacademy/wonder-blocks-core';
10
10
  import Tooltip, { TooltipContent } from '@khanacademy/wonder-blocks-tooltip';
11
11
  import { HeadingMedium, LabelSmall, LabelLarge, Body, LabelMedium } from '@khanacademy/wonder-blocks-typography';
12
12
  import { StyleSheet, css } from 'aphrodite';
@@ -16,13 +16,13 @@ import ReactDOM__default from 'react-dom';
16
16
  import _, { debounce as debounce$1 } from 'underscore';
17
17
  import Clickable from '@khanacademy/wonder-blocks-clickable';
18
18
  import { Popover, PopoverContentCore, PopoverContent } from '@khanacademy/wonder-blocks-popover';
19
- import { color, spacing, font } from '@khanacademy/wonder-blocks-tokens';
19
+ import { color, spacing, font, semanticColor } from '@khanacademy/wonder-blocks-tokens';
20
20
  import $ from 'jquery';
21
21
  import { v4 } from 'uuid';
22
22
  import PropTypes from 'prop-types';
23
23
  import { KhanAnswerTypes, emptyWidgetsFunctional, scoreWidgetsFunctional, flattenScores, inputNumberAnswerTypes, scoreRadio, scoreLabelImageMarker } from '@khanacademy/perseus-score';
24
24
  import { KeypadContext } from '@khanacademy/keypad-context';
25
- import { TextField } from '@khanacademy/wonder-blocks-form';
25
+ import { TextField, TextArea } from '@khanacademy/wonder-blocks-form';
26
26
  import { entries, UnreachableCaseError, keys } from '@khanacademy/wonder-stuff-core';
27
27
  import { CircularSpinner } from '@khanacademy/wonder-blocks-progress-spinner';
28
28
  import { point, KhanMath, number, vector as vector$3, geometry, line, angles, coefficients } from '@khanacademy/kmath';
@@ -30,20 +30,25 @@ import SimpleMarkdown from '@khanacademy/simple-markdown';
30
30
  import { pureMarkdownRules } from '@khanacademy/pure-markdown';
31
31
  import Button from '@khanacademy/wonder-blocks-button';
32
32
  import { Strut } from '@khanacademy/wonder-blocks-layout';
33
+ import IconButton from '@khanacademy/wonder-blocks-icon-button';
34
+ import caretLeftIcon from '@phosphor-icons/core/regular/caret-left.svg';
35
+ import caretRightIcon from '@phosphor-icons/core/regular/caret-right.svg';
33
36
  import Banner from '@khanacademy/wonder-blocks-banner';
34
37
  import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-blocks-dropdown';
35
38
  import caretDown from '@phosphor-icons/core/regular/caret-down.svg';
36
39
  import caretUp from '@phosphor-icons/core/regular/caret-up.svg';
37
- import { vec, Coordinates, Ellipse, Plot as Plot$2, Line as Line$4, Point as Point$2, Polygon, Text as Text$1, useTransformContext, Polyline, Mafs } from 'mafs';
38
40
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
41
+ import { LabeledField } from '@khanacademy/wonder-blocks-labeled-field';
42
+ import warningCircleIcon from '@phosphor-icons/core/regular/warning-circle.svg';
43
+ import { vec, Coordinates, Ellipse, Plot as Plot$2, Line as Line$4, Point as Point$2, Polygon, Text as Text$2, useTransformContext, Polyline, Mafs } from 'mafs';
39
44
  import questionIcon from '@phosphor-icons/core/regular/question.svg';
40
45
  import { useDrag } from '@use-gesture/react';
41
46
  import invariant from 'tiny-invariant';
42
47
  import Switch from '@khanacademy/wonder-blocks-switch';
43
48
  import Pill from '@khanacademy/wonder-blocks-pill';
44
49
  import { Popper } from 'react-popper';
45
- import IconButton from '@khanacademy/wonder-blocks-icon-button';
46
50
  import cornersOutIcon from '@phosphor-icons/core/regular/corners-out.svg';
51
+ import xIcon from '@phosphor-icons/core/regular/x.svg';
47
52
  import Link from '@khanacademy/wonder-blocks-link';
48
53
  import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
49
54
 
@@ -1410,7 +1415,7 @@ function requireJsxRuntime () {
1410
1415
 
1411
1416
  var jsxRuntimeExports = requireJsxRuntime();
1412
1417
 
1413
- const mockStrings={closeKeypad:"close math keypad",openKeypad:"open math keypad",mathInputBox:"Math input box",removeHighlight:"Remove highlight",addHighlight:"Add highlight",hintPos:({pos})=>`Hint #${pos}`,errorRendering:({error})=>`Error rendering: ${error}`,APPROXIMATED_PI_ERROR:"Your answer is close, but you may "+"have approximated pi. Enter your "+"answer as a multiple of pi, like "+"<code>12\\ \\text{pi}</code> or "+"<code>2/3\\ \\text{pi}</code>",EXTRA_SYMBOLS_ERROR:"We could not understand your "+"answer. Please check your answer for extra "+"text or symbols.",NEEDS_TO_BE_SIMPLFIED_ERROR:"Your answer is almost correct, "+"but it needs to be simplified.",MISSING_PERCENT_ERROR:"Your answer is almost correct, "+"but it is missing a "+"<code>\\%</code> at the end.",MULTIPLICATION_SIGN_ERROR:"I'm a computer. I only understand "+"multiplication if you use an asterisk "+"(*) as the multiplication sign.",WRONG_CASE_ERROR:"Your answer includes use of a variable with the wrong case.",WRONG_LETTER_ERROR:"Your answer includes a wrong variable letter.",invalidSelection:"Make sure you select something for every row.",ERROR_TITLE:"Oops!",ERROR_MESSAGE:"Sorry, I don't understand that!",hints:"Hints",getAnotherHint:"Get another hint",deprecatedStandin:"Sorry, this part of the question is no longer available. 😅 Don't worry, you won't be graded on this part. Keep going!",keepTrying:"Keep trying",tryAgain:"Try again",check:"Check",correctExcited:"Correct!",nextQuestion:"Next question",skipToTitle:({title})=>`Skip to ${title}`,current:"Current",correct:"Correct",correctSelected:"Correct (selected)",correctCrossedOut:"Correct (but you crossed it out)",incorrect:"Incorrect",incorrectSelected:"Incorrect (selected)",hideExplanation:"Hide explanation",explain:"Explain",INVALID_MESSAGE_PREFIX:"We couldn't grade your answer.",DEFAULT_INVALID_MESSAGE_1:"It looks like you left something blank or ",DEFAULT_INVALID_MESSAGE_2:"entered in an invalid answer.",integerExample:"an integer, like $6$",properExample:"a *proper* fraction, like $1/2$ or $6/10$",simplifiedProperExample:"a *simplified proper* fraction, like $3/5$",improperExample:"an *improper* fraction, like $10/7$ or $14/8$",simplifiedImproperExample:"a *simplified improper* fraction, like $7/4$",mixedExample:"a mixed number, like $1\\ 3/4$",decimalExample:"an *exact* decimal, like $0.75$",percentExample:"a percent, like $12.34\\%$",piExample:"a multiple of pi, like $12\\ \\text{pi}$ or $2/3\\ \\text{pi}$",yourAnswer:"**Your answer should be** ",yourAnswerLabel:"Your answer:",addPoints:"Click to add points",addVertices:"Click to add vertices",tapMultiple:"Tap each dot on the image to select all answers that apply.",tapSingle:"Tap each dot on the image to select an answer.",clickMultiple:"Click each dot on the image to select all answers that apply.",clickSingle:"Click each dot on the image to select an answer.",choices:"Choices:",answers:({num})=>num===1?`${num} answer`:`${num} answers`,hideAnswersToggleLabel:"Hide answer choices",moves:({num})=>num===1?`Moves: ${num}`:`Moves: ${num}`,clickTiles:"Click on the tiles to change the lights.",turnOffLights:"You must turn on all of the lights to continue.",fillAllCells:"Make sure you fill in all cells in the matrix.",molecularDrawing:({content})=>`A molecular structure drawing. SMILES notation: ${content}`,switchDirection:"Switch direction",circleOpen:"Make circle open",circleFilled:"Make circle filled",numDivisions:"Number of divisions:",divisions:({divRangeString})=>`Please make sure the number of divisions is in the range ${divRangeString}.`,lineRange:({lineRange})=>`lines ${lineRange}`,lineNumber:({lineNumber})=>`line ${lineNumber}`,symbolPassage:({questionSymbol,questionNumber})=>`The symbol ${questionSymbol} indicates that question ${questionNumber} references this portion of the passage.`,symbolQuestion:({sentenceSymbol})=>` The symbol ${sentenceSymbol} indicates that the following sentence is referenced in a question.`,lineLabel:"Line",beginningPassage:"Beginning of reading passage.",beginningFootnotes:"Beginning of reading passage footnotes.",endPassage:"End of reading passage.",questionMarker:({number})=>`[Marker for question ${number}]`,circleMarker:({number})=>`[Circle marker ${number}]`,sentenceMarker:({number})=>`[Sentence ${number}]`,dragHandles:"Drag handles to make graph",tapAddPoints:"Tap to add points",false:"False",true:"True",no:"No",yes:"Yes",chooseCorrectNum:"Please choose the correct number of answers.",notNoneOfTheAbove:"'None of the above' may not be selected when other answers are selected.",noneOfTheAbove:"None of the above",chooseNumAnswers:({numCorrect})=>`Choose ${numCorrect} answers:`,chooseAllAnswers:"Choose all answers that apply:",chooseOneAnswer:"Choose 1 answer:",choiceCheckedCorrect:({letter})=>`(Choice ${letter}, Checked, Correct)`,choiceCrossedOutCorrect:({letter})=>`(Choice ${letter}, Crossed out, Correct)`,choiceCorrect:({letter})=>`(Choice ${letter}, Correct)`,choiceCheckedIncorrect:({letter})=>`(Choice ${letter}, Checked, Incorrect)`,choiceCrossedOutIncorrect:({letter})=>`(Choice ${letter}, Crossed out, Incorrect)`,choiceIncorrect:({letter})=>`(Choice ${letter}, Incorrect)`,choiceChecked:({letter})=>`(Choice ${letter}, Checked)`,choiceCrossedOut:({letter})=>`(Choice ${letter}, Crossed out)`,choice:({letter})=>`(Choice ${letter})`,crossOut:"Cross out",crossOutOption:"Cross out option",crossOutChoice:({letter})=>`Cross out Choice ${letter}`,bringBack:"Bring back",openMenuForChoice:({letter})=>`Open menu for Choice ${letter}`,letters:"A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",rightArrow:"Reaction arrow pointing to the right.",dontUnderstandUnits:"I couldn't understand those units.",checkSigFigs:"Check your significant figures.",answerNumericallyIncorrect:"That answer is numerically incorrect.",checkUnits:"Check your units.",dontUnderstand:"I don't understand that",loading:"Loading...",videoTranscript:"See video transcript",somethingWrong:"Something went wrong.",videoWrapper:"Khan Academy video wrapper",mathInputTitle:"mathematics keyboard",mathInputDescription:"Use keyboard/mouse to interact with math-based input fields",sin:"sin",cos:"cos",tan:"tan",simulationLoadFail:"Sorry, this simulation cannot load.",simulationLocaleWarning:"Sorry, this simulation isn't available in your language.",selectAnAnswer:"Select an answer",srGraphInstructions:"Use the Tab key to move through the interactive elements in the graph. When an interactive element has focus, use Control + Shift + Arrows to move it.",srUnlimitedGraphInstructions:"Press Shift + Enter to interact with the graph. Use the Tab key to move through the interactive elements in the graph and access the graph Action Bar. When an interactive element has focus, use Control + Shift + Arrows to move it or use the Delete key to remove it from the graph. Use the buttons in the Action Bar to add or adjust elements within the graph.",graphKeyboardPrompt:"Press Shift + Enter to interact with the graph",addPoint:"Add Point",removePoint:"Remove Point",closePolygon:"Close shape",openPolygon:"Re-open shape",srPointAtCoordinates:({num,x,y})=>`Point ${num} at ${x} comma ${y}.`,srInteractiveElements:({elements})=>`Interactive elements: ${elements}`,srNoInteractiveElements:"No interactive elements",srCircleGraph:"A circle on a coordinate plane.",srCircleShape:({centerX,centerY})=>`Circle. The center point is at ${centerX} comma ${centerY}.`,srCircleRadiusPointRight:({radiusPointX,radiusPointY})=>`Right radius endpoint at ${radiusPointX} comma ${radiusPointY}.`,srCircleRadiusPointLeft:({radiusPointX,radiusPointY})=>`Left radius endpoint at ${radiusPointX} comma ${radiusPointY}.`,srCircleRadius:({radius})=>`Circle radius is ${radius}.`,srCircleOuterPoints:({point1X,point1Y,point2X,point2Y,point3X,point3Y,point4X,point4Y})=>`Points on the circle at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, ${point3X} comma ${point3Y}, ${point4X} comma ${point4Y}.`,srLinearGraph:"A line on a coordinate plane.",srLinearGraphPoints:({point1X,point1Y,point2X,point2Y})=>`The line has two points, point 1 at ${point1X} comma ${point1Y} and point 2 at ${point2X} comma ${point2Y}.`,srLinearGraphSlopeIncreasing:"Its slope increases from left to right.",srLinearGraphSlopeDecreasing:"Its slope decreases from left to right.",srLinearGraphSlopeHorizontal:"Its slope is zero.",srLinearGraphSlopeVertical:"Its slope is undefined.",srLinearGraphXOnlyIntercept:({xIntercept})=>`The line crosses the X-axis at ${xIntercept} comma 0.`,srLinearGraphYOnlyIntercept:({yIntercept})=>`The line crosses the Y-axis at 0 comma ${yIntercept}.`,srLinearGraphBothIntercepts:({xIntercept,yIntercept})=>`The line crosses the X-axis at ${xIntercept} comma 0 and the Y-axis at 0 comma ${yIntercept}.`,srLinearGraphOriginIntercept:"The line crosses the X and Y axes at the graph's origin.",srLinearGrabHandle:({point1X,point1Y,point2X,point2Y})=>`Line going through point ${point1X} comma ${point1Y} and point ${point2X} comma ${point2Y}.`,srAngleStartingSide:({x,y})=>`Point 3, starting side at ${x} comma ${y}.`,srAngleEndingSide:({x,y})=>`Point 2, ending side at ${x} comma ${y}.`,srAngleVertexWithAngleMeasure:({x,y,angleMeasure})=>`Point 1, vertex at ${x} comma ${y}. Angle ${angleMeasure} degrees.`,srAngleGraphAriaLabel:"An angle on a coordinate plane.",srAngleGraphAriaDescription:({angleMeasure,vertexX,vertexY,startingSideX,startingSideY,endingSideX,endingSideY})=>`The angle measure is ${angleMeasure} degrees with a vertex at ${vertexX} comma ${vertexY}, a point on the starting side at ${startingSideX} comma ${startingSideY} and a point on the ending side at ${endingSideX} comma ${endingSideY}.`,srAngleInteractiveElements:({vertexX,vertexY,startingSideX,startingSideY,endingSideX,endingSideY})=>`An angle formed by 3 points. The vertex is at ${vertexX} comma ${vertexY}. The starting side point is at ${startingSideX} comma ${startingSideY}. The ending side point is at ${endingSideX} comma ${endingSideY}.`,srSingleSegmentGraphAriaLabel:"A line segment on a coordinate plane.",srMultipleSegmentGraphAriaLabel:({countOfSegments})=>`${countOfSegments} segments on a coordinate plane.`,srMultipleSegmentIndividualLabel:({point1X,point1Y,point2X,point2Y,indexOfSegment})=>`Segment ${indexOfSegment}: Endpoint 1 at ${point1X} comma ${point1Y}. Endpoint 2 at ${point2X} comma ${point2Y}.`,srSingleSegmentLabel:({point1X,point1Y,point2X,point2Y})=>`Endpoint 1 at ${point1X} comma ${point1Y}. Endpoint 2 at ${point2X} comma ${point2Y}.`,srSegmentLength:({length})=>`Segment length ${length} units.`,srSingleSegmentGraphEndpointAriaLabel:({endpointNumber,x,y})=>`Endpoint ${endpointNumber} at ${x} comma ${y}.`,srMultipleSegmentGraphEndpointAriaLabel:({endpointNumber,x,y,indexOfSegment})=>`Endpoint ${endpointNumber} on segment ${indexOfSegment} at ${x} comma ${y}.`,srSegmentGrabHandle:({point1X,point1Y,point2X,point2Y})=>`Segment from ${point1X} comma ${point1Y} to ${point2X} comma ${point2Y}.`,srLinearSystemGraph:"Two lines on a coordinate plane.",srLinearSystemPoints:({lineNumber,point1X,point1Y,point2X,point2Y})=>`Line ${lineNumber} has two points, point 1 at ${point1X} comma ${point1Y} and point 2 at ${point2X} comma ${point2Y}.`,srLinearSystemPoint:({lineNumber,pointSequence,x,y})=>`Point ${pointSequence} on line ${lineNumber} at ${x} comma ${y}.`,srLinearSystemGrabHandle:({lineNumber,point1X,point1Y,point2X,point2Y})=>`Line ${lineNumber} going through point ${point1X} comma ${point1Y} and point ${point2X} comma ${point2Y}.`,srLinearSystemIntersection:({x,y})=>`Line 1 and line 2 intersect at point ${x} comma ${y}.`,srLinearSystemParallel:"Line 1 and line 2 are parallel.",srRayGraph:"A ray on a coordinate plane.",srRayPoints:({point1X,point1Y,point2X,point2Y})=>`The endpoint is at ${point1X} comma ${point1Y} and the ray goes through point ${point2X} comma ${point2Y}.`,srRayGrabHandle:({point1X,point1Y,point2X,point2Y})=>`Ray with endpoint ${point1X} comma ${point1Y} going through point ${point2X} comma ${point2Y}.`,srRayEndpoint:({x,y})=>`Endpoint at ${x} comma ${y}.`,srRayTerminalPoint:({x,y})=>`Through point at ${x} comma ${y}.`,srQuadraticGraph:"A parabola on a 4-quadrant coordinate plane.",srQuadraticFaceUp:"The parabola opens upward.",srQuadraticFaceDown:"The parabola opens downward.",srQuadraticGraphVertexOrigin:"Vertex is at the origin.",srQuadraticGraphVertexXAxis:"Vertex is on the X-axis.",srQuadraticGraphVertexYAxis:"Vertex is on the Y-axis.",srQuadraticGraphVertexQuadrant:({quadrant})=>`Vertex is in quadrant ${quadrant}.`,srQuadraticTwoXIntercepts:({intercept1,intercept2})=>`The X-intercepts are at ${intercept1} comma 0 and ${intercept2} comma 0.`,srQuadraticOneXIntercept:({intercept})=>`The X-intercept is at ${intercept} comma 0.`,srQuadraticYIntercept:({intercept})=>`The Y-intercept is at 0 comma ${intercept}.`,srQuadraticPointOrigin:({pointNumber})=>`Point ${pointNumber} on parabola at the origin.`,srQuadraticPointAxis:({pointNumber,x,y})=>`Point ${pointNumber} on parabola at ${x} comma ${y}.`,srQuadraticPointQuadrant:({pointNumber,x,y,quadrant})=>`Point ${pointNumber} on parabola in quadrant ${quadrant} at ${x} comma ${y}.`,srQuadraticInteractiveElements:({point1X,point1Y,point2X,point2Y,point3X,point3Y})=>`Parabola with points at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, and ${point3X} comma ${point3Y}.`,srPolygonGraph:"A polygon.",srPolygonGraphCoordinatePlane:"A polygon on a coordinate plane.",srPolygonGraphPointsNum:({num})=>`The polygon has ${num} points.`,srPolygonGraphPointsOne:"The polygon has 1 point.",srPolygonElementsNum:({num})=>`A polygon with ${num} points.`,srPolygonElementsOne:"A polygon with 1 point.",srPolygonPointAngleApprox:({angle})=>`Angle approximately equal to ${angle} degrees.`,srPolygonPointAngle:({angle})=>`Angle equal to ${angle} degrees.`,srPolygonSideLength:({pointNum,length})=>`A line segment, length equal to ${length} units, connects to point ${pointNum}.`,srPolygonSideLengthApprox:({pointNum,length})=>`A line segment, length approximately equal to ${length} units, connects to point ${pointNum}.`,srUnlimitedPolygonEmpty:"An empty coordinate plane.",srSinusoidGraph:"A sinusoid function on a coordinate plane.",srSinusoidRootPoint:({x,y})=>`Midline intersection at ${x} comma ${y}.`,srSinusoidMaxPoint:({x,y})=>`Maximum point at ${x} comma ${y}.`,srSinusoidMinPoint:({x,y})=>`Minimum point at ${x} comma ${y}.`,srSinusoidFlatPoint:({x,y})=>`Line through point at ${x} comma ${y}.`,srSinusoidDescription:({minValue,maxValue,cycleStart,cycleEnd})=>`The graph shows a wave with a minimum value of ${minValue} and a maximum value of ${maxValue}. The wave completes a full cycle from ${cycleStart} to ${cycleEnd}.`,srSinusoidInteractiveElements:({point1X,point1Y,point2X,point2Y})=>`Sinusoid graph with midline intersection point at ${point1X} comma ${point1Y} and extremum point at ${point2X} comma ${point2Y}.`};const errorToString={MISSING_PERCENT_ERROR:"MISSING_PERCENT_ERROR",NEEDS_TO_BE_SIMPLIFIED_ERROR:"NEEDS_TO_BE_SIMPLFIED_ERROR",APPROXIMATED_PI_ERROR:"APPROXIMATED_PI_ERROR",EXTRA_SYMBOLS_ERROR:"EXTRA_SYMBOLS_ERROR",WRONG_CASE_ERROR:"WRONG_CASE_ERROR",WRONG_LETTER_ERROR:"WRONG_LETTER_ERROR",MULTIPLICATION_SIGN_ERROR:"MULTIPLICATION_SIGN_ERROR",INVALID_SELECTION_ERROR:"invalidSelection",CHOOSE_CORRECT_NUM_ERROR:"chooseCorrectNum",NOT_NONE_ABOVE_ERROR:"notNoneOfTheAbove",FILL_ALL_CELLS_ERROR:"fillAllCells"};function mapErrorToString(err,translatedStrings){if(!err){return err}return translatedStrings[errorToString[err]]||err}
1418
+ const mockStrings={characterCount:({used,num})=>num===1?`${used} / ${num} Character`:`${used} / ${num} Characters`,closeKeypad:"close math keypad",openKeypad:"open math keypad",mathInputBox:"Math input box",removeHighlight:"Remove highlight",addHighlight:"Add highlight",hintPos:({pos})=>`Hint #${pos}`,errorRendering:({error})=>`Error rendering: ${error}`,APPROXIMATED_PI_ERROR:"Your answer is close, but you may "+"have approximated pi. Enter your "+"answer as a multiple of pi, like "+"<code>12\\ \\text{pi}</code> or "+"<code>2/3\\ \\text{pi}</code>",EXTRA_SYMBOLS_ERROR:"We could not understand your "+"answer. Please check your answer for extra "+"text or symbols.",NEEDS_TO_BE_SIMPLFIED_ERROR:"Your answer is almost correct, "+"but it needs to be simplified.",MISSING_PERCENT_ERROR:"Your answer is almost correct, "+"but it is missing a "+"<code>\\%</code> at the end.",MULTIPLICATION_SIGN_ERROR:"I'm a computer. I only understand "+"multiplication if you use an asterisk "+"(*) as the multiplication sign.",USER_INPUT_EMPTY:"Your answer is empty.",WRONG_CASE_ERROR:"Your answer includes use of a variable with the wrong case.",WRONG_LETTER_ERROR:"Your answer includes a wrong variable letter.",invalidSelection:"Make sure you select something for every row.",ERROR_TITLE:"Oops!",ERROR_MESSAGE:"Sorry, I don't understand that!",hints:"Hints",getAnotherHint:"Get another hint",deprecatedStandin:"Sorry, this part of the question is no longer available. 😅 Don't worry, you won't be graded on this part. Keep going!",keepTrying:"Keep trying",tryAgain:"Try again",check:"Check",correctExcited:"Correct!",nextQuestion:"Next question",skipToTitle:({title})=>`Skip to ${title}`,current:"Current",correct:"Correct",correctSelected:"Correct (selected)",correctCrossedOut:"Correct (but you crossed it out)",incorrect:"Incorrect",incorrectSelected:"Incorrect (selected)",hideExplanation:"Hide explanation",explain:"Explain",INVALID_MESSAGE_PREFIX:"We couldn't grade your answer.",DEFAULT_INVALID_MESSAGE_1:"It looks like you left something blank or ",DEFAULT_INVALID_MESSAGE_2:"entered in an invalid answer.",integerExample:"an integer, like $6$",properExample:"a *proper* fraction, like $1/2$ or $6/10$",simplifiedProperExample:"a *simplified proper* fraction, like $3/5$",improperExample:"an *improper* fraction, like $10/7$ or $14/8$",simplifiedImproperExample:"a *simplified improper* fraction, like $7/4$",mixedExample:"a mixed number, like $1\\ 3/4$",decimalExample:"an *exact* decimal, like $0.75$",percentExample:"a percent, like $12.34\\%$",piExample:"a multiple of pi, like $12\\ \\text{pi}$ or $2/3\\ \\text{pi}$",yourAnswer:"**Your answer should be** ",yourAnswerLabel:"Your answer:",addPoints:"Click to add points",addVertices:"Click to add vertices",tapMultiple:"Tap each dot on the image to select all answers that apply.",tapSingle:"Tap each dot on the image to select an answer.",clickMultiple:"Click each dot on the image to select all answers that apply.",clickSingle:"Click each dot on the image to select an answer.",choices:"Choices:",answers:({num})=>num===1?`${num} answer`:`${num} answers`,hideAnswersToggleLabel:"Hide answer choices",moves:({num})=>num===1?`Moves: ${num}`:`Moves: ${num}`,clickTiles:"Click on the tiles to change the lights.",turnOffLights:"You must turn on all of the lights to continue.",fillAllCells:"Make sure you fill in all cells in the matrix.",molecularDrawing:({content})=>`A molecular structure drawing. SMILES notation: ${content}`,switchDirection:"Switch direction",circleOpen:"Make circle open",circleFilled:"Make circle filled",numDivisions:"Number of divisions:",divisions:({divRangeString})=>`Please make sure the number of divisions is in the range ${divRangeString}.`,lineRange:({lineRange})=>`lines ${lineRange}`,lineNumber:({lineNumber})=>`line ${lineNumber}`,symbolPassage:({questionSymbol,questionNumber})=>`The symbol ${questionSymbol} indicates that question ${questionNumber} references this portion of the passage.`,symbolQuestion:({sentenceSymbol})=>` The symbol ${sentenceSymbol} indicates that the following sentence is referenced in a question.`,lineLabel:"Line",beginningPassage:"Beginning of reading passage.",beginningFootnotes:"Beginning of reading passage footnotes.",endPassage:"End of reading passage.",questionMarker:({number})=>`[Marker for question ${number}]`,circleMarker:({number})=>`[Circle marker ${number}]`,sentenceMarker:({number})=>`[Sentence ${number}]`,dragHandles:"Drag handles to make graph",tapAddPoints:"Tap to add points",false:"False",true:"True",no:"No",yes:"Yes",chooseCorrectNum:"Please choose the correct number of answers.",notNoneOfTheAbove:"'None of the above' may not be selected when other answers are selected.",noneOfTheAbove:"None of the above",chooseNumAnswers:({numCorrect})=>`Choose ${numCorrect} answers:`,chooseAllAnswers:"Choose all answers that apply:",chooseOneAnswer:"Choose 1 answer:",choiceCheckedCorrect:({letter})=>`(Choice ${letter}, Checked, Correct)`,choiceCrossedOutCorrect:({letter})=>`(Choice ${letter}, Crossed out, Correct)`,choiceCorrect:({letter})=>`(Choice ${letter}, Correct)`,choiceCheckedIncorrect:({letter})=>`(Choice ${letter}, Checked, Incorrect)`,choiceCrossedOutIncorrect:({letter})=>`(Choice ${letter}, Crossed out, Incorrect)`,choiceIncorrect:({letter})=>`(Choice ${letter}, Incorrect)`,choiceChecked:({letter})=>`(Choice ${letter}, Checked)`,choiceCrossedOut:({letter})=>`(Choice ${letter}, Crossed out)`,choice:({letter})=>`(Choice ${letter})`,crossOut:"Cross out",crossOutOption:"Cross out option",crossOutChoice:({letter})=>`Cross out Choice ${letter}`,bringBack:"Bring back",openMenuForChoice:({letter})=>`Open menu for Choice ${letter}`,letters:"A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",scrollAnswers:"Scroll Answers",scrollLeft:"Scroll left",scrollRight:"Scroll right",rightArrow:"Reaction arrow pointing to the right.",dontUnderstandUnits:"I couldn't understand those units.",checkSigFigs:"Check your significant figures.",answerNumericallyIncorrect:"That answer is numerically incorrect.",checkUnits:"Check your units.",dontUnderstand:"I don't understand that",loading:"Loading...",videoTranscript:"See video transcript",somethingWrong:"Something went wrong.",videoWrapper:"Khan Academy video wrapper",mathInputTitle:"mathematics keyboard",mathInputDescription:"Use keyboard/mouse to interact with math-based input fields",sin:"sin",cos:"cos",tan:"tan",simulationLoadFail:"Sorry, this simulation cannot load.",simulationLocaleWarning:"Sorry, this simulation isn't available in your language.",selectAnAnswer:"Select an answer",srGraphInstructions:"Use the Tab key to move through the interactive elements in the graph. When an interactive element has focus, use Control + Shift + Arrows to move it.",srUnlimitedGraphInstructions:"Press Shift + Enter to interact with the graph. Use the Tab key to move through the interactive elements in the graph and access the graph Action Bar. When an interactive element has focus, use Control + Shift + Arrows to move it or use the Delete key to remove it from the graph. Use the buttons in the Action Bar to add or adjust elements within the graph.",graphKeyboardPrompt:"Press Shift + Enter to interact with the graph",addPoint:"Add Point",removePoint:"Remove Point",closePolygon:"Close shape",openPolygon:"Re-open shape",srPointAtCoordinates:({num,x,y})=>`Point ${num} at ${x} comma ${y}.`,srInteractiveElements:({elements})=>`Interactive elements: ${elements}`,srNoInteractiveElements:"No interactive elements",srCircleGraph:"A circle on a coordinate plane.",srCircleShape:({centerX,centerY})=>`Circle. The center point is at ${centerX} comma ${centerY}.`,srCircleRadiusPointRight:({radiusPointX,radiusPointY})=>`Right radius endpoint at ${radiusPointX} comma ${radiusPointY}.`,srCircleRadiusPointLeft:({radiusPointX,radiusPointY})=>`Left radius endpoint at ${radiusPointX} comma ${radiusPointY}.`,srCircleRadius:({radius})=>`Circle radius is ${radius}.`,srCircleOuterPoints:({point1X,point1Y,point2X,point2Y,point3X,point3Y,point4X,point4Y})=>`Points on the circle at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, ${point3X} comma ${point3Y}, ${point4X} comma ${point4Y}.`,srLinearGraph:"A line on a coordinate plane.",srLinearGraphPoints:({point1X,point1Y,point2X,point2Y})=>`The line has two points, point 1 at ${point1X} comma ${point1Y} and point 2 at ${point2X} comma ${point2Y}.`,srLinearGraphSlopeIncreasing:"Its slope increases from left to right.",srLinearGraphSlopeDecreasing:"Its slope decreases from left to right.",srLinearGraphSlopeHorizontal:"Its slope is zero.",srLinearGraphSlopeVertical:"Its slope is undefined.",srLinearGraphXOnlyIntercept:({xIntercept})=>`The line crosses the X-axis at ${xIntercept} comma 0.`,srLinearGraphYOnlyIntercept:({yIntercept})=>`The line crosses the Y-axis at 0 comma ${yIntercept}.`,srLinearGraphBothIntercepts:({xIntercept,yIntercept})=>`The line crosses the X-axis at ${xIntercept} comma 0 and the Y-axis at 0 comma ${yIntercept}.`,srLinearGraphOriginIntercept:"The line crosses the X and Y axes at the graph's origin.",srLinearGrabHandle:({point1X,point1Y,point2X,point2Y})=>`Line going through point ${point1X} comma ${point1Y} and point ${point2X} comma ${point2Y}.`,srAngleStartingSide:({x,y})=>`Point 3, starting side at ${x} comma ${y}.`,srAngleEndingSide:({x,y})=>`Point 2, ending side at ${x} comma ${y}.`,srAngleVertexWithAngleMeasure:({x,y,angleMeasure})=>`Point 1, vertex at ${x} comma ${y}. Angle ${angleMeasure} degrees.`,srAngleGraphAriaLabel:"An angle on a coordinate plane.",srAngleGraphAriaDescription:({angleMeasure,vertexX,vertexY,startingSideX,startingSideY,endingSideX,endingSideY})=>`The angle measure is ${angleMeasure} degrees with a vertex at ${vertexX} comma ${vertexY}, a point on the starting side at ${startingSideX} comma ${startingSideY} and a point on the ending side at ${endingSideX} comma ${endingSideY}.`,srAngleInteractiveElements:({vertexX,vertexY,startingSideX,startingSideY,endingSideX,endingSideY})=>`An angle formed by 3 points. The vertex is at ${vertexX} comma ${vertexY}. The starting side point is at ${startingSideX} comma ${startingSideY}. The ending side point is at ${endingSideX} comma ${endingSideY}.`,srSingleSegmentGraphAriaLabel:"A line segment on a coordinate plane.",srMultipleSegmentGraphAriaLabel:({countOfSegments})=>`${countOfSegments} segments on a coordinate plane.`,srMultipleSegmentIndividualLabel:({point1X,point1Y,point2X,point2Y,indexOfSegment})=>`Segment ${indexOfSegment}: Endpoint 1 at ${point1X} comma ${point1Y}. Endpoint 2 at ${point2X} comma ${point2Y}.`,srSingleSegmentLabel:({point1X,point1Y,point2X,point2Y})=>`Endpoint 1 at ${point1X} comma ${point1Y}. Endpoint 2 at ${point2X} comma ${point2Y}.`,srSegmentLength:({length})=>`Segment length ${length} units.`,srSingleSegmentGraphEndpointAriaLabel:({endpointNumber,x,y})=>`Endpoint ${endpointNumber} at ${x} comma ${y}.`,srMultipleSegmentGraphEndpointAriaLabel:({endpointNumber,x,y,indexOfSegment})=>`Endpoint ${endpointNumber} on segment ${indexOfSegment} at ${x} comma ${y}.`,srSegmentGrabHandle:({point1X,point1Y,point2X,point2Y})=>`Segment from ${point1X} comma ${point1Y} to ${point2X} comma ${point2Y}.`,srLinearSystemGraph:"Two lines on a coordinate plane.",srLinearSystemPoints:({lineNumber,point1X,point1Y,point2X,point2Y})=>`Line ${lineNumber} has two points, point 1 at ${point1X} comma ${point1Y} and point 2 at ${point2X} comma ${point2Y}.`,srLinearSystemPoint:({lineNumber,pointSequence,x,y})=>`Point ${pointSequence} on line ${lineNumber} at ${x} comma ${y}.`,srLinearSystemGrabHandle:({lineNumber,point1X,point1Y,point2X,point2Y})=>`Line ${lineNumber} going through point ${point1X} comma ${point1Y} and point ${point2X} comma ${point2Y}.`,srLinearSystemIntersection:({x,y})=>`Line 1 and line 2 intersect at point ${x} comma ${y}.`,srLinearSystemParallel:"Line 1 and line 2 are parallel.",srRayGraph:"A ray on a coordinate plane.",srRayPoints:({point1X,point1Y,point2X,point2Y})=>`The endpoint is at ${point1X} comma ${point1Y} and the ray goes through point ${point2X} comma ${point2Y}.`,srRayGrabHandle:({point1X,point1Y,point2X,point2Y})=>`Ray with endpoint ${point1X} comma ${point1Y} going through point ${point2X} comma ${point2Y}.`,srRayEndpoint:({x,y})=>`Endpoint at ${x} comma ${y}.`,srRayTerminalPoint:({x,y})=>`Through point at ${x} comma ${y}.`,srQuadraticGraph:"A parabola on a 4-quadrant coordinate plane.",srQuadraticFaceUp:"The parabola opens upward.",srQuadraticFaceDown:"The parabola opens downward.",srQuadraticGraphVertexOrigin:"Vertex is at the origin.",srQuadraticGraphVertexXAxis:"Vertex is on the X-axis.",srQuadraticGraphVertexYAxis:"Vertex is on the Y-axis.",srQuadraticGraphVertexQuadrant:({quadrant})=>`Vertex is in quadrant ${quadrant}.`,srQuadraticTwoXIntercepts:({intercept1,intercept2})=>`The X-intercepts are at ${intercept1} comma 0 and ${intercept2} comma 0.`,srQuadraticOneXIntercept:({intercept})=>`The X-intercept is at ${intercept} comma 0.`,srQuadraticYIntercept:({intercept})=>`The Y-intercept is at 0 comma ${intercept}.`,srQuadraticPointOrigin:({pointNumber})=>`Point ${pointNumber} on parabola at the origin.`,srQuadraticPointAxis:({pointNumber,x,y})=>`Point ${pointNumber} on parabola at ${x} comma ${y}.`,srQuadraticPointQuadrant:({pointNumber,x,y,quadrant})=>`Point ${pointNumber} on parabola in quadrant ${quadrant} at ${x} comma ${y}.`,srQuadraticInteractiveElements:({point1X,point1Y,point2X,point2Y,point3X,point3Y})=>`Parabola with points at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, and ${point3X} comma ${point3Y}.`,srPolygonGraph:"A polygon.",srPolygonGraphCoordinatePlane:"A polygon on a coordinate plane.",srPolygonGraphPointsNum:({num})=>`The polygon has ${num} points.`,srPolygonGraphPointsOne:"The polygon has 1 point.",srPolygonElementsNum:({num})=>`A polygon with ${num} points.`,srPolygonElementsOne:"A polygon with 1 point.",srPolygonPointAngleApprox:({angle})=>`Angle approximately equal to ${angle} degrees.`,srPolygonPointAngle:({angle})=>`Angle equal to ${angle} degrees.`,srPolygonSideLength:({pointNum,length})=>`A line segment, length equal to ${length} units, connects to point ${pointNum}.`,srPolygonSideLengthApprox:({pointNum,length})=>`A line segment, length approximately equal to ${length} units, connects to point ${pointNum}.`,srUnlimitedPolygonEmpty:"An empty coordinate plane.",srSinusoidGraph:"A sinusoid function on a coordinate plane.",srSinusoidRootPoint:({x,y})=>`Midline intersection at ${x} comma ${y}.`,srSinusoidMaxPoint:({x,y})=>`Maximum point at ${x} comma ${y}.`,srSinusoidMinPoint:({x,y})=>`Minimum point at ${x} comma ${y}.`,srSinusoidFlatPoint:({x,y})=>`Line through point at ${x} comma ${y}.`,srSinusoidDescription:({minValue,maxValue,cycleStart,cycleEnd})=>`The graph shows a wave with a minimum value of ${minValue} and a maximum value of ${maxValue}. The wave completes a full cycle from ${cycleStart} to ${cycleEnd}.`,srSinusoidInteractiveElements:({point1X,point1Y,point2X,point2Y})=>`Sinusoid graph with midline intersection point at ${point1X} comma ${point1Y} and extremum point at ${point2X} comma ${point2Y}.`};const errorToString={MISSING_PERCENT_ERROR:"MISSING_PERCENT_ERROR",NEEDS_TO_BE_SIMPLIFIED_ERROR:"NEEDS_TO_BE_SIMPLFIED_ERROR",APPROXIMATED_PI_ERROR:"APPROXIMATED_PI_ERROR",EXTRA_SYMBOLS_ERROR:"EXTRA_SYMBOLS_ERROR",WRONG_CASE_ERROR:"WRONG_CASE_ERROR",WRONG_LETTER_ERROR:"WRONG_LETTER_ERROR",MULTIPLICATION_SIGN_ERROR:"MULTIPLICATION_SIGN_ERROR",INVALID_SELECTION_ERROR:"invalidSelection",CHOOSE_CORRECT_NUM_ERROR:"chooseCorrectNum",NOT_NONE_ABOVE_ERROR:"notNoneOfTheAbove",FILL_ALL_CELLS_ERROR:"fillAllCells",USER_INPUT_EMPTY:"USER_INPUT_EMPTY"};function mapErrorToString(err,translatedStrings){if(!err){return err}return translatedStrings[errorToString[err]]||err}
1414
1419
 
1415
1420
  const mockPerseusI18nContext={strings:mockStrings,locale:"en"};const PerseusI18nContext=React.createContext(process.env.NODE_ENV==="test"||process.env.STORYBOOK?mockPerseusI18nContext:null);function PerseusI18nContextProvider({children,strings,locale}){return jsxRuntimeExports.jsx(PerseusI18nContext.Provider,{value:{strings,locale},children:children})}const usePerseusI18n=()=>useContext(PerseusI18nContext);
1416
1421
 
@@ -1418,7 +1423,7 @@ var a11y = StyleSheet.create({srOnly:{border:0,clip:"rect(0,0,0,0)",height:1,mar
1418
1423
 
1419
1424
  const debounce=(func,delay)=>{let timer=null;return (...args)=>{if(timer){clearTimeout(timer);}timer=window.setTimeout(()=>{func(...args);},delay);}};
1420
1425
 
1421
- class InnerMathInput extends React.Component{componentDidMount(){this.mathField()?.latex(this.props.value);}openKeypad(){if(this.props.buttonsVisible==="never"){return}this.setState({keypadOpen:true});}closeKeypad(){this.setState({keypadOpen:false});}render(){let className=classNames$1({"perseus-math-input":true,"mq-editable-field":true,"mq-math-mode":true});const popoverContentUniqueId=v4().slice(0,8);if(this.props.className){className=className+" "+this.props.className;}return jsxRuntimeExports.jsx(View,{style:[styles$H.outerWrapper,this.state.focused&&styles$H.wrapperFocused,this.props.hasError&&styles$H.wrapperError],children:jsxRuntimeExports.jsxs("div",{style:{display:"flex",padding:1},onClick:e=>{e.stopPropagation();const mathField=this.mathField();if(!mathField){return}this.setState({cursorContext:getCursorContext(mathField)});},children:[jsxRuntimeExports.jsx("span",{className:className,ref:ref=>this.__mathFieldWrapperRef=ref,onFocus:()=>this.focus(),onBlur:()=>this.blur()}),jsxRuntimeExports.jsx(Popover,{opened:this.state.keypadOpen,dismissEnabled:true,rootBoundary:"document","aria-label":this.context.strings.mathInputTitle,"aria-describedby":`popover-content-${popoverContentUniqueId}`,content:()=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(HeadingMedium,{id:`popover-content-${popoverContentUniqueId}`,style:a11y.srOnly,children:this.context.strings.mathInputDescription}),jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$H.popoverContent,children:jsxRuntimeExports.jsx(DesktopKeypad,{onAnalyticsEvent:this.props.onAnalyticsEvent,extraKeys:this.props.extraKeys,onClickKey:this.handleKeypadPress,cursorContext:this.state.cursorContext,convertDotToTimes:this.props.convertDotToTimes,...this.props.keypadButtonSets??mapButtonSets(this.props?.buttonSets),showDismiss:true})})]}),children:this.props.buttonsVisible==="never"?jsxRuntimeExports.jsx(MathInputIcon,{hovered:false,focused:false,active:false}):jsxRuntimeExports.jsx(Clickable,{"aria-label":this.state.keypadOpen?this.context.strings.closeKeypad:this.context.strings.openKeypad,role:"button",onClick:()=>this.state.keypadOpen?this.closeKeypad():this.openKeypad(),children:props=>jsxRuntimeExports.jsx(MathInputIcon,{active:this.state.keypadOpen,...props})})})]})})}constructor(...args){super(...args),this.__mathFieldWrapperRef=null,this.__mathField=null,this.state={focused:false,keypadOpen:this.props.buttonsVisible==="always"?true:false,cursorContext:CursorContext.NONE},this.insert=value=>{const input=this.mathField();const{locale}=this.context;const customKeyTranslator={...getKeyTranslator(locale,this.context.strings),FRAC:mathQuill=>{const contents=mathQuill.latex();mathQuill.typedText("/");if(mathQuill.latex()===contents){mathQuill.cmd("\\frac");}}};const inputModifier=customKeyTranslator[value];if(inputModifier){inputModifier(input,value);input?.focus();return}if(_(value).isFunction()){value(input);}else if(value[0]==="\\"){input?.cmd(value).focus();}else {input?.write(value).focus();}input?.focus();},this.mathField=()=>{if(!this.__mathField&&this.__mathFieldWrapperRef){const{locale}=this.context;this.__mathField=createMathField(this.__mathFieldWrapperRef,locale,this.props.mathInputStrings,baseConfig=>({...baseConfig,handlers:{edit:debounce(mathField=>{let value=mathField.latex();value=value.replace(/<>/g,"\\ne");if(convertDotToTimesByLocale(locale,this.props.convertDotToTimes)){value=value.replace(/\\cdot/g,"\\times");const left=mathField.cursor()[mathQuillInstance.L];if(left&&left.ctrlSeq==="\\cdot "){mathField.controller().backspace();mathField.cmd("\\times");}}else {value=value.replace(/\\times/g,"\\cdot");}if(this.props.value!==value){this.props.onChange(value);}this.setState({cursorContext:getCursorContext(mathField)});},100),enter:()=>{if(this.__mathFieldWrapperRef){$(this.__mathFieldWrapperRef).submit();}},upOutOf:mathField=>{mathField.typedText("^");}}}));}this.__mathField?.setAriaLabel(this.props.ariaLabel);return this.__mathField},this.focus=()=>{this.mathField()?.focus();this.setState({focused:true});},this.blur=()=>this.setState({focused:false}),this.handleKeypadPress=(key,e)=>{const{locale}=this.context;const translator=getKeyTranslator(locale,this.context.strings)[key];const mathField=this.mathField();if(mathField){if(translator){translator(mathField,key);}this.setState({cursorContext:getCursorContext(mathField)});}if(e?.type==="click"){this.focus();}if(key==="DISMISS"){this.closeKeypad();}};}}InnerMathInput.contextType=PerseusI18nContext;InnerMathInput.defaultProps={value:"",convertDotToTimes:false};class MathInput extends React.Component{blur(){this.inputRef.current?.blur();}focus(){this.inputRef.current?.focus();}insert(value){this.inputRef.current?.insert(value);}render(){return jsxRuntimeExports.jsx(InnerMathInput,{...this.props,ref:this.inputRef,mathInputStrings:this.context.strings})}constructor(...args){super(...args),this.inputRef=React.createRef();}}MathInput.contextType=MathInputI18nContext;MathInput.defaultProps={ariaLabel:"Math input"};const MathInputIcon=({hovered,focused,active})=>{let fillColor;switch(true){case focused||active:fillColor=color.white;break;case hovered:fillColor=color.blue;break;default:fillColor=color.offBlack;break}const dynamicClass=active||focused?styles$H.iconActive:styles$H.iconInactive;return jsxRuntimeExports.jsx(View,{style:[styles$H.iconContainer,dynamicClass],children:jsxRuntimeExports.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",fill:fillColor,viewBox:"0 0 256 256",children:jsxRuntimeExports.jsx("path",{d:"M112,72a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16h64A8,8,0,0,1,112,72Zm-8,104H80V152a8,8,0,0,0-16,0v24H40a8,8,0,0,0,0,16H64v24a8,8,0,0,0,16,0V192h24a8,8,0,0,0,0-16Zm48,0h64a8,8,0,0,0,0-16H152a8,8,0,0,0,0,16Zm64,16H152a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm-61.66-90.34a8,8,0,0,0,11.32,0L184,83.31l18.34,18.35a8,8,0,0,0,11.32-11.32L195.31,72l18.35-18.34a8,8,0,0,0-11.32-11.32L184,60.69,165.66,42.34a8,8,0,0,0-11.32,11.32L172.69,72,154.34,90.34A8,8,0,0,0,154.34,101.66Z"})})})};const mapButtonSets=buttonSets=>{const keypadButtonSets={};if(!buttonSets){return keypadButtonSets}buttonSets.forEach(buttonSet=>{switch(buttonSet){case "advanced relations":keypadButtonSets.advancedRelations=true;break;case "basic relations":keypadButtonSets.basicRelations=true;break;case "basic+div":keypadButtonSets.divisionKey=true;break;case "logarithms":keypadButtonSets.logarithms=true;break;case "prealgebra":keypadButtonSets.preAlgebra=true;break;case "trig":keypadButtonSets.trigonometry=true;break;case "scientific":keypadButtonSets.scientific=true;break;}});return keypadButtonSets};const inputFocused={borderWidth:2,borderColor:color.blue,margin:-1};const styles$H=StyleSheet.create({iconContainer:{display:"flex",justifyContent:"center",height:"100%",padding:spacing.xxxSmall_4,borderRadius:1},iconInactive:{border:"2px solid transparent",backgroundColor:color.offBlack8},iconActive:{border:`2px solid ${color.white}`,backgroundColor:color.offBlack64},outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:color.offBlack50,borderRadius:3,background:color.white,":hover":inputFocused},wrapperFocused:inputFocused,wrapperError:{borderColor:color.red,background:color.fadedRed8,":hover":{borderColor:color.red}},popoverContent:{padding:0,paddingBottom:spacing.xxSmall_6,maxWidth:"initial"}});
1426
+ class InnerMathInput extends React.Component{componentDidMount(){this.mathField()?.latex(this.props.value);}openKeypad(){if(this.props.buttonsVisible==="never"){return}this.setState({keypadOpen:true});}closeKeypad(){this.setState({keypadOpen:false});}render(){let className=classNames$1({"perseus-math-input":true,"mq-editable-field":true,"mq-math-mode":true});const popoverContentUniqueId=v4().slice(0,8);if(this.props.className){className=className+" "+this.props.className;}return jsxRuntimeExports.jsx(View,{style:[styles$K.outerWrapper,this.state.focused&&styles$K.wrapperFocused,this.props.hasError&&styles$K.wrapperError],children:jsxRuntimeExports.jsxs("div",{style:{display:"flex",padding:1},onClick:e=>{e.stopPropagation();const mathField=this.mathField();if(!mathField){return}this.setState({cursorContext:getCursorContext(mathField)});},children:[jsxRuntimeExports.jsx("span",{className:className,ref:ref=>this.__mathFieldWrapperRef=ref,onFocus:()=>this.focus(),onBlur:()=>this.blur()}),jsxRuntimeExports.jsx(Popover,{opened:this.state.keypadOpen,dismissEnabled:true,rootBoundary:"document","aria-label":this.context.strings.mathInputTitle,"aria-describedby":`popover-content-${popoverContentUniqueId}`,content:()=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(HeadingMedium,{id:`popover-content-${popoverContentUniqueId}`,style:a11y.srOnly,children:this.context.strings.mathInputDescription}),jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$K.popoverContent,children:jsxRuntimeExports.jsx(DesktopKeypad,{onAnalyticsEvent:this.props.onAnalyticsEvent,extraKeys:this.props.extraKeys,onClickKey:this.handleKeypadPress,cursorContext:this.state.cursorContext,convertDotToTimes:this.props.convertDotToTimes,...this.props.keypadButtonSets??mapButtonSets(this.props?.buttonSets),showDismiss:true})})]}),children:this.props.buttonsVisible==="never"?jsxRuntimeExports.jsx(MathInputIcon,{hovered:false,focused:false,active:false}):jsxRuntimeExports.jsx(Clickable,{"aria-label":this.state.keypadOpen?this.context.strings.closeKeypad:this.context.strings.openKeypad,role:"button",onClick:()=>this.state.keypadOpen?this.closeKeypad():this.openKeypad(),children:props=>jsxRuntimeExports.jsx(MathInputIcon,{active:this.state.keypadOpen,...props})})})]})})}constructor(...args){super(...args),this.__mathFieldWrapperRef=null,this.__mathField=null,this.state={focused:false,keypadOpen:this.props.buttonsVisible==="always"?true:false,cursorContext:CursorContext.NONE},this.insert=value=>{const input=this.mathField();const{locale}=this.context;const customKeyTranslator={...getKeyTranslator(locale,this.context.strings),FRAC:mathQuill=>{const contents=mathQuill.latex();mathQuill.typedText("/");if(mathQuill.latex()===contents){mathQuill.cmd("\\frac");}}};const inputModifier=customKeyTranslator[value];if(inputModifier){inputModifier(input,value);input?.focus();return}if(_(value).isFunction()){value(input);}else if(value[0]==="\\"){input?.cmd(value).focus();}else {input?.write(value).focus();}input?.focus();},this.mathField=()=>{if(!this.__mathField&&this.__mathFieldWrapperRef){const{locale}=this.context;this.__mathField=createMathField(this.__mathFieldWrapperRef,locale,this.props.mathInputStrings,baseConfig=>({...baseConfig,handlers:{edit:debounce(mathField=>{let value=mathField.latex();value=value.replace(/<>/g,"\\ne");if(convertDotToTimesByLocale(locale,this.props.convertDotToTimes)){value=value.replace(/\\cdot/g,"\\times");const left=mathField.cursor()[mathQuillInstance.L];if(left&&left.ctrlSeq==="\\cdot "){mathField.controller().backspace();mathField.cmd("\\times");}}else {value=value.replace(/\\times/g,"\\cdot");}if(this.props.value!==value){this.props.onChange(value);}this.setState({cursorContext:getCursorContext(mathField)});},100),enter:()=>{if(this.__mathFieldWrapperRef){$(this.__mathFieldWrapperRef).submit();}},upOutOf:mathField=>{mathField.typedText("^");}}}));}this.__mathField?.setAriaLabel(this.props.ariaLabel);return this.__mathField},this.focus=()=>{this.mathField()?.focus();this.setState({focused:true});},this.blur=()=>this.setState({focused:false}),this.handleKeypadPress=(key,e)=>{const{locale}=this.context;const translator=getKeyTranslator(locale,this.context.strings)[key];const mathField=this.mathField();if(mathField){if(translator){translator(mathField,key);}this.setState({cursorContext:getCursorContext(mathField)});}if(e?.type==="click"){this.focus();}if(key==="DISMISS"){this.closeKeypad();}};}}InnerMathInput.contextType=PerseusI18nContext;InnerMathInput.defaultProps={value:"",convertDotToTimes:false};class MathInput extends React.Component{blur(){this.inputRef.current?.blur();}focus(){this.inputRef.current?.focus();}insert(value){this.inputRef.current?.insert(value);}render(){return jsxRuntimeExports.jsx(InnerMathInput,{...this.props,ref:this.inputRef,mathInputStrings:this.context.strings})}constructor(...args){super(...args),this.inputRef=React.createRef();}}MathInput.contextType=MathInputI18nContext;MathInput.defaultProps={ariaLabel:"Math input"};const MathInputIcon=({hovered,focused,active})=>{let fillColor;switch(true){case focused||active:fillColor=color.white;break;case hovered:fillColor=color.blue;break;default:fillColor=color.offBlack;break}const dynamicClass=active||focused?styles$K.iconActive:styles$K.iconInactive;return jsxRuntimeExports.jsx(View,{style:[styles$K.iconContainer,dynamicClass],children:jsxRuntimeExports.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",fill:fillColor,viewBox:"0 0 256 256",children:jsxRuntimeExports.jsx("path",{d:"M112,72a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16h64A8,8,0,0,1,112,72Zm-8,104H80V152a8,8,0,0,0-16,0v24H40a8,8,0,0,0,0,16H64v24a8,8,0,0,0,16,0V192h24a8,8,0,0,0,0-16Zm48,0h64a8,8,0,0,0,0-16H152a8,8,0,0,0,0,16Zm64,16H152a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm-61.66-90.34a8,8,0,0,0,11.32,0L184,83.31l18.34,18.35a8,8,0,0,0,11.32-11.32L195.31,72l18.35-18.34a8,8,0,0,0-11.32-11.32L184,60.69,165.66,42.34a8,8,0,0,0-11.32,11.32L172.69,72,154.34,90.34A8,8,0,0,0,154.34,101.66Z"})})})};const mapButtonSets=buttonSets=>{const keypadButtonSets={};if(!buttonSets){return keypadButtonSets}buttonSets.forEach(buttonSet=>{switch(buttonSet){case "advanced relations":keypadButtonSets.advancedRelations=true;break;case "basic relations":keypadButtonSets.basicRelations=true;break;case "basic+div":keypadButtonSets.divisionKey=true;break;case "logarithms":keypadButtonSets.logarithms=true;break;case "prealgebra":keypadButtonSets.preAlgebra=true;break;case "trig":keypadButtonSets.trigonometry=true;break;case "scientific":keypadButtonSets.scientific=true;break;}});return keypadButtonSets};const inputFocused={borderWidth:2,borderColor:color.blue,margin:-1};const styles$K=StyleSheet.create({iconContainer:{display:"flex",justifyContent:"center",height:"100%",padding:spacing.xxxSmall_4,borderRadius:1},iconInactive:{border:"2px solid transparent",backgroundColor:color.offBlack8},iconActive:{border:`2px solid ${color.white}`,backgroundColor:color.offBlack64},outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:color.offBlack50,borderRadius:3,background:color.white,":hover":inputFocused},wrapperFocused:inputFocused,wrapperError:{borderColor:color.red,background:color.fadedRed8,":hover":{borderColor:color.red}},popoverContent:{padding:0,paddingBottom:spacing.xxSmall_6,maxWidth:"initial"}});
1422
1427
 
1423
1428
  let _dependencies=null;const setDependencies=dependencies=>{_dependencies=dependencies;};const getDependencies=()=>{if(_dependencies){return _dependencies}throw new Error(["Perseus has not been provided required dependencies.","setDependencies(dependencies) must be called first.","Make sure Perseus is being imported from javascript/perseus/perseus.js."].join("\n"))};const DependenciesContext=React.createContext({analytics:{onAnalyticsEvent:async()=>{}},useVideo:()=>{throw new Error("useVideo dependency not provided in Perseus dependencies")}});const useDependencies=()=>{const deps=React.useContext(DependenciesContext);return deps};
1424
1429
 
@@ -1444,11 +1449,11 @@ const textWidthCache={};function getTextWidth(text){if(!textWidthCache[text]){co
1444
1449
 
1445
1450
  const EMPTY_ARRAY=[];class StubTagEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{children:[this.props.showTitle&&jsxRuntimeExports.jsx("div",{style:{fontSize:14},children:"Tags:"}),jsxRuntimeExports.jsx(TextListEditor,{options:this.props.value||EMPTY_ARRAY,layout:"vertical",onChange:this.props.onChange})]})}}StubTagEditor.propTypes={value:PropTypes.arrayOf(PropTypes.string),onChange:PropTypes.func.isRequired,showTitle:PropTypes.bool.isRequired};StubTagEditor.defaultProps={value:EMPTY_ARRAY,showTitle:true};
1446
1451
 
1447
- const ApiOptions={propTypes:PropTypes.shape({isArticle:PropTypes.bool.isRequired,onFocusChange:PropTypes.func.isRequired,GroupMetadataEditor:PropTypes.func.isRequired,showAlignmentOptions:PropTypes.bool.isRequired,readOnly:PropTypes.bool.isRequired,answerableCallback:PropTypes.func,getAnotherHint:PropTypes.func,interactionCallback:PropTypes.func,groupAnnotator:PropTypes.func.isRequired,imagePlaceholder:PropTypes.node,widgetPlaceholder:PropTypes.node,baseElements:PropTypes.shape({Link:PropTypes.func}),imagePreloader:PropTypes.func,trackInteraction:PropTypes.func,customKeypad:PropTypes.bool,nativeKeypadProxy:PropTypes.func,isMobile:PropTypes.bool,setDrawingAreaAvailable:PropTypes.func,hintProgressColor:PropTypes.string,canScrollPage:PropTypes.bool,crossOutEnabled:PropTypes.bool,editorChangeDelay:PropTypes.number}).isRequired,defaults:{isArticle:false,isMobile:false,onFocusChange:function(){},GroupMetadataEditor:StubTagEditor,showAlignmentOptions:false,readOnly:false,groupAnnotator:function(){return null},baseElements:{Link:props=>{return jsxRuntimeExports.jsx("a",{...props})}},setDrawingAreaAvailable:function(){},canScrollPage:false,crossOutEnabled:false,editorChangeDelay:0}};const ClassNames={RENDERER:"perseus-renderer",TWO_COLUMN_RENDERER:"perseus-renderer-two-columns",RESPONSIVE_RENDERER:"perseus-renderer-responsive",INPUT:"perseus-input",FOCUSED:"perseus-focused",RADIO:{OPTION:"perseus-radio-option",SELECTED:"perseus-radio-selected",OPTION_CONTENT:"perseus-radio-option-content"},CORRECT:"perseus-correct",INCORRECT:"perseus-incorrect",UNANSWERED:"perseus-unanswered",MOBILE:"perseus-mobile"};
1452
+ const ApiOptions={propTypes:PropTypes.shape({isArticle:PropTypes.bool.isRequired,onFocusChange:PropTypes.func.isRequired,GroupMetadataEditor:PropTypes.func.isRequired,showAlignmentOptions:PropTypes.bool.isRequired,readOnly:PropTypes.bool.isRequired,answerableCallback:PropTypes.func,getAnotherHint:PropTypes.func,interactionCallback:PropTypes.func,groupAnnotator:PropTypes.func.isRequired,imagePlaceholder:PropTypes.node,widgetPlaceholder:PropTypes.node,baseElements:PropTypes.shape({Link:PropTypes.func}),imagePreloader:PropTypes.func,trackInteraction:PropTypes.func,customKeypad:PropTypes.bool,nativeKeypadProxy:PropTypes.func,isMobile:PropTypes.bool,isMobileApp:PropTypes.bool,setDrawingAreaAvailable:PropTypes.func,hintProgressColor:PropTypes.string,canScrollPage:PropTypes.bool,crossOutEnabled:PropTypes.bool,editorChangeDelay:PropTypes.number}).isRequired,defaults:{isArticle:false,isMobile:false,isMobileApp:false,onFocusChange:function(){},GroupMetadataEditor:StubTagEditor,showAlignmentOptions:false,readOnly:false,groupAnnotator:function(){return null},baseElements:{Link:props=>{return jsxRuntimeExports.jsx("a",{...props})}},setDrawingAreaAvailable:function(){},canScrollPage:false,crossOutEnabled:false,editorChangeDelay:0}};const ClassNames={RENDERER:"perseus-renderer",TWO_COLUMN_RENDERER:"perseus-renderer-two-columns",RESPONSIVE_RENDERER:"perseus-renderer-responsive",INPUT:"perseus-input",FOCUSED:"perseus-focused",RADIO:{OPTION:"perseus-radio-option",SELECTED:"perseus-radio-selected",OPTION_CONTENT:"perseus-radio-option-content"},CORRECT:"perseus-correct",INCORRECT:"perseus-incorrect",UNANSWERED:"perseus-unanswered",MOBILE:"perseus-mobile"};
1448
1453
 
1449
1454
  const getPromptJSON$t=(renderProps,userInput)=>{return {type:"expression",label:renderProps.visibleLabel,userInput:{value:userInput}}};
1450
1455
 
1451
- const englishOperators={arctg:"arctan",cosec:"csc",cossec:"csc",cotg:"cot",ctg:"cot",sen:"sin",tg:"tan"};const anglicizeOperators=tex=>{return tex.replace(/\\operatorname{([a-z]+)}/g,(_,op)=>`\\${englishOperators[op]??op} `)};const normalizeTex=tex=>{return anglicizeOperators(tex)};class Expression extends React.Component{static getUserInputFromProps(props){return normalizeTex(props.value)}getUserInput(){return Expression.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$t(this.props,this.getUserInput())}focusInputPath(inputPath){this.refs.input.focus();}blurInputPath(inputPath){if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}}insert(keyPressed){this.refs.input.insert(keyPressed);}setInputValue(path,newValue,cb){this.props.onChange({value:newValue},cb);}render(){if(this.props.apiOptions.customKeypad){return jsxRuntimeExports.jsxs(View,{className:css(styles$G.mobileLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsx(KeypadInput,{ref:"input",ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,value:this.props.value,keypadElement:this.props.keypadElement,onChange:this.changeAndTrack,onFocus:()=>{this.props.keypadElement?.configure(this.props.keypadConfiguration,()=>{if(this._isMounted){this._handleFocus();}});},onBlur:this._handleBlur})]})}const className=classNames$1({"perseus-widget-expression":true,"show-error-tooltip":this.state.showErrorTooltip});const{ERROR_MESSAGE,ERROR_TITLE}=this.context.strings;return jsxRuntimeExports.jsxs(View,{className:css(styles$G.desktopLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsxs("div",{className:className,onBlur:()=>this.state.invalid&&this.setState({showErrorTooltip:true,showErrorStyle:true}),onFocus:()=>this.setState({showErrorTooltip:false}),children:[jsxRuntimeExports.jsx(View,{style:a11y.srOnly,role:"alert",children:this.state.showErrorTooltip&&ERROR_TITLE+" "+ERROR_MESSAGE}),jsxRuntimeExports.jsx(Tooltip,{forceAnchorFocusivity:false,opened:this.state.showErrorTooltip,title:ERROR_TITLE,content:ERROR_MESSAGE,children:jsxRuntimeExports.jsx(MathInput,{ref:"input",value:this.props.value,onChange:this.changeAndTrack,convertDotToTimes:this.props.times,buttonSets:this.props.buttonSets,onFocus:this._handleFocus,onBlur:this._handleBlur,hasError:this.state.showErrorStyle,ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,extraKeys:this.props.keypadConfiguration?.extraKeys,onAnalyticsEvent:this.props.analytics?.onAnalyticsEvent??(async()=>{})})})]})]})}constructor(...args){super(...args),this._textareaId=`expression_textarea_${Date.now()}`,this._isMounted=false,this.displayName="Expression",this.state={invalid:false,showErrorTooltip:false,showErrorStyle:false},this.componentDidMount=()=>{document.addEventListener("mousedown",this._handleMouseDown);this._isMounted=true;if(this.refs.input){const isMobile=this.props.apiOptions.customKeypad;const container=ReactDOM__default.findDOMNode(this.refs.input);const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=container.querySelector(selector);inputElement?.setAttribute("id",this._textareaId);}},this.componentDidUpdate=prevProps=>{if(!_.isEqual(this.props.value,prevProps.value)||!_.isEqual(this.props.functions,prevProps.functions)){this.setState({invalid:false,showErrorTooltip:false,showErrorStyle:false});if(!this.parse(this.props.value,this.props).parsed){this.setState({invalid:true});}}},this.componentWillUnmount=()=>{this._isMounted=false;},this._handleMouseDown=()=>{if(this._isMounted&&this.state.showErrorTooltip){this.setState({showErrorTooltip:false});}},this.change=(...args)=>{return change.apply(this,args)},this.parse=(value,props)=>{const options=_.pick(props||this.props,"functions");_.extend(options,{decimal_separator:getDecimalSeparator(this.context.locale)});return KAS.parse(normalizeTex(value),options)},this.changeAndTrack=(e,cb)=>{this.change("value",e,cb);this.props.trackInteraction();},this._handleFocus=()=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{if(this.props.apiOptions.customKeypad){this.refs.input.focus();}return true},this.getInputPaths=()=>{return [[]]};}}Expression.contextType=PerseusI18nContext;Expression.defaultProps={value:"",times:false,functions:[],buttonSets:["basic","trig","prealgebra","logarithms"],onFocus:()=>{},onBlur:()=>{},apiOptions:ApiOptions.defaults,linterContext:linterContextDefault};const styles$G=StyleSheet.create({mobileLabelInputWrapper:{padding:"15px 4px 0"},desktopLabelInputWrapper:{margin:"5px 5px 0"}});const ExpressionWithDependencies=React.forwardRef((props,ref)=>{const deps=useDependencies();return jsxRuntimeExports.jsx(Expression,{ref:ref,analytics:deps.analytics,...props})});ExpressionWithDependencies.getUserInputFromProps=Expression.getUserInputFromProps;var Expression$1 = {name:"expression",displayName:"Expression / Equation",accessible:true,widget:ExpressionWithDependencies,transform:widgetOptions=>{const{times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel,extraKeys}=widgetOptions;return {keypadConfiguration:{keypadType:"EXPRESSION",extraKeys,times},times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel}},version:expressionLogic.version,propUpgrades:expressionLogic.widgetOptionsUpgrades,isLintable:true,getOneCorrectAnswerFromRubric(rubric){const correctAnswers=(rubric.answerForms||[]).filter(answerForm=>answerForm.considered==="correct");if(correctAnswers.length===0){return}return correctAnswers[0].value}};
1456
+ const englishOperators={arctg:"arctan",cosec:"csc",cossec:"csc",cotg:"cot",ctg:"cot",sen:"sin",tg:"tan"};const anglicizeOperators=tex=>{return tex.replace(/\\operatorname{([a-z]+)}/g,(_,op)=>`\\${englishOperators[op]??op} `)};const normalizeTex=tex=>{return anglicizeOperators(tex)};class Expression extends React.Component{static getUserInputFromProps(props){return normalizeTex(props.value)}getUserInput(){return Expression.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$t(this.props,this.getUserInput())}focusInputPath(inputPath){this.refs.input.focus();}blurInputPath(inputPath){if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}}insert(keyPressed){this.refs.input.insert(keyPressed);}setInputValue(path,newValue,cb){this.props.onChange({value:newValue},cb);}render(){if(this.props.apiOptions.customKeypad){return jsxRuntimeExports.jsxs(View,{className:css(styles$J.mobileLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsx(KeypadInput,{ref:"input",ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,value:this.props.value,keypadElement:this.props.keypadElement,onChange:this.changeAndTrack,onFocus:()=>{this.props.keypadElement?.configure(this.props.keypadConfiguration,()=>{if(this._isMounted){this._handleFocus();}});},onBlur:this._handleBlur})]})}const className=classNames$1({"perseus-widget-expression":true,"show-error-tooltip":this.state.showErrorTooltip});const{ERROR_MESSAGE,ERROR_TITLE}=this.context.strings;return jsxRuntimeExports.jsxs(View,{className:css(styles$J.desktopLabelInputWrapper),children:[!!this.props.visibleLabel&&jsxRuntimeExports.jsx(LabelSmall,{htmlFor:this._textareaId,tag:"label",children:this.props.visibleLabel}),jsxRuntimeExports.jsxs("div",{className:className,onBlur:()=>this.state.invalid&&this.setState({showErrorTooltip:true,showErrorStyle:true}),onFocus:()=>this.setState({showErrorTooltip:false}),children:[jsxRuntimeExports.jsx(View,{style:a11y.srOnly,role:"alert",children:this.state.showErrorTooltip&&ERROR_TITLE+" "+ERROR_MESSAGE}),jsxRuntimeExports.jsx(Tooltip,{forceAnchorFocusivity:false,opened:this.state.showErrorTooltip,title:ERROR_TITLE,content:ERROR_MESSAGE,children:jsxRuntimeExports.jsx(MathInput,{ref:"input",value:this.props.value,onChange:this.changeAndTrack,convertDotToTimes:this.props.times,buttonSets:this.props.buttonSets,onFocus:this._handleFocus,onBlur:this._handleBlur,hasError:this.state.showErrorStyle,ariaLabel:this.props.ariaLabel||this.context.strings.mathInputBox,extraKeys:this.props.keypadConfiguration?.extraKeys,onAnalyticsEvent:this.props.analytics?.onAnalyticsEvent??(async()=>{})})})]})]})}constructor(...args){super(...args),this._textareaId=`expression_textarea_${Date.now()}`,this._isMounted=false,this.displayName="Expression",this.state={invalid:false,showErrorTooltip:false,showErrorStyle:false},this.componentDidMount=()=>{document.addEventListener("mousedown",this._handleMouseDown);this._isMounted=true;if(this.refs.input){const isMobile=this.props.apiOptions.customKeypad;const container=ReactDOM__default.findDOMNode(this.refs.input);const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=container.querySelector(selector);inputElement?.setAttribute("id",this._textareaId);}},this.componentDidUpdate=prevProps=>{if(!_.isEqual(this.props.value,prevProps.value)||!_.isEqual(this.props.functions,prevProps.functions)){this.setState({invalid:false,showErrorTooltip:false,showErrorStyle:false});if(!this.parse(this.props.value,this.props).parsed){this.setState({invalid:true});}}},this.componentWillUnmount=()=>{this._isMounted=false;},this._handleMouseDown=()=>{if(this._isMounted&&this.state.showErrorTooltip){this.setState({showErrorTooltip:false});}},this.change=(...args)=>{return change.apply(this,args)},this.parse=(value,props)=>{const options=_.pick(props||this.props,"functions");_.extend(options,{decimal_separator:getDecimalSeparator(this.context.locale)});return KAS.parse(normalizeTex(value),options)},this.changeAndTrack=(e,cb)=>{this.change("value",e,cb);this.props.trackInteraction();},this._handleFocus=()=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{if(this.props.apiOptions.customKeypad){this.refs.input.focus();}return true},this.getInputPaths=()=>{return [[]]};}}Expression.contextType=PerseusI18nContext;Expression.defaultProps={value:"",times:false,functions:[],buttonSets:["basic","trig","prealgebra","logarithms"],onFocus:()=>{},onBlur:()=>{},apiOptions:ApiOptions.defaults,linterContext:linterContextDefault};const styles$J=StyleSheet.create({mobileLabelInputWrapper:{padding:"15px 4px 0"},desktopLabelInputWrapper:{margin:"5px 5px 0"}});const ExpressionWithDependencies=React.forwardRef((props,ref)=>{const deps=useDependencies();return jsxRuntimeExports.jsx(Expression,{ref:ref,analytics:deps.analytics,...props})});ExpressionWithDependencies.getUserInputFromProps=Expression.getUserInputFromProps;var Expression$1 = {name:"expression",displayName:"Expression / Equation",accessible:true,widget:ExpressionWithDependencies,transform:widgetOptions=>{const{times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel,extraKeys}=widgetOptions;return {keypadConfiguration:{keypadType:"EXPRESSION",extraKeys,times},times,functions,buttonSets,buttonsVisible,visibleLabel,ariaLabel}},version:expressionLogic.version,propUpgrades:expressionLogic.widgetOptionsUpgrades,isLintable:true,getOneCorrectAnswerFromRubric(rubric){const correctAnswers=(rubric.answerForms||[]).filter(answerForm=>answerForm.considered==="correct");if(correctAnswers.length===0){return}return correctAnswers[0].value}};
1452
1457
 
1453
1458
  class SimpleKeypadInput extends React.Component{componentDidMount(){this._isMounted=true;}componentWillUnmount(){this._isMounted=false;}focus(){this.inputRef.current?.focus(this.context.setKeypadActive);}blur(){this.inputRef.current?.blur();}getValue(){return this.props.value}render(){const _this=this;const{keypadElement,onFocus,value,...rest}=_this.props;return jsxRuntimeExports.jsx(KeypadInput,{ref:this.inputRef,keypadElement:keypadElement,onFocus:()=>{if(keypadElement){keypadElement.configure({keypadType:"FRACTION"},()=>{if(_this._isMounted){onFocus?.();}});}else {onFocus?.();}},value:value==null?"":""+value,...rest})}constructor(...args){super(...args),this._isMounted=false,this.inputRef=React.createRef();}}SimpleKeypadInput.contextType=KeypadContext;SimpleKeypadInput.propTypes={keypadElement:keypadElementPropType,onFocus:PropTypes.func,value:PropTypes.oneOfType([PropTypes.string,PropTypes.number])};
1454
1459
 
@@ -1646,7 +1651,7 @@ function _noop(){}class InteractionTracker{constructor(trackApi,widgetType,widge
1646
1651
 
1647
1652
  const arrayRules={fence:{match:SimpleMarkdown.defaultRules.fence.match,order:1,parse:(capture,state,parse)=>({type:"codeBlock",lang:capture[2]||undefined,content:capture[3]})},paragraph:{match:SimpleMarkdown.defaultRules.paragraph.match,order:2,parse:(capture,state,parse)=>({content:capture[1]})}};const builtArrayParser=SimpleMarkdown.parserFor(arrayRules);const parseToArray=source=>{const paragraphedSource=source.replace(/^\n\s*\n/,"")+"\n\n";return builtArrayParser(paragraphedSource,{inline:false}).map(c=>{return c["content"]})};const joinFromArray=paragraphs=>paragraphs.join("\n\n");var JiptParagraphs = {parseToArray:parseToArray,joinFromArray:joinFromArray};
1648
1653
 
1649
- const exclamationIcon={path:"M6 11a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0-9a1 1 0 0 1 1 1v4a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1z",height:12,width:12};class Lint extends React.Component{componentDidMount(){this._positionTimeout=window.setTimeout(this.getPosition);}componentWillUnmount(){window.clearTimeout(this._positionTimeout);}render(){const{children,inline,blockHighlight,insideTable}=this.props;if(insideTable){if(inline){return jsxRuntimeExports.jsx("span",{"data-lint-inside-table":"true",children:children})}return jsxRuntimeExports.jsx("div",{"data-lint-inside-table":"true",children:children})}if(blockHighlight){return jsxRuntimeExports.jsxs("span",{className:css(styles$F.lintContainer,styles$F.lintContainerBlock),children:[this.renderLink(styles$F.radioWidgetHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}if(inline){return jsxRuntimeExports.jsxs("span",{className:css(styles$F.lintContainer),children:[this.renderLink(styles$F.inlineHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}return jsxRuntimeExports.jsxs("div",{className:css(styles$F.lintContainer),children:[this.renderLink(styles$F.hoverTarget),jsxRuntimeExports.jsx("div",{children:children})]})}constructor(...args){super(...args),this.state={tooltipAbove:true},this.getPosition=()=>{const rect=ReactDOM__default.findDOMNode(this).getBoundingClientRect();this.setState({tooltipAbove:rect.top>100});},this.renderLink=style=>{const tooltipAbove=this.state.tooltipAbove;let severityStyle;let warningText;let warningTextStyle;if(this.props.severity===1){severityStyle=styles$F.indicatorError;warningText="Error";warningTextStyle=styles$F.publishBlockingError;}else if(this.props.severity===2){severityStyle=styles$F.indicatorWarning;warningText="Warning";warningTextStyle=styles$F.warning;}else {severityStyle=styles$F.indicatorGuideline;warningText="Recommendation";warningTextStyle=styles$F.warning;}return jsxRuntimeExports.jsxs("a",{href:`https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,target:"lint-help-window",className:css(style),children:[jsxRuntimeExports.jsx("span",{className:css(styles$F.indicator,severityStyle),children:this.props.severity===1&&jsxRuntimeExports.jsx(InlineIcon,{...exclamationIcon})}),jsxRuntimeExports.jsxs("div",{className:css(styles$F.tooltip,tooltipAbove&&styles$F.tooltipAbove),children:[this.props.message.split("\n\n").map((m,i)=>jsxRuntimeExports.jsxs("p",{className:css(styles$F.tooltipParagraph),children:[jsxRuntimeExports.jsxs("span",{className:css(warningTextStyle),children:[warningText,":"," "]}),m]},i)),jsxRuntimeExports.jsx("div",{className:css(styles$F.tail,tooltipAbove&&styles$F.tailAbove)})]})]})};}}const styles$F=StyleSheet.create({lintContainer:{position:"relative"},lintContainerBlock:{display:"block"},hoverTarget:{position:"absolute",top:0,right:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ div":{outline:"1px solid "+warningColor},":hover ~ div div[data-lint-inside-table]":{outline:"1px solid "+warningColor},":hover ~ div span[data-lint-inside-table]":{backgroundColor:warningColor,color:white}},inlineHoverTarget:{float:"right",position:"relative",marginRight:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ span":{backgroundColor:warningColor,color:white}},radioWidgetHoverTarget:{position:"absolute",left:-40,display:"block",width:24,height:24,minWidth:264,":hover > span":{backgroundColor:warningColorHover},":hover > div":{display:"block",padding:8,width:280},":hover > div > div":{left:8},":hover ~ span":{backgroundColor:warningColor,color:white}},indicator:{alignItems:"center",borderRadius:4,color:"white",display:"flex",fontSize:12,height:8,justifyContent:"center",margin:8,width:8},indicatorError:{backgroundColor:"#be2612",borderRadius:8,height:16,width:16},indicatorWarning:{backgroundColor:"#f86700"},indicatorGuideline:{backgroundColor:"#ffbe26"},tooltip:{position:"absolute",right:-12,display:"none",zIndex:1e3,color:white,backgroundColor:gray17,opacity:.9,fontFamily:baseFontFamily,fontSize:"12px",lineHeight:"15px",width:"320px",borderRadius:"4px"},tooltipAbove:{bottom:32},tail:{position:"absolute",top:-12,right:16,width:0,height:0,borderLeft:"8px solid transparent",borderRight:"8px solid transparent",borderBottom:"12px solid "+gray17},tailAbove:{bottom:-12,borderBottom:"none",borderTop:"12px solid "+gray17,top:"auto"},tooltipParagraph:{margin:12},warning:{color:warningColor,fontFamily:boldFontFamily},publishBlockingError:{color:publishBlockingErrorColor}});
1654
+ const exclamationIcon={path:"M6 11a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0-9a1 1 0 0 1 1 1v4a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1z",height:12,width:12};class Lint extends React.Component{componentDidMount(){this._positionTimeout=window.setTimeout(this.getPosition);}componentWillUnmount(){window.clearTimeout(this._positionTimeout);}render(){const{children,inline,blockHighlight,insideTable}=this.props;if(insideTable){if(inline){return jsxRuntimeExports.jsx("span",{"data-lint-inside-table":"true",children:children})}return jsxRuntimeExports.jsx("div",{"data-lint-inside-table":"true",children:children})}if(blockHighlight){return jsxRuntimeExports.jsxs("span",{className:css(styles$I.lintContainer,styles$I.lintContainerBlock),children:[this.renderLink(styles$I.radioWidgetHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}if(inline){return jsxRuntimeExports.jsxs("span",{className:css(styles$I.lintContainer),children:[this.renderLink(styles$I.inlineHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}return jsxRuntimeExports.jsxs("div",{className:css(styles$I.lintContainer),children:[this.renderLink(styles$I.hoverTarget),jsxRuntimeExports.jsx("div",{children:children})]})}constructor(...args){super(...args),this.state={tooltipAbove:true},this.getPosition=()=>{const rect=ReactDOM__default.findDOMNode(this).getBoundingClientRect();this.setState({tooltipAbove:rect.top>100});},this.renderLink=style=>{const tooltipAbove=this.state.tooltipAbove;let severityStyle;let warningText;let warningTextStyle;if(this.props.severity===1){severityStyle=styles$I.indicatorError;warningText="Error";warningTextStyle=styles$I.publishBlockingError;}else if(this.props.severity===2){severityStyle=styles$I.indicatorWarning;warningText="Warning";warningTextStyle=styles$I.warning;}else {severityStyle=styles$I.indicatorGuideline;warningText="Recommendation";warningTextStyle=styles$I.warning;}return jsxRuntimeExports.jsxs("a",{href:`https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,target:"lint-help-window",className:css(style),children:[jsxRuntimeExports.jsx("span",{className:css(styles$I.indicator,severityStyle),children:this.props.severity===1&&jsxRuntimeExports.jsx(InlineIcon,{...exclamationIcon})}),jsxRuntimeExports.jsxs("div",{className:css(styles$I.tooltip,tooltipAbove&&styles$I.tooltipAbove),children:[this.props.message.split("\n\n").map((m,i)=>jsxRuntimeExports.jsxs("p",{className:css(styles$I.tooltipParagraph),children:[jsxRuntimeExports.jsxs("span",{className:css(warningTextStyle),children:[warningText,":"," "]}),m]},i)),jsxRuntimeExports.jsx("div",{className:css(styles$I.tail,tooltipAbove&&styles$I.tailAbove)})]})]})};}}const styles$I=StyleSheet.create({lintContainer:{position:"relative"},lintContainerBlock:{display:"block"},hoverTarget:{position:"absolute",top:0,right:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ div":{outline:"1px solid "+warningColor},":hover ~ div div[data-lint-inside-table]":{outline:"1px solid "+warningColor},":hover ~ div span[data-lint-inside-table]":{backgroundColor:warningColor,color:white}},inlineHoverTarget:{float:"right",position:"relative",marginRight:-40,display:"block",width:24,height:24,":hover > span":{backgroundColor:warningColorHover},":hover div":{display:"block"},":hover ~ span":{backgroundColor:warningColor,color:white}},radioWidgetHoverTarget:{position:"absolute",left:-40,display:"block",width:24,height:24,minWidth:264,":hover > span":{backgroundColor:warningColorHover},":hover > div":{display:"block",padding:8,width:280},":hover > div > div":{left:8},":hover ~ span":{backgroundColor:warningColor,color:white}},indicator:{alignItems:"center",borderRadius:4,color:"white",display:"flex",fontSize:12,height:8,justifyContent:"center",margin:8,width:8},indicatorError:{backgroundColor:"#be2612",borderRadius:8,height:16,width:16},indicatorWarning:{backgroundColor:"#f86700"},indicatorGuideline:{backgroundColor:"#ffbe26"},tooltip:{position:"absolute",right:-12,display:"none",zIndex:1e3,color:white,backgroundColor:gray17,opacity:.9,fontFamily:baseFontFamily,fontSize:"12px",lineHeight:"15px",width:"320px",borderRadius:"4px"},tooltipAbove:{bottom:32},tail:{position:"absolute",top:-12,right:16,width:0,height:0,borderLeft:"8px solid transparent",borderRight:"8px solid transparent",borderBottom:"12px solid "+gray17},tailAbove:{bottom:-12,borderBottom:"none",borderTop:"12px solid "+gray17,top:"auto"},tooltipParagraph:{margin:12},warning:{color:warningColor,fontFamily:boldFontFamily},publishBlockingError:{color:publishBlockingErrorColor}});
1650
1655
 
1651
1656
  const rules$1={...pureMarkdownRules,columns:{...pureMarkdownRules.columns,react:(node,output,state)=>{return jsxRuntimeExports.jsxs("div",{className:"perseus-two-columns",children:[jsxRuntimeExports.jsx("div",{className:"perseus-column",children:jsxRuntimeExports.jsx("div",{className:"perseus-column-content",children:output(node.col1,state)})}),jsxRuntimeExports.jsx("div",{className:"perseus-column",children:jsxRuntimeExports.jsx("div",{className:"perseus-column-content",children:output(node.col2,state)})})]},state.key)}},crowdinId:{...pureMarkdownRules.crowdinId,react:(node,output,state)=>node.id},table:{...pureMarkdownRules.table,react:function(node,output,state){const table=SimpleMarkdown.defaultRules.table.react(node,output,state);if(!state.isMobile){return table}return React.cloneElement(table,{tabIndex:0})}},titledTable:{...pureMarkdownRules.titledTable,react:(node,output,state)=>{let contents;if(!node.table){contents="//invalid table//";}else if(node.table.type==="lint"){if(node.table.content?.type==="table"){contents=rules$1.lint.react({...node.table,content:{...node,table:node.table.content}},output,{...state,unwrapTitledTableContents:true});}else {contents=rules$1.lint.react(node.table,output,state);}}else {const tableOutput=SimpleMarkdown.defaultRules.table.react(node.table,output,state);const caption=jsxRuntimeExports.jsx("caption",{className:"perseus-table-title",children:output(node.title,state)},"caption");contents=React.cloneElement(tableOutput,null,[caption,...tableOutput.props.children]);}if(state.unwrapTitledTableContents){return contents}return jsxRuntimeExports.jsx("div",{className:"perseus-titled-table",children:contents},state.key)}},widget:{...pureMarkdownRules.widget,react:(node,output,state)=>{return jsxRuntimeExports.jsx("em",{children:`[Widget: ${node.id}]`},state.key)}},blockMath:{...pureMarkdownRules.blockMath,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},math:{...pureMarkdownRules.math,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},unescapedDollar:{...pureMarkdownRules.unescapedDollar,react:(node,output,state)=>{return "$"}},link:{...pureMarkdownRules.link,react:function(node,output,state){const link=SimpleMarkdown.defaultRules.link.react(node,output,state);const href=link.props.href;let rel=null;const isKAUrl=href?href.match(/https?:\/\/[^/]*khanacademy.org|^\//):false;if(!isKAUrl){rel="noopener noreferrer";}const newProps={...link.props,target:"_blank",href,rel};if(state.baseElements&&state.baseElements.Link){return state.baseElements.Link(newProps)}return React.cloneElement(link,newProps)}},codeBlock:{...pureMarkdownRules.codeBlock,react:(node,output,state)=>{if(node.lang==="alt"){return jsxRuntimeExports.jsx("div",{className:"perseus-markdown-alt perseus-sr-only",children:output(node.content,state)},state.key)}return SimpleMarkdown.defaultRules.codeBlock.react(node,output,state)}},lint:{...pureMarkdownRules.lint,react:(node,output,state)=>{return jsxRuntimeExports.jsx(Lint,{message:node.message,ruleName:node.ruleName,inline:isInline(node.content),blockHighlight:node.blockHighlight,insideTable:node.insideTable,severity:node.severity,children:output(node.content,state)})}}};function isInline(node){return !!(node&&node.type&&inlineNodeTypes.hasOwnProperty(node.type))}const inlineNodeTypes={text:true,math:true,unescapedDollar:true,link:true,img:true,strong:true,u:true,em:true,del:true,code:true};const builtParser$1=SimpleMarkdown.parserFor(rules$1);const parse$3=(source,state)=>{const paragraphedSource=source+"\n\n";return builtParser$1(paragraphedSource,{...state,inline:false})};const inlineParser=(source,state)=>{return builtParser$1(source,{...state,inline:true})};const traverseContent=(ast,cb)=>{if(_.isArray(ast)){_.each(ast,node=>traverseContent(node,cb));}else if(_.isObject(ast)){cb(ast);if(ast.type==="table"){traverseContent(ast.header,cb);traverseContent(ast.cells,cb);}else if(ast.type==="list"){traverseContent(ast.items,cb);}else if(ast.type==="titledTable"){traverseContent(ast.table,cb);}else if(ast.type==="columns"){traverseContent(ast.col1,cb);traverseContent(ast.col2,cb);}else if(_.isArray(ast.content)){traverseContent(ast.content,cb);}}};const getContent=ast=>{if(_.isArray(ast)){return _.flatten(_.map(ast,getContent))}if(ast.content&&_.isString(ast.content)){if(ast.type.toLowerCase().indexOf("code")!==-1){return ["",ast.content,""]}return [ast.content.replace(/\s+/g," ")]}const children=_.chain(ast).values().flatten().filter(object=>object!=null&&_.has(object,"type")).value();if(!children.length){return []}const nestedContent=getContent(children);if(ast.type==="paragraph"&&nestedContent.length){nestedContent[0]=nestedContent[0].replace(/^\s+/,"");const last=nestedContent.length-1;nestedContent[last]=nestedContent[last].replace(/\s+$/,"");}return nestedContent};const characterCount=source=>{const ast=parse$3(source);const content=getContent(ast).join("");return content.length};var PerseusMarkdown = {characterCount:characterCount,traverseContent:traverseContent,parse:parse$3,parseInline:inlineParser,reactFor:SimpleMarkdown.reactFor,ruleOutput:SimpleMarkdown.ruleOutput(rules$1,"react"),basicOutput:SimpleMarkdown.reactFor(SimpleMarkdown.ruleOutput(rules$1,"react")),sanitizeUrl:SimpleMarkdown.sanitizeUrl};
1652
1657
 
@@ -1658,7 +1663,7 @@ var preprocessTex = (texCode=>texCode.replace(/\{align[*]?\}/g,"{aligned}").repl
1658
1663
 
1659
1664
  const{interactiveSizes}=constants;const smMax=articleMaxWidthTableInPx;const mdMax=articleMaxWidthInPx;const containerSizeClass={SMALL:"small",MEDIUM:"medium",LARGE:"large",XLARGE:"xlarge"};const getClassFromWidth=width=>{if(!width){return containerSizeClass.MEDIUM}if(width<=smMax){return containerSizeClass.SMALL}if(width<=mdMax){return containerSizeClass.MEDIUM}return containerSizeClass.LARGE};const getInteractiveBoxFromSizeClass=sizeClass=>{if(sizeClass===containerSizeClass.SMALL){return [interactiveSizes.defaultBoxSizeSmall,interactiveSizes.defaultBoxSizeSmall]}return [interactiveSizes.defaultBoxSize,interactiveSizes.defaultBoxSize]};
1660
1665
 
1661
- const DEFAULT_TRACKING="";const DEFAULT_LINTABLE=false;const widgets={};const editors={};const registerWidget=(name,widget)=>{widgets[name]=widget;};const registerWidgets=widgets=>{widgets.forEach(widget=>{registerWidget(widget.name,widget);});};const replaceWidget=(name,replacementName)=>{const substituteWidget=widgets[replacementName];if(!substituteWidget){const errorMsg=`Failed to replace ${name} with ${replacementName}`;throw new PerseusError(errorMsg,Errors.Internal)}registerWidget(name,substituteWidget);};const replaceDeprecatedWidgets=()=>{replaceWidget("transformer","deprecated-standin");replaceWidget("lights-puzzle","deprecated-standin");replaceWidget("reaction-diagram","deprecated-standin");replaceWidget("sequence","deprecated-standin");replaceWidget("simulator","deprecated-standin");replaceWidget("unit-input","deprecated-standin");};const registerEditors=editorsToRegister=>{editorsToRegister.forEach(editor=>{if(!editor.widgetName){throw new PerseusError(`Editor ${editor.displayName} doesn't have a widgetName property`,Errors.Internal)}editors[editor.widgetName]=editor;});};const replaceEditor=(name,replacementName)=>{const substituteEditor=editors[replacementName];if(!substituteEditor&&Log){const errorMsg=`Failed to replace editor ${name} with ${replacementName}`;Log.error(errorMsg,Errors.Internal);return}editors[name]=substituteEditor;};const replaceDeprecatedEditors=()=>{replaceEditor("transformer","deprecated-standin");replaceEditor("lights-puzzle","deprecated-standin");replaceEditor("reaction-diagram","deprecated-standin");replaceEditor("sequence","deprecated-standin");replaceEditor("simulator","deprecated-standin");replaceEditor("unit-input","deprecated-standin");};const getWidget=name=>{if(!_.has(widgets,name)){return null}if(widgets[name]?.getWidget){return widgets[name].getWidget?.()}return widgets[name].widget};const getWidgetExport=name=>{return widgets[name]??null};const getEditor=name=>{return _.has(editors,name)?editors[name]:null};const getTransform=name=>{return _.has(widgets,name)?widgets[name].transform||_.identity:null};const getVersion=name=>{const widgetInfo=widgets[name];if(widgetInfo){return widgets[name].version||{major:0,minor:0}}return};const getVersionVector=()=>{const version={};_.each(_.keys(widgets),function(name){version[name]=getVersion(name);});return version};const getPublicWidgets=()=>{return _.pick(widgets,_.reject(_.keys(widgets),function(name){return widgets[name].hidden}))};const isAccessible=widgetInfo=>{const accessible=widgets[widgetInfo.type].accessible;if(typeof accessible==="function"){return accessible(widgetInfo.options)}return !!accessible};const getAllWidgetTypes=()=>{return _.keys(widgets)};const getRendererPropsForWidgetInfo=(widgetInfo,strings,problemNum)=>{const type=widgetInfo.type;const widgetExports=widgets[type];if(widgetExports==null){return widgetInfo}let transform;if(widgetInfo.static){transform=getStaticTransform(type)||_.identity;}else {transform=widgetExports.transform||_.identity;}return transform(widgetInfo.options,strings,problemNum)};const traverseChildWidgets$3=(widgetInfo,traverseRenderer)=>{if(!traverseRenderer){throw new PerseusError("traverseRenderer must be provided, but was not",Errors.Internal)}if(!widgetInfo||!widgetInfo.type||!widgets[widgetInfo.type]){return widgetInfo}const widgetExports=widgets[widgetInfo.type];const props=widgetInfo.options;if(widgetExports.traverseChildWidgets&&props){const newProps=widgetExports.traverseChildWidgets(props,traverseRenderer);return _.extend({},widgetInfo,{options:newProps})}return widgetInfo};const supportsStaticMode=type=>{const widgetInfo=widgets[type];return widgetInfo&&widgetInfo.staticTransform!=null};const getStaticTransform=type=>{const widgetInfo=widgets[type];return widgetInfo&&widgetInfo.staticTransform};const getTracking=type=>{const widgetExport=widgets[type];return widgetExport&&widgetExport.tracking||DEFAULT_TRACKING};const isLintable=type=>{const widgetExports=widgets[type];return widgetExports&&widgetExports.isLintable||DEFAULT_LINTABLE};
1666
+ const DEFAULT_TRACKING="";const DEFAULT_LINTABLE=false;const widgets=new Registry("Perseus widget registry");const editors=new Registry("Perseus widget editor registry");const identity=val=>val;const registerWidget=(type,widget)=>{widgets.set(type,widget);};const registerWidgets=widgetArr=>{widgetArr.forEach(widget=>{registerWidget(widget.name,widget);});};const replaceWidget=(type,replacementType)=>{const substituteWidget=widgets.get(replacementType);if(!substituteWidget){const errorMsg=`Failed to replace ${type} with ${replacementType}`;throw new PerseusError(errorMsg,Errors.Internal)}registerWidget(type,substituteWidget);};const replaceDeprecatedWidgets=()=>{replaceWidget("transformer","deprecated-standin");replaceWidget("lights-puzzle","deprecated-standin");replaceWidget("reaction-diagram","deprecated-standin");replaceWidget("sequence","deprecated-standin");replaceWidget("simulator","deprecated-standin");replaceWidget("unit-input","deprecated-standin");};const registerEditors=editorsToRegister=>{editorsToRegister.forEach(editor=>{if(!editor.widgetName){throw new PerseusError(`Editor ${editor.displayName} doesn't have a widgetName property`,Errors.Internal)}editors.set(editor.widgetName,editor);});};const replaceEditor=(type,replacementType)=>{const substituteEditor=editors.get(replacementType);if(!substituteEditor&&Log){const errorMsg=`Failed to replace editor ${type} with ${replacementType}`;Log.error(errorMsg,Errors.Internal);return}editors.set(type,substituteEditor);};const replaceDeprecatedEditors=()=>{replaceEditor("transformer","deprecated-standin");replaceEditor("lights-puzzle","deprecated-standin");replaceEditor("reaction-diagram","deprecated-standin");replaceEditor("sequence","deprecated-standin");replaceEditor("simulator","deprecated-standin");replaceEditor("unit-input","deprecated-standin");};const getWidget=type=>{const widget=widgets.get(type);if(widget==null){return null}if(widget.getWidget){return widget.getWidget()}return widget.widget};const getWidgetExport=type=>{return widgets.get(type)??null};const getEditor=type=>{return editors.get(type)??null};const getTransform=type=>{const widget=widgets.get(type);if(widget==null){return null}return widget.transform||identity};const getVersion=type=>{const widget=widgets.get(type);if(widget!=null){return widget.version||{major:0,minor:0}}return};const getVersionVector=()=>{const version={};widgets.keys().forEach(type=>{version[type]=getVersion(type);});return version};const getPublicWidgets=()=>{return widgets.entries().reduce((acc,[key,value])=>{if(!value.hidden){acc[key]=value;}return acc},{})};const isAccessible=widgetInfo=>{const accessible=widgets.get(widgetInfo.type)?.accessible;if(typeof accessible==="function"){return accessible(widgetInfo.options)}return !!accessible};const getAllWidgetTypes=()=>{return widgets.keys()};const getRendererPropsForWidgetInfo=(widgetInfo,strings,problemNum)=>{const type=widgetInfo.type;const widgetExports=widgets.get(type);if(widgetExports==null){return widgetInfo}let transform;if(widgetInfo.static){transform=getStaticTransform(type)||identity;}else {transform=widgetExports.transform||identity;}return transform(widgetInfo.options,strings,problemNum)};const traverseChildWidgets$3=(widgetInfo,traverseRenderer)=>{if(!traverseRenderer){throw new PerseusError("traverseRenderer must be provided, but was not",Errors.Internal)}if(!widgetInfo||!widgetInfo.type){return widgetInfo}const widget=widgets.get(widgetInfo.type);if(widget==null){return widgetInfo}const props=widgetInfo.options;if(widget.traverseChildWidgets&&props){const newProps=widget.traverseChildWidgets(props,traverseRenderer);return {...widgetInfo,options:newProps}}return widgetInfo};const supportsStaticMode=type=>{const widgetInfo=widgets.get(type);return widgetInfo&&widgetInfo.staticTransform!=null};const getStaticTransform=type=>{const widgetInfo=widgets.get(type);return widgetInfo&&widgetInfo.staticTransform};const getTracking=type=>{const widgetExport=widgets.get(type);return widgetExport&&widgetExport.tracking||DEFAULT_TRACKING};const isLintable=type=>{const widgetExports=widgets.get(type);return widgetExports&&widgetExports.isLintable||DEFAULT_LINTABLE};
1662
1667
 
1663
1668
  var widgets$1 = /*#__PURE__*/Object.freeze({
1664
1669
  __proto__: null,
@@ -1688,13 +1693,13 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
1688
1693
 
1689
1694
  class WidgetContainer extends React.Component{componentDidMount(){if(this.state.widgetProps.apiOptions.isMobile){const containerWidth=ReactDOM__default.findDOMNode(this).offsetWidth;this.setState({sizeClass:getClassFromWidth(containerWidth)});}}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.type!==nextProps.type){throw new Error("WidgetContainer can't change widget type; set a different "+"key instead to recreate the container.")}}shouldComponentUpdate(nextProps,nextState){return this.props.shouldHighlight!==nextProps.shouldHighlight||this.props.type!==nextProps.type||this.state.widgetProps!==nextState.widgetProps||this.state.sizeClass!==nextState.sizeClass}render(){let className=classNames$1({"perseus-widget-container":true,"widget-highlight":this.props.shouldHighlight,"widget-nohighlight":!this.props.shouldHighlight,"perseus-widget__definition":this.props.type==="definition"});const type=this.props.type;const userAgent=navigator.userAgent;const WidgetType=getWidget(type);if(WidgetType==null){console.warn(`Widget type '${type}' not found!`);return jsxRuntimeExports.jsx("div",{className:className})}let subType="null";if(type==="interactive-graph"){const props=this.state.widgetProps;subType=props.graph?.type??"null";}let alignment=this.state.widgetProps.alignment;if(alignment==="default"){alignment=CoreWidgetRegistry.getDefaultAlignment(type);}className+=" widget-"+alignment;const apiOptions=this.state.widgetProps.apiOptions;const isStatic=this.state.widgetProps.static||apiOptions.readOnly;const staticContainerStyles={position:"relative",overflow:"visible"};const staticOverlayStyles={width:"100%",height:"100%",position:"absolute",top:0,left:0,zIndex:3};const linterContext=isLintable(type)?this.props.linterContext:{...this.props.linterContext,highlightLint:false};return jsxRuntimeExports.jsx("div",{className:className,style:isStatic?staticContainerStyles:{},children:jsxRuntimeExports.jsx(DependenciesContext.Consumer,{children:({analytics})=>jsxRuntimeExports.jsxs(ErrorBoundary,{metadata:{widget_type:type,widget_id:this.props.id},onError:error=>{analytics.onAnalyticsEvent({type:"perseus:widget-rendering-error:ti",payload:{widgetSubType:subType,widgetType:type,widgetId:this.props.id,message:error.message,userAgent:userAgent}});},children:[jsxRuntimeExports.jsx(WidgetType,{...this.state.widgetProps,linterContext:linterContext,containerSizeClass:this.state.sizeClass,ref:this.widgetRef}),isStatic&&jsxRuntimeExports.jsx("div",{style:staticOverlayStyles})]})})})}constructor(...args){super(...args),this.widgetRef=React.createRef(),this.state={sizeClass:containerSizeClass.MEDIUM,widgetProps:this.props.initialProps},this.getWidget=()=>{return this.widgetRef.current},this.replaceWidgetProps=newWidgetProps=>{this.setState({widgetProps:newWidgetProps});};}}WidgetContainer.defaultProps={linterContext:linterContextDefault};
1690
1695
 
1691
- const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const SHOULD_CLEAR_WIDGETS_PROP_LIST=["content","problemNum","widgets"];const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return _.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return _.isEqual(elem,wholeArray[i])}})};class Renderer extends React.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;if(this.props.serializedState){this.restoreSerializedState(this.props.serializedState);}if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}UNSAFE_componentWillReceiveProps(nextProps){if(!_.isEqual(_.pick(this.props,SHOULD_CLEAR_WIDGETS_PROP_LIST),_.pick(nextProps,SHOULD_CLEAR_WIDGETS_PROP_LIST))){this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!_.isEqual(this.state,nextState);const propsChanged=!_.isEqual(this.props,nextProps);return propsChanged||stateChanged}UNSAFE_componentWillUpdate(nextProps,nextState){const oldJipt=this.shouldRenderJiptPlaceholder(this.props,this.state);const newJipt=this.shouldRenderJiptPlaceholder(nextProps,nextState);const oldContent=this.getContent(this.props,this.state);const newContent=this.getContent(nextProps,nextState);const oldHighlightedWidgets=this.props.highlightedWidgets;const newHighlightedWidgets=nextProps.highlightedWidgets;this.reuseMarkdown=!oldJipt&&!newJipt&&oldContent===newContent&&_.isEqual(this.state.translationLintErrors,nextState.translationLintErrors)&&(!this.props.linterContext.highlightLint||_.isEqual(this.props.widgets,nextProps.widgets))&&this.props.linterContext.highlightLint===nextProps.linterContext.highlightLint&&oldHighlightedWidgets===newHighlightedWidgets;}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);this.widgetIds.forEach(id=>{const container=this._widgetContainers.get(makeContainerId(id));container?.replaceWidgetProps(this.getWidgetProps(id));});if(this.props.serializedState&&!_.isEqual(this.props.serializedState,this.getSerializedState())){this.restoreSerializedState(this.props.serializedState);}if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.state.widgetProps[widgetId]||{};const widgetInfo=this.state.widgetInfo[widgetId];const reviewModeRubric=this.props.reviewMode&&widgetInfo?widgetInfo.options:null;if(!this._interactionTrackers){this._interactionTrackers={};}let interactionTracker=this._interactionTrackers[widgetId];if(!interactionTracker){interactionTracker=this._interactionTrackers[widgetId]=new InteractionTracker(apiOptions.trackInteraction,widgetInfo&&widgetInfo.type,widgetId,getTracking(widgetInfo&&widgetInfo.type));}return {...widgetProps,widgetId:widgetId,alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,questionCompleted:this.props.questionCompleted,showSolutions:this.props.showSolutions,onFocus:_.partial(this._onWidgetFocus,widgetId),onBlur:_.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewModeRubric:reviewModeRubric,reviewMode:this.props.reviewMode,onChange:(newProps,cb,silent=false)=>{this._setWidgetProps(widgetId,newProps,cb,silent);},trackInteraction:interactionTracker.track,isLastUsedWidget:widgetId===this.state.lastUsedWidgetId}}emptyWidgets(){return emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.getUserInputMap(),this.context.locale)}getUserInput(){return this.widgetIds.map(id=>{const widget=this.getWidgetInstance(id);if(widget&&widget.getUserInput){return widget.getUserInput()}})}getUserInputMap(){const userInputMap={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);if(widget?.getUserInputMap){userInputMap[id]=widget.getUserInputMap();}else if(widget?.getUserInput){userInputMap[id]=widget.getUserInput();}});return userInputMap}getPromptJSON(){const{content}=this.props;const widgetJSON={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);widgetJSON[id]=widget?.getPromptJSON?.()||{};});return {content,widgets:widgetJSON}}score(){const scores=scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.getUserInputMap(),this.context.locale);const combinedScore=flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();if(this.reuseMarkdown){return this.lastRenderedMarkdown}const content=this.getContent(this.props,this.state);this.widgetIds=[];if(this.shouldRenderJiptPlaceholder(this.props,this.state)){if(!this.translationIndex){this.translationIndex=getDependencies().rendererTranslationComponents.addComponent(this);}if(!apiOptions.isArticle){return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{"data-perseus-component-index":this.translationIndex,children:content})})}}this._isTwoColumn=false;const parsedMarkdown=this.props.inline?PerseusMarkdown.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown.parse(content,{isJipt:this.translationIndex!=null});if(this.props.linterContext.highlightLint){const fullLinterContext={content:this.props.content,widgets:this.props.widgets,...this.props.linterContext};PerseusLinter.runLinter(parsedMarkdown,fullLinterContext,true);this._translationLinter.applyLintErrors(parsedMarkdown,[...this.state.translationLintErrors,...this.props.legacyPerseusLint||[]]);}const markdownContents=this.outputMarkdown(parsedMarkdown,{baseElements:apiOptions.baseElements});const className=classNames$1({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});this.lastRenderedMarkdown=jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})});return this.lastRenderedMarkdown}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=getUpgradedWidgetOptions(props.widgets);return {widgetInfo:allWidgetInfo,widgetProps:this._getAllWidgetsStartProps(allWidgetInfo,props)}},this._getAllWidgetsStartProps=(allWidgetInfo,props)=>{const{apiOptions,problemNum}=props;const widgetsStartProps={};const{strings}=this.props;entries(allWidgetInfo).forEach(([key,widgetInfo])=>{widgetsStartProps[key]=getRendererPropsForWidgetInfo(widgetInfo,strings,problemNum);});apiOptions?.onWidgetStartProps?.(widgetsStartProps);return widgetsStartProps},this._getDefaultWidgetInfo=widgetId=>{const widgetIdParts=Util.rTypeFromWidgetId.exec(widgetId);if(widgetIdParts==null){return {}}return {type:widgetIdParts[1],graded:true,options:{}}},this._getWidgetInfo=widgetId=>{return this.state.widgetInfo[widgetId]||this._getDefaultWidgetInfo(widgetId)},this.renderWidget=(impliedType,id,state)=>{const widgetInfo=this.state.widgetInfo[id];if(widgetInfo&&widgetInfo.alignment==="full-width"){state.foundFullWidth=true;}if(widgetInfo){const type=widgetInfo&&widgetInfo.type||impliedType;const shouldHighlight=_.contains(this.props.highlightedWidgets,id);return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,initialProps:this.getWidgetProps(id),shouldHighlight:shouldHighlight,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},this.getSerializedState=widgetProps=>{return mapObject(widgetProps||this.state.widgetProps,(props,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return widget.getSerializedState()}return props})},this.restoreSerializedState=(serializedState,callback)=>{const serializedWidgetIds=_.keys(serializedState);const widgetPropIds=_.keys(this.state.widgetProps);if(serializedWidgetIds.length!==widgetPropIds.length||_.intersection(serializedWidgetIds,widgetPropIds).length!==serializedWidgetIds.length){Log.error("Refusing to restore bad serialized state:",Errors.Internal,{loggedMetadata:{serializedState:JSON.stringify(serializedState),currentProps:JSON.stringify(this.state.widgetProps)}});return}let numCallbacks=1;const fireCallback=()=>{--numCallbacks;if(callback&&numCallbacks===0){callback();}};this.setState({widgetProps:mapObject(serializedState,(props,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.restoreSerializedState){++numCallbacks;const restoreResult=widget.restoreSerializedState(props,fireCallback);return _.extend({},this.state.widgetProps[widgetId],restoreResult)}return props})},()=>{setTimeout(fireCallback,0);});},this.showRationalesForCurrentlySelectedChoices=()=>{Object.keys(this.props.widgets).forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.showRationalesForCurrentlySelectedChoices){widget.showRationalesForCurrentlySelectedChoices(this._getWidgetInfo(widgetId).options);}});},this.deselectIncorrectSelectedChoices=()=>{Object.keys(this.props.widgets).forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.deselectIncorrectSelectedChoices){widget.deselectIncorrectSelectedChoices();}});},this.findInternalWidgets=filterCriterion=>{let filterFunc;if(typeof filterCriterion==="string"){if(filterCriterion.indexOf(" ")!==-1){const widgetId=filterCriterion;filterFunc=(id,widgetInfo,widget)=>id===widgetId;}else {const widgetType=filterCriterion;filterFunc=(id,widgetInfo,widget)=>{return widgetInfo.type===widgetType};}}else {filterFunc=filterCriterion;}const results=this.widgetIds.filter(id=>{const widgetInfo=this._getWidgetInfo(id);const widget=this.getWidgetInstance(id);return filterFunc(id,widgetInfo,widget)}).map(this.getWidgetInstance);return results},this.findWidgets=filterCriterion=>{return [...this.findInternalWidgets(filterCriterion),...this.props.findExternalWidgets(filterCriterion)]},this.getWidgetInstance=id=>{const ref=this._widgetContainers.get(makeContainerId(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!_.isArray(focusPath)){throw new PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!_.isEqual(fullPath,blurringFocusPath)){return}_.defer(()=>{if(_.isEqual(this._currentFocus,blurringFocusPath)){this._setCurrentFocus(null);}});},this.getContent=(props,state)=>{return state.jiptContent||props.content},this.shouldRenderJiptPlaceholder=(props,state)=>{return getDependencies().JIPT.useJIPT&&state.jiptContent==null&&props.content.indexOf("crwdns")!==-1},this.replaceJiptContent=(content,paragraphIndex)=>{if(paragraphIndex==null){this.setState({jiptContent:content});}else {const codeFenceRegex=/^\s*(`{3,}|~{3,})\s*(\S+)?\s*\n([\s\S]+?)\s*\1\s*$/;if(codeFenceRegex.test(content));else if(/\S\n\s*\n\S/.test(content)){content="$\\large{\\red{\\text{Please translate each "+"paragraph to a single paragraph.}}}$";}else if(/^\s*$/.test(content)){content="$\\large{\\red{\\text{Translated paragraph is "+"currently empty}}}$";}const allContent=this.getContent(this.props,this.state);const paragraphs=JiptParagraphs.parseToArray(allContent);paragraphs[paragraphIndex]=content;this.setState({jiptContent:JiptParagraphs.joinFromArray(paragraphs)});}},this.outputMarkdown=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;state.paragraphIndex=i;const nodeOut=this.outputMarkdown(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}this._foundTextNodes=false;state.foundFullWidth=false;const output=this.outputNested(ast,state);let className;if(this.translationIndex!=null){className=null;}else {className=classNames$1({"perseus-paragraph-centered":!this._foundTextNodes,"perseus-paragraph-full-width":state.foundFullWidth&&ast.content.length===1});}return jsxRuntimeExports.jsx(QuestionParagraph,{className:className,translationIndex:this.translationIndex,paragraphIndex:state.paragraphIndex,inline:this.props.inline,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:output})},state.key)},this.outputNested=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;const nodeOut=this.outputNested(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}return this.outputNode(ast,this.outputNested,state)},this.outputNode=(node,nestedOutput,state)=>{const apiOptions=this.getApiOptions();const imagePlaceholder=apiOptions.imagePlaceholder;if(node.type==="widget"){const widgetPlaceholder=apiOptions.widgetPlaceholder;if(widgetPlaceholder){return widgetPlaceholder}this._foundTextNodes=true;if(this.widgetIds.includes(node.id)){return jsxRuntimeExports.jsx("span",{className:"renderer-widget-error",children:["Widget [[","☃"," ",node.id,"]] already exists."].join("")},state.key)}this.widgetIds.push(node.id);return this.renderWidget(node.widgetType,node.id,state)}if(node.type==="blockMath"){const content=preprocessTex(node.content);const innerStyle={overflowX:"auto",overflowY:"hidden",paddingTop:10,paddingBottom:10,marginTop:-10,marginBottom:-10};if(apiOptions.isMobile){const margin=16;const outerStyle={marginLeft:-16,marginRight:-16};const horizontalPadding={paddingLeft:margin,paddingRight:margin};const mobileInnerStyle={...innerStyle,...styles$E.mobileZoomableParentFix};return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",style:outerStyle,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:{...mobileInnerStyle,...horizontalPadding},children:jsxRuntimeExports.jsx(ZoomableTeX,{children:content})})})},state.key)}return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:innerStyle,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{setAssetStatus:setAssetStatus,children:content})})})})},state.key)}if(node.type==="math"){const tex=node.content;return jsxRuntimeExports.jsx("span",{style:{whiteSpace:"nowrap"},children:jsxRuntimeExports.jsxs(ErrorBoundary,{children:[jsxRuntimeExports.jsx("span",{}),jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{onRender:this.props.onRender,setAssetStatus:setAssetStatus,children:tex})}),jsxRuntimeExports.jsx("span",{})]})},state.key)}if(node.type==="image"){if(imagePlaceholder){return imagePlaceholder}const extraAttrs=_.has(this.props.images,node.target)?this.props.images[node.target]:null;const responsive=!state.inTable;return jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{setAssetStatus:setAssetStatus,src:PerseusMarkdown.sanitizeUrl(node.target),alt:node.alt,title:node.title,responsive:responsive,onUpdate:this.props.onRender,zoomToFullSizeOnMobile:apiOptions.isMobile&&apiOptions.isArticle,...extraAttrs})})},state.key)}if(node.type==="columns"){this._isTwoColumn=true;return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown.ruleOutput(node,nestedOutput,{...state,isMobile:apiOptions.isMobile,inTable:true});if(!apiOptions.isMobile){return output}const outerStyle={marginLeft:-16,marginRight:-16};const innerStyle={paddingLeft:0,paddingRight:0};const mobileInnerStyle={...innerStyle,...styles$E.mobileZoomableParentFix};const wrappedOutput=jsxRuntimeExports.jsx("div",{style:{...mobileInnerStyle,overflowX:"auto"},children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(Zoomable,{animateHeight:true,children:output})})});return jsxRuntimeExports.jsx("div",{style:outerStyle,children:wrappedOutput})}return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender||oldOnRender!==noopOnRender){const $images=$(ReactDOM__default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender){$images.off("load",oldOnRender);}if(onRender!==noopOnRender){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix(path,this._currentFocus)){const prevFocus=this._currentFocus;if(prevFocus){this.blurPath(prevFocus);}this._currentFocus=path;apiOptions.onFocusChange(this._currentFocus,prevFocus);}},this.focus=()=>{let id;let focusResult;for(let i=0;i<this.widgetIds.length;i++){const widgetId=this.widgetIds[i];const widget=this.getWidgetInstance(widgetId);const widgetFocusResult=widget?.focus?.();if(widgetFocusResult){id=widgetId;focusResult=widgetFocusResult;break}}if(id){let path;if(typeof focusResult==="object"){path=[id].concat(focusResult.path||[]);Log.error("Renderer received a focus result of type 'object' "+"instead of the expected type 'boolean'",Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult),currentProps:JSON.stringify(this.state.widgetProps)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){return ReactDOM__default.findDOMNode(widget)}},this.getInputPaths=()=>{const inputPaths=[];this.widgetIds.forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getInputPaths){const widgetInputPaths=widget.getInputPaths();widgetInputPaths.forEach(inputPath=>{const relativeInputPath=[widgetId].concat(inputPath);inputPaths.push(relativeInputPath);});}});return inputPaths},this.focusPath=path=>{if(_.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!_.isEqual(this._currentFocus,path)){return}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget){const blurWidget=this.getWidgetInstance(widgetId);blurWidget?.blurInputPath?.(interWidgetPath);}},this.blur=()=>{if(this._currentFocus){this.blurPath(this._currentFocus);}},this.serialize=()=>{const state={};_.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!_.isEmpty(s)){state[id]=s;}},this);return state},this._setWidgetProps=(id,newProps,cb,silent)=>{this.setState(prevState=>{const widgetProps={...prevState.widgetProps,[id]:{...prevState.widgetProps[id],...newProps}};const lastUsedWidgetId=silent?prevState.lastUsedWidgetId:id;if(!silent){this.props.onSerializedStateUpdated(this.getSerializedState(widgetProps));}return {lastUsedWidgetId,widgetProps}},()=>{setTimeout(()=>{const cbResult=cb&&cb();if(!silent){this.props.onInteractWithWidget(id);}if(cbResult!==false){this._setCurrentFocus([id]);}},0);});},this.setInputValue=(path,newValue,cb)=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);widget?.setInputValue?.(interWidgetPath,newValue,cb);},this.getWidgetIds=()=>{return this.widgetIds},this.handletranslationLintErrors=lintErrors=>{if(!this._isMounted){return}this.setState({translationLintErrors:lintErrors});};this._translationLinter=new TranslationLinter;this.state={jiptContent:null,translationLintErrors:[],lastUsedWidgetId:null,...this._getInitialWidgetState(props)};}}Renderer.contextType=PerseusI18nContext;Renderer.defaultProps={content:"",widgets:{},images:{},highlightedWidgets:[],questionCompleted:false,showSolutions:"none",onRender:noopOnRender,onInteractWithWidget:function(){},findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,serializedState:null,onSerializedStateUpdated:()=>{},linterContext:PerseusLinter.linterContextDefault};const styles$E={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
1696
+ const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const SHOULD_CLEAR_WIDGETS_PROP_LIST=["content","problemNum","widgets"];const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return _.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return _.isEqual(elem,wholeArray[i])}})};class Renderer extends React.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;if(this.props.serializedState){this.restoreSerializedState(this.props.serializedState);}if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}UNSAFE_componentWillReceiveProps(nextProps){if(!_.isEqual(_.pick(this.props,SHOULD_CLEAR_WIDGETS_PROP_LIST),_.pick(nextProps,SHOULD_CLEAR_WIDGETS_PROP_LIST))){this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!_.isEqual(this.state,nextState);const propsChanged=!_.isEqual(this.props,nextProps);return propsChanged||stateChanged}UNSAFE_componentWillUpdate(nextProps,nextState){const oldJipt=this.shouldRenderJiptPlaceholder(this.props,this.state);const newJipt=this.shouldRenderJiptPlaceholder(nextProps,nextState);const oldContent=this.getContent(this.props,this.state);const newContent=this.getContent(nextProps,nextState);const oldHighlightedWidgets=this.props.highlightedWidgets;const newHighlightedWidgets=nextProps.highlightedWidgets;this.reuseMarkdown=!oldJipt&&!newJipt&&oldContent===newContent&&_.isEqual(this.state.translationLintErrors,nextState.translationLintErrors)&&(!this.props.linterContext.highlightLint||_.isEqual(this.props.widgets,nextProps.widgets))&&this.props.linterContext.highlightLint===nextProps.linterContext.highlightLint&&oldHighlightedWidgets===newHighlightedWidgets;}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);this.widgetIds.forEach(id=>{const container=this._widgetContainers.get(makeContainerId(id));container?.replaceWidgetProps(this.getWidgetProps(id));});if(this.props.serializedState&&!_.isEqual(this.props.serializedState,this.getSerializedState())){this.restoreSerializedState(this.props.serializedState);}if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.state.widgetProps[widgetId]||{};const widgetInfo=this.state.widgetInfo[widgetId];const reviewModeRubric=this.props.reviewMode&&widgetInfo?widgetInfo.options:null;if(!this._interactionTrackers){this._interactionTrackers={};}let interactionTracker=this._interactionTrackers[widgetId];if(!interactionTracker){interactionTracker=this._interactionTrackers[widgetId]=new InteractionTracker(apiOptions.trackInteraction,widgetInfo&&widgetInfo.type,widgetId,getTracking(widgetInfo&&widgetInfo.type));}return {...widgetProps,widgetId:widgetId,alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,questionCompleted:this.props.questionCompleted,showSolutions:this.props.showSolutions,onFocus:_.partial(this._onWidgetFocus,widgetId),onBlur:_.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewModeRubric:reviewModeRubric,reviewMode:this.props.reviewMode,onChange:(newProps,cb,silent=false)=>{this._setWidgetProps(widgetId,newProps,cb,silent);},trackInteraction:interactionTracker.track,isLastUsedWidget:widgetId===this.state.lastUsedWidgetId}}emptyWidgets(){return emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.getUserInputMap(),this.context.locale)}getUserInput(){return this.widgetIds.map(id=>{const widget=this.getWidgetInstance(id);if(widget&&widget.getUserInput){return widget.getUserInput()}})}getUserInputMap(){const userInputMap={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);if(widget?.getUserInputMap){userInputMap[id]=widget.getUserInputMap();}else if(widget?.getUserInput){userInputMap[id]=widget.getUserInput();}});return userInputMap}getPromptJSON(){const{content}=this.props;const widgetJSON={};this.widgetIds.forEach(id=>{const widget=this.getWidgetInstance(id);widgetJSON[id]=widget?.getPromptJSON?.()||{};});return {content,widgets:widgetJSON}}score(){const scores=scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.getUserInputMap(),this.context.locale);const combinedScore=flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();if(this.reuseMarkdown){return this.lastRenderedMarkdown}const content=this.getContent(this.props,this.state);this.widgetIds=[];if(this.shouldRenderJiptPlaceholder(this.props,this.state)){if(!this.translationIndex){this.translationIndex=getDependencies().rendererTranslationComponents.addComponent(this);}if(!apiOptions.isArticle){return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{"data-perseus-component-index":this.translationIndex,children:content})})}}this._isTwoColumn=false;const parsedMarkdown=this.props.inline?PerseusMarkdown.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown.parse(content,{isJipt:this.translationIndex!=null});if(this.props.linterContext.highlightLint){const fullLinterContext={content:this.props.content,widgets:this.props.widgets,...this.props.linterContext};PerseusLinter.runLinter(parsedMarkdown,fullLinterContext,true);this._translationLinter.applyLintErrors(parsedMarkdown,[...this.state.translationLintErrors,...this.props.legacyPerseusLint||[]]);}const markdownContents=this.outputMarkdown(parsedMarkdown,{baseElements:apiOptions.baseElements});const className=classNames$1({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});this.lastRenderedMarkdown=jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})});return this.lastRenderedMarkdown}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=getUpgradedWidgetOptions(props.widgets);return {widgetInfo:allWidgetInfo,widgetProps:this._getAllWidgetsStartProps(allWidgetInfo,props)}},this._getAllWidgetsStartProps=(allWidgetInfo,props)=>{const{apiOptions,problemNum}=props;const widgetsStartProps={};const{strings}=this.props;entries(allWidgetInfo).forEach(([key,widgetInfo])=>{widgetsStartProps[key]=getRendererPropsForWidgetInfo(widgetInfo,strings,problemNum);});apiOptions?.onWidgetStartProps?.(widgetsStartProps);return widgetsStartProps},this._getDefaultWidgetInfo=widgetId=>{const widgetIdParts=Util.rTypeFromWidgetId.exec(widgetId);if(widgetIdParts==null){return {}}return {type:widgetIdParts[1],graded:true,options:{}}},this._getWidgetInfo=widgetId=>{return this.state.widgetInfo[widgetId]||this._getDefaultWidgetInfo(widgetId)},this.renderWidget=(impliedType,id,state)=>{const widgetInfo=this.state.widgetInfo[id];if(widgetInfo&&widgetInfo.alignment==="full-width"){state.foundFullWidth=true;}if(widgetInfo){const type=widgetInfo&&widgetInfo.type||impliedType;const shouldHighlight=_.contains(this.props.highlightedWidgets,id);return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,initialProps:this.getWidgetProps(id),shouldHighlight:shouldHighlight,linterContext:PerseusLinter.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},this.getSerializedState=widgetProps=>{return mapObject(widgetProps||this.state.widgetProps,(props,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return widget.getSerializedState()}return props})},this.restoreSerializedState=(serializedState,callback)=>{const serializedWidgetIds=_.keys(serializedState);const widgetPropIds=_.keys(this.state.widgetProps);if(serializedWidgetIds.length!==widgetPropIds.length||_.intersection(serializedWidgetIds,widgetPropIds).length!==serializedWidgetIds.length){Log.error("Refusing to restore bad serialized state:",Errors.Internal,{loggedMetadata:{serializedState:JSON.stringify(serializedState),currentProps:JSON.stringify(this.state.widgetProps)}});return}let numCallbacks=1;const fireCallback=()=>{--numCallbacks;if(callback&&numCallbacks===0){callback();}};this.setState({widgetProps:mapObject(serializedState,(props,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.restoreSerializedState){++numCallbacks;const restoreResult=widget.restoreSerializedState(props,fireCallback);return _.extend({},this.state.widgetProps[widgetId],restoreResult)}return props})},()=>{setTimeout(fireCallback,0);});},this.showRationalesForCurrentlySelectedChoices=()=>{Object.keys(this.props.widgets).forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.showRationalesForCurrentlySelectedChoices){widget.showRationalesForCurrentlySelectedChoices(this._getWidgetInfo(widgetId).options);}});},this.deselectIncorrectSelectedChoices=()=>{Object.keys(this.props.widgets).forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.deselectIncorrectSelectedChoices){widget.deselectIncorrectSelectedChoices();}});},this.findInternalWidgets=filterCriterion=>{let filterFunc;if(typeof filterCriterion==="string"){if(filterCriterion.indexOf(" ")!==-1){const widgetId=filterCriterion;filterFunc=(id,widgetInfo,widget)=>id===widgetId;}else {const widgetType=filterCriterion;filterFunc=(id,widgetInfo,widget)=>{return widgetInfo.type===widgetType};}}else {filterFunc=filterCriterion;}const results=this.widgetIds.filter(id=>{const widgetInfo=this._getWidgetInfo(id);const widget=this.getWidgetInstance(id);return filterFunc(id,widgetInfo,widget)}).map(this.getWidgetInstance);return results},this.findWidgets=filterCriterion=>{return [...this.findInternalWidgets(filterCriterion),...this.props.findExternalWidgets(filterCriterion)]},this.getWidgetInstance=id=>{const ref=this._widgetContainers.get(makeContainerId(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!_.isArray(focusPath)){throw new PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!_.isEqual(fullPath,blurringFocusPath)){return}_.defer(()=>{if(_.isEqual(this._currentFocus,blurringFocusPath)){this._setCurrentFocus(null);}});},this.getContent=(props,state)=>{return state.jiptContent||props.content},this.shouldRenderJiptPlaceholder=(props,state)=>{return getDependencies().JIPT.useJIPT&&state.jiptContent==null&&props.content.indexOf("crwdns")!==-1},this.replaceJiptContent=(content,paragraphIndex)=>{if(paragraphIndex==null){this.setState({jiptContent:content});}else {const codeFenceRegex=/^\s*(`{3,}|~{3,})\s*(\S+)?\s*\n([\s\S]+?)\s*\1\s*$/;if(codeFenceRegex.test(content));else if(/\S\n\s*\n\S/.test(content)){content="$\\large{\\red{\\text{Please translate each "+"paragraph to a single paragraph.}}}$";}else if(/^\s*$/.test(content)){content="$\\large{\\red{\\text{Translated paragraph is "+"currently empty}}}$";}const allContent=this.getContent(this.props,this.state);const paragraphs=JiptParagraphs.parseToArray(allContent);paragraphs[paragraphIndex]=content;this.setState({jiptContent:JiptParagraphs.joinFromArray(paragraphs)});}},this.outputMarkdown=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;state.paragraphIndex=i;const nodeOut=this.outputMarkdown(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}this._foundTextNodes=false;state.foundFullWidth=false;const output=this.outputNested(ast,state);let className;if(this.translationIndex!=null){className=null;}else {className=classNames$1({"perseus-paragraph-centered":!this._foundTextNodes,"perseus-paragraph-full-width":state.foundFullWidth&&ast.content.length===1});}return jsxRuntimeExports.jsx(QuestionParagraph,{className:className,translationIndex:this.translationIndex,paragraphIndex:state.paragraphIndex,inline:this.props.inline,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:output})},state.key)},this.outputNested=(ast,state)=>{if(_.isArray(ast)){const oldKey=state.key;const result=[];let lastWasString=false;for(let i=0;i<ast.length;i++){state.key=i;const nodeOut=this.outputNested(ast[i],state);const isString=typeof nodeOut==="string";if(typeof nodeOut==="string"&&lastWasString){result[result.length-1]+=nodeOut;}else {result.push(nodeOut);}lastWasString=isString;}state.key=oldKey;return result}return this.outputNode(ast,this.outputNested,state)},this.outputNode=(node,nestedOutput,state)=>{const apiOptions=this.getApiOptions();const imagePlaceholder=apiOptions.imagePlaceholder;if(node.type==="widget"){const widgetPlaceholder=apiOptions.widgetPlaceholder;if(widgetPlaceholder){return widgetPlaceholder}this._foundTextNodes=true;if(this.widgetIds.includes(node.id)){return jsxRuntimeExports.jsx("span",{className:"renderer-widget-error",children:["Widget [[","☃"," ",node.id,"]] already exists."].join("")},state.key)}this.widgetIds.push(node.id);return this.renderWidget(node.widgetType,node.id,state)}if(node.type==="blockMath"){const content=preprocessTex(node.content);const innerStyle={overflowX:"auto",overflowY:"hidden",paddingTop:10,paddingBottom:10,marginTop:-10,marginBottom:-10};if(apiOptions.isMobile){const margin=16;const outerStyle={marginLeft:-16,marginRight:-16};const horizontalPadding={paddingLeft:margin,paddingRight:margin};const mobileInnerStyle={...innerStyle,...styles$H.mobileZoomableParentFix};return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",style:outerStyle,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:{...mobileInnerStyle,...horizontalPadding},children:jsxRuntimeExports.jsx(ZoomableTeX,{children:content})})})},state.key)}return jsxRuntimeExports.jsx("div",{className:"perseus-block-math",children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx("div",{className:"perseus-block-math-inner",style:innerStyle,children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{setAssetStatus:setAssetStatus,children:content})})})})},state.key)}if(node.type==="math"){const tex=node.content;return jsxRuntimeExports.jsx("span",{style:{whiteSpace:"nowrap"},children:jsxRuntimeExports.jsxs(ErrorBoundary,{children:[jsxRuntimeExports.jsx("span",{}),jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(Tex,{onRender:this.props.onRender,setAssetStatus:setAssetStatus,children:tex})}),jsxRuntimeExports.jsx("span",{})]})},state.key)}if(node.type==="image"){if(imagePlaceholder){return imagePlaceholder}const extraAttrs=_.has(this.props.images,node.target)?this.props.images[node.target]:null;const responsive=!state.inTable;return jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{setAssetStatus:setAssetStatus,src:PerseusMarkdown.sanitizeUrl(node.target),alt:node.alt,title:node.title,responsive:responsive,onUpdate:this.props.onRender,zoomToFullSizeOnMobile:apiOptions.isMobile&&apiOptions.isArticle,...extraAttrs})})},state.key)}if(node.type==="columns"){this._isTwoColumn=true;return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown.ruleOutput(node,nestedOutput,{...state,isMobile:apiOptions.isMobile,inTable:true});if(!apiOptions.isMobile){return output}const outerStyle={marginLeft:-16,marginRight:-16};const innerStyle={paddingLeft:0,paddingRight:0};const mobileInnerStyle={...innerStyle,...styles$H.mobileZoomableParentFix};const wrappedOutput=jsxRuntimeExports.jsx("div",{style:{...mobileInnerStyle,overflowX:"auto"},children:jsxRuntimeExports.jsx(ErrorBoundary,{children:jsxRuntimeExports.jsx(Zoomable,{animateHeight:true,children:output})})});return jsxRuntimeExports.jsx("div",{style:outerStyle,children:wrappedOutput})}return jsxRuntimeExports.jsx(ErrorBoundary,{children:PerseusMarkdown.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender||oldOnRender!==noopOnRender){const $images=$(ReactDOM__default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender){$images.off("load",oldOnRender);}if(onRender!==noopOnRender){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix(path,this._currentFocus)){const prevFocus=this._currentFocus;if(prevFocus){this.blurPath(prevFocus);}this._currentFocus=path;apiOptions.onFocusChange(this._currentFocus,prevFocus);}},this.focus=()=>{let id;let focusResult;for(let i=0;i<this.widgetIds.length;i++){const widgetId=this.widgetIds[i];const widget=this.getWidgetInstance(widgetId);const widgetFocusResult=widget?.focus?.();if(widgetFocusResult){id=widgetId;focusResult=widgetFocusResult;break}}if(id){let path;if(typeof focusResult==="object"){path=[id].concat(focusResult.path||[]);Log.error("Renderer received a focus result of type 'object' "+"instead of the expected type 'boolean'",Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult),currentProps:JSON.stringify(this.state.widgetProps)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){return ReactDOM__default.findDOMNode(widget)}},this.getInputPaths=()=>{const inputPaths=[];this.widgetIds.forEach(widgetId=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getInputPaths){const widgetInputPaths=widget.getInputPaths();widgetInputPaths.forEach(inputPath=>{const relativeInputPath=[widgetId].concat(inputPath);inputPaths.push(relativeInputPath);});}});return inputPaths},this.focusPath=path=>{if(_.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!_.isEqual(this._currentFocus,path)){return}const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget){const blurWidget=this.getWidgetInstance(widgetId);blurWidget?.blurInputPath?.(interWidgetPath);}},this.blur=()=>{if(this._currentFocus){this.blurPath(this._currentFocus);}},this.serialize=()=>{const state={};_.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!_.isEmpty(s)){state[id]=s;}},this);return state},this._setWidgetProps=(id,newProps,cb,silent)=>{this.setState(prevState=>{const widgetProps={...prevState.widgetProps,[id]:{...prevState.widgetProps[id],...newProps}};const lastUsedWidgetId=silent?prevState.lastUsedWidgetId:id;if(!silent){this.props.onSerializedStateUpdated(this.getSerializedState(widgetProps));}return {lastUsedWidgetId,widgetProps}},()=>{setTimeout(()=>{const cbResult=cb&&cb();if(!silent){this.props.onInteractWithWidget(id);}if(cbResult!==false){this._setCurrentFocus([id]);}},0);});},this.setInputValue=(path,newValue,cb)=>{const widgetId=_.first(path);const interWidgetPath=_.rest(path);const widget=this.getWidgetInstance(widgetId);widget?.setInputValue?.(interWidgetPath,newValue,cb);},this.getWidgetIds=()=>{return this.widgetIds},this.handletranslationLintErrors=lintErrors=>{if(!this._isMounted){return}this.setState({translationLintErrors:lintErrors});};this._translationLinter=new TranslationLinter;this.state={jiptContent:null,translationLintErrors:[],lastUsedWidgetId:null,...this._getInitialWidgetState(props)};}}Renderer.contextType=PerseusI18nContext;Renderer.defaultProps={content:"",widgets:{},images:{},highlightedWidgets:[],questionCompleted:false,showSolutions:"none",onRender:noopOnRender,onInteractWithWidget:function(){},findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,serializedState:null,onSerializedStateUpdated:()=>{},linterContext:PerseusLinter.linterContextDefault};const styles$H={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
1692
1697
 
1693
1698
  const{captureScratchpadTouchStart: captureScratchpadTouchStart$3}=Util;const InputWithExamples=forwardRef(({shouldShowExamples=true,onFocus=()=>{},onBlur=()=>{},disabled=false,linterContext=PerseusLinter.linterContextDefault,className="",...props},ref)=>{const context=React.useContext(PerseusI18nContext);const inputRef=React.useRef(null);const[inputFocused,setInputFocused]=React.useState(false);const id=useId();const ariaId=`aria-for-${id}`;useImperativeHandle(ref,()=>({current:inputRef.current,focus:()=>{if(inputRef.current){inputRef.current.focus();}},blur:()=>{if(inputRef.current){inputRef.current.blur();}}}));const getInputClassName=()=>{let inputClassName=ClassNames.INPUT;if(inputFocused){inputClassName+=" "+ClassNames.FOCUSED;}if(className){inputClassName+=" "+className;}return inputClassName};const handleFocus=()=>{onFocus();setInputFocused(true);};const handleBlur=()=>{onBlur();setInputFocused(false);};const renderInput=()=>{const examplesAria=shouldShowExamples?`${props.examples[0]}
1694
1699
  ${props.examples.slice(1).join(", or\n")}`.replaceAll("*","").replaceAll("$","").replaceAll("\\ \\text{pi}"," pi").replaceAll("\\ "," and "):"";const inputProps={id:id,"aria-describedby":shouldShowExamples?ariaId:undefined,ref:inputRef,className:getInputClassName(),labelText:props.labelText,value:props.value,onFocus:handleFocus,onBlur:handleBlur,disabled:disabled,style:props.style,onChange:props.onChange,onTouchStart:captureScratchpadTouchStart$3,autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:"false"};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(TextInput,{...inputProps}),jsxRuntimeExports.jsx("span",{id:ariaId,style:{display:"none"},children:examplesAria})]})};const renderTooltipContent=()=>{return jsxRuntimeExports.jsx(TooltipContent,{children:jsxRuntimeExports.jsx("div",{id:id,className:"input-with-examples-tooltip",children:jsxRuntimeExports.jsx(Renderer,{content:examplesContent,linterContext:PerseusLinter.pushContextStack(linterContext,"input-with-examples"),strings:context.strings})})})};const examplesContent=props.examples.length<=2?props.examples.join(" "):props.examples.map((example,index)=>{return index===0&&example.startsWith("**")?`${example}
1695
1700
  `:`- ${example}`}).join("\n");const showExamplesTooltip=shouldShowExamples&&inputFocused;return jsxRuntimeExports.jsx(Tooltip,{content:renderTooltipContent(),opened:showExamplesTooltip,placement:"bottom",children:renderInput()})});
1696
1701
 
1697
- const formExamples={integer:function(_,strings){return strings.integerExample},proper:function(options,strings){if(options.simplify==="optional"){return strings.properExample}return strings.simplifiedProperExample},improper:function(options,strings){if(options.simplify==="optional"){return strings.improperExample}return strings.simplifiedImproperExample},mixed:function(_,strings){return strings.mixedExample},decimal:function(_,strings){return strings.decimalExample},percent:function(_,strings){return strings.percentExample},pi:function(_,strings){return strings.piExample}};class InputNumber extends React.Component{static getUserInputFromProps(props){return {currentValue:props.currentValue}}getUserInput(){return InputNumber.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$s(this.props,this.getUserInput())}examples(){const{strings}=this.context;const type=this.props.answerType;const forms=inputNumberAnswerTypes[type].forms.split(/\s*,\s*/);const examples=forms.map(form=>formExamples[form](this.props,strings));return [strings.yourAnswer].concat(examples)}render(){if(this.props.apiOptions.customKeypad){const input=jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:"input",value:this.props.currentValue,keypadElement:this.props.keypadElement,onChange:this.handleChange,onFocus:this._handleFocus,onBlur:this._handleBlur});if(this.props.rightAlign){return jsxRuntimeExports.jsx("div",{className:"perseus-input-right-align",children:input})}return input}const inputStyles=[styles$D.default,this.props.size==="small"?styles$D.small:null,this.props.rightAlign?styles$D.rightAlign:styles$D.leftAlign];if(this.props.reviewMode&&!this.props.currentValue){inputStyles.push(styles$D.answerStateUnanswered);}return jsxRuntimeExports.jsx(InputWithExamples,{ref:"input",value:this.props.currentValue,onChange:this.handleChange,style:inputStyles,examples:this.examples(),shouldShowExamples:this.shouldShowExamples(),onFocus:this._handleFocus,onBlur:this._handleBlur,id:this.props.widgetId,disabled:this.props.apiOptions.readOnly,linterContext:this.props.linterContext})}constructor(...args){super(...args),this.shouldShowExamples=()=>{return this.props.answerType!=="number"},this.handleChange=(newValue,cb)=>{this.props.onChange({currentValue:newValue},cb);},this._handleFocus=()=>{this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{this.refs.input.focus();return true},this.focusInputPath=inputPath=>{this.refs.input.focus();},this.blurInputPath=inputPath=>{if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}},this.getInputPaths=()=>{return [[]]},this.setInputValue=(path,newValue,cb)=>{this.props.onChange({currentValue:newValue},cb);};}}InputNumber.contextType=PerseusI18nContext;InputNumber.defaultProps={currentValue:"",size:"normal",answerType:"number",rightAlign:false,apiOptions:ApiOptions.defaults,linterContext:linterContextDefault};const styles$D=StyleSheet.create({default:{width:80,height:"auto"},small:{width:40},leftAlign:{paddingLeft:spacing.xxxSmall_4,paddingRight:0},rightAlign:{textAlign:"right",paddingLeft:0,paddingRight:spacing.xxxSmall_4},answerStateUnanswered:{backgroundColor:"#eee",border:"solid 1px #999"}});function transform$4(widgetOptions){const{simplify,size,answerType,rightAlign}=widgetOptions;return {simplify,size,answerType,rightAlign}}function getOneCorrectAnswerFromRubric(rubric){if(rubric.value==null){return}let answerString=String(rubric.value);if(rubric.inexact&&rubric.maxError){answerString+=" ± "+rubric.maxError;}return answerString}var InputNumber$1 = {name:"input-number",displayName:"Input number (deprecated - use numeric input instead)",hidden:true,widget:InputNumber,isLintable:true,transform: transform$4,getOneCorrectAnswerFromRubric};
1702
+ const formExamples={integer:function(_,strings){return strings.integerExample},proper:function(options,strings){if(options.simplify==="optional"){return strings.properExample}return strings.simplifiedProperExample},improper:function(options,strings){if(options.simplify==="optional"){return strings.improperExample}return strings.simplifiedImproperExample},mixed:function(_,strings){return strings.mixedExample},decimal:function(_,strings){return strings.decimalExample},percent:function(_,strings){return strings.percentExample},pi:function(_,strings){return strings.piExample}};class InputNumber extends React.Component{static getUserInputFromProps(props){return {currentValue:props.currentValue}}getUserInput(){return InputNumber.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$s(this.props,this.getUserInput())}examples(){const{strings}=this.context;const type=this.props.answerType;const forms=inputNumberAnswerTypes[type].forms.split(/\s*,\s*/);const examples=forms.map(form=>formExamples[form](this.props,strings));return [strings.yourAnswer].concat(examples)}render(){if(this.props.apiOptions.customKeypad){const input=jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:"input",value:this.props.currentValue,keypadElement:this.props.keypadElement,onChange:this.handleChange,onFocus:this._handleFocus,onBlur:this._handleBlur});if(this.props.rightAlign){return jsxRuntimeExports.jsx("div",{className:"perseus-input-right-align",children:input})}return input}const inputStyles=[styles$G.default,this.props.size==="small"?styles$G.small:null,this.props.rightAlign?styles$G.rightAlign:styles$G.leftAlign];if(this.props.reviewMode&&!this.props.currentValue){inputStyles.push(styles$G.answerStateUnanswered);}return jsxRuntimeExports.jsx(InputWithExamples,{ref:"input",value:this.props.currentValue,onChange:this.handleChange,style:inputStyles,examples:this.examples(),shouldShowExamples:this.shouldShowExamples(),onFocus:this._handleFocus,onBlur:this._handleBlur,id:this.props.widgetId,disabled:this.props.apiOptions.readOnly,linterContext:this.props.linterContext})}constructor(...args){super(...args),this.shouldShowExamples=()=>{return this.props.answerType!=="number"},this.handleChange=(newValue,cb)=>{this.props.onChange({currentValue:newValue},cb);},this._handleFocus=()=>{this.props.onFocus([]);},this._handleBlur=()=>{this.props.onBlur([]);},this.focus=()=>{this.refs.input.focus();return true},this.focusInputPath=inputPath=>{this.refs.input.focus();},this.blurInputPath=inputPath=>{if(typeof this.refs.input?.blur==="function"){this.refs.input?.blur();}},this.getInputPaths=()=>{return [[]]},this.setInputValue=(path,newValue,cb)=>{this.props.onChange({currentValue:newValue},cb);};}}InputNumber.contextType=PerseusI18nContext;InputNumber.defaultProps={currentValue:"",size:"normal",answerType:"number",rightAlign:false,apiOptions:ApiOptions.defaults,linterContext:linterContextDefault};const styles$G=StyleSheet.create({default:{width:80,height:"auto"},small:{width:40},leftAlign:{paddingLeft:spacing.xxxSmall_4,paddingRight:0},rightAlign:{textAlign:"right",paddingLeft:0,paddingRight:spacing.xxxSmall_4},answerStateUnanswered:{backgroundColor:"#eee",border:"solid 1px #999"}});function transform$4(widgetOptions){const{simplify,size,answerType,rightAlign}=widgetOptions;return {simplify,size,answerType,rightAlign}}function getOneCorrectAnswerFromRubric(rubric){if(rubric.value==null){return}let answerString=String(rubric.value);if(rubric.inexact&&rubric.maxError){answerString+=" ± "+rubric.maxError;}return answerString}var InputNumber$1 = {name:"input-number",displayName:"Input number (deprecated - use numeric input instead)",hidden:true,widget:InputNumber,isLintable:true,transform: transform$4,getOneCorrectAnswerFromRubric};
1698
1703
 
1699
1704
  const getPromptJSON$r=(renderProps,userInput)=>{return {type:"numeric-input",label:renderProps.labelText,userInput:{value:userInput.currentValue}}};
1700
1705
 
@@ -1714,9 +1719,9 @@ function addHighlight(existingHighlights,newHighlight){const newHighlights={};le
1714
1719
 
1715
1720
  function getRelativePosition(child,parent){return {left:child.left-parent.left,top:child.top-parent.top}}function getRelativeRect({left,top,width,height},parent){return {...getRelativePosition({left,top},parent),width,height}}function getClientRectsForTextInRange(range){const mutableRects=[];addClientRectsForTextInNodeAndRange(range.commonAncestorContainer,range,mutableRects);return mutableRects}function addClientRectsForTextInNodeAndRange(node,range,mutableRects){const nodeContentsRange=new Range;nodeContentsRange.selectNodeContents(node);if(node.nodeType===Node.TEXT_NODE){const intersectedRange=intersectRanges(range,nodeContentsRange);if(intersectedRange){addClientRectsForText(node,intersectedRange,mutableRects);}}else if(node.nodeType===Node.ELEMENT_NODE){if(!rangesOverlap(range,nodeContentsRange)){return}for(const child of Array.from(node.childNodes)){addClientRectsForTextInNodeAndRange(child,range,mutableRects);}}}function addClientRectsForText(textNode,textRange,mutableRects){const parentElement=textNode.parentElement;const computedStyle=window.getComputedStyle(parentElement);let lineHeight=null;if(typeof computedStyle.lineHeight==="string"&&computedStyle.lineHeight.endsWith("px")){const parsedLineHeight=parseFloat(computedStyle.lineHeight);if(!isNaN(parsedLineHeight)){lineHeight=parsedLineHeight;}}const boundingRects=Array.from(textRange.getClientRects());for(const boundingRect of boundingRects){const rect={left:boundingRect.left,top:boundingRect.top,height:boundingRect.height,width:boundingRect.width};if(lineHeight!==null){const heightIncrease=lineHeight-rect.height;rect.top-=heightIncrease;rect.height=lineHeight;}mutableRects.push(rect);}}
1716
1721
 
1717
- class HighlightRenderer extends React.PureComponent{UNSAFE_componentWillReceiveProps(nextProps){if(this.props.highlight!==nextProps.highlight||this.props.offsetParent!==nextProps.offsetParent){this.setState({cachedHighlightRects:this._computeRects(nextProps)});}}_computeRects(props){const{highlight,offsetParent}=props;const clientRects=getClientRectsForTextInRange(highlight.domRange);const{left,top}=offsetParent.getBoundingClientRect();const relativeRects=clientRects.map(rect=>getRelativeRect(rect,{left,top}));return relativeRects}_rectIsHovered(rect,mouseOffsetPosition){const positionWithinRect=getRelativePosition(mouseOffsetPosition,{left:rect.left,top:rect.top});return 0<=positionWithinRect.left&&positionWithinRect.left<rect.width&&0<=positionWithinRect.top&&positionWithinRect.top<rect.height}isHovered(mouseClientPosition){if(!mouseClientPosition){return false}const{offsetParent}=this.props;const{cachedHighlightRects}=this.state;const{left,top}=offsetParent.getBoundingClientRect();const mouseOffsetPosition=getRelativePosition(mouseClientPosition,{left,top});return cachedHighlightRects.some(rect=>this._rectIsHovered(rect,mouseOffsetPosition))}render(){const rects=this.state.cachedHighlightRects;return jsxRuntimeExports.jsx("div",{children:rects.map((rect,index)=>jsxRuntimeExports.jsx("div",{className:css(styles$C.highlightRect),style:{position:"absolute",width:rect.width,height:rect.height,top:rect.top,left:rect.left,zIndex:this.props.zIndexes.belowContent}},index))})}constructor(...args){super(...args),this.state={cachedHighlightRects:this._computeRects(this.props),tooltipIsHovered:false};}}const styles$C=StyleSheet.create({highlightRect:{background:"#fffabe"}});
1722
+ class HighlightRenderer extends React.PureComponent{UNSAFE_componentWillReceiveProps(nextProps){if(this.props.highlight!==nextProps.highlight||this.props.offsetParent!==nextProps.offsetParent){this.setState({cachedHighlightRects:this._computeRects(nextProps)});}}_computeRects(props){const{highlight,offsetParent}=props;const clientRects=getClientRectsForTextInRange(highlight.domRange);const{left,top}=offsetParent.getBoundingClientRect();const relativeRects=clientRects.map(rect=>getRelativeRect(rect,{left,top}));return relativeRects}_rectIsHovered(rect,mouseOffsetPosition){const positionWithinRect=getRelativePosition(mouseOffsetPosition,{left:rect.left,top:rect.top});return 0<=positionWithinRect.left&&positionWithinRect.left<rect.width&&0<=positionWithinRect.top&&positionWithinRect.top<rect.height}isHovered(mouseClientPosition){if(!mouseClientPosition){return false}const{offsetParent}=this.props;const{cachedHighlightRects}=this.state;const{left,top}=offsetParent.getBoundingClientRect();const mouseOffsetPosition=getRelativePosition(mouseClientPosition,{left,top});return cachedHighlightRects.some(rect=>this._rectIsHovered(rect,mouseOffsetPosition))}render(){const rects=this.state.cachedHighlightRects;return jsxRuntimeExports.jsx("div",{children:rects.map((rect,index)=>jsxRuntimeExports.jsx("div",{className:css(styles$F.highlightRect),style:{position:"absolute",width:rect.width,height:rect.height,top:rect.top,left:rect.left,zIndex:this.props.zIndexes.belowContent}},index))})}constructor(...args){super(...args),this.state={cachedHighlightRects:this._computeRects(this.props),tooltipIsHovered:false};}}const styles$F=StyleSheet.create({highlightRect:{background:"#fffabe"}});
1718
1723
 
1719
- class HighlightTooltip extends React.PureComponent{_getFocusRect(){const{focusNode,focusOffset,offsetParent}=this.props;const focusRange=document.createRange();focusRange.setStart(focusNode,focusOffset);focusRange.setEnd(focusNode,focusOffset);const focusRect=focusRange.getClientRects()[0];if(!focusRect){Log.log("[Highlighting] Known bug: Could not determine the focus "+'position, so did not show an "Add Highlight" tooltip. '+"https://app.asana.com/0/329800276300868/413878480039713 "+"(see also /r/asana-links)");return null}const{left,top}=offsetParent.getBoundingClientRect();const relativeFocusRect=getRelativeRect({left:focusRect.left,top:focusRect.top,width:focusRect.width,height:focusRect.height},{left,top});return relativeFocusRect}render(){const focusRect=this._getFocusRect();if(!focusRect){return null}const content=jsxRuntimeExports.jsx("div",{className:css(styles$B.tooltipLabel),onClick:this.props.onClick,children:this.props.label});const style={position:"absolute",left:focusRect.left,top:`calc(${Math.round(focusRect.top)}px + 0.95em)`,height:0};return jsxRuntimeExports.jsx("div",{style:style,onMouseEnter:this.props.onMouseEnter,onMouseLeave:this.props.onMouseLeave,children:jsxRuntimeExports.jsx(Tooltip,{content:content,opened:true,children:jsxRuntimeExports.jsx("div",{})})})}}const styles$B=StyleSheet.create({tooltipLabel:{userSelect:"none",fontFamily:`"Lato", sans-serif`,padding:`10px ${spacing.medium_16}px`,cursor:"pointer"}});
1724
+ class HighlightTooltip extends React.PureComponent{_getFocusRect(){const{focusNode,focusOffset,offsetParent}=this.props;const focusRange=document.createRange();focusRange.setStart(focusNode,focusOffset);focusRange.setEnd(focusNode,focusOffset);const focusRect=focusRange.getClientRects()[0];if(!focusRect){Log.log("[Highlighting] Known bug: Could not determine the focus "+'position, so did not show an "Add Highlight" tooltip. '+"https://app.asana.com/0/329800276300868/413878480039713 "+"(see also /r/asana-links)");return null}const{left,top}=offsetParent.getBoundingClientRect();const relativeFocusRect=getRelativeRect({left:focusRect.left,top:focusRect.top,width:focusRect.width,height:focusRect.height},{left,top});return relativeFocusRect}render(){const focusRect=this._getFocusRect();if(!focusRect){return null}const content=jsxRuntimeExports.jsx("div",{className:css(styles$E.tooltipLabel),onClick:this.props.onClick,children:this.props.label});const style={position:"absolute",left:focusRect.left,top:`calc(${Math.round(focusRect.top)}px + 0.95em)`,height:0};return jsxRuntimeExports.jsx("div",{style:style,onMouseEnter:this.props.onMouseEnter,onMouseLeave:this.props.onMouseLeave,children:jsxRuntimeExports.jsx(Tooltip,{content:content,opened:true,children:jsxRuntimeExports.jsx("div",{})})})}}const styles$E=StyleSheet.create({tooltipLabel:{userSelect:"none",fontFamily:`"Lato", sans-serif`,padding:`10px ${spacing.medium_16}px`,cursor:"pointer"}});
1720
1725
 
1721
1726
  class HighlightSetRenderer extends React.PureComponent{componentDidMount(){this._updateEditListeners(false,this.props.editable);}UNSAFE_componentWillReceiveProps(nextProps){this._updateEditListeners(this.props.editable,nextProps.editable);if(this.state.hoveredHighlightKey!=null&&!(this.state.hoveredHighlightKey in nextProps.highlights)){this.setState({hoveredHighlightKey:null});}if(this.state.hoveringTooltipFor!=null&&!(this.state.hoveringTooltipFor in nextProps.highlights)){this.setState({hoveringTooltipFor:null});}}componentWillUnmount(){this._updateEditListeners(this.props.editable,false);}_updateEditListeners(wasListening,willListen){if(!wasListening&&willListen){window.addEventListener("mousemove",this._handleMouseMove);}else if(wasListening&&!willListen){window.removeEventListener("mousemove",this._handleMouseMove);this.setState({hoveredHighlightKey:null,hoveringTooltipFor:null});}}_getHoveredHighlightKey(mouseClientPosition){const{hoveringTooltipFor}=this.state;if(typeof hoveringTooltipFor==="string"){return hoveringTooltipFor}const highlightKeys=Object.keys(this.props.highlights);return highlightKeys.find(key=>{const highlightRenderer=this._highlightRenderers[key];return highlightRenderer&&highlightRenderer.isHovered(mouseClientPosition)})}_renderTooltip(){const{hoveredHighlightKey}=this.state;if(hoveredHighlightKey==null){return null}const hoveredHighlight=this.props.highlights[hoveredHighlightKey];return jsxRuntimeExports.jsx(HighlightTooltip,{label:this.context.strings.removeHighlight,focusNode:hoveredHighlight.domRange.endContainer,focusOffset:hoveredHighlight.domRange.endOffset,offsetParent:this.props.offsetParent,onClick:()=>this.props.onRemoveHighlight(hoveredHighlightKey),onMouseEnter:()=>this.setState({hoveringTooltipFor:hoveredHighlightKey}),onMouseLeave:()=>this.setState({hoveringTooltipFor:null})})}render(){return jsxRuntimeExports.jsxs("div",{children:[Object.keys(this.props.highlights).map(key=>jsxRuntimeExports.jsx(HighlightRenderer,{ref:r=>{if(r){this._highlightRenderers[key]=r;}else {delete this._highlightRenderers[key];}},highlight:this.props.highlights[key],highlightKey:key,offsetParent:this.props.offsetParent,zIndexes:this.props.zIndexes},key)),this.props.editable&&this._renderTooltip()]})}constructor(...args){super(...args),this.state={hoveredHighlightKey:null,hoveringTooltipFor:null},this._highlightRenderers={},this._handleMouseMove=e=>{const mouseClientPosition={left:e.clientX,top:e.clientY};const hoveredHighlightKey=this._getHoveredHighlightKey(mouseClientPosition);this.setState({hoveredHighlightKey});};}}HighlightSetRenderer.contextType=PerseusI18nContext;
1722
1727
 
@@ -1726,13 +1731,13 @@ class HighlightingUI extends React.PureComponent{_handleAddHighlight(highlightTo
1726
1731
 
1727
1732
  class WordIndexer extends React.PureComponent{componentDidMount(){this._sendWordsUpdate();}componentDidUpdate(){this._sendWordsUpdate();}_sendWordsUpdate(){this.props.onWordsUpdate(this._getWordRanges());}_getWordRanges(){const container=this._container;if(!container){throw new PerseusError("invariant violation: `this._container` is not defined, but "+"this method is only called after mount/update",Errors.NotAllowed)}const treeWalker=container.ownerDocument.createTreeWalker(container,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,()=>NodeFilter.FILTER_ACCEPT,false);const index=[];let trailingWordRange=null;while(treeWalker.nextNode()){const node=treeWalker.currentNode;if(node.nodeType===Node.ELEMENT_NODE){const element=node;if(getComputedStyle(element).display!=="inline"){trailingWordRange=null;}}else if(node.nodeType===Node.TEXT_NODE){const text=node.nodeValue;const wordPattern=/\S+/g;let wordMatch;let newTrailingWordRange=null;while((wordMatch=wordPattern.exec(text))!==null){const startOffset=wordMatch.index;const endOffset=wordMatch.index+wordMatch[0].length;let range;if(startOffset===0&&trailingWordRange){range=trailingWordRange;range.setEnd(node,endOffset);}else {range=node.ownerDocument.createRange();range.setStart(node,startOffset);range.setEnd(node,endOffset);index.push(range);}if(endOffset===text.length){newTrailingWordRange=range;}}trailingWordRange=newTrailingWordRange;}}return index}render(){return jsxRuntimeExports.jsx("div",{ref:container=>this._container=container,children:this.props.children})}}
1728
1733
 
1729
- class HighlightableContent extends React.PureComponent{_buildHighlight(highlightRange){return buildHighlight(this._getDOMHighlights(),this.state.wordRanges,highlightRange)}_getDOMHighlights(){const{serializedHighlights}=this.props;const{wordRanges}=this.state;const domHighlights={};for(const key of Object.keys(serializedHighlights)){domHighlights[key]=deserializeHighlight(serializedHighlights[key],wordRanges);}return domHighlights}render(){const highlights=this._getDOMHighlights();const buildHighlight=r=>this._buildHighlight(r);return jsxRuntimeExports.jsxs("div",{className:css(styles$A.container),ref:container=>this._container=container,children:[jsxRuntimeExports.jsx("div",{children:this.props.enabled&&this._container&&this._content&&jsxRuntimeExports.jsx(HighlightingUI,{buildHighlight:buildHighlight,contentNode:this._content,editable:this.props.editable,highlights:highlights,offsetParent:this._container,zIndexes:{belowContent:0},onAddHighlight:this._handleAddHighlight,onRemoveHighlight:this._handleRemoveHighlight})}),jsxRuntimeExports.jsx("div",{className:css(styles$A.content),ref:content=>this._content=content,children:jsxRuntimeExports.jsx(WordIndexer,{onWordsUpdate:this._handleWordsUpdate,children:this.props.children})})]})}constructor(...args){super(...args),this.state={wordRanges:[]},this._handleAddHighlight=highlight=>{const newDomHighlights=addHighlight(this._getDOMHighlights(),highlight);const newSerializedHighlights={};for(const key of Object.keys(newDomHighlights)){newSerializedHighlights[key]=serializeHighlight(newDomHighlights[key]);}this.props.onSerializedHighlightsUpdate(newSerializedHighlights);},this._handleRemoveHighlight=keyToRemove=>{const{serializedHighlights}=this.props;const newSerializedHighlights={...serializedHighlights};delete newSerializedHighlights[keyToRemove];this.props.onSerializedHighlightsUpdate(newSerializedHighlights);},this._handleWordsUpdate=wordRanges=>{this.setState({wordRanges});};}}const styles$A=StyleSheet.create({container:{position:"relative",zIndex:0},content:{position:"relative",zIndex:1}});
1734
+ class HighlightableContent extends React.PureComponent{_buildHighlight(highlightRange){return buildHighlight(this._getDOMHighlights(),this.state.wordRanges,highlightRange)}_getDOMHighlights(){const{serializedHighlights}=this.props;const{wordRanges}=this.state;const domHighlights={};for(const key of Object.keys(serializedHighlights)){domHighlights[key]=deserializeHighlight(serializedHighlights[key],wordRanges);}return domHighlights}render(){const highlights=this._getDOMHighlights();const buildHighlight=r=>this._buildHighlight(r);return jsxRuntimeExports.jsxs("div",{className:css(styles$D.container),ref:container=>this._container=container,children:[jsxRuntimeExports.jsx("div",{children:this.props.enabled&&this._container&&this._content&&jsxRuntimeExports.jsx(HighlightingUI,{buildHighlight:buildHighlight,contentNode:this._content,editable:this.props.editable,highlights:highlights,offsetParent:this._container,zIndexes:{belowContent:0},onAddHighlight:this._handleAddHighlight,onRemoveHighlight:this._handleRemoveHighlight})}),jsxRuntimeExports.jsx("div",{className:css(styles$D.content),ref:content=>this._content=content,children:jsxRuntimeExports.jsx(WordIndexer,{onWordsUpdate:this._handleWordsUpdate,children:this.props.children})})]})}constructor(...args){super(...args),this.state={wordRanges:[]},this._handleAddHighlight=highlight=>{const newDomHighlights=addHighlight(this._getDOMHighlights(),highlight);const newSerializedHighlights={};for(const key of Object.keys(newDomHighlights)){newSerializedHighlights[key]=serializeHighlight(newDomHighlights[key]);}this.props.onSerializedHighlightsUpdate(newSerializedHighlights);},this._handleRemoveHighlight=keyToRemove=>{const{serializedHighlights}=this.props;const newSerializedHighlights={...serializedHighlights};delete newSerializedHighlights[keyToRemove];this.props.onSerializedHighlightsUpdate(newSerializedHighlights);},this._handleWordsUpdate=wordRanges=>{this.setState({wordRanges});};}}const styles$D=StyleSheet.create({container:{position:"relative",zIndex:0},content:{position:"relative",zIndex:1}});
1730
1735
 
1731
1736
  const getPromptJSON$o=renderProps=>{return {type:"passage",options:{passageTitle:renderProps.passageTitle,passageText:renderProps.passageText,footnotes:renderProps.footnotes}}};
1732
1737
 
1733
1738
  function getInitialParseState(){return {currentRef:[],useRefs:true,lastRef:0,firstSentenceRef:null,firstQuestionRef:null,lastFootnote:{id:0,text:""}}}class RefStart extends React.Component{render(){return jsxRuntimeExports.jsx("span",{style:REF_STYLE,children:"_"})}constructor(...args){super(...args),this.getRefContent=()=>{return this.props.refContent};}}class RefEnd extends React.Component{render(){return jsxRuntimeExports.jsx("span",{style:REF_STYLE,children:"_"})}}const AltText=({id,number})=>{const{strings}=usePerseusI18n();return jsxRuntimeExports.jsx("span",{className:"perseus-sr-only",children:strings[id]({number})},"alt-text")};const rules={newline:SimpleMarkdown.defaultRules.newline,paragraph:SimpleMarkdown.defaultRules.paragraph,escape:SimpleMarkdown.defaultRules.escape,passageFootnote:{order:SimpleMarkdown.defaultRules.escape.order+.1,match:SimpleMarkdown.inlineRegex(/^\^/),parse:(capture,parse,state)=>{const id=state.lastFootnote.id+1;const footnote={id:id,text:id===1?"*":""+id};if(state.lastFootnote.text==="*"){state.lastFootnote.text=""+state.lastFootnote.id;}state.lastFootnote=footnote;return footnote},react:(node,output,state)=>{return jsxRuntimeExports.jsx("sup",{children:node.text},state.key)}},refStart:{order:SimpleMarkdown.defaultRules.escape.order+.2,match:function(source){const capture=/^\{\{/.exec(source);if(capture){let closeIndex=2;let refNestingLevel=0;while(closeIndex<source.length){const token=source.slice(closeIndex,closeIndex+2);if(token==="{{"){refNestingLevel++;closeIndex++;}else if(token==="}}"){if(refNestingLevel>0){refNestingLevel--;closeIndex++;}else {break}}closeIndex++;}capture[1]=source.slice(2,closeIndex);return capture}return null},parse:(capture,parse,state)=>{if(!state.useRefs){return {ref:null,refContent:null}}const ref=state.lastRef+1;state.lastRef=ref;state.currentRef.push(ref);const refContent=parse("(“"+capture[1]+"”)\n\n",_.defaults({useRefs:false},getInitialParseState()));return {ref:ref,refContent:refContent}},react:(node,output,state)=>{const ref=node.ref;if(ref==null){return null}const refContent=output(node.refContent,{});return jsxRuntimeExports.jsx(RefStart,{ref:START_REF_PREFIX+ref,refContent:refContent},START_REF_PREFIX+ref)}},refEnd:{order:SimpleMarkdown.defaultRules.escape.order+.3,match:SimpleMarkdown.inlineRegex(/^\}\}/),parse:(capture,parse,state)=>{if(!state.useRefs){return {ref:null}}const ref=state.currentRef.pop()||null;return {ref:ref}},react:(node,output,state)=>{if(node.ref!=null){return jsxRuntimeExports.jsx(RefEnd,{ref:END_REF_PREFIX+node.ref},END_REF_PREFIX+node.ref)}return null}},squareLabel:{order:SimpleMarkdown.defaultRules.escape.order+.4,match:SimpleMarkdown.inlineRegex(/^\[\[(\w+)\]\]( *)/),parse:(capture,parse,state)=>{if(!state.firstQuestionRef){state.firstQuestionRef=capture[1];}return {content:capture[1],space:capture[2].length>0}},react:(node,output,state)=>{return [jsxRuntimeExports.jsx("span",{className:"perseus-passage-square-label",style:LABEL_OUTER_STYLE,"aria-hidden":"true",children:jsxRuntimeExports.jsx("span",{style:SQUARE_LABEL_STYLE,children:node.content})},"visual-square"),jsxRuntimeExports.jsx(AltText,{id:"questionMarker",number:node.content},"alt-text"),node.space?" ":null]}},circleLabel:{order:SimpleMarkdown.defaultRules.escape.order+.5,match:SimpleMarkdown.inlineRegex(/^\(\((\w+)\)\)( *)/),parse:(capture,parse,state)=>{return {content:capture[1],space:capture[2].length>0}},react:(node,output,state)=>{return [jsxRuntimeExports.jsx("span",{className:"perseus-passage-circle-label",style:LABEL_OUTER_STYLE,"aria-hidden":true,children:jsxRuntimeExports.jsx("span",{style:CIRCLE_LABEL_STYLE,children:node.content})},"visual-circle"),jsxRuntimeExports.jsx(AltText,{id:"circleMarker",number:node.content},"alt-text"),node.space?" ":null]}},squareBracketRef:{order:SimpleMarkdown.defaultRules.escape.order+.6,match:SimpleMarkdown.inlineRegex(/^\[(\d+)\]( *)/),parse:(capture,parse,state)=>{if(!state.firstSentenceRef){state.firstSentenceRef=capture[1];}return {content:capture[1],space:capture[2].length>0}},react:(node,output,state)=>{return [jsxRuntimeExports.jsxs("span",{className:"perseus-passage-bracket-label","aria-hidden":"true",children:["[",node.content,"]"]},"visual-brackets"),jsxRuntimeExports.jsx(AltText,{id:"sentenceMarker",number:node.content},"alt-text"),node.space?" ":null]}},highlight:{order:SimpleMarkdown.defaultRules.escape.order+.7,match:SimpleMarkdown.inlineRegex(/^{highlighting.start}(.+?){highlighting.end}/),parse:(capture,parse,state)=>{return {content:capture[1]}},react:(node,output,state)=>{return [jsxRuntimeExports.jsx("span",{className:"perseus-highlight",children:node.content},0)]}},reviewHighlight:{order:SimpleMarkdown.defaultRules.escape.order+.7,match:SimpleMarkdown.inlineRegex(/^{review-highlighting.start}(.+?){review-highlighting.end}/),parse:(capture,parse,state)=>{return {content:capture[1]}},react:(node,output,state)=>{return [jsxRuntimeExports.jsx("span",{className:"perseus-review-highlight",children:node.content},0)]}},strong:SimpleMarkdown.defaultRules.strong,u:SimpleMarkdown.defaultRules.u,em:SimpleMarkdown.defaultRules.em,del:SimpleMarkdown.defaultRules.del,text:{...SimpleMarkdown.defaultRules.text,react(node,output,state){return jsxRuntimeExports.jsx("span",{children:node.content},state.key)}}};const START_REF_PREFIX="start-ref-";const END_REF_PREFIX="end-ref-";const REF_STYLE={display:"inline-block",width:0,visibility:"hidden"};const LABEL_OUTER_STYLE={display:"inline",whiteSpace:"nowrap"};const SQUARE_LABEL_STYLE={display:"inline-block",color:"rgb(255, 255, 255)",backgroundColor:"rgb(90, 90, 90)",paddingLeft:10,paddingRight:10,userSelect:"none",WebkitUserSelect:"none"};const CIRCLE_LABEL_STYLE={display:"inline-block",color:"rgb(255, 255, 255)",backgroundColor:"rgb(90, 90, 90)",userSelect:"none",WebkitUserSelect:"none",width:22,height:22,borderRadius:"50%",textAlign:"center"};const builtParser=SimpleMarkdown.parserFor(rules);const parse$2=(source,state)=>{state=state||{};const paragraphedSource=source+"\n\n";return builtParser(paragraphedSource,_.extend(state,getInitialParseState()))};const output=SimpleMarkdown.reactFor(SimpleMarkdown.ruleOutput(rules,"react"));var PassageMarkdown = {parse: parse$2,output,START_REF_PREFIX,END_REF_PREFIX,getInitialParseState};
1734
1739
 
1735
- class LineHeightMeasurer extends React.Component{measureLineHeight(){if(!this._line){return 0}return this._line.clientHeight}render(){return jsxRuntimeExports.jsx("div",{className:css(styles$z.measurer),"aria-hidden":"true",children:jsxRuntimeExports.jsx("div",{ref:ref=>this._line=ref,className:"paragraph",children:"Line Height Measurement"})})}}const styles$z=StyleSheet.create({measurer:{position:"absolute",top:0,left:0,visibility:"hidden",zIndex:-1}});class Passage extends React.Component{componentDidMount(){this._updateState();this._onResize=_.throttle(()=>{if(this.shouldRenderJipt()){return}this._lineHeightMeasurerRef?.measureLineHeight();this._updateState();},500);window.addEventListener("resize",this._onResize);this._stylesAppiedTimer=window.setTimeout(()=>{this.setState({stylesAreApplied:true});},0);}shouldComponentUpdate(nextProps,nextState){return !_.isEqual(this.props,nextProps)||!_.isEqual(this.state,nextState)}componentDidUpdate(){this._updateState();}componentWillUnmount(){window.removeEventListener("resize",this._onResize);clearTimeout(this._stylesAppiedTimer);}_updateState(){if(this.shouldRenderJipt()){return}this.setState({nLines:this._measureLines(),startLineNumbersAfter:this._getInitialLineNumber()});}_measureLines(){const renderer=ReactDOM.findDOMNode(this._contentRef);const contentsHeight=$(renderer).height();const lineHeight=this._getLineHeight();const nLines=Math.round(contentsHeight/lineHeight);return nLines}_getInitialLineNumber(){let isPassageBeforeThisPassage=true;const passagesBeforeUs=this.props.findWidgets((id,widgetInfo)=>{if(widgetInfo.type!=="passage"){return false}if(id===this.props.widgetId){isPassageBeforeThisPassage=false;}return isPassageBeforeThisPassage}).filter(isPassageWidget);return passagesBeforeUs.map(passageWidget=>{return passageWidget.getLineCount()}).reduce((a,b)=>a+b,0)}_getLineHeight(){return this._lineHeightMeasurerRef?.measureLineHeight()||0}getLineCount(){if(this.state.nLines!=null){return this.state.nLines}return this._measureLines()}_getStartRefLineNumber(referenceNumber){const refRef=PassageMarkdown.START_REF_PREFIX+referenceNumber;const ref=this.refs[refRef];if(!ref){return null}const $ref=$(ReactDOM.findDOMNode(ref));let $refText=$ref.next();if($refText.length===0){$refText=$ref;}const vPos=$refText.offset().top;return this.state.startLineNumbersAfter+1+this._convertPosToLineNumber(vPos)}_getEndRefLineNumber(referenceNumber){const refRef=PassageMarkdown.END_REF_PREFIX+referenceNumber;const ref=this.refs[refRef];if(!ref){return null}const $ref=$(ReactDOM.findDOMNode(ref));let $refText=$ref.prev();if($refText.length===0){$refText=$ref;}const height=$refText.height();const vPos=$refText.offset().top;let line=this._convertPosToLineNumber(vPos+height);if(height===0){line+=1;}return this.state.startLineNumbersAfter+line}_convertPosToLineNumber(absoluteVPos){const content=ReactDOM.findDOMNode(this._contentRef);const relativeVPos=absoluteVPos-$(content).offset().top;const lineHeight=this._getLineHeight();const line=Math.round(relativeVPos/lineHeight);return line}_getRefContent(referenceNumber){const refRef=PassageMarkdown.START_REF_PREFIX+referenceNumber;const ref=this.refs[refRef];if(!ref){return null}return ref.getRefContent()}getReference(referenceNumber){const refStartLine=this._getStartRefLineNumber(referenceNumber);const refEndLine=this._getEndRefLineNumber(referenceNumber);if(refStartLine==null||refEndLine==null){return null}const refContent=this._getRefContent(referenceNumber);return {startLine:refStartLine,endLine:refEndLine,content:refContent}}getPromptJSON(){return getPromptJSON$o(this.props)}_renderInstructions(parseState){const firstQuestionNumber=parseState.firstQuestionRef;const firstSentenceRef=parseState.firstSentenceRef;const{strings}=this.context;let instructions="";if(firstQuestionNumber){instructions+=strings.symbolPassage({questionSymbol:"[["+firstQuestionNumber+"]]",questionNumber:firstQuestionNumber});}if(firstSentenceRef){instructions+=strings.symbolQuestion({sentenceSymbol:"["+firstSentenceRef+"]"});}const parsedInstructions=PassageMarkdown.parse(instructions);return jsxRuntimeExports.jsx("div",{className:"perseus-widget-passage-instructions",children:PassageMarkdown.output(parsedInstructions)})}shouldRenderJipt(){const{JIPT}=getDependencies();return JIPT.useJIPT&&this.props.passageText.indexOf("crwdns")!==-1}_renderContent(parsed){const enabled=this.state.stylesAreApplied;const editable=!this.props.reviewMode;return jsxRuntimeExports.jsx(HighlightableContent,{editable:editable,enabled:enabled,onSerializedHighlightsUpdate:this._handleSerializedHighlightsUpdate,serializedHighlights:this.props.highlights,children:jsxRuntimeExports.jsxs("div",{ref:ref=>this._contentRef=ref,children:[jsxRuntimeExports.jsx(LineHeightMeasurer,{ref:ref=>this._lineHeightMeasurerRef=ref}),PassageMarkdown.output(parsed)]})})}_hasFootnotes(){const rawContent=this.props.footnotes;const isEmpty=/^\s*$/.test(rawContent);return !isEmpty}_renderFootnotes(){const rawContent=this.props.footnotes;const parsed=PassageMarkdown.parse(rawContent);return PassageMarkdown.output(parsed)}render(){const{strings}=this.context;let lineNumbers;const nLines=this.state.nLines;if(this.props.showLineNumbers&&nLines){lineNumbers=_.range(1,nLines+1).map(lineN=>{const lineAt=lineN+this.state.startLineNumbersAfter;if(lineAt===4){const translatedLine=strings.lineLabel;return jsxRuntimeExports.jsx("span",{className:"line-marker",children:translatedLine},"line-marker")}return jsxRuntimeExports.jsx("span",{children:lineAt},lineN)});}const parseState=PassageMarkdown.getInitialParseState();const re=/("{1})([^"]*)("{1})/g;const doubleQuoteParsedContent=this.props.passageText.replace(re,"“$2”");const parsedContent=PassageMarkdown.parse(doubleQuoteParsedContent,parseState);const hasTitle=/\S/.test(this.props.passageTitle);return jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-passage-container",children:[this._renderInstructions(parseState),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-passage",children:[hasTitle&&jsxRuntimeExports.jsx("h3",{className:"passage-title",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.passageTitle,linterContext:this.props.linterContext,strings:strings})}),lineNumbers&&jsxRuntimeExports.jsx("div",{className:"line-numbers","aria-hidden":true,children:lineNumbers}),!hasTitle&&jsxRuntimeExports.jsx("h3",{className:"perseus-sr-only",children:strings.beginningPassage}),jsxRuntimeExports.jsx("div",{className:"passage-text",children:this.shouldRenderJipt()?jsxRuntimeExports.jsx(Renderer,{content:this.props.passageText,strings:strings}):this._renderContent(parsedContent)}),this._hasFootnotes()&&[jsxRuntimeExports.jsx("h4",{className:"perseus-sr-only",children:strings.beginningFootnotes},"footnote-start"),jsxRuntimeExports.jsx("div",{className:"footnotes",children:this._renderFootnotes()},"footnotes")],jsxRuntimeExports.jsx("div",{className:"perseus-sr-only",children:strings.endPassage})]})]})})}constructor(...args){super(...args),this.isWidget=true,this.state={nLines:null,startLineNumbersAfter:0,stylesAreApplied:false},this._handleSerializedHighlightsUpdate=serializedHighlights=>{this.props.onChange({highlights:serializedHighlights});};}}Passage.contextType=PerseusI18nContext;Passage.defaultProps={passageTitle:"",passageText:"",footnotes:"",showLineNumbers:true,highlights:{},linterContext:linterContextDefault};var Passage$1 = {name:"passage",displayName:"Passage (SAT only)",hidden:true,widget:Passage,transform:editorProps=>{return _.pick(editorProps,"passageTitle","passageText","footnotes","showLineNumbers")},isLintable:true};
1740
+ class LineHeightMeasurer extends React.Component{measureLineHeight(){if(!this._line){return 0}return this._line.clientHeight}render(){return jsxRuntimeExports.jsx("div",{className:css(styles$C.measurer),"aria-hidden":"true",children:jsxRuntimeExports.jsx("div",{ref:ref=>this._line=ref,className:"paragraph",children:"Line Height Measurement"})})}}const styles$C=StyleSheet.create({measurer:{position:"absolute",top:0,left:0,visibility:"hidden",zIndex:-1}});class Passage extends React.Component{componentDidMount(){this._updateState();this._onResize=_.throttle(()=>{if(this.shouldRenderJipt()){return}this._lineHeightMeasurerRef?.measureLineHeight();this._updateState();},500);window.addEventListener("resize",this._onResize);this._stylesAppiedTimer=window.setTimeout(()=>{this.setState({stylesAreApplied:true});},0);}shouldComponentUpdate(nextProps,nextState){return !_.isEqual(this.props,nextProps)||!_.isEqual(this.state,nextState)}componentDidUpdate(){this._updateState();}componentWillUnmount(){window.removeEventListener("resize",this._onResize);clearTimeout(this._stylesAppiedTimer);}_updateState(){if(this.shouldRenderJipt()){return}this.setState({nLines:this._measureLines(),startLineNumbersAfter:this._getInitialLineNumber()});}_measureLines(){const renderer=ReactDOM.findDOMNode(this._contentRef);const contentsHeight=$(renderer).height();const lineHeight=this._getLineHeight();const nLines=Math.round(contentsHeight/lineHeight);return nLines}_getInitialLineNumber(){let isPassageBeforeThisPassage=true;const passagesBeforeUs=this.props.findWidgets((id,widgetInfo)=>{if(widgetInfo.type!=="passage"){return false}if(id===this.props.widgetId){isPassageBeforeThisPassage=false;}return isPassageBeforeThisPassage}).filter(isPassageWidget);return passagesBeforeUs.map(passageWidget=>{return passageWidget.getLineCount()}).reduce((a,b)=>a+b,0)}_getLineHeight(){return this._lineHeightMeasurerRef?.measureLineHeight()||0}getLineCount(){if(this.state.nLines!=null){return this.state.nLines}return this._measureLines()}_getStartRefLineNumber(referenceNumber){const refRef=PassageMarkdown.START_REF_PREFIX+referenceNumber;const ref=this.refs[refRef];if(!ref){return null}const $ref=$(ReactDOM.findDOMNode(ref));let $refText=$ref.next();if($refText.length===0){$refText=$ref;}const vPos=$refText.offset().top;return this.state.startLineNumbersAfter+1+this._convertPosToLineNumber(vPos)}_getEndRefLineNumber(referenceNumber){const refRef=PassageMarkdown.END_REF_PREFIX+referenceNumber;const ref=this.refs[refRef];if(!ref){return null}const $ref=$(ReactDOM.findDOMNode(ref));let $refText=$ref.prev();if($refText.length===0){$refText=$ref;}const height=$refText.height();const vPos=$refText.offset().top;let line=this._convertPosToLineNumber(vPos+height);if(height===0){line+=1;}return this.state.startLineNumbersAfter+line}_convertPosToLineNumber(absoluteVPos){const content=ReactDOM.findDOMNode(this._contentRef);const relativeVPos=absoluteVPos-$(content).offset().top;const lineHeight=this._getLineHeight();const line=Math.round(relativeVPos/lineHeight);return line}_getRefContent(referenceNumber){const refRef=PassageMarkdown.START_REF_PREFIX+referenceNumber;const ref=this.refs[refRef];if(!ref){return null}return ref.getRefContent()}getReference(referenceNumber){const refStartLine=this._getStartRefLineNumber(referenceNumber);const refEndLine=this._getEndRefLineNumber(referenceNumber);if(refStartLine==null||refEndLine==null){return null}const refContent=this._getRefContent(referenceNumber);return {startLine:refStartLine,endLine:refEndLine,content:refContent}}getPromptJSON(){return getPromptJSON$o(this.props)}_renderInstructions(parseState){const firstQuestionNumber=parseState.firstQuestionRef;const firstSentenceRef=parseState.firstSentenceRef;const{strings}=this.context;let instructions="";if(firstQuestionNumber){instructions+=strings.symbolPassage({questionSymbol:"[["+firstQuestionNumber+"]]",questionNumber:firstQuestionNumber});}if(firstSentenceRef){instructions+=strings.symbolQuestion({sentenceSymbol:"["+firstSentenceRef+"]"});}const parsedInstructions=PassageMarkdown.parse(instructions);return jsxRuntimeExports.jsx("div",{className:"perseus-widget-passage-instructions",children:PassageMarkdown.output(parsedInstructions)})}shouldRenderJipt(){const{JIPT}=getDependencies();return JIPT.useJIPT&&this.props.passageText.indexOf("crwdns")!==-1}_renderContent(parsed){const enabled=this.state.stylesAreApplied;const editable=!this.props.reviewMode;return jsxRuntimeExports.jsx(HighlightableContent,{editable:editable,enabled:enabled,onSerializedHighlightsUpdate:this._handleSerializedHighlightsUpdate,serializedHighlights:this.props.highlights,children:jsxRuntimeExports.jsxs("div",{ref:ref=>this._contentRef=ref,children:[jsxRuntimeExports.jsx(LineHeightMeasurer,{ref:ref=>this._lineHeightMeasurerRef=ref}),PassageMarkdown.output(parsed)]})})}_hasFootnotes(){const rawContent=this.props.footnotes;const isEmpty=/^\s*$/.test(rawContent);return !isEmpty}_renderFootnotes(){const rawContent=this.props.footnotes;const parsed=PassageMarkdown.parse(rawContent);return PassageMarkdown.output(parsed)}render(){const{strings}=this.context;let lineNumbers;const nLines=this.state.nLines;if(this.props.showLineNumbers&&nLines){lineNumbers=_.range(1,nLines+1).map(lineN=>{const lineAt=lineN+this.state.startLineNumbersAfter;if(lineAt===4){const translatedLine=strings.lineLabel;return jsxRuntimeExports.jsx("span",{className:"line-marker",children:translatedLine},"line-marker")}return jsxRuntimeExports.jsx("span",{children:lineAt},lineN)});}const parseState=PassageMarkdown.getInitialParseState();const re=/("{1})([^"]*)("{1})/g;const doubleQuoteParsedContent=this.props.passageText.replace(re,"“$2”");const parsedContent=PassageMarkdown.parse(doubleQuoteParsedContent,parseState);const hasTitle=/\S/.test(this.props.passageTitle);return jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-passage-container",children:[this._renderInstructions(parseState),jsxRuntimeExports.jsxs("div",{className:"perseus-widget-passage",children:[hasTitle&&jsxRuntimeExports.jsx("h3",{className:"passage-title",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.passageTitle,linterContext:this.props.linterContext,strings:strings})}),lineNumbers&&jsxRuntimeExports.jsx("div",{className:"line-numbers","aria-hidden":true,children:lineNumbers}),!hasTitle&&jsxRuntimeExports.jsx("h3",{className:"perseus-sr-only",children:strings.beginningPassage}),jsxRuntimeExports.jsx("div",{className:"passage-text",children:this.shouldRenderJipt()?jsxRuntimeExports.jsx(Renderer,{content:this.props.passageText,strings:strings}):this._renderContent(parsedContent)}),this._hasFootnotes()&&[jsxRuntimeExports.jsx("h4",{className:"perseus-sr-only",children:strings.beginningFootnotes},"footnote-start"),jsxRuntimeExports.jsx("div",{className:"footnotes",children:this._renderFootnotes()},"footnotes")],jsxRuntimeExports.jsx("div",{className:"perseus-sr-only",children:strings.endPassage})]})]})})}constructor(...args){super(...args),this.isWidget=true,this.state={nLines:null,startLineNumbersAfter:0,stylesAreApplied:false},this._handleSerializedHighlightsUpdate=serializedHighlights=>{this.props.onChange({highlights:serializedHighlights});};}}Passage.contextType=PerseusI18nContext;Passage.defaultProps={passageTitle:"",passageText:"",footnotes:"",showLineNumbers:true,highlights:{},linterContext:linterContextDefault};var Passage$1 = {name:"passage",displayName:"Passage (SAT only)",hidden:true,widget:Passage,transform:editorProps=>{return _.pick(editorProps,"passageTitle","passageText","footnotes","showLineNumbers")},isLintable:true};
1736
1741
 
1737
1742
  function isPassageWidget(widget){return widget instanceof Passage}
1738
1743
 
@@ -1746,41 +1751,49 @@ const BASE_ICON_SIZE=10;class Icon extends React.Component{render(){const{color,
1746
1751
 
1747
1752
  function getA11yText$1(letter,checked,correct,crossedOut,showCorrectness,strings){if(showCorrectness&&correct){if(checked){return strings.choiceCheckedCorrect({letter})}if(crossedOut){return strings.choiceCrossedOutCorrect({letter})}return strings.choiceCorrect({letter})}if(showCorrectness&&!correct){if(checked){return strings.choiceCheckedIncorrect({letter})}if(crossedOut){return strings.choiceCrossedOutIncorrect({letter})}return strings.choiceIncorrect({letter})}if(checked){return strings.choiceChecked({letter})}if(crossedOut){return strings.choiceCrossedOut({letter})}return strings.choice({letter})}
1748
1753
 
1749
- const FocusRing=function({visible=true,color=kaGreen,multipleSelect=false,children}){const borderColor=visible?color:"transparent";const borderRadius=multipleSelect?5:"50%";const style={borderColor,borderRadius};return jsxRuntimeExports.jsx("span",{"data-testid":"focus-ring",className:css(styles$y.ring),style:style,children:children})};const styles$y=StyleSheet.create({ring:{margin:"auto",display:"inline-block",borderWidth:2,padding:2,borderStyle:"solid"}});
1754
+ const FocusRing=function({visible=true,color=kaGreen,multipleSelect=false,children}){const borderColor=visible?color:"transparent";const borderRadius=multipleSelect?5:"50%";const style={borderColor,borderRadius};return jsxRuntimeExports.jsx("span",{"data-testid":"focus-ring",className:css(styles$B.ring),style:style,children:children})};const styles$B=StyleSheet.create({ring:{margin:"auto",display:"inline-block",borderWidth:2,padding:2,borderStyle:"solid"}});
1750
1755
 
1751
- function getChoiceLetter(pos,strings){const lettersString=strings.letters;const letters=lettersString.split(" ");if(pos<letters.length){return letters[pos]}return " "}
1756
+ function getChoiceLetter$1(pos,strings){const lettersString=strings.letters;const letters=lettersString.split(" ");if(pos<letters.length){return letters[pos]}return " "}
1752
1757
 
1753
- const CHOICE_ICON_SIZE=24;const styles$x=StyleSheet.create({iconWrapper:{display:"inline-block",position:"relative"}});
1758
+ const CHOICE_ICON_SIZE$1=24;const styles$A=StyleSheet.create({iconWrapper:{display:"inline-block",position:"relative"}});
1754
1759
 
1755
- const CROSS_OUT_LINE_PADDING=2;const CROSS_OUT_LINE_SIZE=CHOICE_ICON_SIZE+CROSS_OUT_LINE_PADDING*2;const CrossOutLine=function(props){return jsxRuntimeExports.jsx("svg",{width:CROSS_OUT_LINE_SIZE,height:CROSS_OUT_LINE_SIZE,viewBox:`0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,className:css(styles$w.crossOutLine),"data-testid":"choice-icon__cross-out-line",children:jsxRuntimeExports.jsx("line",{x1:CROSS_OUT_LINE_PADDING,x2:CROSS_OUT_LINE_SIZE-CROSS_OUT_LINE_PADDING,y1:CROSS_OUT_LINE_SIZE-CROSS_OUT_LINE_PADDING,y2:CROSS_OUT_LINE_PADDING,stroke:props.color,strokeWidth:"2",strokeLinecap:"round"})})};const styles$w=StyleSheet.create({crossOutLine:{position:"absolute",top:`2px`,left:`2px`}});
1760
+ const CROSS_OUT_LINE_PADDING=2;const CROSS_OUT_LINE_SIZE=CHOICE_ICON_SIZE$1+CROSS_OUT_LINE_PADDING*2;const CrossOutLine=function(props){return jsxRuntimeExports.jsx("svg",{width:CROSS_OUT_LINE_SIZE,height:CROSS_OUT_LINE_SIZE,viewBox:`0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,className:css(styles$z.crossOutLine),"data-testid":"choice-icon__cross-out-line",children:jsxRuntimeExports.jsx("line",{x1:CROSS_OUT_LINE_PADDING,x2:CROSS_OUT_LINE_SIZE-CROSS_OUT_LINE_PADDING,y1:CROSS_OUT_LINE_SIZE-CROSS_OUT_LINE_PADDING,y2:CROSS_OUT_LINE_PADDING,stroke:props.color,strokeWidth:"2",strokeLinecap:"round"})})};const styles$z=StyleSheet.create({crossOutLine:{position:"absolute",top:`2px`,left:`2px`}});
1756
1761
 
1757
- function ChoiceInner$1(props){const{pos,showCorrectness,correct}=props;const{strings}=usePerseusI18n();const letter=getChoiceLetter(pos,strings);if(!showCorrectness){return jsxRuntimeExports.jsx("span",{children:letter})}if(correct){return jsxRuntimeExports.jsx(InlineIcon,{...iconCheck,style:{position:"relative",top:-1}})}return jsxRuntimeExports.jsx(InlineIcon,{...iconMinus})}const ChoiceIcon$1=function(props){const{checked,crossedOut,showCorrectness,correct,focused,hovered,multipleSelect,pos,previouslyAnswered,pressed}=props;const choiceIsChecked=checked||showCorrectness&&!correct&&previouslyAnswered;const choiceStyling=[styles$v.choiceBase,multipleSelect?styles$v.multiSelectShape:styles$v.singleSelectShape,showCorrectness?styles$v.choiceHasIcon:styles$v.choiceHasLetter,choiceIsChecked?styles$v.choiceIsChecked:styles$v.choiceIsUnchecked];let crossOutColor;if(showCorrectness&&correct&&checked){choiceStyling.push(styles$v.choiceCorrect);crossOutColor=color.green;}else if(showCorrectness&&!correct&&(checked||previouslyAnswered)){choiceStyling.push(styles$v.choiceIncorrect);crossOutColor=color.red;}else if(checked){choiceStyling.push(styles$v.choiceNeutral);crossOutColor=color.blue;}else if(pressed){choiceStyling.push(styles$v.activeNeutral);crossOutColor=color.blue;}else {choiceStyling.push(styles$v.uncheckedColors);crossOutColor=color.offBlack64;}return jsxRuntimeExports.jsxs("div",{className:css(styles$x.iconWrapper),children:[jsxRuntimeExports.jsx(FocusRing,{color:color.blue,visible:focused||hovered,multipleSelect:multipleSelect,children:jsxRuntimeExports.jsx("div",{"data-testid":"choice-icon__library-choice-icon",className:css(...choiceStyling),"data-is-radio-icon":true,children:jsxRuntimeExports.jsx("div",{className:css(styles$v.innerWrapper),children:jsxRuntimeExports.jsx(ChoiceInner$1,{pos:pos,showCorrectness:showCorrectness,correct:correct})})})}),crossedOut&&jsxRuntimeExports.jsx(CrossOutLine,{color:crossOutColor})]})};const styles$v=StyleSheet.create({innerWrapper:{width:CHOICE_ICON_SIZE,height:CHOICE_ICON_SIZE,display:"flex",alignItems:"center",justifyContent:"center"},choiceBase:{width:CHOICE_ICON_SIZE,height:CHOICE_ICON_SIZE,boxSizing:"border-box",borderStyle:"solid",borderWidth:2,fontFamily:baseFontFamily,fontWeight:"bold",display:"flex",alignItems:"center",justifyContent:"center"},choiceHasLetter:{fontSize:12},choiceHasIcon:{fontSize:CHOICE_ICON_SIZE},choiceIsChecked:{color:color.white},choiceIsUnchecked:{color:color.offBlack64},choiceCorrect:{backgroundColor:color.green,borderColor:color.green},choiceIncorrect:{backgroundColor:color.red,borderColor:color.red},choiceNeutral:{backgroundColor:color.blue,borderColor:color.blue},activeNeutral:{color:color.blue,borderColor:color.blue,backgroundColor:"transparent"},multiSelectShape:{borderRadius:3},singleSelectShape:{borderRadius:CHOICE_ICON_SIZE},uncheckedColors:{borderColor:color.offBlack64}});
1762
+ function ChoiceInner$1(props){const{pos,showCorrectness,correct}=props;const{strings}=usePerseusI18n();const letter=getChoiceLetter$1(pos,strings);if(!showCorrectness){return jsxRuntimeExports.jsx("span",{children:letter})}if(correct){return jsxRuntimeExports.jsx(InlineIcon,{...iconCheck,style:{position:"relative",top:-1}})}return jsxRuntimeExports.jsx(InlineIcon,{...iconMinus})}const ChoiceIcon$1=function(props){const{checked,crossedOut,showCorrectness,correct,focused,hovered,multipleSelect,pos,previouslyAnswered,pressed}=props;const choiceIsChecked=checked||showCorrectness&&!correct&&previouslyAnswered;const choiceStyling=[styles$y.choiceBase,multipleSelect?styles$y.multiSelectShape:styles$y.singleSelectShape,showCorrectness?styles$y.choiceHasIcon:styles$y.choiceHasLetter,choiceIsChecked?styles$y.choiceIsChecked:styles$y.choiceIsUnchecked];let crossOutColor;if(showCorrectness&&correct&&checked){choiceStyling.push(styles$y.choiceCorrect);crossOutColor=color.green;}else if(showCorrectness&&!correct&&(checked||previouslyAnswered)){choiceStyling.push(styles$y.choiceIncorrect);crossOutColor=color.red;}else if(checked){choiceStyling.push(styles$y.choiceNeutral);crossOutColor=color.blue;}else if(pressed){choiceStyling.push(styles$y.activeNeutral);crossOutColor=color.blue;}else {choiceStyling.push(styles$y.uncheckedColors);crossOutColor=color.offBlack64;}return jsxRuntimeExports.jsxs("div",{className:css(styles$A.iconWrapper),children:[jsxRuntimeExports.jsx(FocusRing,{color:color.blue,visible:focused||hovered,multipleSelect:multipleSelect,children:jsxRuntimeExports.jsx("div",{"data-testid":"choice-icon__library-choice-icon",className:css(...choiceStyling),"data-is-radio-icon":true,children:jsxRuntimeExports.jsx("div",{className:css(styles$y.innerWrapper),children:jsxRuntimeExports.jsx(ChoiceInner$1,{pos:pos,showCorrectness:showCorrectness,correct:correct})})})}),crossedOut&&jsxRuntimeExports.jsx(CrossOutLine,{color:crossOutColor})]})};const styles$y=StyleSheet.create({innerWrapper:{width:CHOICE_ICON_SIZE$1,height:CHOICE_ICON_SIZE$1,display:"flex",alignItems:"center",justifyContent:"center"},choiceBase:{width:CHOICE_ICON_SIZE$1,height:CHOICE_ICON_SIZE$1,boxSizing:"border-box",borderStyle:"solid",borderWidth:2,fontFamily:baseFontFamily,fontWeight:"bold",display:"flex",alignItems:"center",justifyContent:"center"},choiceHasLetter:{fontSize:12},choiceHasIcon:{fontSize:CHOICE_ICON_SIZE$1},choiceIsChecked:{color:color.white},choiceIsUnchecked:{color:color.offBlack64},choiceCorrect:{backgroundColor:color.green,borderColor:color.green},choiceIncorrect:{backgroundColor:color.red,borderColor:color.red},choiceNeutral:{backgroundColor:color.blue,borderColor:color.blue},activeNeutral:{color:color.blue,borderColor:color.blue,backgroundColor:"transparent"},multiSelectShape:{borderRadius:3},singleSelectShape:{borderRadius:CHOICE_ICON_SIZE$1},uncheckedColors:{borderColor:color.offBlack64}});
1758
1763
 
1759
- function renderText$1(checked,correct,crossedOut,strings){if(correct){if(checked){return strings.correctSelected}if(crossedOut){return strings.correctCrossedOut}return strings.correct}if(checked){return strings.incorrectSelected}return strings.incorrect}const OptionStatus$1=function(props){const{checked,correct,crossedOut,previouslyAnswered,reviewMode}=props;const{strings}=usePerseusI18n();if(!reviewMode&&!previouslyAnswered){return null}let textStyle;if(correct){textStyle=styles$u.correct;}else {if(checked||previouslyAnswered){textStyle=styles$u.incorrectAnswered;}else {textStyle=styles$u.incorrect;}}return jsxRuntimeExports.jsx("div",{className:css(styles$u.text,textStyle),children:renderText$1(checked,correct,crossedOut,strings)})};const styles$u=StyleSheet.create({text:{alignItems:"center",display:"flex",fontSize:12,height:32,textTransform:"uppercase"},correct:{color:color.green},incorrectAnswered:{color:color.red},incorrect:{color:color.offBlack64}});
1764
+ function renderText(checked,correct,crossedOut,strings){if(correct){if(checked){return strings.correctSelected}if(crossedOut){return strings.correctCrossedOut}return strings.correct}if(checked){return strings.incorrectSelected}return strings.incorrect}const OptionStatus$1=function(props){const{checked,correct,crossedOut,previouslyAnswered,reviewMode}=props;const{strings}=usePerseusI18n();if(!reviewMode&&!previouslyAnswered){return null}let textStyle;if(correct){textStyle=styles$x.correct;}else {if(checked||previouslyAnswered){textStyle=styles$x.incorrectAnswered;}else {textStyle=styles$x.incorrect;}}return jsxRuntimeExports.jsx("div",{className:css(styles$x.text,textStyle),children:renderText(checked,correct,crossedOut,strings)})};const styles$x=StyleSheet.create({text:{alignItems:"center",display:"flex",fontSize:12,height:32,textTransform:"uppercase"},correct:{color:color.green},incorrectAnswered:{color:color.red},incorrect:{color:color.offBlack64}});
1760
1765
 
1761
- const intermediateCheckboxPadding$1=`16px 16px`;const intermediateCheckboxPaddingPhone$1=`12px 16px`;const ellipsisHorizontalIcon$1={path:"M27.218 6.82l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836z",width:100,height:27.284};const Choice$2=function(props){const{disabled=false,checked=false,content,crossedOut,showCorrectness,multipleSelect,onChange=newValues=>{},reviewMode,correct=false,apiOptions=ApiOptions.defaults,previouslyAnswered=false,pos=0,showRationale=false,rationale,forwardedRef}=props;const[isInputFocused,setIsInputFocused]=useState(false);const{strings}=usePerseusI18n();useEffect(()=>{if(isInputFocused&&disabled){setIsInputFocused(false);}},[disabled,isInputFocused,setIsInputFocused]);function sendChange(newValues){const updatedChecked=newValues.checked??checked;const updatedCrossedOut=newValues.crossedOut??crossedOut;onChange({checked:updatedChecked,crossedOut:updatedCrossedOut});}const descriptionClassName=classNames$1("description",css(styles$t.description));const rationaleClassName=classNames$1("perseus-radio-rationale-content",css(styles$t.rationale));const showDimmed=!reviewMode&&apiOptions.readOnly||crossedOut;const letter=getChoiceLetter(pos,strings);const a11yText=getA11yText$1(letter,checked,correct,crossedOut,showCorrectness,strings);return jsxRuntimeExports.jsxs("div",{style:{dispay:"flex",flexDirection:"column",color:color.offBlack},className:descriptionClassName,children:[jsxRuntimeExports.jsxs("div",{style:{display:"flex",flexDirection:"row",opacity:showDimmed?.5:1,overflowX:"auto",overflowY:"hidden"},children:[jsxRuntimeExports.jsx("div",{className:"perseus-sr-only",children:jsxRuntimeExports.jsxs("label",{children:[a11yText,"   ",content,jsxRuntimeExports.jsx("input",{type:multipleSelect?"checkbox":"radio",checked:checked,onClick:()=>{sendChange({checked:!checked,crossedOut:false});},onChange:()=>{},disabled:disabled||apiOptions.readOnly,tabIndex:-1,className:ClassNames.RADIO.OPTION_CONTENT})]})}),jsxRuntimeExports.jsx(Clickable,{onClick:()=>{sendChange({checked:!checked,crossedOut:false});},disabled:disabled||apiOptions.readOnly,style:{flex:1,color:color.offBlack,userSelect:"text"},ref:forwardedRef,"aria-hidden":"true",children:({hovered,focused,pressed})=>jsxRuntimeExports.jsxs("div",{style:{display:"flex",flexDirection:"row",justifyContent:"center",alignContent:"center",paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,paddingLeft:spacing.xSmall_8},children:[jsxRuntimeExports.jsx(ChoiceIcon$1,{pos:pos,correct:correct,crossedOut:crossedOut,pressed:pressed,focused:focused,checked:checked,hovered:hovered,showCorrectness:showCorrectness,multipleSelect:multipleSelect,reviewMode:reviewMode,previouslyAnswered:previouslyAnswered}),jsxRuntimeExports.jsxs("span",{style:{paddingLeft:spacing.small_12,textAlign:"left",flex:1,paddingTop:4},children:[jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(OptionStatus$1,{checked:checked,correct:correct,crossedOut:crossedOut,previouslyAnswered:previouslyAnswered,reviewMode:reviewMode})}),jsxRuntimeExports.jsx("div",{children:content})]})]})}),apiOptions.crossOutEnabled&&!reviewMode&&jsxRuntimeExports.jsx(Popover,{dismissEnabled:true,content:({close})=>jsxRuntimeExports.jsx(PopoverContent,{title:strings.crossOut,content:strings.crossOutOption,closeButtonVisible:true,actions:jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsx(Button,{kind:"primary","aria-label":strings.crossOutChoice({letter:getChoiceLetter(pos,strings)}),disabled:apiOptions.readOnly||reviewMode,onClick:()=>{if(!crossedOut){sendChange({checked:false,crossedOut:true});}else {sendChange({crossedOut:false});}close();},children:crossedOut?strings.bringBack:strings.crossOut})]})}),children:({open})=>jsxRuntimeExports.jsx(Clickable,{onClick:open,"aria-label":strings.openMenuForChoice({letter:getChoiceLetter(pos,strings)}),style:{alignSelf:"center",padding:"5px",display:"flex",justifyContent:"center",alignItems:"center",marginLeft:"10px"},children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(Icon,{icon:ellipsisHorizontalIcon$1,size:3,color:color.offBlack64})})})]}),showRationale&&jsxRuntimeExports.jsx("div",{className:rationaleClassName,"data-testid":`perseus-radio-rationale-content-${pos}`,children:rationale})]})};const styles$t=StyleSheet.create({description:{display:"inline-block",width:"100%"},rationale:{display:"block",padding:intermediateCheckboxPadding$1,paddingTop:0,marginLeft:54,color:color.offBlack64,[mediaQueries.smOrSmaller]:{padding:intermediateCheckboxPaddingPhone$1,paddingTop:0}}});var Choice$3 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(Choice$2,{...props,forwardedRef:ref}));
1766
+ const intermediateCheckboxPadding$1=`16px 16px`;const intermediateCheckboxPaddingPhone$1=`12px 16px`;const ellipsisHorizontalIcon$1={path:"M27.218 6.82l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836z",width:100,height:27.284};const Choice$1=function(props){const{disabled=false,checked=false,content,crossedOut,showCorrectness,multipleSelect,onChange=newValues=>{},reviewMode,correct=false,apiOptions=ApiOptions.defaults,previouslyAnswered=false,pos=0,showRationale=false,rationale,forwardedRef}=props;const[isInputFocused,setIsInputFocused]=useState(false);const{strings}=usePerseusI18n();useEffect(()=>{if(isInputFocused&&disabled){setIsInputFocused(false);}},[disabled,isInputFocused,setIsInputFocused]);function sendChange(newValues){const updatedChecked=newValues.checked??checked;const updatedCrossedOut=newValues.crossedOut??crossedOut;onChange({checked:updatedChecked,crossedOut:updatedCrossedOut});}const descriptionClassName=classNames$1("description",css(styles$w.description));const rationaleClassName=classNames$1("perseus-radio-rationale-content",css(styles$w.rationale));const showDimmed=!reviewMode&&apiOptions.readOnly||crossedOut;const letter=getChoiceLetter$1(pos,strings);const a11yText=getA11yText$1(letter,checked,correct,crossedOut,showCorrectness,strings);return jsxRuntimeExports.jsxs("div",{style:{dispay:"flex",flexDirection:"column",color:color.offBlack},className:descriptionClassName,children:[jsxRuntimeExports.jsxs("div",{style:{display:"flex",flexDirection:"row",opacity:showDimmed?.5:1,overflowX:"auto",overflowY:"hidden"},children:[jsxRuntimeExports.jsx("div",{className:"perseus-sr-only",children:jsxRuntimeExports.jsxs("label",{children:[a11yText,"   ",content,jsxRuntimeExports.jsx("input",{type:multipleSelect?"checkbox":"radio",checked:checked,onClick:()=>{sendChange({checked:!checked,crossedOut:false});},onChange:()=>{},disabled:disabled||apiOptions.readOnly,tabIndex:-1,className:ClassNames.RADIO.OPTION_CONTENT})]})}),jsxRuntimeExports.jsx(Clickable,{onClick:()=>{sendChange({checked:!checked,crossedOut:false});},disabled:disabled||apiOptions.readOnly,style:{flex:1,color:color.offBlack,userSelect:"text"},ref:forwardedRef,"aria-hidden":"true",children:({hovered,focused,pressed})=>jsxRuntimeExports.jsxs("div",{style:{display:"flex",flexDirection:"row",justifyContent:"center",alignContent:"center",paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,paddingLeft:spacing.xSmall_8},children:[jsxRuntimeExports.jsx(ChoiceIcon$1,{pos:pos,correct:correct,crossedOut:crossedOut,pressed:pressed,focused:focused,checked:checked,hovered:hovered,showCorrectness:showCorrectness,multipleSelect:multipleSelect,reviewMode:reviewMode,previouslyAnswered:previouslyAnswered}),jsxRuntimeExports.jsxs("span",{style:{paddingLeft:spacing.small_12,textAlign:"left",flex:1,paddingTop:4},children:[jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(OptionStatus$1,{checked:checked,correct:correct,crossedOut:crossedOut,previouslyAnswered:previouslyAnswered,reviewMode:reviewMode})}),jsxRuntimeExports.jsx("div",{children:content})]})]})}),apiOptions.crossOutEnabled&&!reviewMode&&jsxRuntimeExports.jsx(Popover,{dismissEnabled:true,content:({close})=>jsxRuntimeExports.jsx(PopoverContent,{title:strings.crossOut,content:strings.crossOutOption,closeButtonVisible:true,actions:jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsx(Button,{kind:"primary","aria-label":strings.crossOutChoice({letter:getChoiceLetter$1(pos,strings)}),disabled:apiOptions.readOnly||reviewMode,onClick:()=>{if(!crossedOut){sendChange({checked:false,crossedOut:true});}else {sendChange({crossedOut:false});}close();},children:crossedOut?strings.bringBack:strings.crossOut})]})}),children:({open})=>jsxRuntimeExports.jsx(Clickable,{onClick:open,"aria-label":strings.openMenuForChoice({letter:getChoiceLetter$1(pos,strings)}),style:{alignSelf:"center",padding:"5px",display:"flex",justifyContent:"center",alignItems:"center",marginLeft:"10px"},children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(Icon,{icon:ellipsisHorizontalIcon$1,size:3,color:color.offBlack64})})})]}),showRationale&&jsxRuntimeExports.jsx("div",{className:rationaleClassName,"data-testid":`perseus-radio-rationale-content-${pos}`,children:rationale})]})};const styles$w=StyleSheet.create({description:{display:"inline-block",width:"100%"},rationale:{display:"block",padding:intermediateCheckboxPadding$1,paddingTop:0,marginLeft:54,color:color.offBlack64,[mediaQueries.smOrSmaller]:{padding:intermediateCheckboxPaddingPhone$1,paddingTop:0}}});var Choice$2 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(Choice$1,{...props,forwardedRef:ref}));
1762
1767
 
1763
- const ChoiceNoneAbove$2=function({content,forwardedRef,showContent=true,...rest}){const{strings}=usePerseusI18n();const choiceProps={...rest,content:showContent?content:jsxRuntimeExports.jsx(Renderer,{content:strings.noneOfTheAbove,strings:strings},"noneOfTheAboveRenderer")};return jsxRuntimeExports.jsx(Choice$3,{...choiceProps,ref:forwardedRef})};var ChoiceNoneAbove$3 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(ChoiceNoneAbove$2,{...props,forwardedRef:ref}));
1768
+ const ChoiceNoneAbove$1=function({content,forwardedRef,showContent=true,...rest}){const{strings}=usePerseusI18n();const choiceProps={...rest,content:showContent?content:jsxRuntimeExports.jsx(Renderer,{content:strings.noneOfTheAbove,strings:strings},"noneOfTheAboveRenderer")};return jsxRuntimeExports.jsx(Choice$2,{...choiceProps,ref:forwardedRef})};var ChoiceNoneAbove$2 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(ChoiceNoneAbove$1,{...props,forwardedRef:ref}));
1764
1769
 
1765
- const{captureScratchpadTouchStart: captureScratchpadTouchStart$2}=Util;function getInstructionsText$1(multipleSelect,countChoices,numCorrect,strings){if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer}const BaseRadio$1=function({apiOptions,reviewModeRubric,reviewMode,choices,editMode=false,multipleSelect=false,labelWrap,countChoices,numCorrect,isLastUsedWidget,onChange,registerFocusFunction}){const{strings}=usePerseusI18n();const prevReviewModeRubric=useRef();const choiceRefs=useRef([]);useEffect(()=>{if(apiOptions.canScrollPage&&isLastUsedWidget&&reviewModeRubric&&!prevReviewModeRubric.current){const checkedIndex=choices.findIndex(c=>c.checked);if(checkedIndex>=0){const ref=choiceRefs.current[checkedIndex];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){scrollElementIntoView(buttonNode);}}}prevReviewModeRubric.current=reviewModeRubric;},[apiOptions,choices,isLastUsedWidget,reviewModeRubric]);function updateChoice(choiceIndex,newValues){let newCheckedList;if(newValues.checked&&!multipleSelect){newCheckedList=choices.map(_=>false);}else {newCheckedList=choices.map(c=>c.checked);}const newCrossedOutList=choices.map(c=>c.crossedOut);newCheckedList[choiceIndex]=newValues.checked;newCrossedOutList[choiceIndex]=newValues.crossedOut;onChange({checked:newCheckedList,crossedOut:newCrossedOutList});}registerFocusFunction?.(choiceIndex=>{const ref=choiceRefs.current[choiceIndex||0];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){buttonNode.focus();}else {return false}return true});const isMobile=apiOptions.isMobile;const firstChoiceHighlighted=choices[0].highlighted;const lastChoiceHighlighted=choices[choices.length-1].highlighted;const className=classNames$1("perseus-widget-radio",!editMode&&"perseus-rendered-radio",css(styles$s.radio,styles$s.responsiveRadioContainer,firstChoiceHighlighted&&isMobile&&styles$s.radioContainerFirstHighlighted,lastChoiceHighlighted&&isMobile&&styles$s.radioContainerLastHighlighted));const instructionsClassName=classNames$1("instructions",css(styles$s.instructions,isMobile&&styles$s.instructionsMobile));const instructions=getInstructionsText$1(multipleSelect,countChoices,numCorrect,strings);const responsiveClassName=css(styles$s.responsiveFieldset);const fieldset=jsxRuntimeExports.jsxs("fieldset",{className:`perseus-widget-radio-fieldset ${responsiveClassName}`,children:[jsxRuntimeExports.jsx("legend",{className:"perseus-sr-only",children:instructions}),jsxRuntimeExports.jsx("div",{className:instructionsClassName,"aria-hidden":"true",children:instructions}),jsxRuntimeExports.jsx("ul",{className:className,style:{listStyle:"none"},children:choices.map((choice,i)=>{let Element=Choice$3;const ref=React.createRef();choiceRefs.current[i]=ref;const elementProps={apiOptions:apiOptions,multipleSelect:multipleSelect,checked:choice.checked,crossedOut:choice.crossedOut,previouslyAnswered:choice.previouslyAnswered,reviewMode,correct:choice.correct,rationale:choice.rationale,content:choice.content,disabled:apiOptions.readOnly||choice.disabled,showCorrectness:reviewMode||!!choice.showCorrectness,showRationale:choice.hasRationale&&(reviewMode||choice.showRationale),pos:i,onChange:newValues=>{if(editMode){return}updateChoice(i,newValues);}};if(choice.isNoneOfTheAbove){Element=ChoiceNoneAbove$3;_.extend(elementProps,{showContent:choice.revealNoneOfTheAbove});}const nextChoice=choices[i+1];const nextChoiceHighlighted=!!nextChoice&&nextChoice.highlighted;const aphroditeClassName=checked=>{return css(styles$s.item,styles$s.responsiveItem,checked&&styles$s.selectedItem,checked&&choice.highlighted&&styles$s.aboveBackdrop,checked&&choice.highlighted&&apiOptions.isMobile&&styles$s.aboveBackdropMobile,nextChoiceHighlighted&&apiOptions.isMobile&&styles$s.nextHighlighted)};aphroditeClassName(true);let correctnessClass;if(reviewMode&&reviewModeRubric){correctnessClass=reviewModeRubric.choices[i].correct?ClassNames.CORRECT:ClassNames.INCORRECT;}const className=classNames$1(aphroditeClassName(choice.checked),ClassNames.RADIO.OPTION,choice.checked&&ClassNames.RADIO.SELECTED,correctnessClass);let listElem=null;let clickHandler;if(editMode){clickHandler=e=>{let elem=e.target;while(elem&&elem!==listElem){if(elem.getAttribute("data-is-radio-icon")){updateChoice(i,{checked:!choice.checked,crossedOut:choice.crossedOut});return}elem=elem.parentNode;}};}return jsxRuntimeExports.jsx("li",{ref:e=>listElem=e,className:className,onClick:clickHandler,onTouchStart:labelWrap?undefined:captureScratchpadTouchStart$2,children:jsxRuntimeExports.jsx(Element,{...elementProps,ref:ref})},i)})})]});return jsxRuntimeExports.jsx("div",{className:css(styles$s.responsiveContainer),children:fieldset})};const styles$s=StyleSheet.create({instructions:{display:"block",color:gray17,fontSize:14,lineHeight:1.25,fontFamily:"inherit",fontStyle:"normal",fontWeight:"bold",marginBottom:16},instructionsMobile:{fontSize:18,[mediaQueries.smOrSmaller]:{fontSize:16},[mediaQueries.xl]:{fontSize:20}},radio:{padding:0},responsiveRadioContainer:{borderBottom:`1px solid ${radioBorderColor$1}`,borderTop:`1px solid ${radioBorderColor$1}`,width:"auto",[mediaQueries.smOrSmaller]:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin}},radioContainerFirstHighlighted:{borderTop:`1px solid rgba(0, 0, 0, 0)`},radioContainerLastHighlighted:{borderBottom:`1px solid rgba(0, 0, 0, 0)`},item:{marginLeft:20},responsiveItem:{marginLeft:0,padding:0,":not(:last-child)":{borderBottom:`1px solid ${radioBorderColor$1}`}},selectedItem:{background:"white"},aboveBackdrop:{position:"relative",zIndex:1062},aboveBackdropMobile:{boxShadow:"0 0 4px 0 rgba(0, 0, 0, 0.2),"+"0 0 2px 0 rgba(0, 0, 0, 0.1)",":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},nextHighlighted:{":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},responsiveContainer:{overflow:"auto",marginLeft:negativePhoneMargin,paddingLeft:phoneMargin},responsiveFieldset:{paddingRight:phoneMargin,minWidth:"auto"}});
1770
+ const{captureScratchpadTouchStart: captureScratchpadTouchStart$2}=Util;function getInstructionsText$1(multipleSelect,countChoices,numCorrect,strings){if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer}const BaseRadio$1=function({apiOptions,reviewModeRubric,reviewMode,choices,editMode=false,multipleSelect=false,labelWrap,countChoices,numCorrect,isLastUsedWidget,onChange,registerFocusFunction}){const{strings}=usePerseusI18n();const prevReviewModeRubric=useRef();const choiceRefs=useRef([]);useEffect(()=>{if(apiOptions.canScrollPage&&isLastUsedWidget&&reviewModeRubric&&!prevReviewModeRubric.current){const checkedIndex=choices.findIndex(c=>c.checked);if(checkedIndex>=0){const ref=choiceRefs.current[checkedIndex];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){scrollElementIntoView(buttonNode);}}}prevReviewModeRubric.current=reviewModeRubric;},[apiOptions,choices,isLastUsedWidget,reviewModeRubric]);function updateChoice(choiceIndex,newValues){let newCheckedList;if(newValues.checked&&!multipleSelect){newCheckedList=choices.map(_=>false);}else {newCheckedList=choices.map(c=>c.checked);}const newCrossedOutList=choices.map(c=>c.crossedOut);newCheckedList[choiceIndex]=newValues.checked;newCrossedOutList[choiceIndex]=newValues.crossedOut;onChange({checked:newCheckedList,crossedOut:newCrossedOutList});}registerFocusFunction?.(choiceIndex=>{const ref=choiceRefs.current[choiceIndex||0];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){buttonNode.focus();}else {return false}return true});const isMobile=apiOptions.isMobile;const firstChoiceHighlighted=choices[0].highlighted;const lastChoiceHighlighted=choices[choices.length-1].highlighted;const className=classNames$1("perseus-widget-radio",!editMode&&"perseus-rendered-radio",css(styles$v.radio,styles$v.responsiveRadioContainer,firstChoiceHighlighted&&isMobile&&styles$v.radioContainerFirstHighlighted,lastChoiceHighlighted&&isMobile&&styles$v.radioContainerLastHighlighted));const instructionsClassName=classNames$1("instructions",css(styles$v.instructions,isMobile&&styles$v.instructionsMobile));const instructions=getInstructionsText$1(multipleSelect,countChoices,numCorrect,strings);const responsiveClassName=css(styles$v.responsiveFieldset);const fieldset=jsxRuntimeExports.jsxs("fieldset",{className:`perseus-widget-radio-fieldset ${responsiveClassName}`,children:[jsxRuntimeExports.jsx("legend",{className:"perseus-sr-only",children:instructions}),jsxRuntimeExports.jsx("div",{className:instructionsClassName,"aria-hidden":"true",children:instructions}),jsxRuntimeExports.jsx("ul",{className:className,style:{listStyle:"none"},children:choices.map((choice,i)=>{let Element=Choice$2;const ref=React.createRef();choiceRefs.current[i]=ref;const elementProps={apiOptions:apiOptions,multipleSelect:multipleSelect,checked:choice.checked,crossedOut:choice.crossedOut,previouslyAnswered:choice.previouslyAnswered,reviewMode,correct:choice.correct,rationale:choice.rationale,content:choice.content,disabled:apiOptions.readOnly||choice.disabled,showCorrectness:reviewMode||!!choice.showCorrectness,showRationale:choice.hasRationale&&(reviewMode||choice.showRationale),pos:i,onChange:newValues=>{if(editMode){return}updateChoice(i,newValues);}};if(choice.isNoneOfTheAbove){Element=ChoiceNoneAbove$2;_.extend(elementProps,{showContent:choice.revealNoneOfTheAbove});}const nextChoice=choices[i+1];const nextChoiceHighlighted=!!nextChoice&&nextChoice.highlighted;const aphroditeClassName=checked=>{return css(styles$v.item,styles$v.responsiveItem,checked&&styles$v.selectedItem,checked&&choice.highlighted&&styles$v.aboveBackdrop,checked&&choice.highlighted&&apiOptions.isMobile&&styles$v.aboveBackdropMobile,nextChoiceHighlighted&&apiOptions.isMobile&&styles$v.nextHighlighted)};aphroditeClassName(true);let correctnessClass;if(reviewMode&&reviewModeRubric){correctnessClass=reviewModeRubric.choices[i].correct?ClassNames.CORRECT:ClassNames.INCORRECT;}const className=classNames$1(aphroditeClassName(choice.checked),ClassNames.RADIO.OPTION,choice.checked&&ClassNames.RADIO.SELECTED,correctnessClass);let listElem=null;let clickHandler;if(editMode){clickHandler=e=>{let elem=e.target;while(elem&&elem!==listElem){if(elem.getAttribute("data-is-radio-icon")){updateChoice(i,{checked:!choice.checked,crossedOut:choice.crossedOut});return}elem=elem.parentNode;}};}return jsxRuntimeExports.jsx("li",{ref:e=>listElem=e,className:className,onClick:clickHandler,onTouchStart:labelWrap?undefined:captureScratchpadTouchStart$2,children:jsxRuntimeExports.jsx(Element,{...elementProps,ref:ref})},i)})})]});return jsxRuntimeExports.jsx("div",{className:css(styles$v.responsiveContainer),children:fieldset})};const styles$v=StyleSheet.create({instructions:{display:"block",color:gray17,fontSize:14,lineHeight:1.25,fontFamily:"inherit",fontStyle:"normal",fontWeight:"bold",marginBottom:16},instructionsMobile:{fontSize:18,[mediaQueries.smOrSmaller]:{fontSize:16},[mediaQueries.xl]:{fontSize:20}},radio:{padding:0},responsiveRadioContainer:{borderBottom:`1px solid ${radioBorderColor$1}`,borderTop:`1px solid ${radioBorderColor$1}`,width:"auto",[mediaQueries.smOrSmaller]:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin}},radioContainerFirstHighlighted:{borderTop:`1px solid rgba(0, 0, 0, 0)`},radioContainerLastHighlighted:{borderBottom:`1px solid rgba(0, 0, 0, 0)`},item:{marginLeft:20},responsiveItem:{marginLeft:0,padding:0,":not(:last-child)":{borderBottom:`1px solid ${radioBorderColor$1}`}},selectedItem:{background:"white"},aboveBackdrop:{position:"relative",zIndex:1062},aboveBackdropMobile:{boxShadow:"0 0 4px 0 rgba(0, 0, 0, 0.2),"+"0 0 2px 0 rgba(0, 0, 0, 0.1)",":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},nextHighlighted:{":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},responsiveContainer:{overflow:"auto",marginLeft:negativePhoneMargin,paddingLeft:phoneMargin},responsiveFieldset:{paddingRight:phoneMargin,minWidth:"auto"}});
1766
1771
 
1767
1772
  let Radio$3 = class Radio extends React.Component{static getUserInputFromProps(props,unshuffle=true){if(props.choiceStates){const choiceStates=props.choiceStates;const choicesSelected=choiceStates.map(()=>false);for(let i=0;i<choicesSelected.length;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=choiceStates[i].selected;}return {choicesSelected}}const{values}=props;if(values){const choicesSelected=[...values];const valuesLength=values.length;for(let i=0;i<valuesLength;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=values[i];}return {choicesSelected}}return {choicesSelected:props.choices.map(()=>false)}}componentDidUpdate(prevProps){if(this.props.showSolutions==="selected"&&prevProps.showSolutions!=="selected"){this.showRationalesForCurrentlySelectedChoices(this.props);}}focus(choiceIndex){if(this.focusFunction){return this.focusFunction(choiceIndex)}return false}registerFocusFunction(fun){this.focusFunction=fun;}getUserInput(){return Radio.getUserInputFromProps(this.props)}getPromptJSON(){const userInput=Radio.getUserInputFromProps(this.props,false);return getPromptJSON$q(this.props,userInput)}render(){const{choices}=this.props;const{strings}=this.context;let choiceStates;if(this.props.static){choiceStates=choices.map(choice=>({selected:!!choice.correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.showSolutions==="all"){choiceStates=choices.map(({correct})=>({selected:!!correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.choiceStates){choiceStates=this.props.choiceStates;}else if(this.props.values){choiceStates=this.props.values.map(val=>({selected:val,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}else {choiceStates=choices.map(()=>({selected:false,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}const choicesProp=choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,crossedOut,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];const reviewChoice=this.props.reviewModeRubric?.choices[i];return {content:this._renderRenderer(content),checked:selected,correct:choice.correct===undefined?!!reviewChoice&&!!reviewChoice.correct:choice.correct,disabled:readOnly,hasRationale:!!choice.clue,rationale:this._renderRenderer(choice.clue),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(this.props.questionCompleted&&selected),crossedOut,highlighted,previouslyAnswered:previouslyAnswered}});return jsxRuntimeExports.jsx(BaseRadio$1,{labelWrap:true,multipleSelect:this.props.multipleSelect,countChoices:this.props.countChoices,numCorrect:this.props.numCorrect,choices:choicesProp,onChange:this.updateChoices,reviewModeRubric:this.props.reviewModeRubric,reviewMode:this.props.reviewMode,deselectEnabled:this.props.deselectEnabled,apiOptions:this.props.apiOptions,isLastUsedWidget:this.props.isLastUsedWidget,registerFocusFunction:i=>this.registerFocusFunction(i)})}constructor(...args){super(...args),this._renderRenderer=(content="")=>{let nextPassageRefId=1;const widgets={};const modContent=content.replace(/\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,(match,passageNum,refNum,summaryText)=>{const widgetId="passage-ref "+nextPassageRefId;nextPassageRefId++;widgets[widgetId]={type:"passage-ref",graded:false,options:{passageNumber:parseInt(passageNum),referenceNumber:parseInt(refNum),summaryText:summaryText},version:PassageRef$1.version};return "[["+Util.snowman+" "+widgetId+"]]"});return jsxRuntimeExports.jsx(Renderer,{content:modContent,widgets:widgets,findExternalWidgets:this.props.findWidgets,alwaysUpdate:true,linterContext:{...this.props.linterContext,blockHighlight:true},strings:this.context.strings},"choiceContentRenderer")},this.updateChoices=newValueLists=>{const{choiceStates,choices}=this.props;const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,crossedOut:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{choiceState.selected=newValueLists.checked[i];choiceState.crossedOut=newValueLists.crossedOut[i];});this.props.onChange({choiceStates:newChoiceStates});this.props.trackInteraction();},this.showRationalesForCurrentlySelectedChoices=rubric=>{const{choiceStates}=this.props;if(choiceStates){const score=scoreRadio(this.getUserInput(),rubric);const widgetCorrect=score.type==="points"&&score.total===score.earned;const newStates=choiceStates.map(state=>({...state,highlighted:state.selected,rationaleShown:state.selected||state.rationaleShown||widgetCorrect,readOnly:state.selected||state.readOnly||widgetCorrect||this.props.showSolutions!=="none",correctnessShown:state.selected||state.correctnessShown,previouslyAnswered:state.previouslyAnswered||state.selected}));this.props.onChange({choiceStates:newStates},null,true);}},this.deselectIncorrectSelectedChoices=()=>{if(this.props.choiceStates){const newStates=this.props.choiceStates.map((state,i)=>({...state,selected:state.selected&&!!this.props.choices[i].correct,highlighted:false}));this.props.onChange({choiceStates:newStates},null,false);}};}};Radio$3.contextType=PerseusI18nContext;Radio$3.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:linterContextDefault,showSolutions:"none"};
1768
1773
 
1769
- const ChoiceNoneAbove=function({content,forwardedRef,showContent=true,...rest}){const{strings}=usePerseusI18n();const choiceProps={...rest,content:showContent?content:jsxRuntimeExports.jsx(Renderer,{content:strings.noneOfTheAbove,strings:strings},"noneOfTheAboveRenderer")};return jsxRuntimeExports.jsx(Choice$3,{...choiceProps,ref:forwardedRef})};var ChoiceNoneAbove$1 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(ChoiceNoneAbove,{...props,forwardedRef:ref}));
1774
+ const SCROLL_DISTANCE=100;function ScrollableView({overflowX,overflowY,children,scrollDescription,style,role="group",...additionalProps}){const{strings}=usePerseusI18n();const containerRef=useRef(null);const[isScrollable,setIsScrollable]=React.useState(false);const[canScrollLeft,setCanScrollLeft]=React.useState(false);const[canScrollRight,setCanScrollRight]=React.useState(false);const updateScrollState=()=>{if(!containerRef.current){return}const{scrollLeft,scrollWidth,clientWidth}=containerRef.current;setIsScrollable(scrollWidth>clientWidth+1);setCanScrollLeft(scrollLeft>0);setCanScrollRight(scrollLeft+clientWidth<scrollWidth-1);};const scroll=direction=>{if(!containerRef.current){return}containerRef.current.scrollBy({left:direction==="left"?-100:SCROLL_DISTANCE,behavior:"smooth"});};useEffect(()=>{const container=containerRef.current;if(!container){return}updateScrollState();container.addEventListener("scroll",updateScrollState);window.addEventListener("resize",updateScrollState);return ()=>{container.removeEventListener("scroll",updateScrollState);window.removeEventListener("resize",updateScrollState);}},[children]);const mergeStyle={overflowX,overflowY,...style};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[canScrollRight&&jsxRuntimeExports.jsx("div",{style:styles$u.scrollFadeRight}),jsxRuntimeExports.jsx("div",{...additionalProps,role:role,style:mergeStyle,ref:containerRef,children:children}),isScrollable&&jsxRuntimeExports.jsx(ScrollButtons,{onScrollLeft:()=>scroll("left"),onScrollRight:()=>scroll("right"),canScrollLeft:canScrollLeft,canScrollRight:canScrollRight,scrollDescription:scrollDescription?scrollDescription:strings.scrollAnswers})]})}function ScrollButtons({onScrollLeft,onScrollRight,canScrollLeft,canScrollRight,scrollDescription}){const{strings}=usePerseusI18n();return jsxRuntimeExports.jsxs(View,{style:styles$u.scrollButtonsContainer,children:[jsxRuntimeExports.jsx(IconButton,{icon:caretLeftIcon,actionType:"neutral",kind:"secondary",size:"small",onClick:onScrollLeft,"aria-label":strings.scrollLeft,disabled:!canScrollLeft}),jsxRuntimeExports.jsx(IconButton,{icon:caretRightIcon,actionType:"neutral",kind:"secondary",size:"small",onClick:onScrollRight,"aria-label":strings.scrollRight,disabled:!canScrollRight}),jsxRuntimeExports.jsx(LabelSmall,{children:scrollDescription})]})}const styles$u={scrollButtonsContainer:{alignItems:"center",flexDirection:"row",gap:spacing.xSmall_8,padding:spacing.small_12},scrollFadeRight:{position:"absolute",top:0,right:0,width:"max-content",height:"100%",background:"linear-gradient(to left, white 40%, transparent)",pointerEvents:"none",zIndex:2,transition:"opacity 0.3s ease"}};
1775
+
1776
+ const CHOICE_ICON_SIZE=24;const styles$t={iconWrapper:{display:"inline-block",position:"relative",backgroundColor:color.white}};
1777
+
1778
+ function ChoiceInner(props){const{pos,showCorrectness,correct}=props;const{strings}=usePerseusI18n();const letter=getChoiceLetter$1(pos,strings);if(!showCorrectness){return jsxRuntimeExports.jsx("span",{children:letter})}if(correct){return jsxRuntimeExports.jsx(InlineIcon,{...iconCheck,style:{position:"relative",top:-1}})}return jsxRuntimeExports.jsx(InlineIcon,{...iconMinus})}const ChoiceIcon=function(props){const{checked,crossedOut,showCorrectness,correct,focused,hovered,multipleSelect,pos,previouslyAnswered,pressed}=props;const choiceIsChecked=checked||showCorrectness&&!correct&&previouslyAnswered;const choiceStyling=[styles$s.choiceBase,multipleSelect?styles$s.multiSelectShape:styles$s.singleSelectShape,showCorrectness?styles$s.choiceHasIcon:styles$s.choiceHasLetter,choiceIsChecked?styles$s.choiceIsChecked:styles$s.choiceIsUnchecked];let crossOutColor;if(showCorrectness&&correct&&checked){choiceStyling.push(styles$s.choiceCorrect);crossOutColor=color.green;}else if(showCorrectness&&!correct&&(checked||previouslyAnswered)){choiceStyling.push(styles$s.choiceIncorrect);crossOutColor=color.red;}else if(checked){choiceStyling.push(styles$s.choiceNeutral);crossOutColor=color.blue;}else if(pressed){choiceStyling.push(styles$s.activeNeutral);crossOutColor=color.blue;}else {choiceStyling.push(styles$s.uncheckedColors);crossOutColor=color.offBlack64;}return jsxRuntimeExports.jsxs("div",{style:styles$t.iconWrapper,children:[jsxRuntimeExports.jsx(FocusRing,{color:color.blue,visible:focused||hovered,multipleSelect:multipleSelect,children:jsxRuntimeExports.jsx("div",{"data-testid":"choice-icon__library-choice-icon",className:css(...choiceStyling),"data-is-radio-icon":true,children:jsxRuntimeExports.jsx("div",{className:css(styles$s.innerWrapper),children:jsxRuntimeExports.jsx(ChoiceInner,{pos:pos,showCorrectness:showCorrectness,correct:correct})})})}),crossedOut&&jsxRuntimeExports.jsx(CrossOutLine,{color:crossOutColor})]})};const styles$s=StyleSheet.create({innerWrapper:{width:CHOICE_ICON_SIZE,height:CHOICE_ICON_SIZE,display:"flex",alignItems:"center",justifyContent:"center"},choiceBase:{width:CHOICE_ICON_SIZE,height:CHOICE_ICON_SIZE,boxSizing:"border-box",borderStyle:"solid",borderWidth:2,fontFamily:baseFontFamily,fontWeight:"bold",display:"flex",alignItems:"center",justifyContent:"center"},choiceHasLetter:{fontSize:12},choiceHasIcon:{fontSize:CHOICE_ICON_SIZE},choiceIsChecked:{color:color.white},choiceIsUnchecked:{color:color.offBlack64},choiceCorrect:{backgroundColor:color.green,borderColor:color.green},choiceIncorrect:{backgroundColor:color.red,borderColor:color.red},choiceNeutral:{backgroundColor:color.blue,borderColor:color.blue},activeNeutral:{color:color.blue,borderColor:color.blue,backgroundColor:"transparent"},multiSelectShape:{borderRadius:3},singleSelectShape:{borderRadius:CHOICE_ICON_SIZE},uncheckedColors:{borderColor:color.offBlack64}});
1770
1779
 
1771
- function getA11yText(letter,checked,correct,crossedOut,showCorrectness,strings){if(showCorrectness&&correct){if(checked){return strings.choiceCheckedCorrect({letter})}if(crossedOut){return strings.choiceCrossedOutCorrect({letter})}return strings.choiceCorrect({letter})}if(showCorrectness&&!correct){if(checked){return strings.choiceCheckedIncorrect({letter})}if(crossedOut){return strings.choiceCrossedOutIncorrect({letter})}return strings.choiceIncorrect({letter})}if(checked){return strings.choiceChecked({letter})}if(crossedOut){return strings.choiceCrossedOut({letter})}return strings.choice({letter})}
1780
+ const getChoiceLetter=(pos,strings)=>{const lettersString=strings.letters;const letters=lettersString.split(" ");if(pos<letters.length){return letters[pos]}return " "};const getOptionStatusText=({checked,correct,crossedOut,strings})=>{if(correct){if(checked){return strings.correctSelected}if(crossedOut){return strings.correctCrossedOut}return strings.correct}if(checked){return strings.incorrectSelected}return strings.incorrect};const getInstructionsText=({multipleSelect,countChoices,numCorrect,strings})=>{if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer};const getA11yText=({letter,checked,correct,crossedOut,showCorrectness,strings})=>{if(showCorrectness&&correct){if(checked){return strings.choiceCheckedCorrect({letter})}if(crossedOut){return strings.choiceCrossedOutCorrect({letter})}return strings.choiceCorrect({letter})}if(showCorrectness&&!correct){if(checked){return strings.choiceCheckedIncorrect({letter})}if(crossedOut){return strings.choiceCrossedOutIncorrect({letter})}return strings.choiceIncorrect({letter})}if(checked){return strings.choiceChecked({letter})}if(crossedOut){return strings.choiceCrossedOut({letter})}return strings.choice({letter})};
1772
1781
 
1773
- function ChoiceInner(props){const{pos,showCorrectness,correct}=props;const{strings}=usePerseusI18n();const letter=getChoiceLetter(pos,strings);if(!showCorrectness){return jsxRuntimeExports.jsx("span",{children:letter})}if(correct){return jsxRuntimeExports.jsx(InlineIcon,{...iconCheck,style:{position:"relative",top:-1}})}return jsxRuntimeExports.jsx(InlineIcon,{...iconMinus})}const ChoiceIcon=function(props){const{checked,crossedOut,showCorrectness,correct,focused,hovered,multipleSelect,pos,previouslyAnswered,pressed}=props;const choiceIsChecked=checked||showCorrectness&&!correct&&previouslyAnswered;const choiceStyling=[styles$r.choiceBase,multipleSelect?styles$r.multiSelectShape:styles$r.singleSelectShape,showCorrectness?styles$r.choiceHasIcon:styles$r.choiceHasLetter,choiceIsChecked?styles$r.choiceIsChecked:styles$r.choiceIsUnchecked];let crossOutColor;if(showCorrectness&&correct&&checked){choiceStyling.push(styles$r.choiceCorrect);crossOutColor=color.green;}else if(showCorrectness&&!correct&&(checked||previouslyAnswered)){choiceStyling.push(styles$r.choiceIncorrect);crossOutColor=color.red;}else if(checked){choiceStyling.push(styles$r.choiceNeutral);crossOutColor=color.blue;}else if(pressed){choiceStyling.push(styles$r.activeNeutral);crossOutColor=color.blue;}else {choiceStyling.push(styles$r.uncheckedColors);crossOutColor=color.offBlack64;}return jsxRuntimeExports.jsxs("div",{className:css(styles$x.iconWrapper),children:[jsxRuntimeExports.jsx(FocusRing,{color:color.blue,visible:focused||hovered,multipleSelect:multipleSelect,children:jsxRuntimeExports.jsx("div",{"data-testid":"choice-icon__library-choice-icon",className:css(...choiceStyling),"data-is-radio-icon":true,children:jsxRuntimeExports.jsx("div",{className:css(styles$r.innerWrapper),children:jsxRuntimeExports.jsx(ChoiceInner,{pos:pos,showCorrectness:showCorrectness,correct:correct})})})}),crossedOut&&jsxRuntimeExports.jsx(CrossOutLine,{color:crossOutColor})]})};const styles$r=StyleSheet.create({innerWrapper:{width:CHOICE_ICON_SIZE,height:CHOICE_ICON_SIZE,display:"flex",alignItems:"center",justifyContent:"center"},choiceBase:{width:CHOICE_ICON_SIZE,height:CHOICE_ICON_SIZE,boxSizing:"border-box",borderStyle:"solid",borderWidth:2,fontFamily:baseFontFamily,fontWeight:"bold",display:"flex",alignItems:"center",justifyContent:"center"},choiceHasLetter:{fontSize:12},choiceHasIcon:{fontSize:CHOICE_ICON_SIZE},choiceIsChecked:{color:color.white},choiceIsUnchecked:{color:color.offBlack64},choiceCorrect:{backgroundColor:color.green,borderColor:color.green},choiceIncorrect:{backgroundColor:color.red,borderColor:color.red},choiceNeutral:{backgroundColor:color.blue,borderColor:color.blue},activeNeutral:{color:color.blue,borderColor:color.blue,backgroundColor:"transparent"},multiSelectShape:{borderRadius:3},singleSelectShape:{borderRadius:CHOICE_ICON_SIZE},uncheckedColors:{borderColor:color.offBlack64}});
1782
+ const OptionStatus=({checked,correct,crossedOut,previouslyAnswered,reviewMode})=>{const{strings}=usePerseusI18n();if(!reviewMode&&!previouslyAnswered){return null}let textStyle;if(correct){textStyle=styles$r.correct;}else {if(checked||previouslyAnswered){textStyle=styles$r.incorrectAnswered;}else {textStyle=styles$r.incorrect;}}return jsxRuntimeExports.jsx("div",{className:css(styles$r.text,textStyle),children:getOptionStatusText({checked,correct,crossedOut,strings})})};const styles$r=StyleSheet.create({text:{alignItems:"center",display:"flex",fontSize:12,height:32,textTransform:"uppercase"},correct:{color:color.green},incorrectAnswered:{color:color.red},incorrect:{color:color.offBlack64}});
1774
1783
 
1775
- function renderText(checked,correct,crossedOut,strings){if(correct){if(checked){return strings.correctSelected}if(crossedOut){return strings.correctCrossedOut}return strings.correct}if(checked){return strings.incorrectSelected}return strings.incorrect}const OptionStatus=function(props){const{checked,correct,crossedOut,previouslyAnswered,reviewMode}=props;const{strings}=usePerseusI18n();if(!reviewMode&&!previouslyAnswered){return null}let textStyle;if(correct){textStyle=styles$q.correct;}else {if(checked||previouslyAnswered){textStyle=styles$q.incorrectAnswered;}else {textStyle=styles$q.incorrect;}}return jsxRuntimeExports.jsx("div",{className:css(styles$q.text,textStyle),children:renderText(checked,correct,crossedOut,strings)})};const styles$q=StyleSheet.create({text:{alignItems:"center",display:"flex",fontSize:12,height:32,textTransform:"uppercase"},correct:{color:color.green},incorrectAnswered:{color:color.red},incorrect:{color:color.offBlack64}});
1784
+ const intermediateCheckboxPadding=`16px 16px`;const intermediateCheckboxPaddingPhone=`12px 16px`;const ellipsisHorizontalIcon={path:"M27.218 6.82l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836z",width:100,height:27.284};const Choice=React.forwardRef(({disabled=false,checked=false,content,crossedOut,showCorrectness,multipleSelect,onChange=newValues=>{},reviewMode,correct=false,apiOptions=ApiOptions.defaults,previouslyAnswered=false,pos=0,showRationale=false,rationale},ref)=>{const[isInputFocused,setIsInputFocused]=useState(false);const{strings}=usePerseusI18n();useEffect(()=>{if(isInputFocused&&disabled){setIsInputFocused(false);}},[disabled,isInputFocused,setIsInputFocused]);function sendChange(newValues){const updatedChecked=newValues.checked??checked;const updatedCrossedOut=newValues.crossedOut??crossedOut;onChange({checked:updatedChecked,crossedOut:updatedCrossedOut});}const descriptionClassName=classNames$1("description");const rationaleClassName=classNames$1("perseus-radio-rationale-content");const showDimmed=!reviewMode&&apiOptions.readOnly||crossedOut;const letter=getChoiceLetter(pos,strings);const a11yText=getA11yText({letter,checked,correct,crossedOut,showCorrectness,strings});return jsxRuntimeExports.jsxs("div",{className:descriptionClassName,style:styles$q.description,children:[jsxRuntimeExports.jsxs("div",{style:{display:"flex",opacity:showDimmed?.5:1},children:[jsxRuntimeExports.jsx("div",{className:"perseus-sr-only",children:jsxRuntimeExports.jsxs("label",{children:[a11yText,"   ",content,jsxRuntimeExports.jsx("input",{type:multipleSelect?"checkbox":"radio",checked:checked,onClick:()=>{sendChange({checked:!checked,crossedOut:false});},onChange:()=>{},disabled:disabled||apiOptions.readOnly,tabIndex:-1,className:ClassNames.RADIO.OPTION_CONTENT})]})}),jsxRuntimeExports.jsx(Clickable,{onClick:()=>{sendChange({checked:!checked,crossedOut:false});},disabled:disabled||apiOptions.readOnly,style:{flex:1,color:color.offBlack,userSelect:"text"},ref:ref,"aria-hidden":"true",children:({hovered,focused,pressed})=>jsxRuntimeExports.jsxs("div",{style:styles$q.choiceRow,children:[jsxRuntimeExports.jsx("div",{style:styles$q.choiceIcon,children:jsxRuntimeExports.jsx(ChoiceIcon,{pos:pos,correct:correct,crossedOut:crossedOut,pressed:pressed,focused:focused,checked:checked,hovered:hovered,showCorrectness:showCorrectness,multipleSelect:multipleSelect,reviewMode:reviewMode,previouslyAnswered:previouslyAnswered})}),jsxRuntimeExports.jsxs("span",{style:styles$q.choiceContent,children:[jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(OptionStatus,{checked:checked,correct:correct,crossedOut:crossedOut,previouslyAnswered:previouslyAnswered,reviewMode:reviewMode})}),jsxRuntimeExports.jsx("div",{children:content})]})]})}),apiOptions.crossOutEnabled&&!reviewMode&&jsxRuntimeExports.jsx(Popover,{dismissEnabled:true,content:({close})=>jsxRuntimeExports.jsx(PopoverContent,{title:strings.crossOut,content:strings.crossOutOption,closeButtonVisible:true,actions:jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsx(Button,{kind:"primary","aria-label":strings.crossOutChoice({letter:getChoiceLetter(pos,strings)}),disabled:apiOptions.readOnly||reviewMode,onClick:()=>{if(!crossedOut){sendChange({checked:false,crossedOut:true});}else {sendChange({crossedOut:false});}close();},children:crossedOut?strings.bringBack:strings.crossOut})]})}),children:({open})=>jsxRuntimeExports.jsx(Clickable,{onClick:open,"aria-label":strings.openMenuForChoice({letter:getChoiceLetter(pos,strings)}),style:{alignSelf:"center",padding:"5px",display:"flex",justifyContent:"center",alignItems:"center",marginLeft:"10px"},children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(Icon,{icon:ellipsisHorizontalIcon,size:3,color:color.offBlack64})})})]}),showRationale&&jsxRuntimeExports.jsx("div",{className:rationaleClassName,style:styles$q.rationale,"data-testid":`perseus-radio-rationale-content-${pos}`,children:rationale})]})});const styles$q={description:{display:"inline-block",width:"100%",flexDirection:"column",color:color.offBlack},choiceRow:{display:"flex",flexDirection:"row",justifyContent:"flex-start",alignItems:"center",paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,paddingLeft:spacing.xSmall_8,position:"relative",background:color.white64,minWidth:"100%",left:0},choiceIcon:{flexGrow:0,flexShrink:0,flexBasis:"30px",position:"sticky",left:0,background:"linear-gradient(to right, white 70%, rba(255,255,255, 0.8) 100%)",zIndex:1,alignItems:"center",justifyContent:"center"},choiceContent:{paddingLeft:spacing.small_12,textAlign:"left",flex:1,paddingTop:spacing.xxxSmall_4,minWidth:0},rationale:{display:"block",padding:intermediateCheckboxPadding,paddingTop:0,marginLeft:54,color:color.offBlack64,[mediaQueries.smOrSmaller]:{padding:intermediateCheckboxPaddingPhone,paddingTop:0}}};
1776
1785
 
1777
- const intermediateCheckboxPadding=`16px 16px`;const intermediateCheckboxPaddingPhone=`12px 16px`;const ellipsisHorizontalIcon={path:"M27.218 6.82l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836zm36.27 0l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836z",width:100,height:27.284};const Choice=function(props){const{disabled=false,checked=false,content,crossedOut,showCorrectness,multipleSelect,onChange=newValues=>{},reviewMode,correct=false,apiOptions=ApiOptions.defaults,previouslyAnswered=false,pos=0,showRationale=false,rationale,forwardedRef}=props;const[isInputFocused,setIsInputFocused]=useState(false);const{strings}=usePerseusI18n();useEffect(()=>{if(isInputFocused&&disabled){setIsInputFocused(false);}},[disabled,isInputFocused,setIsInputFocused]);function sendChange(newValues){const updatedChecked=newValues.checked??checked;const updatedCrossedOut=newValues.crossedOut??crossedOut;onChange({checked:updatedChecked,crossedOut:updatedCrossedOut});}const descriptionClassName=classNames$1("description",css(styles$p.description));const rationaleClassName=classNames$1("perseus-radio-rationale-content",css(styles$p.rationale));const showDimmed=!reviewMode&&apiOptions.readOnly||crossedOut;const letter=getChoiceLetter(pos,strings);const a11yText=getA11yText(letter,checked,correct,crossedOut,showCorrectness,strings);return jsxRuntimeExports.jsxs("div",{style:{dispay:"flex",flexDirection:"column",color:color.offBlack},className:descriptionClassName,children:[jsxRuntimeExports.jsxs("div",{style:{display:"flex",flexDirection:"row",opacity:showDimmed?.5:1,overflowX:"auto",overflowY:"hidden"},children:[jsxRuntimeExports.jsx("div",{className:"perseus-sr-only",children:jsxRuntimeExports.jsxs("label",{children:[a11yText,"   ",content,jsxRuntimeExports.jsx("input",{type:multipleSelect?"checkbox":"radio",checked:checked,onClick:()=>{sendChange({checked:!checked,crossedOut:false});},onChange:()=>{},disabled:disabled||apiOptions.readOnly,tabIndex:-1,className:ClassNames.RADIO.OPTION_CONTENT})]})}),jsxRuntimeExports.jsx(Clickable,{onClick:()=>{sendChange({checked:!checked,crossedOut:false});},disabled:disabled||apiOptions.readOnly,style:{flex:1,color:color.offBlack,userSelect:"text"},ref:forwardedRef,"aria-hidden":"true",children:({hovered,focused,pressed})=>jsxRuntimeExports.jsxs("div",{style:{display:"flex",flexDirection:"row",justifyContent:"center",alignContent:"center",paddingTop:spacing.xSmall_8,paddingBottom:spacing.xSmall_8,paddingLeft:spacing.xSmall_8},children:[jsxRuntimeExports.jsx(ChoiceIcon,{pos:pos,correct:correct,crossedOut:crossedOut,pressed:pressed,focused:focused,checked:checked,hovered:hovered,showCorrectness:showCorrectness,multipleSelect:multipleSelect,reviewMode:reviewMode,previouslyAnswered:previouslyAnswered}),jsxRuntimeExports.jsxs("span",{style:{paddingLeft:spacing.small_12,textAlign:"left",flex:1,paddingTop:4},children:[jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(OptionStatus,{checked:checked,correct:correct,crossedOut:crossedOut,previouslyAnswered:previouslyAnswered,reviewMode:reviewMode})}),jsxRuntimeExports.jsx("div",{children:content})]})]})}),apiOptions.crossOutEnabled&&!reviewMode&&jsxRuntimeExports.jsx(Popover,{dismissEnabled:true,content:({close})=>jsxRuntimeExports.jsx(PopoverContent,{title:strings.crossOut,content:strings.crossOutOption,closeButtonVisible:true,actions:jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsx(Strut,{size:spacing.medium_16}),jsxRuntimeExports.jsx(Button,{kind:"primary","aria-label":strings.crossOutChoice({letter:getChoiceLetter(pos,strings)}),disabled:apiOptions.readOnly||reviewMode,onClick:()=>{if(!crossedOut){sendChange({checked:false,crossedOut:true});}else {sendChange({crossedOut:false});}close();},children:crossedOut?strings.bringBack:strings.crossOut})]})}),children:({open})=>jsxRuntimeExports.jsx(Clickable,{onClick:open,"aria-label":strings.openMenuForChoice({letter:getChoiceLetter(pos,strings)}),style:{alignSelf:"center",padding:"5px",display:"flex",justifyContent:"center",alignItems:"center",marginLeft:"10px"},children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(Icon,{icon:ellipsisHorizontalIcon,size:3,color:color.offBlack64})})})]}),showRationale&&jsxRuntimeExports.jsx("div",{className:rationaleClassName,"data-testid":`perseus-radio-rationale-content-${pos}`,children:rationale})]})};const styles$p=StyleSheet.create({description:{display:"inline-block",width:"100%"},rationale:{display:"block",padding:intermediateCheckboxPadding,paddingTop:0,marginLeft:54,color:color.offBlack64,[mediaQueries.smOrSmaller]:{padding:intermediateCheckboxPaddingPhone,paddingTop:0}}});var Choice$1 = React.forwardRef((props,ref)=>jsxRuntimeExports.jsx(Choice,{...props,forwardedRef:ref}));
1786
+ const ChoiceNoneAbove=React.forwardRef(({content,showContent=true,...otherChoiceProps},forwardedRef)=>{const{strings}=usePerseusI18n();const choiceProps={...otherChoiceProps,content:showContent?content:jsxRuntimeExports.jsx(Renderer,{content:strings.noneOfTheAbove,strings:strings},"noneOfTheAboveRenderer")};return jsxRuntimeExports.jsx(Choice,{...choiceProps,ref:forwardedRef})});
1778
1787
 
1779
- const{captureScratchpadTouchStart: captureScratchpadTouchStart$1}=Util;function getInstructionsText(multipleSelect,countChoices,numCorrect,strings){if(multipleSelect){if(usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer}const BaseRadio=function({apiOptions,reviewModeRubric,reviewMode,choices,editMode=false,multipleSelect=false,labelWrap,countChoices,numCorrect,isLastUsedWidget,onChange,registerFocusFunction}){const{strings}=usePerseusI18n();const prevReviewModeRubric=useRef();const choiceRefs=useRef([]);useEffect(()=>{if(apiOptions.canScrollPage&&isLastUsedWidget&&reviewModeRubric&&!prevReviewModeRubric.current){const checkedIndex=choices.findIndex(c=>c.checked);if(checkedIndex>=0){const ref=choiceRefs.current[checkedIndex];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){scrollElementIntoView(buttonNode);}}}prevReviewModeRubric.current=reviewModeRubric;},[apiOptions,choices,isLastUsedWidget,reviewModeRubric]);function updateChoice(choiceIndex,newValues){let newCheckedList;if(newValues.checked&&!multipleSelect){newCheckedList=choices.map(_=>false);}else {newCheckedList=choices.map(c=>c.checked);}const newCrossedOutList=choices.map(c=>c.crossedOut);newCheckedList[choiceIndex]=newValues.checked;newCrossedOutList[choiceIndex]=newValues.crossedOut;onChange({checked:newCheckedList,crossedOut:newCrossedOutList});}registerFocusFunction?.(choiceIndex=>{const ref=choiceRefs.current[choiceIndex||0];const anyNode=ReactDOM__default.findDOMNode(ref.current);const buttonNode=anyNode;if(buttonNode){buttonNode.focus();}else {return false}return true});const isMobile=apiOptions.isMobile;const firstChoiceHighlighted=choices[0].highlighted;const lastChoiceHighlighted=choices[choices.length-1].highlighted;const className=classNames$1("perseus-widget-radio",!editMode&&"perseus-rendered-radio",css(styles$o.radio,styles$o.responsiveRadioContainer,firstChoiceHighlighted&&isMobile&&styles$o.radioContainerFirstHighlighted,lastChoiceHighlighted&&isMobile&&styles$o.radioContainerLastHighlighted));const instructionsClassName=classNames$1("instructions",css(styles$o.instructions,isMobile&&styles$o.instructionsMobile));const instructions=getInstructionsText(multipleSelect,countChoices,numCorrect,strings);const responsiveClassName=css(styles$o.responsiveFieldset);const fieldset=jsxRuntimeExports.jsxs("fieldset",{className:`perseus-widget-radio-fieldset ${responsiveClassName}`,"data-feature-flag":"feature flag is ON",children:[jsxRuntimeExports.jsx("legend",{className:"perseus-sr-only",children:instructions}),jsxRuntimeExports.jsx("div",{className:instructionsClassName,"aria-hidden":"true",children:instructions}),jsxRuntimeExports.jsx("ul",{className:className,style:{listStyle:"none"},children:choices.map((choice,i)=>{let Element=Choice$1;const ref=React.createRef();choiceRefs.current[i]=ref;const elementProps={apiOptions:apiOptions,multipleSelect:multipleSelect,checked:choice.checked,crossedOut:choice.crossedOut,previouslyAnswered:choice.previouslyAnswered,reviewMode,correct:choice.correct,rationale:choice.rationale,content:choice.content,disabled:apiOptions.readOnly||choice.disabled,showCorrectness:reviewMode||!!choice.showCorrectness,showRationale:choice.hasRationale&&(reviewMode||choice.showRationale),pos:i,onChange:newValues=>{if(editMode){return}updateChoice(i,newValues);}};if(choice.isNoneOfTheAbove){Element=ChoiceNoneAbove$1;_.extend(elementProps,{showContent:choice.revealNoneOfTheAbove});}const nextChoice=choices[i+1];const nextChoiceHighlighted=!!nextChoice&&nextChoice.highlighted;const aphroditeClassName=checked=>{return 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)};aphroditeClassName(true);let correctnessClass;if(reviewMode&&reviewModeRubric){correctnessClass=reviewModeRubric.choices[i].correct?ClassNames.CORRECT:ClassNames.INCORRECT;}const className=classNames$1(aphroditeClassName(choice.checked),ClassNames.RADIO.OPTION,choice.checked&&ClassNames.RADIO.SELECTED,correctnessClass);let listElem=null;let clickHandler;if(editMode){clickHandler=e=>{let elem=e.target;while(elem&&elem!==listElem){if(elem.getAttribute("data-is-radio-icon")){updateChoice(i,{checked:!choice.checked,crossedOut:choice.crossedOut});return}elem=elem.parentNode;}};}return jsxRuntimeExports.jsx("li",{ref:e=>listElem=e,className:className,onClick:clickHandler,onTouchStart:labelWrap?undefined:captureScratchpadTouchStart$1,children:jsxRuntimeExports.jsx(Element,{...elementProps,ref:ref})},i)})})]});return jsxRuntimeExports.jsx("div",{className:css(styles$o.responsiveContainer),children:fieldset})};const styles$o=StyleSheet.create({instructions:{display:"block",color:gray17,fontSize:14,lineHeight:1.25,fontFamily:"inherit",fontStyle:"normal",fontWeight:"bold",marginBottom:16},instructionsMobile:{fontSize:18,[mediaQueries.smOrSmaller]:{fontSize:16},[mediaQueries.xl]:{fontSize:20}},radio:{padding:0},responsiveRadioContainer:{borderBottom:`1px solid ${radioBorderColor$1}`,borderTop:`1px solid ${radioBorderColor$1}`,width:"auto",[mediaQueries.smOrSmaller]:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin}},radioContainerFirstHighlighted:{borderTop:`1px solid rgba(0, 0, 0, 0)`},radioContainerLastHighlighted:{borderBottom:`1px solid rgba(0, 0, 0, 0)`},item:{marginLeft:20},responsiveItem:{marginLeft:0,padding:0,":not(:last-child)":{borderBottom:`1px solid ${radioBorderColor$1}`}},selectedItem:{background:"white"},aboveBackdrop:{position:"relative",zIndex:1062},aboveBackdropMobile:{boxShadow:"0 0 4px 0 rgba(0, 0, 0, 0.2),"+"0 0 2px 0 rgba(0, 0, 0, 0.1)",":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},nextHighlighted:{":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},responsiveContainer:{overflow:"auto",marginLeft:negativePhoneMargin,paddingLeft:phoneMargin},responsiveFieldset:{paddingRight:phoneMargin,minWidth:"auto"}});
1788
+ const{captureScratchpadTouchStart: captureScratchpadTouchStart$1}=Util;const BaseRadio=({apiOptions,reviewModeRubric,reviewMode,choices,editMode=false,multipleSelect=false,labelWrap,countChoices,numCorrect,isLastUsedWidget,onChange})=>{const{strings}=usePerseusI18n();const prevReviewModeRubric=useRef();const choiceRefs=useRef([]);useEffect(()=>{if(apiOptions.canScrollPage&&isLastUsedWidget&&reviewModeRubric&&!prevReviewModeRubric.current){const checkedIndex=choices.findIndex(c=>c.checked);if(checkedIndex>=0){const ref=choiceRefs.current[checkedIndex];const buttonNode=ReactDOM__default.findDOMNode(ref.current);if(buttonNode){scrollElementIntoView(buttonNode);}}}prevReviewModeRubric.current=reviewModeRubric;},[apiOptions,choices,isLastUsedWidget,reviewModeRubric]);function updateChoice(choiceIndex,newValues){let newCheckedList;if(newValues.checked&&!multipleSelect){newCheckedList=choices.map(_=>false);}else {newCheckedList=choices.map(c=>c.checked);}const newCrossedOutList=choices.map(c=>c.crossedOut);newCheckedList[choiceIndex]=newValues.checked;newCrossedOutList[choiceIndex]=newValues.crossedOut;onChange({checked:newCheckedList,crossedOut:newCrossedOutList});}const isMobile=apiOptions.isMobile;const firstChoiceHighlighted=choices[0].highlighted;const lastChoiceHighlighted=choices[choices.length-1].highlighted;const className=classNames$1("perseus-widget-radio",!editMode&&"perseus-rendered-radio",css(styles$p.radio,styles$p.responsiveRadioContainer,firstChoiceHighlighted&&isMobile&&styles$p.radioContainerFirstHighlighted,lastChoiceHighlighted&&isMobile&&styles$p.radioContainerLastHighlighted));const instructionsClassName=classNames$1("instructions",css(styles$p.instructions,isMobile&&styles$p.instructionsMobile));const instructions=getInstructionsText({multipleSelect,countChoices,numCorrect,strings});const responsiveClassName=css(styles$p.responsiveFieldset);const fieldset=jsxRuntimeExports.jsxs("fieldset",{className:`perseus-widget-radio-fieldset ${responsiveClassName}`,"data-feature-flag":"feature flag is ON",children:[jsxRuntimeExports.jsx("legend",{className:"perseus-sr-only",children:instructions}),jsxRuntimeExports.jsx("div",{className:instructionsClassName,"aria-hidden":"true",children:instructions}),jsxRuntimeExports.jsx(ScrollableView,{overflowX:"auto",children:jsxRuntimeExports.jsx("ul",{className:className,style:styles$p.fieldSetContent,children:choices.map((choice,i)=>{let Element=Choice;const ref=React.createRef();choiceRefs.current[i]=ref;const elementProps={apiOptions:apiOptions,multipleSelect:multipleSelect,checked:choice.checked,crossedOut:choice.crossedOut,previouslyAnswered:choice.previouslyAnswered,reviewMode,correct:choice.correct,rationale:choice.rationale,content:choice.content,disabled:apiOptions.readOnly||choice.disabled,showCorrectness:reviewMode||!!choice.showCorrectness,showRationale:choice.hasRationale&&(reviewMode||choice.showRationale),pos:i,onChange:newValues=>{if(editMode){return}updateChoice(i,newValues);}};if(choice.isNoneOfTheAbove){Element=ChoiceNoneAbove;_.extend(elementProps,{showContent:choice.revealNoneOfTheAbove});}const nextChoice=choices[i+1];const nextChoiceHighlighted=nextChoice?.highlighted||false;const aphroditeClassName=checked=>{return css(styles$p.item,styles$p.responsiveItem,checked&&styles$p.selectedItem,checked&&choice.highlighted&&styles$p.aboveBackdrop,checked&&choice.highlighted&&apiOptions.isMobile&&styles$p.aboveBackdropMobile,nextChoiceHighlighted&&apiOptions.isMobile&&styles$p.nextHighlighted)};aphroditeClassName(true);let correctnessClass;if(reviewMode&&reviewModeRubric){correctnessClass=reviewModeRubric.choices[i].correct?ClassNames.CORRECT:ClassNames.INCORRECT;}const className=classNames$1(aphroditeClassName(choice.checked),ClassNames.RADIO.OPTION,choice.checked&&ClassNames.RADIO.SELECTED,correctnessClass);let listElem=null;let clickHandler;if(editMode){clickHandler=e=>{let elem=e.target;while(elem&&elem!==listElem){if(elem.getAttribute("data-is-radio-icon")){updateChoice(i,{checked:!choice.checked,crossedOut:choice.crossedOut});return}elem=elem.parentNode;}};}return jsxRuntimeExports.jsx("li",{ref:e=>listElem=e,className:className,onClick:clickHandler,onTouchStart:labelWrap?undefined:captureScratchpadTouchStart$1,children:jsxRuntimeExports.jsx(Element,{...elementProps,ref:ref})},i)})})})]});return jsxRuntimeExports.jsx("div",{className:css(styles$p.responsiveContainer),children:fieldset})};const styles$p=StyleSheet.create({instructions:{display:"block",color:gray17,fontSize:14,lineHeight:1.25,fontFamily:"inherit",fontStyle:"normal",fontWeight:"bold",marginBottom:16},instructionsMobile:{fontSize:18,[mediaQueries.smOrSmaller]:{fontSize:16},[mediaQueries.xl]:{fontSize:20}},radio:{padding:0},responsiveRadioContainer:{display:"inline-block",minWidth:"max-content",width:"100%",borderBottom:`1px solid ${radioBorderColor$1}`,borderTop:`1px solid ${radioBorderColor$1}`,scrollbarWidth:"thin",[mediaQueries.smOrSmaller]:{marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin}},fieldSetContent:{listStyle:"none"},radioContainerFirstHighlighted:{borderTop:`1px solid rgba(0, 0, 0, 0)`},radioContainerLastHighlighted:{borderBottom:`1px solid rgba(0, 0, 0, 0)`},item:{marginLeft:20},responsiveItem:{marginLeft:0,padding:0,":not(:last-child)":{borderBottom:`1px solid ${radioBorderColor$1}`}},selectedItem:{background:"white"},aboveBackdrop:{position:"relative",zIndex:1062},aboveBackdropMobile:{boxShadow:"0 0 4px 0 rgba(0, 0, 0, 0.2),"+"0 0 2px 0 rgba(0, 0, 0, 0.1)",":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},nextHighlighted:{":not(:last-child)":{borderBottom:`1px solid rgba(0, 0, 0, 0)`}},responsiveContainer:{overflow:"auto",marginLeft:negativePhoneMargin,paddingLeft:phoneMargin},responsiveFieldset:{paddingRight:phoneMargin,minWidth:"auto"}});
1780
1789
 
1781
- let Radio$2 = class Radio extends React.Component{static getUserInputFromProps(props,unshuffle=true){if(props.choiceStates){const choiceStates=props.choiceStates;const choicesSelected=choiceStates.map(()=>false);for(let i=0;i<choicesSelected.length;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=choiceStates[i].selected;}return {choicesSelected}}const{values}=props;if(values){const choicesSelected=[...values];const valuesLength=values.length;for(let i=0;i<valuesLength;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=values[i];}return {choicesSelected}}return {choicesSelected:props.choices.map(()=>false)}}componentDidUpdate(prevProps){if(this.props.showSolutions==="selected"&&prevProps.showSolutions!=="selected"){this.showRationalesForCurrentlySelectedChoices(this.props);}}focus(choiceIndex){if(this.focusFunction){return this.focusFunction(choiceIndex)}return false}registerFocusFunction(fun){this.focusFunction=fun;}getUserInput(){return Radio.getUserInputFromProps(this.props)}getPromptJSON(){const userInput=Radio.getUserInputFromProps(this.props,false);return getPromptJSON$q(this.props,userInput)}render(){const{choices}=this.props;const{strings}=this.context;let choiceStates;if(this.props.static){choiceStates=choices.map(choice=>({selected:!!choice.correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.showSolutions==="all"){choiceStates=choices.map(({correct})=>({selected:!!correct,crossedOut:false,readOnly:true,highlighted:false,rationaleShown:true,correctnessShown:true,previouslyAnswered:false}));}else if(this.props.choiceStates){choiceStates=this.props.choiceStates;}else if(this.props.values){choiceStates=this.props.values.map(val=>({selected:val,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}else {choiceStates=choices.map(()=>({selected:false,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}));}const choicesProp=choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,crossedOut,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];const reviewChoice=this.props.reviewModeRubric?.choices[i];return {content:this._renderRenderer(content),checked:selected,correct:choice.correct===undefined?!!reviewChoice&&!!reviewChoice.correct:choice.correct,disabled:readOnly,hasRationale:!!choice.clue,rationale:this._renderRenderer(choice.clue),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(this.props.questionCompleted&&selected),crossedOut,highlighted,previouslyAnswered:previouslyAnswered}});console.log("This is the new radio component.");return jsxRuntimeExports.jsx(BaseRadio,{labelWrap:true,multipleSelect:this.props.multipleSelect,countChoices:this.props.countChoices,numCorrect:this.props.numCorrect,choices:choicesProp,onChange:this.updateChoices,reviewModeRubric:this.props.reviewModeRubric,reviewMode:this.props.reviewMode,deselectEnabled:this.props.deselectEnabled,apiOptions:this.props.apiOptions,isLastUsedWidget:this.props.isLastUsedWidget,registerFocusFunction:i=>this.registerFocusFunction(i)})}constructor(...args){super(...args),this._renderRenderer=(content="")=>{let nextPassageRefId=1;const widgets={};const modContent=content.replace(/\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,(match,passageNum,refNum,summaryText)=>{const widgetId="passage-ref "+nextPassageRefId;nextPassageRefId++;widgets[widgetId]={type:"passage-ref",graded:false,options:{passageNumber:parseInt(passageNum),referenceNumber:parseInt(refNum),summaryText:summaryText},version:PassageRef$1.version};return "[["+Util.snowman+" "+widgetId+"]]"});return jsxRuntimeExports.jsx(Renderer,{content:modContent,widgets:widgets,findExternalWidgets:this.props.findWidgets,alwaysUpdate:true,linterContext:{...this.props.linterContext,blockHighlight:true},strings:this.context.strings},"choiceContentRenderer")},this.updateChoices=newValueLists=>{const{choiceStates,choices}=this.props;const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,crossedOut:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{choiceState.selected=newValueLists.checked[i];choiceState.crossedOut=newValueLists.crossedOut[i];});this.props.onChange({choiceStates:newChoiceStates});this.props.trackInteraction();},this.showRationalesForCurrentlySelectedChoices=rubric=>{const{choiceStates}=this.props;if(choiceStates){const score=scoreRadio(this.getUserInput(),rubric);const widgetCorrect=score.type==="points"&&score.total===score.earned;const newStates=choiceStates.map(state=>({...state,highlighted:state.selected,rationaleShown:state.selected||state.rationaleShown||widgetCorrect,readOnly:state.selected||state.readOnly||widgetCorrect||this.props.showSolutions!=="none",correctnessShown:state.selected||state.correctnessShown,previouslyAnswered:state.previouslyAnswered||state.selected}));this.props.onChange({choiceStates:newStates},null,true);}},this.deselectIncorrectSelectedChoices=()=>{if(this.props.choiceStates){const newStates=this.props.choiceStates.map((state,i)=>({...state,selected:state.selected&&!!this.props.choices[i].correct,highlighted:false}));this.props.onChange({choiceStates:newStates},null,false);}};}};Radio$2.contextType=PerseusI18nContext;Radio$2.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:linterContextDefault,showSolutions:"none"};
1790
+ const getChoiceStates=({choices,isStatic,showSolutions,choiceStates,values})=>{const defaultState={selected:false,crossedOut:false,readOnly:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false};if(isStatic||showSolutions==="all"){return choices.map(choice=>({...defaultState,selected:!!choice.correct,readOnly:true,rationaleShown:true,correctnessShown:true}))}if(choiceStates){return choiceStates}if(values){return values.map(val=>({...defaultState,selected:val}))}return choices.map(()=>({...defaultState}))};const parseNestedWidgets=content=>{let nextPassageRefId=1;const extractedWidgets={};const parsedContent=content.replace(/\{\{passage-ref (\d+) (\d+)(?: "([^"]*)")?\}\}/g,(_,passageNum,refNum,summaryText)=>{const widgetId="passage-ref "+nextPassageRefId;nextPassageRefId++;extractedWidgets[widgetId]={type:"passage-ref",graded:false,options:{passageNumber:parseInt(passageNum),referenceNumber:parseInt(refNum),summaryText:summaryText},version:PassageRef$1.version};return "[["+Util.snowman+" "+widgetId+"]]"});return {parsedContent,extractedWidgets}};
1782
1791
 
1783
- let Radio$1 = class Radio extends Radio$3{focus(choiceIndex){if(this.radioRef.current){return this.radioRef.current.focus(choiceIndex)}return false}render(){const RadioProper=this.ffIsOn?Radio$2:Radio$3;return jsxRuntimeExports.jsx(RadioProper,{ref:this.radioRef,...this.props})}constructor(props){super(props),this.ffIsOn=false,this.radioRef=React.createRef();this.ffIsOn=props.apiOptions.flags?.["new-radio-widget"]??false;}};
1792
+ const defaultProps={multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:linterContextDefault,showSolutions:"none"};const RadioComponent=({choices,multipleSelect=defaultProps.multipleSelect,countChoices=defaultProps.countChoices,deselectEnabled=defaultProps.deselectEnabled,linterContext=defaultProps.linterContext,showSolutions=defaultProps.showSolutions,static:isStatic,reviewModeRubric,reviewMode,apiOptions,isLastUsedWidget,questionCompleted,findWidgets,onChange,trackInteraction,numCorrect,choiceStates,values})=>{const{strings}=useContext(PerseusI18nContext);useEffect(()=>{console.log("New Radio Component");},[]);const renderRenderer=(content="")=>{const{parsedContent,extractedWidgets}=parseNestedWidgets(content);return jsxRuntimeExports.jsx(Renderer,{content:parsedContent,widgets:extractedWidgets,findExternalWidgets:findWidgets,alwaysUpdate:true,linterContext:{...linterContext,blockHighlight:true},strings:strings},"choiceContentRenderer")};const updateChoices=newValueLists=>{const newChoiceStates=choiceStates?choiceStates.map(state=>({...state})):choices.map(()=>({selected:false,crossedOut:false,highlighted:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false,readOnly:false}));newChoiceStates.forEach((choiceState,i)=>{choiceState.selected=newValueLists.checked[i];choiceState.crossedOut=newValueLists.crossedOut[i];});onChange({choiceStates:newChoiceStates});trackInteraction();};const buildChoiceProps=(choices,choiceStates)=>{return choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected,crossedOut,rationaleShown,correctnessShown,readOnly,highlighted,previouslyAnswered}=choiceStates[i];const reviewChoice=reviewModeRubric?.choices[i];return {content:renderRenderer(content),checked:selected,correct:choice.correct===undefined?!!reviewChoice&&!!reviewChoice.correct:choice.correct,disabled:readOnly,hasRationale:!!choice.clue,rationale:renderRenderer(choice.clue),showRationale:rationaleShown,showCorrectness:correctnessShown,isNoneOfTheAbove:!!choice.isNoneOfTheAbove,revealNoneOfTheAbove:!!(questionCompleted&&selected),crossedOut,highlighted,previouslyAnswered}})};const updatedChoiceStates=getChoiceStates({choices,isStatic,showSolutions,choiceStates,values});const updatedChoicesProp=buildChoiceProps(choices,updatedChoiceStates);return jsxRuntimeExports.jsx(BaseRadio,{labelWrap:true,multipleSelect:multipleSelect,countChoices:countChoices,numCorrect:numCorrect,choices:updatedChoicesProp,onChange:updateChoices,reviewModeRubric:reviewModeRubric,reviewMode:reviewMode,deselectEnabled:deselectEnabled,apiOptions:apiOptions,isLastUsedWidget:isLastUsedWidget})};
1793
+
1794
+ let Radio$2 = class Radio extends React.Component{static getUserInputFromProps(props,unshuffle=true){if(props.choiceStates){const choiceStates=props.choiceStates;const choicesSelected=choiceStates.map(()=>false);for(let i=0;i<choicesSelected.length;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=choiceStates[i].selected;}return {choicesSelected}}const{values}=props;if(values){const choicesSelected=[...values];const valuesLength=values.length;for(let i=0;i<valuesLength;i++){const index=unshuffle?props.choices[i].originalIndex:i;choicesSelected[index]=values[i];}return {choicesSelected}}return {choicesSelected:props.choices.map(()=>false)}}getUserInput(){return Radio.getUserInputFromProps(this.props)}getPromptJSON(){const userInput=Radio.getUserInputFromProps(this.props,false);return getPromptJSON$q(this.props,userInput)}render(){return jsxRuntimeExports.jsx(RadioComponent,{...this.props})}constructor(...args){super(...args),this.showRationalesForCurrentlySelectedChoices=rubric=>{const{choiceStates}=this.props;if(choiceStates){const score=scoreRadio(this.getUserInput(),rubric);const widgetCorrect=score.type==="points"&&score.total===score.earned;const newStates=choiceStates.map(state=>({...state,highlighted:state.selected,rationaleShown:state.selected||state.rationaleShown||widgetCorrect,readOnly:state.selected||state.readOnly||widgetCorrect||this.props.showSolutions!=="none",correctnessShown:state.selected||state.correctnessShown,previouslyAnswered:state.previouslyAnswered||state.selected}));this.props.onChange({choiceStates:newStates},()=>{},true);}},this.deselectIncorrectSelectedChoices=()=>{if(this.props.choiceStates){const newStates=this.props.choiceStates.map((state,i)=>({...state,selected:state.selected&&!!this.props.choices[i].correct,highlighted:false}));this.props.onChange({choiceStates:newStates},()=>{},false);}};}};Radio$2.defaultProps={choices:[],multipleSelect:false,countChoices:false,deselectEnabled:false,linterContext:linterContextDefault,showSolutions:"none"};
1795
+
1796
+ let Radio$1 = class Radio extends Radio$3{focus(choiceIndex){if(this.radioRef.current?.focus){return this.radioRef.current.focus(choiceIndex)}return false}render(){return this.ffIsOn?jsxRuntimeExports.jsx(Radio$2,{...this.props}):jsxRuntimeExports.jsx(Radio$3,{ref:this.radioRef,...this.props})}constructor(props){super(props),this.ffIsOn=false,this.radioRef=React.createRef();this.ffIsOn=props.apiOptions.flags?.["new-radio-widget"]??false;}};
1784
1797
 
1785
1798
  const _choiceTransform=(widgetOptions,strings,problemNum)=>{const _maybeRandomize=function(array){const randomSeed=problemNum===undefined?random:problemNum;return widgetOptions.randomize?shuffle(array,randomSeed??0):array};const _addNoneOfAbove=function(choices){let noneOfTheAbove=null;const newChoices=choices.filter((choice,index)=>{if(choice.isNoneOfTheAbove){noneOfTheAbove=choice;return false}return true});if(noneOfTheAbove){newChoices.push(noneOfTheAbove);}return newChoices};const enforceOrdering=choices=>{const ReversedChoices=[[strings.false,strings.true],[strings.no,strings.yes]];const content=choices.map(c=>c.content);if(ReversedChoices.some(reversed=>_.isEqual(content,reversed))){return [choices[1],choices[0]]}return choices};const choices=widgetOptions.choices.map((choice,i)=>{return {...choice,originalIndex:i,correct:Boolean(choice.correct)}});return _addNoneOfAbove(enforceOrdering(_maybeRandomize(choices)))};const transform$3=(widgetOptions,strings,problemNum)=>{const choices=_choiceTransform(widgetOptions,strings,problemNum);const{hasNoneOfTheAbove,multipleSelect,countChoices,deselectEnabled,numCorrect}=widgetOptions;return {numCorrect:numCorrect,hasNoneOfTheAbove,multipleSelect,countChoices,deselectEnabled,choices,selectedChoices:_.pluck(choices,"correct")}};var Radio = {name:"radio",displayName:"Radio / Multiple choice",accessible:true,widget:Radio$1,transform:transform$3,staticTransform:transform$3,version:radioLogic.version,propUpgrades:radioLogic.widgetOptionsUpgrades,isLintable:true};
1786
1799
 
@@ -1790,7 +1803,7 @@ const{radioBorderColor,checkedColor,circleSize,radioMarginWidth}=constants;var s
1790
1803
 
1791
1804
  const getPromptJSON$n=(renderProps,userInput)=>{return {type:"categorizer",options:{items:renderProps.items,categories:renderProps.categories},userInput:{itemToCategoryMapping:userInput.values}}};
1792
1805
 
1793
- class Categorizer extends React.Component{static getUserInputFromProps(props){return {values:props.values}}getUserInput(){return Categorizer.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$n(this.props,this.getUserInput())}onChange(itemNum,catNum){const values=[...this.props.values];values[itemNum]=catNum;this.change("values",values);this.props.trackInteraction();}render(){const self=this;const isMobile=this.props.apiOptions.isMobile;let indexedItems=this.props.items.map((item,n)=>[item,n]);if(this.props.randomizeItems){indexedItems=shuffle(indexedItems,this.props.problemNum);}const table=jsxRuntimeExports.jsxs("table",{className:"categorizer-table "+css(styles$n.mobileTable),children:[jsxRuntimeExports.jsx("thead",{children:jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{className:css(styles$n.emptyHeaderCell)}),this.props.categories.map((category,i)=>{return jsxRuntimeExports.jsx("th",{className:css(styles$n.header),children:jsxRuntimeExports.jsx(Renderer,{content:category,linterContext:this.props.linterContext,strings:this.context.strings})},i)})]})}),jsxRuntimeExports.jsx("tbody",{children:indexedItems.map(indexedItem=>{const item=indexedItem[0];const itemNum=indexedItem[1];const uniqueId=self.state.uniqueId+"_"+itemNum;return jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{children:jsxRuntimeExports.jsx(Renderer,{content:item,linterContext:this.props.linterContext,strings:this.context.strings})}),self.props.categories.map((catName,catNum)=>{const selected=self.props.values[itemNum]===catNum;return jsxRuntimeExports.jsx("td",{className:"category "+css(styles$n.cell),children:jsxRuntimeExports.jsxs("div",{role:"button","aria-label":catName,onClick:()=>this.onChange(itemNum,catNum),children:[isMobile&&jsxRuntimeExports.jsx("input",{type:"radio",name:uniqueId,className:css(sharedStyles.responsiveInput,sharedStyles.responsiveRadioInput),checked:selected,onChange:()=>this.onChange(itemNum,catNum),onClick:e=>e.stopPropagation()}),!isMobile&&jsxRuntimeExports.jsx("span",{className:css(styles$n.radioSpan,selected&&styles$n.checkedRadioSpan,this.props.static&&selected&&styles$n.staticCheckedRadioSpan),children:selected?jsxRuntimeExports.jsx(InlineIcon,{...iconCircle}):jsxRuntimeExports.jsx(InlineIcon,{...iconCircleThin})})]})},catNum)})]},itemNum)})})]});const extraClassNames=classNames$1({"categorizer-container":true,"static-mode":this.props.static});const inlineStyles=this.props.apiOptions.isMobile?[styles$n.fullBleedContainer]:[];return jsxRuntimeExports.jsx("div",{className:extraClassNames+" "+css(...inlineStyles),children:table})}constructor(...args){super(...args),this.state={uniqueId:_.uniqueId("perseus_radio_")},this.change=(...args)=>{return change.apply(this,args)};}}Categorizer.contextType=PerseusI18nContext;Categorizer.defaultProps={items:[],categories:[],values:[],linterContext:linterContextDefault};const styles$n=StyleSheet.create({mobileTable:{[mediaQueries.smOrSmaller]:{minWidth:"auto"}},fullBleedContainer:{[mediaQueries.mdOrSmaller]:{marginLeft:-16,marginRight:-16,overflowX:"auto"}},header:{textAlign:"center",verticalAlign:"bottom"},cell:{textAlign:"center",padding:0,color:"#ccc",verticalAlign:"middle"},emptyHeaderCell:{backgroundColor:"inherit",borderBottom:"2px solid #ccc"},radioSpan:{fontSize:30,paddingRight:3,":hover":{color:"#999"}},checkedRadioSpan:{color:"#333"},staticCheckedRadioSpan:{color:"#888"}});var Categorizer$1 = {name:"categorizer",displayName:"Categorizer",hidden:true,widget:Categorizer,transform:widgetOptions=>{return {items:widgetOptions.items,categories:widgetOptions.categories,randomizeItems:widgetOptions.randomizeItems}},staticTransform:editorProps=>{return {items:editorProps.items,categories:editorProps.categories,values:editorProps.values,randomizeItems:editorProps.randomizeItems}},isLintable:true};
1806
+ class Categorizer extends React.Component{static getUserInputFromProps(props){return {values:props.values}}getUserInput(){return Categorizer.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$n(this.props,this.getUserInput())}onChange(itemNum,catNum){const values=[...this.props.values];values[itemNum]=catNum;this.change("values",values);this.props.trackInteraction();}render(){const self=this;const isMobile=this.props.apiOptions.isMobile;let indexedItems=this.props.items.map((item,n)=>[item,n]);if(this.props.randomizeItems){indexedItems=shuffle(indexedItems,this.props.problemNum);}const table=jsxRuntimeExports.jsxs("table",{className:"categorizer-table "+css(styles$o.mobileTable),children:[jsxRuntimeExports.jsx("thead",{children:jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{className:css(styles$o.emptyHeaderCell)}),this.props.categories.map((category,i)=>{return jsxRuntimeExports.jsx("th",{className:css(styles$o.header),children:jsxRuntimeExports.jsx(Renderer,{content:category,linterContext:this.props.linterContext,strings:this.context.strings})},i)})]})}),jsxRuntimeExports.jsx("tbody",{children:indexedItems.map(indexedItem=>{const item=indexedItem[0];const itemNum=indexedItem[1];const uniqueId=self.state.uniqueId+"_"+itemNum;return jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{children:jsxRuntimeExports.jsx(Renderer,{content:item,linterContext:this.props.linterContext,strings:this.context.strings})}),self.props.categories.map((catName,catNum)=>{const selected=self.props.values[itemNum]===catNum;return jsxRuntimeExports.jsx("td",{className:"category "+css(styles$o.cell),children:jsxRuntimeExports.jsxs("div",{role:"button","aria-label":catName,onClick:()=>this.onChange(itemNum,catNum),children:[isMobile&&jsxRuntimeExports.jsx("input",{type:"radio",name:uniqueId,className:css(sharedStyles.responsiveInput,sharedStyles.responsiveRadioInput),checked:selected,onChange:()=>this.onChange(itemNum,catNum),onClick:e=>e.stopPropagation()}),!isMobile&&jsxRuntimeExports.jsx("span",{className:css(styles$o.radioSpan,selected&&styles$o.checkedRadioSpan,this.props.static&&selected&&styles$o.staticCheckedRadioSpan),children:selected?jsxRuntimeExports.jsx(InlineIcon,{...iconCircle}):jsxRuntimeExports.jsx(InlineIcon,{...iconCircleThin})})]})},catNum)})]},itemNum)})})]});const extraClassNames=classNames$1({"categorizer-container":true,"static-mode":this.props.static});const inlineStyles=this.props.apiOptions.isMobile?[styles$o.fullBleedContainer]:[];return jsxRuntimeExports.jsx("div",{className:extraClassNames+" "+css(...inlineStyles),children:table})}constructor(...args){super(...args),this.state={uniqueId:_.uniqueId("perseus_radio_")},this.change=(...args)=>{return change.apply(this,args)};}}Categorizer.contextType=PerseusI18nContext;Categorizer.defaultProps={items:[],categories:[],values:[],linterContext:linterContextDefault};const styles$o=StyleSheet.create({mobileTable:{[mediaQueries.smOrSmaller]:{minWidth:"auto"}},fullBleedContainer:{[mediaQueries.mdOrSmaller]:{marginLeft:-16,marginRight:-16,overflowX:"auto"}},header:{textAlign:"center",verticalAlign:"bottom"},cell:{textAlign:"center",padding:0,color:"#ccc",verticalAlign:"middle"},emptyHeaderCell:{backgroundColor:"inherit",borderBottom:"2px solid #ccc"},radioSpan:{fontSize:30,paddingRight:3,":hover":{color:"#999"}},checkedRadioSpan:{color:"#333"},staticCheckedRadioSpan:{color:"#888"}});var Categorizer$1 = {name:"categorizer",displayName:"Categorizer",hidden:true,widget:Categorizer,transform:widgetOptions=>{return {items:widgetOptions.items,categories:widgetOptions.categories,randomizeItems:widgetOptions.randomizeItems}},staticTransform:editorProps=>{return {items:editorProps.items,categories:editorProps.categories,values:editorProps.values,randomizeItems:editorProps.randomizeItems}},isLintable:true};
1794
1807
 
1795
1808
  const isFileProtocol=protocol=>{if(protocol&&protocol.toLowerCase()==="file:"){return true}return false};
1796
1809
 
@@ -1800,11 +1813,11 @@ const getUnsupportedPromptJSON=(widgetType,message="")=>{return {type:widgetType
1800
1813
 
1801
1814
  const getPromptJSON$m=()=>{return getUnsupportedPromptJSON("cs-program")};
1802
1815
 
1803
- const{updateQueryString: updateQueryString$1}=Util;function getUrlFromProgramID$1(programID){const{InitialRequestUrl}=getDependencies();const path="/computer-programming/program/"+`${programID}/embedded?embed=yes&author=no`;if(isFileProtocol(InitialRequestUrl.protocol)){return `https://khanacademy.org${path}`}return toAbsoluteUrl(path)}class CSProgram extends React.Component{componentDidMount(){$(window).on("message",this.handleMessageEvent);}componentWillUnmount(){$(window).off("message",this.handleMessageEvent);}getUserInput(){return {status:this.props.status,message:this.props.message}}getPromptJSON(){return getPromptJSON$m()}render(){if(!this.props.programID){return jsxRuntimeExports.jsx("div",{})}let styleContainer=false;let url=getUrlFromProgramID$1(this.props.programID);let className;const style={height:this.props.height,width:"100%"};if(this.props.showEditor){url+="&editor=yes";className="perseus-scratchpad-editor";}else {url+=`&editor=no&width=${articleMaxWidthInPx}`;className="perseus-scratchpad";if(this.props.programType!=="webpage"){styleContainer=true;}}if(this.props.showButtons){url+="&buttons=yes";style.height+=67;}else {url+="&buttons=no";}if(this.props.settings){const settings={};_.each(this.props.settings,function(setting){if(setting.name&&setting.value){settings[setting.name]=setting.value;}});url=updateQueryString$1(url,"settings",JSON.stringify(settings));}const sandboxOptions=["allow-popups","allow-same-origin","allow-scripts","allow-top-navigation"].join(" ");return jsxRuntimeExports.jsx("div",{className:css(styles$m.widthOverride,styleContainer&&styles$m.container),children:jsxRuntimeExports.jsx("iframe",{sandbox:sandboxOptions,src:url,style:style,className:className,allowFullScreen:true})})}constructor(...args){super(...args),this.handleMessageEvent=e=>{let data={};try{data=JSON.parse(e.originalEvent.data);}catch{return}if(_.isUndefined(data.testsPassed)){return}const status=data.testsPassed?"correct":"incorrect";this.change({status:status,message:data.message});},this.change=(...args)=>{return change.apply(this,args)};}}CSProgram.defaultProps={showEditor:false,showButtons:false,status:"incomplete",message:null};const styles$m=StyleSheet.create({widthOverride:{width:820},container:{margin:"auto"}});var CSProgram$1 = {name:"cs-program",displayName:"CS Program",widget:CSProgram,hidden:true};
1816
+ const{updateQueryString: updateQueryString$1}=Util;function getUrlFromProgramID$1(programID){const{InitialRequestUrl}=getDependencies();const path="/computer-programming/program/"+`${programID}/embedded?embed=yes&author=no`;if(isFileProtocol(InitialRequestUrl.protocol)){return `https://khanacademy.org${path}`}return toAbsoluteUrl(path)}class CSProgram extends React.Component{componentDidMount(){$(window).on("message",this.handleMessageEvent);}componentWillUnmount(){$(window).off("message",this.handleMessageEvent);}getUserInput(){return {status:this.props.status,message:this.props.message}}getPromptJSON(){return getPromptJSON$m()}render(){if(!this.props.programID){return jsxRuntimeExports.jsx("div",{})}let styleContainer=false;let url=getUrlFromProgramID$1(this.props.programID);let className;const style={height:this.props.height,width:"100%"};if(this.props.showEditor){url+="&editor=yes";className="perseus-scratchpad-editor";}else {url+=`&editor=no&width=${articleMaxWidthInPx}`;className="perseus-scratchpad";if(this.props.programType!=="webpage"){styleContainer=true;}}if(this.props.showButtons){url+="&buttons=yes";style.height+=67;}else {url+="&buttons=no";}if(this.props.settings){const settings={};_.each(this.props.settings,function(setting){if(setting.name&&setting.value){settings[setting.name]=setting.value;}});url=updateQueryString$1(url,"settings",JSON.stringify(settings));}const sandboxOptions=["allow-popups","allow-same-origin","allow-scripts","allow-top-navigation"].join(" ");return jsxRuntimeExports.jsx("div",{className:css(styles$n.widthOverride,styleContainer&&styles$n.container),children:jsxRuntimeExports.jsx("iframe",{sandbox:sandboxOptions,src:url,style:style,className:className,allowFullScreen:true})})}constructor(...args){super(...args),this.handleMessageEvent=e=>{let data={};try{data=JSON.parse(e.originalEvent.data);}catch{return}if(_.isUndefined(data.testsPassed)){return}const status=data.testsPassed?"correct":"incorrect";this.change({status:status,message:data.message});},this.change=(...args)=>{return change.apply(this,args)};}}CSProgram.defaultProps={showEditor:false,showButtons:false,status:"incomplete",message:null};const styles$n=StyleSheet.create({widthOverride:{width:820},container:{margin:"auto"}});var CSProgram$1 = {name:"cs-program",displayName:"CS Program",widget:CSProgram,hidden:true};
1804
1817
 
1805
1818
  const getPromptJSON$l=renderProps=>{return {type:"definition",definition:renderProps.definition,togglePrompt:renderProps.togglePrompt}};
1806
1819
 
1807
- class Definition extends React.Component{getPromptJSON(){return getPromptJSON$l(this.props)}render(){return jsxRuntimeExports.jsx(DefinitionConsumer,{children:({activeDefinitionId,setActiveDefinitionId})=>jsxRuntimeExports.jsx(Popover,{content:jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$l.tooltipBody,closeButtonVisible:true,children:jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.definition,widgets:this.props.widgets,strings:this.context.strings})}),opened:activeDefinitionId===this.props.widgetId,onClose:()=>setActiveDefinitionId(null),placement:"top",children:jsxRuntimeExports.jsx(Clickable,{onClick:()=>{this.props.trackInteraction();setActiveDefinitionId(this.props.widgetId);},children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx("span",{style:{color:color.blue,borderBottom:hovered||focused||pressed?`2px solid ${color.blue}`:"none"},children:this.props.togglePrompt})})})})}constructor(...args){super(...args),this.isWidget=true;}}Definition.contextType=PerseusI18nContext;Definition.defaultProps={togglePrompt:"define me",definition:"definition goes here"};const styles$l={tooltipBody:{color:color.offBlack,fontSize:20,fontWeight:500,lineHeight:"30px"}};var Definition$1 = {name:"definition",displayName:"Definition",accessible:true,widget:Definition,transform:x=>x};
1820
+ class Definition extends React.Component{getPromptJSON(){return getPromptJSON$l(this.props)}render(){return jsxRuntimeExports.jsx(DefinitionConsumer,{children:({activeDefinitionId,setActiveDefinitionId})=>jsxRuntimeExports.jsx(Popover,{content:jsxRuntimeExports.jsx(PopoverContentCore,{style:styles$m.tooltipBody,closeButtonVisible:true,children:jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.definition,widgets:this.props.widgets,strings:this.context.strings})}),opened:activeDefinitionId===this.props.widgetId,onClose:()=>setActiveDefinitionId(null),placement:"top",children:jsxRuntimeExports.jsx(Clickable,{onClick:()=>{this.props.trackInteraction();setActiveDefinitionId(this.props.widgetId);},children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx("span",{style:{color:color.blue,borderBottom:hovered||focused||pressed?`2px solid ${color.blue}`:"none"},children:this.props.togglePrompt})})})})}constructor(...args){super(...args),this.isWidget=true;}}Definition.contextType=PerseusI18nContext;Definition.defaultProps={togglePrompt:"define me",definition:"definition goes here"};const styles$m={tooltipBody:{color:color.offBlack,fontSize:20,fontWeight:500,lineHeight:"30px"}};var Definition$1 = {name:"definition",displayName:"Definition",accessible:true,widget:Definition,transform:x=>x};
1808
1821
 
1809
1822
  class DeprecatedStandin extends React__default.Component{render(){return jsxRuntimeExports.jsx("div",{style:{paddingTop:8,paddingBottom:8},children:jsxRuntimeExports.jsx(Banner,{text:this.context.strings.deprecatedStandin,kind:"info",layout:"full-width"})})}constructor(...args){super(...args),this.isWidget=true;}}DeprecatedStandin.contextType=PerseusI18nContext;var DeprecatedStandin$1 = {name:"deprecated-standin",displayName:"Deprecated Standin",widget:DeprecatedStandin,hidden:true};
1810
1823
 
@@ -1814,7 +1827,9 @@ class Dropdown extends React.Component{getUserInput(){return {value:this.props.s
1814
1827
 
1815
1828
  const getPromptJSON$j=renderProps=>{return {type:"explanation",showPrompt:renderProps.showPrompt,explanation:renderProps.explanation}};
1816
1829
 
1817
- function mediaQueryIsMatched(mediaQuery){if(typeof window.matchMedia!=="function"){return false}return window.matchMedia(mediaQuery).matches}class Explanation extends React.Component{componentDidMount(){this._mounted=true;}componentWillUnmount(){this._mounted=false;}getPromptJSON(){return getPromptJSON$j(this.props)}render(){const promptText=this.state.expanded?this.props.hidePrompt:this.props.showPrompt;const caretIcon=this.state.expanded?caretUp:caretDown;const allowTransition=this._mounted&&mediaQueryIsMatched("(prefers-reduced-motion: no-preference)");const buttonStyleOverrides={height:"auto",lineHeight:"inherit",marginLeft:"-2px",marginRight:"2px",paddingLeft:"2px"};const labelStyle={fontSize:"18px",lineHeight:"inherit","text-align":"left",marginRight:"-6px","white-space":"normal"};const contentStyling=[styles$k.content,this.state.expanded?styles$k.contentExpanded:styles$k.contentCollapsed,allowTransition&&(this.state.expanded?styles$k.transitionExpanded:styles$k.transitionCollapsed)];return jsxRuntimeExports.jsx(Id,{children:contentId=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{"aria-expanded":this.state.expanded,"aria-controls":contentId,endIcon:caretIcon,kind:"tertiary",labelStyle:labelStyle,onClick:this._onClick,size:"small",style:buttonStyleOverrides,children:promptText}),jsxRuntimeExports.jsx(View,{id:contentId,style:contentStyling,"aria-hidden":!this.state.expanded,testId:"content-container",children:jsxRuntimeExports.jsx(View,{style:styles$k.contentWrapper,children:jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.explanation,widgets:this.props.widgets,linterContext:this.props.linterContext,strings:this.context.strings})})})]})})}constructor(...args){super(...args),this.isWidget=true,this.state={expanded:false},this._mounted=false,this.change=(...args)=>{return change.apply(this,args)},this._onClick=()=>{this.setState({expanded:!this.state.expanded});this.props.trackInteraction();};}}Explanation.contextType=PerseusI18nContext;Explanation.defaultProps={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{},linterContext:linterContextDefault};const leftBorderSpacing=23;const verticalContentPadding=10;const arrowHeight=14;const styles$k=StyleSheet.create({content:{borderLeft:"0px solid #ccc",display:"inline-grid",position:"relative"},contentCollapsed:{gridTemplateColumns:"0fr",gridTemplateRows:"0fr",marginBottom:0,marginTop:0,minWidth:"0",paddingBottom:0,visibility:"hidden"},contentExpanded:{borderLeftWidth:"5px",gridTemplateColumns:"1fr",gridTemplateRows:"1fr",marginLeft:-23,minWidth:"100%",paddingLeft:leftBorderSpacing,paddingBottom:verticalContentPadding,visibility:"visible",marginBottom:arrowHeight,marginTop:arrowHeight},contentWrapper:{overflow:"hidden"},transitionCollapsed:{transition:"all 0.25s step-end, grid-template-rows 0.25s, margin-top 0.25s, margin-bottom 0.25s, padding-bottom 0.25s"},transitionExpanded:{transition:"grid-template-rows 0.5s, margin-top 0.5s, margin-bottom 0.5s, padding-bottom 0.5s"}});var Explanation$1 = {name:"explanation",displayName:"Explanation",accessible:true,widget:Explanation,transform:_.identity,isLintable:true};
1830
+ function mediaQueryIsMatched(mediaQuery){if(typeof window.matchMedia!=="function"){return false}return window.matchMedia(mediaQuery).matches}class Explanation extends React.Component{componentDidMount(){this._mounted=true;}componentWillUnmount(){this._mounted=false;}getPromptJSON(){return getPromptJSON$j(this.props)}render(){const promptText=this.state.expanded?this.props.hidePrompt:this.props.showPrompt;const caretIcon=this.state.expanded?caretUp:caretDown;const allowTransition=this._mounted&&mediaQueryIsMatched("(prefers-reduced-motion: no-preference)");const buttonStyleOverrides={height:"auto",lineHeight:"inherit",marginLeft:"-2px",marginRight:"2px",paddingLeft:"2px"};const labelStyle={fontSize:"18px",lineHeight:"inherit","text-align":"left",marginRight:"-6px","white-space":"normal"};const contentStyling=[styles$l.content,this.state.expanded?styles$l.contentExpanded:styles$l.contentCollapsed,allowTransition&&(this.state.expanded?styles$l.transitionExpanded:styles$l.transitionCollapsed)];return jsxRuntimeExports.jsx(Id,{children:contentId=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button,{"aria-expanded":this.state.expanded,"aria-controls":contentId,endIcon:caretIcon,kind:"tertiary",labelStyle:labelStyle,onClick:this._onClick,size:"small",style:buttonStyleOverrides,children:promptText}),jsxRuntimeExports.jsx(View,{id:contentId,style:contentStyling,"aria-hidden":!this.state.expanded,testId:"content-container",children:jsxRuntimeExports.jsx(View,{style:styles$l.contentWrapper,children:jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.explanation,widgets:this.props.widgets,linterContext:this.props.linterContext,strings:this.context.strings})})})]})})}constructor(...args){super(...args),this.isWidget=true,this.state={expanded:false},this._mounted=false,this.change=(...args)=>{return change.apply(this,args)},this._onClick=()=>{this.setState({expanded:!this.state.expanded});this.props.trackInteraction();};}}Explanation.contextType=PerseusI18nContext;Explanation.defaultProps={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{},linterContext:linterContextDefault};const leftBorderSpacing=23;const verticalContentPadding=10;const arrowHeight=14;const styles$l=StyleSheet.create({content:{borderLeft:"0px solid #ccc",display:"inline-grid",position:"relative"},contentCollapsed:{gridTemplateColumns:"0fr",gridTemplateRows:"0fr",marginBottom:0,marginTop:0,minWidth:"0",paddingBottom:0,visibility:"hidden"},contentExpanded:{borderLeftWidth:"5px",gridTemplateColumns:"1fr",gridTemplateRows:"1fr",marginLeft:-23,minWidth:"100%",paddingLeft:leftBorderSpacing,paddingBottom:verticalContentPadding,visibility:"visible",marginBottom:arrowHeight,marginTop:arrowHeight},contentWrapper:{overflow:"hidden"},transitionCollapsed:{transition:"all 0.25s step-end, grid-template-rows 0.25s, margin-top 0.25s, margin-bottom 0.25s, padding-bottom 0.25s"},transitionExpanded:{transition:"grid-template-rows 0.5s, margin-top 0.5s, margin-bottom 0.5s, padding-bottom 0.5s"}});var Explanation$1 = {name:"explanation",displayName:"Explanation",accessible:true,widget:Explanation,transform:_.identity,isLintable:true};
1831
+
1832
+ class FreeResponse extends React.Component{getUserInput(){return {currentValue:this.state.currentValue}}isOverLimit(){return !this.props.allowUnlimitedCharacters&&this.characterCount()>this.props.characterLimit}renderCharacterCount(){if(this.props.allowUnlimitedCharacters){return null}const characterCountText=this.context.strings.characterCount({used:this.characterCount(),num:this.props.characterLimit});return jsxRuntimeExports.jsx(View,{children:jsxRuntimeExports.jsxs(Text$1,{role:"status",style:[styles$k.characterCountText,this.isOverLimit()?styles$k.overCharacterLimit:undefined],children:[this.isOverLimit()&&jsxRuntimeExports.jsx(PhosphorIcon,{icon:warningCircleIcon,size:"small",style:styles$k.warningCircleIcon}),characterCountText]})})}render(){return jsxRuntimeExports.jsxs(View,{style:styles$k.container,className:"free-response",children:[jsxRuntimeExports.jsx(LabeledField,{label:jsxRuntimeExports.jsx(View,{className:"free-response-question",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.question,strings:this.context.strings})}),field:jsxRuntimeExports.jsx(TextArea,{error:this.isOverLimit(),onChange:this.handleChange,placeholder:this.props.placeholder,style:styles$k.textarea,value:this.state.currentValue}),styles:{label:styles$k.questionLabel}}),this.renderCharacterCount()]})}constructor(...args){super(...args),this.state={currentValue:""},this.characterCount=()=>{return this.state.currentValue.replace(/\n/g,"").length},this.handleChange=newValue=>{this.setState({currentValue:newValue});};}}FreeResponse.contextType=PerseusI18nContext;var FreeResponse$1 = {name:"free-response",accessible:true,displayName:"Free Response",widget:FreeResponse,hidden:true};const styles$k=StyleSheet.create({container:{gap:spacing.xSmall_8},characterCountText:{color:semanticColor.text.secondary,fontSize:font.size.small},overCharacterLimit:{color:color.red},questionLabel:{fontWeight:font.weight.bold},textarea:{padding:spacing.medium_16},warningCircleIcon:{marginInlineEnd:spacing.xSmall_8}});
1818
1833
 
1819
1834
  const getPromptJSON$i=(title,rendererJSON,hintRendererJSON)=>{if(!rendererJSON){return {type:"graded-group",title,content:"",widgets:{},hint:hintRendererJSON}}return {...rendererJSON,title,type:"graded-group",hint:hintRendererJSON}};
1820
1835
 
@@ -1832,7 +1847,7 @@ const getPromptJSON$g=(renderProps,userInput)=>{const{type,coords}=userInput;con
1832
1847
 
1833
1848
  const movableTypeToComponent={PLOT:Graphie.Plot,PARABOLA:Graphie.Parabola,SINUSOID:Graphie.Sinusoid};const DEFAULT_BACKGROUND_IMAGE={url:null};const getEquationString=props=>{const plot=props.plot;if(plot.type&&plot.coords){const handler=GrapherUtil$1.functionForType(plot.type);const result=handler.getEquationString(plot.coords,plot.asymptote);return result||""}return ""};const pointsFromNormalized=(coordsList,range,step,snapStep)=>{const numSteps=function(range,step){return Math.floor((range[1]-range[0])/step)};return coordsList.map(coords=>{const unsnappedPoint=coords.map((coord,i)=>{const currRange=range[i];const currStep=step[i];const nSteps=numSteps(currRange,currStep);const tick=Math.round(coord*nSteps);return currRange[0]+currStep*tick});return point.roundTo(unsnappedPoint,snapStep)})};const maybePointsFromNormalized=(coordsList,range,step,snapStep)=>{if(coordsList){return pointsFromNormalized(coordsList,range,step,snapStep)}return coordsList};const defaultPlotProps=(type,graph)=>{const model=GrapherUtil$1.functionForType(type);const defaultAsymptote="defaultAsymptote"in model?model.defaultAsymptote:null;const gridStep=[1,1];const snapStep=Util.snapStepFromGridStep(gridStep);return {type,asymptote:maybePointsFromNormalized(defaultAsymptote,graph.range,graph.step,snapStep),coords:null}};const chooseType=_.first;const getGridAndSnapSteps=(options,boxSize)=>{const gridStep=options.gridStep||Util.getGridStep(options.range,options.step,boxSize);const snapStep=options.snapStep||Util.snapStepFromGridStep(gridStep);return {gridStep:gridStep,snapStep:snapStep}};const defaultGraph={labels:["x","y"],range:[[-10,10],[-10,10]],step:[1,1],backgroundImage:DEFAULT_BACKGROUND_IMAGE,markings:"graph",rulerLabel:"",rulerTicks:10,valid:true,showTooltips:false};const defaultPlot=defaultPlotProps("linear",defaultGraph);const DEFAULT_GRAPHER_PROPS={graph:defaultGraph,plot:defaultPlot,availableTypes:[defaultPlot.type]};const typeToButton=type=>{const capitalized=type.charAt(0).toUpperCase()+type.substring(1);const staticUrl=getDependencies().staticUrl;return {value:type,title:capitalized,content:jsxRuntimeExports.jsx("img",{src:staticUrl(GrapherUtil$1.functionForType(type).url),alt:capitalized})}};
1834
1849
 
1835
- const MovablePoint$3=Graphie.MovablePoint;const MovableLine$2=Graphie.MovableLine;function isFlipped(newCoord,oldCoord,line){const CCW=(a,b,c)=>{return (b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1])};return CCW(line[0],line[1],oldCoord)>0!==CCW(line[0],line[1],newCoord)>0}const typeSelectorStyle={padding:"5px 5px"};class FunctionGrapher extends React.Component{render(){const pointForCoord=(coord,i)=>{return jsxRuntimeExports.jsx(MovablePoint$3,{coord:coord,static:this.props.static,constraints:[Interactive2.MovablePoint.constraints.bound(),Interactive2.MovablePoint.constraints.snap(),coord=>{const isFunction=this._coords().every((otherCoord,j)=>{return i===j||!otherCoord||!number.equal(coord[0],otherCoord[0])});if(!isFunction){return false}if(this.props.model&&this.props.model.extraCoordConstraint){const extraConstraint=this.props.model.extraCoordConstraint;const proposedCoords=deepClone(this._coords());const oldCoord=deepClone(proposedCoords[i]);proposedCoords[i]=coord;return extraConstraint(coord,oldCoord,proposedCoords,this._asymptote(),this.props.graph)}return isFunction}],onMove:(newCoord,oldCoord)=>{let coords;const asymptote=this._asymptote();if(asymptote&&this.props.model.allowReflectOverAsymptote&&isFlipped(newCoord,oldCoord,asymptote)){coords=this._coords().map(coord=>{return point.reflectOverLine(coord,asymptote)});}else {coords=deepClone(this._coords());}coords[i]=newCoord;this.props.onChange({coords:coords});},showHairlines:this.props.showHairlines,hideHairlines:this.props.hideHairlines,showTooltips:this.props.showTooltips,isMobile:this.props.isMobile},i)};const points=this._coords().map(pointForCoord);const box=this.props.graph.box;const imageDescription=this.props.graph.backgroundImage;let image=null;if(imageDescription.url){const scale=box[0]/interactiveSizes$1.defaultBoxSize;image=jsxRuntimeExports.jsx(SvgImage,{src:imageDescription.url,width:imageDescription.width,height:imageDescription.height,scale:scale});}return jsxRuntimeExports.jsx("div",{className:"perseus-widget "+"perseus-widget-grapher",style:{width:box[0],height:box[1],boxSizing:"initial"},children:jsxRuntimeExports.jsxs("div",{className:"graphie-container blank-background",style:{width:box[0],height:box[1]},children:[image,jsxRuntimeExports.jsxs(Graphie,{...this.props.graph,setDrawingAreaAvailable:this.props.setDrawingAreaAvailable,children:[this.props.model&&this.renderPlot(),this.props.model&&this.renderAsymptote(),this.props.model&&points]})]})})}constructor(...args){super(...args),this._coords=()=>{const props=this.props;const graph=props.graph;const defaultModelCoords=props.model&&maybePointsFromNormalized(props.model.defaultCoords,graph.range,graph.step,graph.snapStep);return props.coords||defaultModelCoords||null},this._asymptote=()=>{return this.props.asymptote},this.change=(...args)=>{return change.apply(this,args)},this.renderPlot=()=>{const model=this.props.model;const xRange=this.props.graph.range[0];const style={stroke:this.props.isMobile?KhanColors.BLUE_C:KhanColors.DYNAMIC,...this.props.isMobile?{"stroke-width":3}:{}};const coeffs=model.getCoefficients(this._coords(),this._asymptote());if(!coeffs){return}const functionProps=model.getPropsForCoeffs(coeffs,xRange);const Movable=movableTypeToComponent[model.movable];return createElement(Movable,{...functionProps,key:this.props.model.url,range:xRange,style:style})},this.renderAsymptote=()=>{const model=this.props.model;const graph=this.props.graph;const asymptote=this._asymptote();const showAsymptote=asymptote?.length>0;const dashed={strokeDasharray:"- "};return showAsymptote&&jsxRuntimeExports.jsx(MovableLine$2,{onMove:(newCoord,oldCoord)=>{const delta=vector$3.subtract(newCoord,oldCoord);const newAsymptote=this._asymptote().map(coord=>vector$3.add(coord,delta));this.props.onChange({asymptote:newAsymptote});},constraints:[Interactive2.MovableLine.constraints.bound(),Interactive2.MovableLine.constraints.snap(),(newCoord,oldCoord)=>{const delta=vector$3.subtract(newCoord,oldCoord);const proposedAsymptote=this._asymptote().map(coord=>vector$3.add(coord,delta));if(model.extraAsymptoteConstraint){return model.extraAsymptoteConstraint(newCoord,oldCoord,this._coords(),proposedAsymptote,graph)}return true}],normalStyle:dashed,highlightStyle:dashed,children:asymptote.map((coord,i)=>jsxRuntimeExports.jsx(MovablePoint$3,{coord:coord,static:true,draw:null,extendLine:true,showHairlines:this.props.showHairlines,hideHairlines:this.props.hideHairlines,showTooltips:this.props.showTooltips,isMobile:this.props.isMobile},`asymptoteCoord-${i}`))})};}}FunctionGrapher.defaultProps={graph:{range:[[-10,10],[-10,10]],step:[1,1]},coords:null,asymptote:null,isMobile:false};class Grapher extends React.Component{static getUserInputFromProps(props){return props.plot}_getGridConfig(options){return options.step.map((step,i)=>{return Util.gridDimensionConfig(step,options.range[i],options.box[i],options.gridStep[i])})}_calculateMobileTickStep(gridStep,step,ranges){const tickStep=Util.constrainedTickStepsFromTickSteps(step,ranges);tickStep[0]=tickStep[0]/gridStep[0];tickStep[1]=tickStep[1]/gridStep[1];return tickStep}getUserInput(){return Grapher.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$g(this.props,this.getUserInput())}render(){const type=this.props.plot.type;const coords=this.props.plot.coords;const asymptote="asymptote"in this.props.plot?this.props.plot.asymptote:undefined;const typeSelector=jsxRuntimeExports.jsx("div",{style:typeSelectorStyle,children:jsxRuntimeExports.jsx(ButtonGroup,{value:type,allowEmpty:true,buttons:this.props.availableTypes.map(typeToButton),onChange:this.handleActiveTypeChange})});const box=getInteractiveBoxFromSizeClass(this.props.containerSizeClass);const options={...this.props.graph,...getGridAndSnapSteps(this.props.graph,box[0]),gridConfig:this._getGridConfig({...this.props.graph,box:box,...getGridAndSnapSteps(this.props.graph,box[0])})};const grapherProps={graph:{box:box,range:options.range,step:options.step,snapStep:options.snapStep,backgroundImage:options.backgroundImage,options:options,setup:this._setupGraphie},onChange:this.handlePlotChanges,model:type&&GrapherUtil$1.functionForType(type),coords:coords,asymptote:asymptote,static:this.props.static,setDrawingAreaAvailable:this.props.apiOptions.setDrawingAreaAvailable,isMobile:this.props.apiOptions.isMobile,showTooltips:this.props.graph.showTooltips,showHairlines:this.showHairlines,hideHairlines:this.hideHairlines};return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(FunctionGrapher,{...grapherProps}),this.props.availableTypes.length>1&&typeSelector]})}constructor(...args){super(...args),this.handlePlotChanges=newPlot=>{const plot={...this.props.plot,...newPlot};this.props.onChange({plot:plot});this.props.trackInteraction();},this.handleActiveTypeChange=newType=>{const graph=this.props.graph;const plot={...this.props.plot,...defaultPlotProps(newType,graph)};this.props.onChange({plot:plot});},this._setupGraphie=(graphie,options)=>{const isMobile=this.props.apiOptions.isMobile;if(options.markings==="graph"){graphie.graphInit({range:options.range,scale:options.gridConfig.map(e=>e.scale),axisArrows:"<->",labelFormat:function(s){return "\\small{"+s+"}"},gridStep:options.gridStep,snapStep:options.snapStep,tickStep:isMobile?this._calculateMobileTickStep(options.gridStep,options.step,options.range):options.gridConfig.map(e=>e.tickStep),labelStep:1,unityLabels:options.gridConfig.map(e=>e.unityLabel),isMobile:isMobile});graphie.label([0,options.range[1][1]],options.labels[1],isMobile?"below right":"above");graphie.label([options.range[0][1],0],options.labels[0],isMobile?"above left":"right");}else if(options.markings==="grid"){graphie.graphInit({range:options.range,scale:options.gridConfig.map(e=>e.scale),gridStep:options.gridStep,axes:false,ticks:false,labels:false,isMobile:isMobile});}else if(options.markings==="none"){graphie.init({range:options.range,scale:options.gridConfig.map(e=>e.scale)});}if(this.props.apiOptions.isMobile){const hairlineStyle={normalStyle:{strokeWidth:1}};this.horizHairline=new WrappedLine(graphie,[0,0],[0,0],hairlineStyle);this.horizHairline.attr({stroke:KhanColors.INTERACTIVE});this.horizHairline.hide();this.vertHairline=new WrappedLine(graphie,[0,0],[0,0],hairlineStyle);this.vertHairline.attr({stroke:KhanColors.INTERACTIVE});this.vertHairline.hide();}},this.showHairlines=point=>{if(this.props.apiOptions.isMobile&&this.props.markings!=="none"){this.horizHairline.moveTo([this.props.graph.range[0][0],point[1]],[this.props.graph.range[0][1],point[1]]);this.horizHairline.show();this.vertHairline.moveTo([point[0],this.props.graph.range[1][0]],[point[0],this.props.graph.range[1][1]]);this.vertHairline.show();}},this.hideHairlines=()=>{if(this.props.apiOptions.isMobile){this.horizHairline.hide();this.vertHairline.hide();}};}}Grapher.defaultProps=DEFAULT_GRAPHER_PROPS;const transform$1=editorProps=>{const widgetProps={availableTypes:editorProps.availableTypes,graph:editorProps.graph};if(widgetProps.availableTypes.length===1){const graph=widgetProps.graph;const type=chooseType(widgetProps.availableTypes);widgetProps.plot=defaultPlotProps(type,graph);}return widgetProps};const staticTransform$4=editorProps=>{return {...transform$1(editorProps),availableTypes:[editorProps.correct.type],plot:editorProps.correct}};var Grapher$1 = {name:"grapher",displayName:"Grapher",hidden:true,widget:Grapher,transform: transform$1,staticTransform: staticTransform$4};
1850
+ const MovablePoint$3=Graphie.MovablePoint;const MovableLine$2=Graphie.MovableLine;function isFlipped(newCoord,oldCoord,line){const CCW=(a,b,c)=>{return (b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1])};return CCW(line[0],line[1],oldCoord)>0!==CCW(line[0],line[1],newCoord)>0}const typeSelectorStyle={padding:"5px 5px"};class FunctionGrapher extends React.Component{render(){const pointForCoord=(coord,i)=>{return jsxRuntimeExports.jsx(MovablePoint$3,{coord:coord,static:this.props.static,constraints:[Interactive2.MovablePoint.constraints.bound(),Interactive2.MovablePoint.constraints.snap(),coord=>{const isFunction=this._coords().every((otherCoord,j)=>{return i===j||!otherCoord||!number.equal(coord[0],otherCoord[0])});if(!isFunction){return false}if(this.props.model&&this.props.model.extraCoordConstraint){const extraConstraint=this.props.model.extraCoordConstraint;const proposedCoords=deepClone(this._coords());const oldCoord=deepClone(proposedCoords[i]);proposedCoords[i]=coord;return extraConstraint(coord,oldCoord,proposedCoords,this._asymptote(),this.props.graph)}return isFunction}],onMove:(newCoord,oldCoord)=>{let coords;const asymptote=this._asymptote();if(asymptote&&this.props.model.allowReflectOverAsymptote&&isFlipped(newCoord,oldCoord,asymptote)){coords=this._coords().map(coord=>{return point.reflectOverLine(coord,asymptote)});}else {coords=deepClone(this._coords());}coords[i]=newCoord;this.props.onChange({coords:coords});},showHairlines:this.props.showHairlines,hideHairlines:this.props.hideHairlines,showTooltips:this.props.showTooltips,isMobile:this.props.isMobile},i)};const points=this._coords().map(pointForCoord);const box=this.props.graph.box;const imageDescription=this.props.graph.backgroundImage;let image=null;if(imageDescription.url){const scale=box[0]/interactiveSizes$1.defaultBoxSize;image=jsxRuntimeExports.jsx(SvgImage,{src:imageDescription.url,width:imageDescription.width,height:imageDescription.height,scale:scale});}return jsxRuntimeExports.jsx("div",{className:"perseus-widget "+"perseus-widget-grapher",style:{width:box[0],height:box[1],boxSizing:"initial"},children:jsxRuntimeExports.jsxs("div",{className:"graphie-container blank-background",style:{width:box[0],height:box[1]},children:[image,jsxRuntimeExports.jsxs(Graphie,{...this.props.graph,setDrawingAreaAvailable:this.props.setDrawingAreaAvailable,children:[this.props.model&&this.renderPlot(),this.props.model&&this.renderAsymptote(),this.props.model&&points]})]})})}constructor(...args){super(...args),this._coords=()=>{const props=this.props;const graph=props.graph;const defaultModelCoords=props.model&&maybePointsFromNormalized(props.model.defaultCoords,graph.range,graph.step,graph.snapStep);return props.coords||defaultModelCoords||null},this._asymptote=()=>{return this.props.asymptote},this.change=(...args)=>{return change.apply(this,args)},this.renderPlot=()=>{const model=this.props.model;const xRange=this.props.graph.range[0];const style={stroke:this.props.isMobile?KhanColors.BLUE_C:KhanColors.DYNAMIC,...this.props.isMobile?{"stroke-width":3}:{}};const coeffs=model.getCoefficients(this._coords(),this._asymptote());if(!coeffs){return}const functionProps=model.getPropsForCoeffs(coeffs,xRange);const Movable=movableTypeToComponent[model.movable];return createElement(Movable,{...functionProps,key:this.props.model.url,range:xRange,style:style})},this.renderAsymptote=()=>{const model=this.props.model;const graph=this.props.graph;const asymptote=this._asymptote();const showAsymptote=asymptote?.length>0;const dashed={strokeDasharray:"- "};return showAsymptote&&jsxRuntimeExports.jsx(MovableLine$2,{onMove:(newCoord,oldCoord)=>{const delta=vector$3.subtract(newCoord,oldCoord);const newAsymptote=this._asymptote().map(coord=>vector$3.add(coord,delta));this.props.onChange({asymptote:newAsymptote});},constraints:[Interactive2.MovableLine.constraints.bound(),Interactive2.MovableLine.constraints.snap(),(newCoord,oldCoord)=>{const delta=vector$3.subtract(newCoord,oldCoord);const proposedAsymptote=this._asymptote().map(coord=>vector$3.add(coord,delta));if(model.extraAsymptoteConstraint){return model.extraAsymptoteConstraint(newCoord,oldCoord,this._coords(),proposedAsymptote,graph)}return true}],normalStyle:dashed,highlightStyle:dashed,children:asymptote.map((coord,i)=>jsxRuntimeExports.jsx(MovablePoint$3,{coord:coord,static:true,draw:null,extendLine:true,showHairlines:this.props.showHairlines,hideHairlines:this.props.hideHairlines,showTooltips:this.props.showTooltips,isMobile:this.props.isMobile},`asymptoteCoord-${i}`))})};}}FunctionGrapher.defaultProps={graph:{range:[[-10,10],[-10,10]],step:[1,1]},coords:null,asymptote:null,isMobile:false};class Grapher extends React.Component{static getUserInputFromProps(props){return props.plot}_getGridConfig(options){return options.step.map((step,i)=>{return Util.gridDimensionConfig(step,options.range[i],options.box[i],options.gridStep[i])})}_calculateMobileTickStep(gridStep,step,ranges){const tickStep=Util.constrainedTickStepsFromTickSteps(step,ranges);tickStep[0]=tickStep[0]/gridStep[0];tickStep[1]=tickStep[1]/gridStep[1];return tickStep}getUserInput(){return Grapher.getUserInputFromProps(this.props)}getPromptJSON(){return getPromptJSON$g(this.props,this.getUserInput())}render(){const type=this.props.plot.type;const coords=this.props.plot.coords;const asymptote="asymptote"in this.props.plot?this.props.plot.asymptote:undefined;const typeSelector=jsxRuntimeExports.jsx("div",{style:typeSelectorStyle,children:jsxRuntimeExports.jsx(ButtonGroup,{value:type,allowEmpty:true,buttons:this.props.availableTypes.map(typeToButton),onChange:this.handleActiveTypeChange})});const box=getInteractiveBoxFromSizeClass(this.props.containerSizeClass);const options={...this.props.graph,...getGridAndSnapSteps(this.props.graph,box[0]),gridConfig:this._getGridConfig({...this.props.graph,box:box,...getGridAndSnapSteps(this.props.graph,box[0])})};const grapherProps={graph:{box:box,range:options.range,step:options.step,snapStep:options.snapStep,backgroundImage:options.backgroundImage,options:options,setup:this._setupGraphie},onChange:this.handlePlotChanges,model:type&&GrapherUtil$1.functionForType(type),coords:coords,asymptote:asymptote,static:this.props.static,setDrawingAreaAvailable:this.props.apiOptions.setDrawingAreaAvailable,isMobile:this.props.apiOptions.isMobile,showTooltips:this.props.graph.showTooltips,showHairlines:this.showHairlines,hideHairlines:this.hideHairlines};return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx(FunctionGrapher,{...grapherProps}),this.props.availableTypes.length>1&&typeSelector]})}constructor(...args){super(...args),this.handlePlotChanges=newPlot=>{const plot={...this.props.plot,...newPlot};this.props.onChange({plot:plot});this.props.trackInteraction();},this.handleActiveTypeChange=newType=>{const graph=this.props.graph;const plot={...this.props.plot,...defaultPlotProps(newType,graph)};this.props.onChange({plot:plot});},this._setupGraphie=(graphie,options)=>{const isMobile=this.props.apiOptions.isMobile;if(options.markings==="graph"){graphie.graphInit({range:options.range,scale:options.gridConfig.map(e=>e.scale),axisArrows:"<->",labelFormat:function(s){return "\\small{"+s+"}"},gridStep:options.gridStep,snapStep:options.snapStep,tickStep:isMobile?this._calculateMobileTickStep(options.gridStep,options.step,options.range):options.gridConfig.map(e=>e.tickStep),labelStep:1,unityLabels:options.gridConfig.map(e=>e.unityLabel),isMobile:isMobile});graphie.label([0,options.range[1][1]],options.labels[1],isMobile?"below right":"above");graphie.label([options.range[0][1],0],options.labels[0],isMobile?"above left":"right");}else if(options.markings==="grid"){graphie.graphInit({range:options.range,scale:options.gridConfig.map(e=>e.scale),gridStep:options.gridStep,axes:false,ticks:false,labels:false,isMobile:isMobile});}else if(options.markings==="none"){graphie.init({range:options.range,scale:options.gridConfig.map(e=>e.scale)});}if(this.props.apiOptions.isMobile){const hairlineStyle={normalStyle:{strokeWidth:1}};this.horizHairline=new WrappedLine(graphie,[0,0],[0,0],hairlineStyle);this.horizHairline.attr({stroke:KhanColors.INTERACTIVE});this.horizHairline.hide();this.vertHairline=new WrappedLine(graphie,[0,0],[0,0],hairlineStyle);this.vertHairline.attr({stroke:KhanColors.INTERACTIVE});this.vertHairline.hide();}},this.showHairlines=point=>{if(this.props.apiOptions.isMobile){this.horizHairline.moveTo([this.props.graph.range[0][0],point[1]],[this.props.graph.range[0][1],point[1]]);this.horizHairline.show();this.vertHairline.moveTo([point[0],this.props.graph.range[1][0]],[point[0],this.props.graph.range[1][1]]);this.vertHairline.show();}},this.hideHairlines=()=>{if(this.props.apiOptions.isMobile){this.horizHairline.hide();this.vertHairline.hide();}};}}Grapher.defaultProps=DEFAULT_GRAPHER_PROPS;const transform$1=editorProps=>{const widgetProps={availableTypes:editorProps.availableTypes,graph:editorProps.graph};if(widgetProps.availableTypes.length===1){const graph=widgetProps.graph;const type=chooseType(widgetProps.availableTypes);widgetProps.plot=defaultPlotProps(type,graph);}return widgetProps};const staticTransform$4=editorProps=>{return {...transform$1(editorProps),availableTypes:[editorProps.correct.type],plot:editorProps.correct}};var Grapher$1 = {name:"grapher",displayName:"Grapher",hidden:true,widget:Grapher,transform: transform$1,staticTransform: staticTransform$4};
1836
1851
 
1837
1852
  const getPromptJSON$f=rendererJSON=>{if(!rendererJSON){return {type:"group",content:"",widgets:{}}}return {...rendererJSON,type:"group"}};
1838
1853
 
@@ -1949,7 +1964,7 @@ const actions={global:{deleteIntent,changeInteractionMode,changeKeyboardInvitati
1949
1964
 
1950
1965
  const MafsCssTransformWrapper=({children})=>jsxRuntimeExports.jsx("g",{style:{transform:`var(--mafs-view-transform) var(--mafs-user-transform)`},children:children});
1951
1966
 
1952
- const TextLabel=({children,...rest})=>jsxRuntimeExports.jsx(Text$1,{size:16,svgTextProps:{filter:"url(#background)",fontWeight:"bold"},...rest,children:children});const SvgDefs=()=>jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsxs("filter",{id:"background",x:"-5%",width:"110%",y:"0%",height:"100%",children:[jsxRuntimeExports.jsx("feFlood",{floodColor:"#FFF",floodOpacity:"0.64"}),jsxRuntimeExports.jsx("feComposite",{operator:"over",in:"SourceGraphic"})]})});
1967
+ const TextLabel=({children,...rest})=>jsxRuntimeExports.jsx(Text$2,{size:16,svgTextProps:{filter:"url(#background)",fontWeight:"bold"},...rest,children:children});const SvgDefs=()=>jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsxs("filter",{id:"background",x:"-5%",width:"110%",y:"0%",height:"100%",children:[jsxRuntimeExports.jsx("feFlood",{floodColor:"#FFF",floodOpacity:"0.64"}),jsxRuntimeExports.jsx("feComposite",{operator:"over",in:"SourceGraphic"})]})});
1953
1968
 
1954
1969
  const{clockwise}=geometry;const{getAngleFromVertex: getAngleFromVertex$1}=angles;const PolygonAngle=({centerPoint,endPoints,range,polygonLines,showAngles,snapTo})=>{const[centerX,centerY]=centerPoint;const areClockwise=clockwise([centerPoint,...endPoints]);const[[startX,startY],[endX,endY]]=areClockwise?endPoints:endPoints.reverse();const radius=.3;const a=vec.dist(centerPoint,endPoints[0]);const b=vec.dist(centerPoint,endPoints[1]);const c=vec.dist(endPoints[0],endPoints[1]);let lawOfCosinesRadicand=(a**2+b**2-c**2)/(2*a*b);if(lawOfCosinesRadicand<-1||lawOfCosinesRadicand>1){lawOfCosinesRadicand=Math.round(lawOfCosinesRadicand);}const angle=Math.acos(lawOfCosinesRadicand);const y1=centerY+(startY-centerY)/a*radius;const x2=centerX+(endX-centerX)/b*radius;const x1=centerX+(startX-centerX)/a*radius;const y2=centerY+(endY-centerY)/b*radius;const[x3,y3]=vec.add(centerPoint,vec.add(vec.sub([x1,y1],centerPoint),vec.sub([x2,y2],centerPoint)));if(!showAngles){return isRightPolygonAngle(angle)?jsxRuntimeExports.jsx(RightAngleSquare,{start:[x1,y1],vertex:[x2,y2],end:[x3,y3]}):null}const isOutside=shouldDrawArcOutside([x3,y3],centerPoint,range,polygonLines);const largeArcFlag=isOutside?1:0;const sweepFlag=isOutside?1:0;const arc=`M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${x2} ${y2}`;let angleInDegrees=angle*(180/Math.PI);if(isOutside){angleInDegrees=360-angleInDegrees;}const angleLabelNumber=parseFloat(angleInDegrees.toFixed(snapTo==="angles"?0:1));const angleLabel=Number.isInteger(angleLabelNumber)?angleLabelNumber:"≈ "+angleLabelNumber;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsxs("filter",{id:"background",x:"-5%",width:"110%",y:"0%",height:"100%",children:[jsxRuntimeExports.jsx("feFlood",{floodColor:"#FFF",floodOpacity:"0.5"}),jsxRuntimeExports.jsx("feComposite",{operator:"over",in:"SourceGraphic"})]})}),!isOutside&&isRightPolygonAngle(angle)?jsxRuntimeExports.jsx(RightAngleSquare,{start:[x1,y1],vertex:[x2,y2],end:[x3,y3]}):jsxRuntimeExports.jsx(Arc,{arc:arc}),jsxRuntimeExports.jsxs(TextLabel,{x:x3,y:y3,attach:y3-centerY>0?"s":"n",attachDistance:Math.abs(y3-centerY)<.2||vec.dist([x3,y3],centerPoint)<.3?20:10,children:[angleLabel,"°"]})]})};const Angle=({vertex,coords,showAngles,allowReflexAngles,range})=>{const areClockwise=clockwise([...coords,vertex]);const shouldReverseCoords=areClockwise&&!allowReflexAngles;const clockwiseCoords=shouldReverseCoords?coords:coords.reverse();const startAngle=getAngleFromVertex$1(clockwiseCoords[0],vertex);const endAngle=getAngleFromVertex$1(clockwiseCoords[1],vertex);const angle=(startAngle+360-endAngle)%360;const isReflexive=angle>180;const[centerX,centerY]=vertex;const[point1,point2]=clockwiseCoords;const[startX,startY]=point1;const[endX,endY]=point2;const a=vec.dist(vertex,point1);const b=vec.dist(vertex,point2);const radius=2;const y1=centerY+(startY-centerY)/a*radius;const x2=centerX+(endX-centerX)/b*radius;const x1=centerX+(startX-centerX)/a*radius;const y2=centerY+(endY-centerY)/b*radius;const[x3,y3]=vec.add(vertex,vec.add(vec.sub([x1,y1],vertex),vec.sub([x2,y2],vertex)));const isOutside=shouldDrawArcOutside([x3,y3],vertex,range,[[vertex,point1],[vertex,point2]]);const largeArcFlag=isOutside||isReflexive?1:0;const sweepFlag=isOutside&&isReflexive?1:0;const arc=`M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${x2} ${y2}`;const angleLabel=parseFloat(angle.toFixed(0));const[textX,textY]=calculateBisectorPoint(point1,point2,vertex,isReflexive,allowReflexAngles,radius);const{disableKeyboardInteraction}=useGraphConfig();const arcClassName=disableKeyboardInteraction?"angle-arc-static":"angle-arc-interactive";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsxs("filter",{id:"background",x:"-5%",width:"110%",y:"0%",height:"100%",children:[jsxRuntimeExports.jsx("feFlood",{floodColor:"#FFF",floodOpacity:"0.5"}),jsxRuntimeExports.jsx("feComposite",{operator:"over",in:"SourceGraphic"})]})}),isRightAngle(angle)?jsxRuntimeExports.jsx(RightAngleSquare,{start:[x1,y1],vertex:[x2,y2],end:[x3,y3],className:arcClassName}):jsxRuntimeExports.jsx(Arc,{arc:arc,className:arcClassName}),showAngles&&jsxRuntimeExports.jsxs(TextLabel,{x:textX,y:textY,color:color.blue,children:[angleLabel,"°"]})]})};const RightAngleSquare=({start:[x1,y1],vertex:[x2,y2],end:[x3,y3],className})=>jsxRuntimeExports.jsx(MafsCssTransformWrapper,{children:jsxRuntimeExports.jsx("path",{"aria-hidden":true,d:`M ${x1} ${y1} L ${x3} ${y3} M ${x3} ${y3} L ${x2} ${y2}`,strokeWidth:.02,fill:"none",className:className,"data-testid":"angle-indicators__right-angle"})});const Arc=({arc,className})=>{return jsxRuntimeExports.jsx(MafsCssTransformWrapper,{children:jsxRuntimeExports.jsx("path",{"aria-hidden":true,d:arc,strokeWidth:.02,fill:"none",className:className,"data-testid":"angle-indicators__arc"})})};const isRightPolygonAngle=angle=>Math.abs(angle-Math.PI/2)<.01;const isRightAngle=angle=>Math.round(angle)===90;const shouldDrawArcOutside=(midpoint,vertex,range,polygonLines)=>{const rangeIntersectionPoint=getIntersectionOfRayWithBox(midpoint,vertex,range);let lineIntersectionCount=0;polygonLines.forEach(line=>segmentsIntersect([vertex,rangeIntersectionPoint],line)&&lineIntersectionCount++);return !isEven(lineIntersectionCount)};const isEven=n=>n%2===0;function calculateBisectorPoint(point1,point2,vertex,isReflex,allowReflex,arcRadius){const[originX,originY]=vertex;const[x1,y1]=point1;const[x2,y2]=point2;const vectorA=[x1-originX,y1-originY];const vectorB=[x2-originX,y2-originY];const angleA=Math.atan2(vectorA[1],vectorA[0]);const angleB=Math.atan2(vectorB[1],vectorB[0]);let averageAngle=(angleA+angleB)/2;const angleRadians=Math.abs(angleA-angleB);if(allowReflex){if(angleRadians<=Math.PI&&isReflex||angleB>angleA){averageAngle+=Math.PI;}}else {if(angleRadians>Math.PI){averageAngle-=Math.PI;}}const sum=[Math.cos(averageAngle),Math.sin(averageAngle)];const sumMagnitude=Math.sqrt(sum[0]**2+sum[1]**2);const bisectorDirection=[sum[0]/sumMagnitude,sum[1]/sumMagnitude];const initialDistance=Math.sqrt(bisectorDirection[0]**2+bisectorDirection[1]**2);const requiredDistance=arcRadius*1.75;let radius=requiredDistance/initialDistance;if(initialDistance>=requiredDistance){radius=1;}const bisectorPoint=[bisectorDirection[0]*radius,bisectorDirection[1]*radius];const scaledBisector=vec.add(bisectorPoint,vertex);return scaledBisector}
1955
1970
 
@@ -2051,7 +2066,7 @@ class PassageRefTarget extends React.Component{render(){return jsxRuntimeExports
2051
2066
 
2052
2067
  const getPromptJSON$4=()=>{return getUnsupportedPromptJSON("phet-simulation")};
2053
2068
 
2054
- class PhetSimulation extends React.Component{async componentDidMount(){await this.updateSimState(this.props.url);}async componentDidUpdate(prevProps){if(prevProps.url!==this.props.url){await this.updateSimState(this.props.url);}}getPromptJSON(){return getPromptJSON$4()}async updateSimState(urlString){const url=makeSafeUrl(urlString,this.locale);if(url===null){this.displayLoadFailure();return}const response=await fetch(url);if(!response.ok){this.displayLoadFailure();return}const showLocaleWarning=await this.showLocaleWarning(url);this.setState({url:url,banner:showLocaleWarning?{message:this.context.strings.simulationLocaleWarning,kind:"warning"}:null});}async showLocaleWarning(url){if(!url){return false}const phetRegex=/https:\/\/phet\.colorado\.edu\/sims\/html\/([a-zA-Z0-9-]+)\/.*/g;const match=phetRegex.exec(url.toString());if(match===null){return false}const simName=match[1];const response=await fetch(`https://phet.colorado.edu/sims/html/${simName}/latest/string-map.json`);if(!response.ok){return false}let responseJson;try{responseJson=await response.json();}catch{return false}const locales=Object.keys(responseJson);const baseLocale=this.locale.split("_")[0];for(const l of locales){if(baseLocale===l.split("_")[0]){return false}}return true}render(){const sandboxProperties="allow-same-origin allow-scripts";return jsxRuntimeExports.jsxs(View,{style:styles$5.widgetContainer,children:[this.state.banner!==null&&jsxRuntimeExports.jsx(View,{style:{marginBottom:phoneMargin},children:jsxRuntimeExports.jsx(Banner,{layout:"floating",kind:this.state.banner.kind,text:this.state.banner.message})}),jsxRuntimeExports.jsx(View,{style:styles$5.iframeContainer,children:jsxRuntimeExports.jsx("iframe",{ref:this.iframeRef,title:this.props.description,sandbox:sandboxProperties,className:css(styles$5.iframeResponsive),src:this.state.url?.toString(),allow:"fullscreen"})}),this.state.url!==null&&jsxRuntimeExports.jsx(IconButton,{icon:cornersOutIcon,onClick:()=>{this.iframeRef.current?.requestFullscreen();},kind:"tertiary",actionType:"neutral","aria-label":"Fullscreen",style:{marginTop:5,marginBottom:5,alignSelf:"flex-end"}})]})}constructor(props){super(props),this.iframeRef=React.createRef(),this.isWidget=true,this.state={url:null,banner:null},this.getPhetCompatibleLocale=kaLocale=>{switch(kaLocale){case "pt-pt":return "pt";case "zh-hans":return "zh_CN";case "zh-hant":return "zh_TW";case "fa-af":return "fa_DA";default:return kaLocale}},this.displayLoadFailure=()=>{this.setState({url:null,banner:{message:this.context.strings.simulationLoadFail,kind:"critical"}});};this.locale=this.getPhetCompatibleLocale(getDependencies().kaLocale);}}PhetSimulation.contextType=PerseusI18nContext;const makeSafeUrl=(urlString,locale)=>{if(!URL.canParse(urlString)){return null}const url=new URL(urlString);if(url.origin!=="https://phet.colorado.edu"){return null}url.searchParams.set("locale",locale);return url};const styles$5=StyleSheet.create({widgetContainer:{borderRadius:6,borderWidth:1,borderColor:"#CCC",padding:spacing.medium_16,paddingBottom:0},iframeContainer:{position:"relative",overflow:"hidden",width:"100%",paddingTop:"56.25%"},iframeResponsive:{borderWidth:0,position:"absolute",top:0,left:0,bottom:0,right:0,width:"100%",height:"100%"}});var PhetSimulation$1 = {name:"phet-simulation",displayName:"PhET Simulation",widget:PhetSimulation,isLintable:true};
2069
+ const MOBILE_APP_BOTTOM_BAR_HEIGHT=66;class PhetSimulation extends React.Component{async componentDidMount(){await this.updateSimState(this.props.url);}async componentDidUpdate(prevProps){if(prevProps.url!==this.props.url){await this.updateSimState(this.props.url);}}getPromptJSON(){return getPromptJSON$4()}async updateSimState(urlString){const url=makeSafeUrl(urlString,this.locale);if(url===null){this.displayLoadFailure();return}const response=await fetch(url);if(!response.ok){this.displayLoadFailure();return}const showLocaleWarning=await this.showLocaleWarning(url);this.setState({url:url,banner:showLocaleWarning?{message:this.context.strings.simulationLocaleWarning,kind:"warning"}:null});}async showLocaleWarning(url){if(!url){return false}const phetRegex=/https:\/\/phet\.colorado\.edu\/sims\/html\/([a-zA-Z0-9-]+)\/.*/g;const match=phetRegex.exec(url.toString());if(match===null){return false}const simName=match[1];const response=await fetch(`https://phet.colorado.edu/sims/html/${simName}/latest/string-map.json`);if(!response.ok){return false}let responseJson;try{responseJson=await response.json();}catch{return false}const locales=Object.keys(responseJson);const baseLocale=this.locale.split("_")[0];for(const l of locales){if(baseLocale===l.split("_")[0]){return false}}return true}render(){const{isFullScreen,banner,url}=this.state;const{isMobileApp}=this.props.apiOptions;const isMobileAppFullscreen=isFullScreen&&isMobileApp;const containerStyle=isMobileAppFullscreen?{...styles$5.appFullScreenWidgetContainer}:styles$5.widgetContainer;const iframeContainerStyle=isMobileAppFullscreen?styles$5.appFullScreenIframeContainer:styles$5.iframeContainer;const sandboxProperties="allow-same-origin allow-scripts";return jsxRuntimeExports.jsxs(View,{style:containerStyle,children:[banner!==null&&jsxRuntimeExports.jsx(View,{style:{marginBottom:phoneMargin},children:jsxRuntimeExports.jsx(Banner,{layout:"floating",kind:banner.kind,text:banner.message})}),isMobileAppFullscreen&&jsxRuntimeExports.jsx(View,{style:styles$5.closeButtonContainer,children:jsxRuntimeExports.jsx(IconButton,{icon:xIcon,onClick:this.toggleFullScreen,kind:"tertiary",actionType:"neutral","aria-label":"Exit fullscreen",style:styles$5.closeButton})}),jsxRuntimeExports.jsx(View,{style:iframeContainerStyle,children:jsxRuntimeExports.jsx("iframe",{ref:this.iframeRef,title:this.props.description,sandbox:sandboxProperties,className:css(styles$5.iframeResponsive),src:url?.toString(),allow:"fullscreen"})}),url!==null&&!isMobileAppFullscreen&&jsxRuntimeExports.jsx(IconButton,{icon:cornersOutIcon,onClick:isMobileApp?this.toggleFullScreen:()=>{this.iframeRef.current?.requestFullscreen();},kind:"tertiary",actionType:"neutral","aria-label":"Fullscreen",style:{marginTop:5,marginBottom:5,alignSelf:"flex-end"}})]})}constructor(props){super(props),this.iframeRef=React.createRef(),this.isWidget=true,this.state={url:null,banner:null,isFullScreen:false},this.getPhetCompatibleLocale=kaLocale=>{switch(kaLocale){case "pt-pt":return "pt";case "zh-hans":return "zh_CN";case "zh-hant":return "zh_TW";case "fa-af":return "fa_DA";default:return kaLocale}},this.displayLoadFailure=()=>{this.setState({url:null,banner:{message:this.context.strings.simulationLoadFail,kind:"critical"}});},this.toggleFullScreen=()=>{this.setState(prevState=>({isFullScreen:!prevState.isFullScreen}));};this.locale=this.getPhetCompatibleLocale(getDependencies().kaLocale);}}PhetSimulation.contextType=PerseusI18nContext;const makeSafeUrl=(urlString,locale)=>{if(!URL.canParse(urlString)){return null}const url=new URL(urlString);if(url.origin!=="https://phet.colorado.edu"){return null}url.searchParams.set("locale",locale);return url};const styles$5=StyleSheet.create({widgetContainer:{borderRadius:6,borderWidth:1,borderColor:"#CCC",padding:spacing.medium_16,paddingBottom:0},iframeContainer:{position:"relative",overflow:"hidden",width:"100%",paddingTop:"56.25%"},iframeResponsive:{borderWidth:0,position:"absolute",top:0,left:0,bottom:0,right:0,width:"100%",height:"100%"},appFullScreenWidgetContainer:{position:"fixed",top:0,left:0,right:0,bottom:MOBILE_APP_BOTTOM_BAR_HEIGHT,width:"100%",height:"auto",zIndex:1e3,backgroundColor:"white",display:"flex",flexDirection:"column"},appFullScreenIframeContainer:{position:"relative",overflow:"hidden",width:"100%",flex:1},closeButtonContainer:{position:"absolute",top:spacing.xSmall_8,right:spacing.xSmall_8,zIndex:1001},closeButton:{backgroundColor:"rgba(255, 255, 255, 0.8)",borderRadius:"50%"}});var PhetSimulation$1 = {name:"phet-simulation",displayName:"PhET Simulation",widget:PhetSimulation,isLintable:true};
2055
2070
 
2056
2071
  const getPromptJSON$3=()=>{return getUnsupportedPromptJSON("plotter")};
2057
2072
 
@@ -2063,21 +2078,21 @@ function getUrlFromProgramID(programID){const path=`/python-program/${programID}
2063
2078
 
2064
2079
  const getPromptJSON$1=userInput=>{return {type:"sorter",userInput:{values:userInput.options,changed:userInput.changed}}};
2065
2080
 
2066
- class Sorter extends React.Component{componentDidMount(){this._isMounted=true;}componentWillUnmount(){this._isMounted=false;}getUserInput(){const options=this.refs.sortable.getOptions();return {options,changed:this.state.changed}}getPromptJSON(){return getPromptJSON$1(this.getUserInput())}render(){const options=shuffle(this.props.correct,this.props.problemNum,true);const{apiOptions}=this.props;const marginPx=apiOptions.isMobile?8:5;return jsxRuntimeExports.jsx("div",{className:"perseus-widget-sorter perseus-clearfix",children:jsxRuntimeExports.jsx(Sortable,{options:options,layout:this.props.layout,margin:marginPx,padding:this.props.padding,onChange:this.handleChange,linterContext:this.props.linterContext,ref:"sortable"})})}constructor(...args){super(...args),this._isMounted=false,this.state={changed:false},this.handleChange=e=>{if(!this._isMounted){return}this.setState({changed:true},()=>{setTimeout(()=>{this.props.onChange(e);this.props.trackInteraction();},0);});},this.moveOptionToIndex=(option,index)=>{this.refs.sortable.moveOptionToIndex(option,index);};}}Sorter.defaultProps={correct:[],layout:"horizontal",padding:true,problemNum:0,onChange:function(){},linterContext:linterContextDefault};var Sorter$1 = {name:"sorter",displayName:"Sorter",widget:Sorter,isLintable:true};
2081
+ class Sorter extends React.Component{componentDidMount(){this._isMounted=true;}componentWillUnmount(){this._isMounted=false;}getUserInput(){const options=this.refs.sortable.getOptions();return {options,changed:this.state.changed}}getPromptJSON(){return getPromptJSON$1(this.getUserInput())}render(){const options=shuffleSorter(this.props);const{apiOptions}=this.props;const marginPx=apiOptions.isMobile?8:5;return jsxRuntimeExports.jsx("div",{className:"perseus-widget-sorter perseus-clearfix",children:jsxRuntimeExports.jsx(Sortable,{options:options,layout:this.props.layout,margin:marginPx,padding:this.props.padding,onChange:this.handleChange,linterContext:this.props.linterContext,ref:"sortable"})})}constructor(...args){super(...args),this._isMounted=false,this.state={changed:false},this.handleChange=e=>{if(!this._isMounted){return}this.setState({changed:true},()=>{setTimeout(()=>{this.props.onChange(e);this.props.trackInteraction();},0);});},this.moveOptionToIndex=(option,index)=>{this.refs.sortable.moveOptionToIndex(option,index);};}}Sorter.defaultProps={correct:[],layout:"horizontal",padding:true,problemNum:0,onChange:function(){},linterContext:linterContextDefault};var Sorter$1 = {name:"sorter",displayName:"Sorter",widget:Sorter,isLintable:true};
2067
2082
 
2068
2083
  const{assert}=InteractiveUtil;function getInputPath(row,column){return [""+row,""+column]}function getDefaultPath(){return getInputPath(0,0)}function getRowFromPath(path){assert(Array.isArray(path)&&path.length===2);return +path[0]}function getColumnFromPath(path){assert(Array.isArray(path)&&path.length===2);return +path[1]}function getRefForPath(path){const row=getRowFromPath(path);const column=getColumnFromPath(path);return "answer"+row+","+column}class Table extends React.Component{_getRows(){return this.props.answers.length}_getColumns(){return this.props.answers[0].length}_getAnswersClone(){return JSON.parse(JSON.stringify(this.props.answers))}getUserInput(){return this._getAnswersClone()}onValueChange(row,column,eventOrValue){const answers=this._getAnswersClone();answers[row][column]=eventOrValue.target?eventOrValue.target.value:eventOrValue;this.props.onChange({answers:answers});this.props.trackInteraction();}onHeaderChange(index,e){const headers=this.props.headers.slice();headers[index]=e.content;this.props.onChange({headers:headers});}_handleFocus(inputPath){this.props.onFocus(inputPath);}_handleBlur(inputPath){this.props.onBlur(inputPath);}focus(){this.focusInputPath(getDefaultPath());return true}focusInputPath(path){const inputID=getRefForPath(path);const inputComponent=this.answerRefs[inputID];if(this.props.apiOptions.customKeypad){inputComponent.focus();}else {ReactDOM__default.findDOMNode(inputComponent).focus();}}blurInputPath(path){const inputID=getRefForPath(path);const inputComponent=this.answerRefs[inputID];if(this.props.apiOptions.customKeypad){inputComponent.blur();}else {ReactDOM__default.findDOMNode(inputComponent).blur();}}getDOMNodeForPath(path){const inputID=getRefForPath(path);const inputRef=this.answerRefs[inputID];return ReactDOM__default.findDOMNode(inputRef)}getInputPaths(){const rows=this._getRows();const columns=this._getColumns();const inputPaths=[];for(let r=0;r<rows;r++){for(let c=0;c<columns;c++){const inputPath=getInputPath(r,c);inputPaths.push(inputPath);}}return inputPaths}setInputValue(path,newValue,cb){const typedPath=path;const row=getRowFromPath(typedPath);const column=getColumnFromPath(typedPath);const answers=this._getAnswersClone();answers[row][column]=newValue;this.props.onChange({answers:answers},cb);}render(){const headers=this.props.headers;let InputComponent;let inputStyle;const extraInputProps={};if(this.props.apiOptions.customKeypad){InputComponent=SimpleKeypadInput;inputStyle={width:80};extraInputProps.keypadElement=this.props.keypadElement;}else {InputComponent="input";inputStyle={};}return jsxRuntimeExports.jsxs("table",{className:"perseus-widget-table-of-values non-markdown",children:[jsxRuntimeExports.jsx("thead",{children:jsxRuntimeExports.jsx("tr",{children:headers.map((header,i)=>{if(this.props.editableHeaders){return jsxRuntimeExports.jsx("th",{children:jsxRuntimeExports.jsx(this.props.Editor,{ref:ref=>{this.headerRefs["columnHeader"+i]=ref;},apiOptions:this.props.apiOptions,content:header,widgetEnabled:false,onChange:e=>this.onHeaderChange(i,e)})},i)}return jsxRuntimeExports.jsx("th",{children:jsxRuntimeExports.jsx(Renderer,{content:header,linterContext:this.props.linterContext,strings:this.context.strings})},i)})})}),jsxRuntimeExports.jsx("tbody",{children:this.props.answers.map((rowArr,r)=>{return jsxRuntimeExports.jsx("tr",{children:rowArr.map((answer,c)=>{return jsxRuntimeExports.jsx("td",{children:jsxRuntimeExports.jsx(InputComponent,{ref:ref=>{this.answerRefs[getRefForPath(getInputPath(r,c))]=ref;},type:"text",value:answer,disabled:this.props.apiOptions.readOnly,onFocus:()=>this._handleFocus(getInputPath(r,c)),onBlur:()=>this._handleBlur(getInputPath(r,c)),onChange:e=>this.onValueChange(r,c,e),style:inputStyle,...extraInputProps})},c)})},r)})})]})}constructor(...args){super(...args),this.headerRefs={},this.answerRefs={};}}Table.contextType=PerseusI18nContext;Table.defaultProps=function(){const defaultRows=4;const defaultColumns=1;const blankAnswers=Util.stringArrayOfSize2D({rows:defaultRows,columns:defaultColumns});return {apiOptions:ApiOptions.defaults,headers:[""],editableHeaders:false,rows:defaultRows,columns:defaultColumns,answers:blankAnswers,linterContext:linterContextDefault}}();function propTransform(options){const rows=options.rows;const columns=options.columns;const blankAnswers=Util.stringArrayOfSize2D({rows,columns});return {...options,answers:blankAnswers}}var Table$1 = {name:"table",displayName:"Table (deprecated - use markdown table instead)",accessible:true,widget:Table,transform:propTransform,hidden:true,isLintable:true};
2069
2084
 
2070
2085
  const getPromptJSON=()=>{return getUnsupportedPromptJSON("video")};
2071
2086
 
2072
- const IS_URL$1=/^https?:\/\//;const getYoutubeId=url=>{const regExp=/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;const match=url.match(regExp);if(match&&match[7].length===11){return match[7]}return "videoNotFound"};const VideoTranscriptLink=props=>{const{location}=props;const{useVideo}=useDependencies();const[id,kind]=IS_URL$1.test(location)?[getYoutubeId(location),"YOUTUBE_ID"]:[location,"READABLE_ID"];const result=useVideo(id,kind);const{strings}=usePerseusI18n();switch(result.status){case "loading":return jsxRuntimeExports.jsx(View,{children:strings.loading});case "success":{const video=result.data?.video;return jsxRuntimeExports.jsxs(View,{style:styles$3.transcriptLink,children:[jsxRuntimeExports.jsx(Text$2,{children:video?.title}),jsxRuntimeExports.jsx(Strut,{size:10}),jsxRuntimeExports.jsx(Link,{href:"/transcript/"+(video?.contentId||"videoNotFound"),target:"_blank",className:"visited-no-recolor",children:strings.videoTranscript})]})}case "error":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});case "aborted":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});default:return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong})}};const styles$3=StyleSheet.create({transcriptLink:{flexDirection:"row",width:"100%",justifyContent:"center"}});
2087
+ const IS_URL$1=/^https?:\/\//;const getYoutubeId=url=>{const regExp=/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;const match=url.match(regExp);if(match&&match[7].length===11){return match[7]}return "videoNotFound"};const VideoTranscriptLink=props=>{const{location}=props;const{useVideo}=useDependencies();const[id,kind]=IS_URL$1.test(location)?[getYoutubeId(location),"YOUTUBE_ID"]:[location,"READABLE_ID"];const result=useVideo(id,kind);const{strings}=usePerseusI18n();switch(result.status){case "loading":return jsxRuntimeExports.jsx(View,{children:strings.loading});case "success":{const video=result.data?.video;return jsxRuntimeExports.jsxs(View,{style:styles$3.transcriptLink,children:[jsxRuntimeExports.jsx(Text$1,{children:video?.title}),jsxRuntimeExports.jsx(Strut,{size:10}),jsxRuntimeExports.jsx(Link,{href:"/transcript/"+(video?.contentId||"videoNotFound"),target:"_blank",className:"visited-no-recolor",children:strings.videoTranscript})]})}case "error":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});case "aborted":return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong});default:return jsxRuntimeExports.jsx(View,{children:strings.somethingWrong})}};const styles$3=StyleSheet.create({transcriptLink:{flexDirection:"row",width:"100%",justifyContent:"center"}});
2073
2088
 
2074
2089
  const DEFAULT_WIDTH=1280;const DEFAULT_HEIGHT=720;const KA_EMBED="{host}/embed_video?slug={slug}"+"&internal_video_only=1";const IS_URL=/^https?:\/\//;const IS_KA_SITE=/(khanacademy\.org|localhost)/;const IS_VIMEO=/(vimeo\.com)/;class Video extends React.Component{getPromptJSON(){return getPromptJSON()}render(){const{InitialRequestUrl}=getDependencies();const location=this.props.location;if(!location){return jsxRuntimeExports.jsx("div",{})}let url;if(IS_URL.test(location)){url=location;if(IS_VIMEO.test(url)){if(url.indexOf("?")===-1){url+="?dnt=1";}else {url+="&dnt=1";}}}else {url=KA_EMBED.replace("{slug}",location);let embedHostname="https://www.khanacademy.org";if(IS_KA_SITE.test(InitialRequestUrl.host)){embedHostname=InitialRequestUrl.origin;}url=url.replace("{host}",embedHostname);}return jsxRuntimeExports.jsxs(View,{children:[jsxRuntimeExports.jsxs(FixedToResponsive,{width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,children:[jsxRuntimeExports.jsx(View,{style:a11y.srOnly,children:this.context.strings.videoWrapper}),jsxRuntimeExports.jsx("iframe",{className:"perseus-video-widget",sandbox:"allow-same-origin allow-scripts",width:DEFAULT_WIDTH,height:DEFAULT_HEIGHT,src:url,allowFullScreen:true})]},location+this.props.alignment),jsxRuntimeExports.jsx(VideoTranscriptLink,{location:location})]})}constructor(...args){super(...args),this.isWidget=true,this.change=(...args)=>{return change.apply(this,args)};}}Video.contextType=PerseusI18nContext;var Video$1 = {name:"video",displayName:"Video",widget:Video};
2075
2090
 
2076
- var extraWidgets = [Categorizer$1,CSProgram$1,Dropdown$1,Explanation$1,Definition$1,Grapher$1,GradedGroup$1,GradedGroupSet$1,Group$1,Iframe$1,Image$1,Interactive,InteractiveGraph$1,LabelImage$1,Matrix$1,Matcher$1,Measurer$1,Molecule$1,NumberLine$1,Orderer$1,Passage$1,PassageRef$1,PassageRefTarget$1,PhetSimulation$1,Plotter$1,PythonProgram$1,Sorter$1,Table$1,Video$1,DeprecatedStandin$1];
2091
+ var extraWidgets = [CSProgram$1,Categorizer$1,Definition$1,DeprecatedStandin$1,Dropdown$1,Explanation$1,FreeResponse$1,GradedGroup$1,GradedGroupSet$1,Grapher$1,Group$1,Iframe$1,Image$1,Interactive,InteractiveGraph$1,LabelImage$1,Matcher$1,Matrix$1,Measurer$1,Molecule$1,NumberLine$1,Orderer$1,Passage$1,PassageRef$1,PassageRefTarget$1,PhetSimulation$1,Plotter$1,PythonProgram$1,Sorter$1,Table$1,Video$1];
2077
2092
 
2078
2093
  const init=function(){registerCoreWidgets();registerWidgets(basicWidgets);registerWidgets(extraWidgets);replaceDeprecatedWidgets();};
2079
2094
 
2080
- const libName="@khanacademy/perseus";const libVersion="61.2.1";addLibraryVersionToPerseusDebug(libName,libVersion);
2095
+ const libName="@khanacademy/perseus";const libVersion="63.0.0";addLibraryVersionToPerseusDebug(libName,libVersion);
2081
2096
 
2082
2097
  const apiVersion={major:12,minor:0};
2083
2098
 
@@ -2121,7 +2136,7 @@ ${table}`);}break;case "numeric-input":case "input-number":case "expression":con
2121
2136
 
2122
2137
  function generateTestRadioWidget(){return {type:"radio",options:{choices:[]}}}function generateTestInteractiveGraphWidget(){return {type:"interactive-graph",options:{step:[1,1],gridStep:[1,1],snapStep:[1,1],markings:"graph",labels:["x","y"],lockedFigures:[],showProtractor:false,range:[[-10,10],[-10,10]],graph:{type:"angle"},correct:{type:"angle"}}}}function generateTestCategorizerWidget(){return {type:"categorizer",options:{items:[],categories:[],randomizeItems:false,static:false,values:[]}}}function generateTestExpressionWidget(){return {type:"expression",options:{answerForms:[],buttonSets:["basic"],functions:[],times:false}}}function generateTestNumericInputWidget(){return {type:"numeric-input",options:{answers:[],labelText:"",size:"normal",coefficient:false,static:false}}}
2123
2138
 
2124
- const widgetNameToEnum={categorizer:"CATEGORIZER","cs-program":"CS_PROGRAM",definition:"DEFINITION","deprecated-standin":"DEPRECATED_STANDIN",dropdown:"DROPDOWN",explanation:"EXPLANATION",expression:"EXPRESSION","graded-group-set":"GRADED_GROUP_SET","graded-group":"GRADED_GROUP",grapher:"GRAPHER",group:"GROUP",iframe:"IFRAME",image:"IMAGE","input-number":"INPUT_NUMBER",interaction:"INTERACTIVE","interactive-graph":"INTERACTIVE_GRAPH","label-image":"LABEL_IMAGE","lights-puzzle":"LIGHTS_PUZZLE",matcher:"MATCHER",matrix:"MATRIX",measurer:"MEASURER","molecule-renderer":"MOLECULE","number-line":"NUMBER_LINE","numeric-input":"NUMERIC_INPUT",orderer:"ORDERER",passage:"PASSAGE","passage-ref":"PASSAGE_REF","passage-ref-target":"PASSAGE_REF_TARGET","phet-simulation":"PHET_SIMULATION",plotter:"PLOTTER","python-program":"PYTHON_PROGRAM","reaction-diagram":"REACTION_DIAGRAM",radio:"RADIO",sequence:"SEQUENCE",simulator:"SIMULATOR",sorter:"SORTER",table:"TABLE",video:"VIDEO"};function convertWidgetNameToEnum(name){const widgetEnum=widgetNameToEnum[name];if(!widgetEnum){throw new Error(`Unknown widget name: ${name}`)}return widgetEnum}
2139
+ const widgetNameToEnum={categorizer:"CATEGORIZER","cs-program":"CS_PROGRAM",definition:"DEFINITION","deprecated-standin":"DEPRECATED_STANDIN",dropdown:"DROPDOWN",explanation:"EXPLANATION",expression:"EXPRESSION","free-response":"FREE_RESPONSE","graded-group-set":"GRADED_GROUP_SET","graded-group":"GRADED_GROUP",grapher:"GRAPHER",group:"GROUP",iframe:"IFRAME",image:"IMAGE","input-number":"INPUT_NUMBER",interaction:"INTERACTIVE","interactive-graph":"INTERACTIVE_GRAPH","label-image":"LABEL_IMAGE","lights-puzzle":"LIGHTS_PUZZLE",matcher:"MATCHER",matrix:"MATRIX",measurer:"MEASURER","molecule-renderer":"MOLECULE","number-line":"NUMBER_LINE","numeric-input":"NUMERIC_INPUT",orderer:"ORDERER",passage:"PASSAGE","passage-ref":"PASSAGE_REF","passage-ref-target":"PASSAGE_REF_TARGET","phet-simulation":"PHET_SIMULATION",plotter:"PLOTTER","python-program":"PYTHON_PROGRAM","reaction-diagram":"REACTION_DIAGRAM",radio:"RADIO",sequence:"SEQUENCE",simulator:"SIMULATOR",sorter:"SORTER",table:"TABLE",video:"VIDEO"};function convertWidgetNameToEnum(name){const widgetEnum=widgetNameToEnum[name];if(!widgetEnum){throw new Error(`Unknown widget name: ${name}`)}return widgetEnum}
2125
2140
 
2126
2141
  const EditorJsonify={serialize:function(){return _.omit(this.props,denylist)}};
2127
2142