@khanacademy/perseus 82.1.0 → 83.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/sortable.d.ts +1 -1
- package/dist/components.d.ts +0 -2
- package/dist/es/index.css +2 -2
- package/dist/es/index.css.map +1 -1
- package/dist/es/index.js +88 -98
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +1 -1
- package/dist/es/strings.js.map +1 -1
- package/dist/index.css +2 -2
- package/dist/index.css.map +1 -1
- package/dist/index.js +89 -98
- package/dist/index.js.map +1 -1
- package/dist/question-paragraph.new.d.ts +9 -0
- package/dist/renderer.new.d.ts +1 -1
- package/dist/renderer.old.d.ts +1 -1
- package/dist/strings.d.ts +6 -0
- package/dist/strings.js +1 -1
- package/dist/strings.js.map +1 -1
- package/dist/styles/constants.d.ts +2 -7
- package/dist/util.d.ts +23 -0
- package/dist/widget-ai-utils/input-number/input-number-ai-utils.d.ts +1 -1
- package/dist/widget-ai-utils/numeric-input/prompt-utils.d.ts +1 -1
- package/dist/{widget-container.d.ts → widget-container.new.d.ts} +5 -0
- package/dist/widget-container.old.d.ts +31 -0
- package/dist/widgets/categorizer/categorizer.d.ts +63 -8
- package/dist/widgets/cs-program/cs-program.d.ts +1 -2
- package/dist/widgets/dropdown/dropdown.d.ts +1 -2
- package/dist/widgets/image/image.d.ts +1 -2
- package/dist/widgets/input-number/input-number.d.ts +60 -4
- package/dist/widgets/interaction/interaction.d.ts +2 -2
- package/dist/widgets/matcher/matcher.d.ts +66 -32
- package/dist/widgets/measurer/measurer.d.ts +1 -4
- package/dist/widgets/number-line/number-line.d.ts +1 -4
- package/dist/widgets/numeric-input/index.d.ts +1 -1
- package/dist/widgets/numeric-input/numeric-input.d.ts +76 -53
- package/dist/widgets/numeric-input/utils.d.ts +14 -1
- package/dist/widgets/phet-simulation/phet-simulation.d.ts +2 -0
- package/dist/widgets/table/table.d.ts +17 -56
- package/package.json +12 -11
- package/dist/components/info-tip/index.d.ts +0 -19
- package/dist/components/info-tip/info-tip-base.d.ts +0 -6
- package/dist/components/text-list-editor.d.ts +0 -15
- package/dist/widgets/numeric-input/numeric-input.class.d.ts +0 -127
package/dist/index.js
CHANGED
|
@@ -13,17 +13,17 @@ var wonderBlocksPopover = require('@khanacademy/wonder-blocks-popover');
|
|
|
13
13
|
var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
|
|
14
14
|
var classNames$2 = require('classnames');
|
|
15
15
|
var $ = require('jquery');
|
|
16
|
-
var _ = require('underscore');
|
|
17
16
|
var uuid = require('uuid');
|
|
18
17
|
var PropTypes = require('prop-types');
|
|
19
|
-
var kmath = require('@khanacademy/kmath');
|
|
20
18
|
var PerseusLinter = require('@khanacademy/perseus-linter');
|
|
21
19
|
var Tooltip = require('@khanacademy/wonder-blocks-tooltip');
|
|
22
20
|
var perseusCore = require('@khanacademy/perseus-core');
|
|
23
21
|
var wonderBlocksForm = require('@khanacademy/wonder-blocks-form');
|
|
24
22
|
var perseusScore = require('@khanacademy/perseus-score');
|
|
25
23
|
var ReactDOM = require('react-dom');
|
|
24
|
+
var _ = require('underscore');
|
|
26
25
|
var wonderBlocksProgressSpinner = require('@khanacademy/wonder-blocks-progress-spinner');
|
|
26
|
+
var kmath = require('@khanacademy/kmath');
|
|
27
27
|
var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
28
28
|
var wonderBlocksModal = require('@khanacademy/wonder-blocks-modal');
|
|
29
29
|
var IconButton = require('@khanacademy/wonder-blocks-icon-button');
|
|
@@ -47,7 +47,6 @@ var wonderBlocksLabeledField = require('@khanacademy/wonder-blocks-labeled-field
|
|
|
47
47
|
var warningCircleIcon = require('@phosphor-icons/core/regular/warning-circle.svg');
|
|
48
48
|
var invariant = require('tiny-invariant');
|
|
49
49
|
var mafs = require('mafs');
|
|
50
|
-
var questionIcon = require('@phosphor-icons/core/regular/question.svg');
|
|
51
50
|
var KAS = require('@khanacademy/kas');
|
|
52
51
|
var react = require('@use-gesture/react');
|
|
53
52
|
var infoIconBold = require('@phosphor-icons/core/bold/info-bold.svg');
|
|
@@ -56,11 +55,13 @@ var playIcon = require('@phosphor-icons/core/fill/play-fill.svg');
|
|
|
56
55
|
var Switch = require('@khanacademy/wonder-blocks-switch');
|
|
57
56
|
var Pill = require('@khanacademy/wonder-blocks-pill');
|
|
58
57
|
var reactPopper = require('react-popper');
|
|
58
|
+
var arrowSquareOutIcon = require('@phosphor-icons/core/regular/arrow-square-out.svg');
|
|
59
59
|
var cornersOutIcon = require('@phosphor-icons/core/regular/corners-out.svg');
|
|
60
60
|
var xIcon = require('@phosphor-icons/core/regular/x.svg');
|
|
61
61
|
var wonderBlocksLayout = require('@khanacademy/wonder-blocks-layout');
|
|
62
62
|
var Link = require('@khanacademy/wonder-blocks-link');
|
|
63
63
|
var perseusUtils = require('@khanacademy/perseus-utils');
|
|
64
|
+
var plus = require('@phosphor-icons/core/regular/plus.svg');
|
|
64
65
|
|
|
65
66
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
66
67
|
|
|
@@ -86,11 +87,11 @@ var React__namespace = /*#__PURE__*/_interopNamespaceCompat(React);
|
|
|
86
87
|
var Clickable__default = /*#__PURE__*/_interopDefaultCompat(Clickable);
|
|
87
88
|
var classNames__default = /*#__PURE__*/_interopDefaultCompat(classNames$2);
|
|
88
89
|
var $__default = /*#__PURE__*/_interopDefaultCompat($);
|
|
89
|
-
var ___default = /*#__PURE__*/_interopDefaultCompat(_);
|
|
90
90
|
var PropTypes__default = /*#__PURE__*/_interopDefaultCompat(PropTypes);
|
|
91
91
|
var PerseusLinter__namespace = /*#__PURE__*/_interopNamespaceCompat(PerseusLinter);
|
|
92
92
|
var Tooltip__default = /*#__PURE__*/_interopDefaultCompat(Tooltip);
|
|
93
93
|
var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceCompat(ReactDOM);
|
|
94
|
+
var ___default = /*#__PURE__*/_interopDefaultCompat(_);
|
|
94
95
|
var IconButton__default = /*#__PURE__*/_interopDefaultCompat(IconButton);
|
|
95
96
|
var closeIcon__default = /*#__PURE__*/_interopDefaultCompat(closeIcon);
|
|
96
97
|
var SimpleMarkdown__default = /*#__PURE__*/_interopDefaultCompat(SimpleMarkdown);
|
|
@@ -104,16 +105,17 @@ var caretDown__default = /*#__PURE__*/_interopDefaultCompat(caretDown);
|
|
|
104
105
|
var caretUp__default = /*#__PURE__*/_interopDefaultCompat(caretUp);
|
|
105
106
|
var warningCircleIcon__default = /*#__PURE__*/_interopDefaultCompat(warningCircleIcon);
|
|
106
107
|
var invariant__default = /*#__PURE__*/_interopDefaultCompat(invariant);
|
|
107
|
-
var questionIcon__default = /*#__PURE__*/_interopDefaultCompat(questionIcon);
|
|
108
108
|
var KAS__namespace = /*#__PURE__*/_interopNamespaceCompat(KAS);
|
|
109
109
|
var infoIconBold__default = /*#__PURE__*/_interopDefaultCompat(infoIconBold);
|
|
110
110
|
var pauseIcon__default = /*#__PURE__*/_interopDefaultCompat(pauseIcon);
|
|
111
111
|
var playIcon__default = /*#__PURE__*/_interopDefaultCompat(playIcon);
|
|
112
112
|
var Switch__default = /*#__PURE__*/_interopDefaultCompat(Switch);
|
|
113
113
|
var Pill__default = /*#__PURE__*/_interopDefaultCompat(Pill);
|
|
114
|
+
var arrowSquareOutIcon__default = /*#__PURE__*/_interopDefaultCompat(arrowSquareOutIcon);
|
|
114
115
|
var cornersOutIcon__default = /*#__PURE__*/_interopDefaultCompat(cornersOutIcon);
|
|
115
116
|
var xIcon__default = /*#__PURE__*/_interopDefaultCompat(xIcon);
|
|
116
117
|
var Link__default = /*#__PURE__*/_interopDefaultCompat(Link);
|
|
118
|
+
var plus__default = /*#__PURE__*/_interopDefaultCompat(plus);
|
|
117
119
|
|
|
118
120
|
var jsxRuntime = {exports: {}};
|
|
119
121
|
|
|
@@ -1459,7 +1461,7 @@ function requireJsxRuntime () {
|
|
|
1459
1461
|
|
|
1460
1462
|
var jsxRuntimeExports = requireJsxRuntime();
|
|
1461
1463
|
|
|
1462
|
-
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>",EMPTY_RESPONSE_ERROR:"There are still more parts of this question to answer.",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.",USER_INPUT_TOO_LONG:"Please shorten your response.",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.",INVALID_CHOICE_SELECTION:"Invalid choice selection",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)",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}.`,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)`,choiceCorrect:({letter})=>`(Choice ${letter}, Correct)`,choiceCheckedIncorrect:({letter})=>`(Choice ${letter}, Checked, Incorrect)`,choiceIncorrect:({letter})=>`(Choice ${letter}, Incorrect)`,choiceChecked:({letter})=>`(Choice ${letter}, Checked)`,choice:({letter})=>`(Choice ${letter})`,notSelected:"not selected",choicesSelected:({num})=>num===1?`${num} choice selected`:`${num} choices selected`,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",scrollStart:"Scroll to view start of the content",scrollEnd:"Scroll to view the end of the content",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",pythonProgram:"Python program",computerScienceProgram:"Computer science program",embeddedContent:"Embedded content",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:"Enable Forms or Focus mode and use the Tab key to move through the interactive elements in the graph. When an interactive element has focus, use Arrow keys to move it.",srUnlimitedGraphInstructions:"Press Shift + Enter to interact with the graph. Enable Forms or Focus mode and 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 Arrow keys 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",ungradedInteractiveGraph:"Use this graph to check your thinking, but it does not count as your answer.",srPointAtCoordinates:({pointLabel,x,y})=>`Point ${pointLabel} 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}.`,srCircleRadiusPointRightWithLabel:({pointLabel,radiusPointX,radiusPointY})=>`Right radius endpoint ${pointLabel} at ${radiusPointX} comma ${radiusPointY}.`,srCircleRadiusPointLeftWithLabel:({pointLabel,radiusPointX,radiusPointY})=>`Left radius endpoint ${pointLabel} 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:({pointLabel,x,y})=>`Point ${pointLabel}, starting side at ${x} comma ${y}.`,srAngleEndingSide:({pointLabel,x,y})=>`Point ${pointLabel}, ending side at ${x} comma ${y}.`,srAngleVertexWithAngleMeasure:({pointLabel,x,y,angleMeasure})=>`Point ${pointLabel}, 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:({pointLabel,x,y})=>`Endpoint ${pointLabel} at ${x} comma ${y}.`,srMultipleSegmentGraphEndpointAriaLabel:({pointLabel,x,y,indexOfSegment})=>`Endpoint ${pointLabel} 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,pointLabel,x,y})=>`Point ${pointLabel} 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}.`,srRayEndpointWithLabel:({pointLabel,x,y})=>`Endpoint ${pointLabel} at ${x} comma ${y}.`,srRayTerminalPoint:({x,y})=>`Through point at ${x} comma ${y}.`,srRayTerminalPointWithLabel:({pointLabel,x,y})=>`Through point ${pointLabel} at ${x} comma ${y}.`,srVectorGraph:"A vector on a coordinate plane.",srVectorPoints:({tailX,tailY,headX,headY})=>`The tail is at ${tailX} comma ${tailY} and the head is at ${headX} comma ${headY}.`,srVectorHeadPoint:({x,y})=>`Vector head at ${x} comma ${y}.`,srVectorMagnitudeDirection:({magnitude,direction})=>`The vector has a magnitude of ${magnitude} and a direction of ${direction} degrees.`,srVectorGrabHandle:({tailX,tailY,headX,headY})=>`Vector from ${tailX} comma ${tailY} to ${headX} comma ${headY}.`,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:({pointLabel})=>`Point ${pointLabel} on parabola at the origin.`,srQuadraticPointAxis:({pointLabel,x,y})=>`Point ${pointLabel} on parabola at ${x} comma ${y}.`,srQuadraticPointQuadrant:({pointLabel,x,y,quadrant})=>`Point ${pointLabel} 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}.`,srSinusoidRootPointWithLabel:({pointLabel,x,y})=>`Midline intersection point ${pointLabel} at ${x} comma ${y}.`,srSinusoidMaxPoint:({x,y})=>`Maximum point at ${x} comma ${y}.`,srSinusoidMaxPointWithLabel:({pointLabel,x,y})=>`Maximum point ${pointLabel} at ${x} comma ${y}.`,srSinusoidMinPoint:({x,y})=>`Minimum point at ${x} comma ${y}.`,srSinusoidMinPointWithLabel:({pointLabel,x,y})=>`Minimum point ${pointLabel} at ${x} comma ${y}.`,srSinusoidFlatPoint:({x,y})=>`Line through point at ${x} comma ${y}.`,srSinusoidFlatPointWithLabel:({pointLabel,x,y})=>`Line through point ${pointLabel} 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}.`,srExponentialGraph:"An exponential curve on a coordinate plane.",srExponentialPoint:({pointLabel,x,y})=>`Point ${pointLabel} on an exponential curve at ${x} comma ${y}.`,srExponentialDescriptionRightNeg:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches y equals ${asymptoteY} from the right and extends to negative infinity.`,srExponentialDescriptionLeftPos:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches y equals ${asymptoteY} from the left and extends to positive infinity.`,srExponentialAboveAsymptote:"The curve lies above the asymptote.",srExponentialBelowAsymptote:"The curve lies below the asymptote.",srExponentialNoCurve:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`No exponential curve can be drawn through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} with a horizontal asymptote at y equals ${asymptoteY}. Move both points to the same side of the asymptote to draw the curve.`,srExponentialIntercepts:({xIntercept,yIntercept})=>`The x-intercept is at ${xIntercept} comma 0. The y-intercept is at 0 comma ${yIntercept}.`,srExponentialYIntercept:({yIntercept})=>`The y-intercept is at 0 comma ${yIntercept}.`,srExponentialInteractiveElements:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`Exponential graph with points at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, and a horizontal asymptote at y equals ${asymptoteY}.`,srExponentialAsymptote:({asymptoteY})=>`Horizontal asymptote at y equals ${asymptoteY}`,srLogarithmGraph:"A logarithmic curve on a coordinate plane.",srLogarithmPoint:({pointLabel,x,y})=>`Point ${pointLabel} on a logarithmic curve at ${x} comma ${y}.`,srLogarithmDescriptionRightNeg:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the right and extends to negative infinity.`,srLogarithmDescriptionRightPos:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the right and extends to positive infinity.`,srLogarithmDescriptionLeftNeg:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the left and extends to negative infinity.`,srLogarithmDescriptionLeftPos:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the left and extends to positive infinity.`,srLogarithmToRightOfAsymptote:"The curve is to the right of the asymptote.",srLogarithmToLeftOfAsymptote:"The curve is to the left of the asymptote.",srLogarithmNoCurve:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`No curve can be drawn through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} with a vertical asymptote at x equals ${asymptoteX}. Move both points to the same side of the asymptote to draw the curve.`,srLogarithmIntercepts:({xIntercept,yIntercept})=>`The x-intercept is at ${xIntercept} comma 0. The y-intercept is at 0 comma ${yIntercept}.`,srLogarithmXIntercept:({xIntercept})=>`The x-intercept is at ${xIntercept} comma 0.`,srLogarithmInteractiveElements:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`Logarithmic graph with points at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, and a vertical asymptote at x equals ${asymptoteX}.`,srLogarithmAsymptote:({asymptoteX})=>`Vertical asymptote at x equals ${asymptoteX}.`,srAbsoluteValueGraph:"An absolute value on a coordinate plane.",srAbsoluteValueVertexPoint:({x,y})=>`Vertex point at ${x} comma ${y}.`,srAbsoluteValueVertexPointWithLabel:({pointLabel,x,y})=>`Vertex point ${pointLabel} at ${x} comma ${y}.`,srAbsoluteValueArmPoint:({x,y})=>`Point on arm at ${x} comma ${y}.`,srAbsoluteValueArmPointWithLabel:({pointLabel,x,y})=>`Point ${pointLabel} on arm at ${x} comma ${y}.`,srAbsoluteValueSlope:({slope})=>`The slope is ${slope}.`,srAbsoluteValueOpensUp:"The graph opens upward.",srAbsoluteValueOpensDown:"The graph opens downward.",srAbsoluteValueVertex:({x,y})=>`Vertex is at ${x} comma ${y}.`,srAbsoluteValueVertexOrigin:"Vertex is at the origin.",srAbsoluteValueTwoXIntercepts:({intercept1,intercept2})=>`The X-intercepts are at ${intercept1} comma 0 and ${intercept2} comma 0.`,srAbsoluteValueOneXIntercept:({intercept})=>`The X-intercept is at ${intercept} comma 0.`,srAbsoluteValueYIntercept:({intercept})=>`The Y-intercept is at 0 comma ${intercept}.`,srAbsoluteValueInteractiveElements:({point1X,point1Y,point2X,point2Y,slope})=>`Absolute value graph with vertex point at ${point1X} comma ${point1Y}, arm point at ${point2X} comma ${point2Y} and slope of ${slope}.`,srTangentGraph:"A tangent curve on a coordinate plane.",srTangentInflectionPoint:({x,y})=>`Inflection point at ${x} comma ${y}.`,srTangentInflectionPointWithLabel:({pointLabel,x,y})=>`Inflection point ${pointLabel} at ${x} comma ${y}.`,srTangentControlPoint:({x,y})=>`Control point at ${x} comma ${y}.`,srTangentControlPointWithLabel:({pointLabel,x,y})=>`Control point ${pointLabel} at ${x} comma ${y}.`,srTangentDescriptionPoints:({inflectionX,inflectionY,controlX,controlY})=>`The curve passes through an inflection point at ${inflectionX} comma ${inflectionY} and a control point at ${controlX} comma ${controlY}.`,srTangentIncreasing:({period})=>`The curve increases through the inflection point, repeating every ${period} units.`,srTangentDecreasing:({period})=>`The curve decreases through the inflection point, repeating every ${period} units.`,srTangentAsymptotes:({leftAsymptote,rightAsymptote})=>`The nearest vertical asymptotes are at x equals ${leftAsymptote} and x equals ${rightAsymptote}.`,srTangentInteractiveElements:({point1X,point1Y,point2X,point2Y})=>`Tangent graph with inflection point at ${point1X} comma ${point1Y} and control point at ${point2X} comma ${point2Y}.`,imageExploreButton:"Explore image",imageExploreButtonAriaLabel:"Explore image and description",imageAlternativeTitle:"Explore image and description",imageDescriptionLabel:"Description",imageZoomAriaLabel:"Make image bigger.",imageResetZoomAriaLabel:"Close image.",gifPlayButtonLabel:"Play Animation",gifPauseButtonLabel:"Pause Animation",definitionIdentifier:({word})=>`Definition of: ${word}`};const errorToString={APPROXIMATED_PI_ERROR:"APPROXIMATED_PI_ERROR",CHOOSE_CORRECT_NUM_ERROR:"chooseCorrectNum",EMPTY_RESPONSE_ERROR:"EMPTY_RESPONSE_ERROR",EXTRA_SYMBOLS_ERROR:"EXTRA_SYMBOLS_ERROR",FILL_ALL_CELLS_ERROR:"fillAllCells",INVALID_CHOICE_SELECTION:"INVALID_CHOICE_SELECTION",INVALID_SELECTION_ERROR:"invalidSelection",MISSING_PERCENT_ERROR:"MISSING_PERCENT_ERROR",MULTIPLICATION_SIGN_ERROR:"MULTIPLICATION_SIGN_ERROR",NEEDS_TO_BE_SIMPLIFIED_ERROR:"NEEDS_TO_BE_SIMPLFIED_ERROR",NOT_NONE_ABOVE_ERROR:"notNoneOfTheAbove",USER_INPUT_EMPTY:"USER_INPUT_EMPTY",USER_INPUT_TOO_LONG:"USER_INPUT_TOO_LONG",WRONG_CASE_ERROR:"WRONG_CASE_ERROR",WRONG_LETTER_ERROR:"WRONG_LETTER_ERROR"};function mapErrorToString(err,translatedStrings){if(!err){return err}return translatedStrings[errorToString[err]]||err}
|
|
1464
|
+
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>",EMPTY_RESPONSE_ERROR:"There are still more parts of this question to answer.",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.",USER_INPUT_TOO_LONG:"Please shorten your response.",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.",INVALID_CHOICE_SELECTION:"Invalid choice selection",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)",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}.`,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)`,choiceCorrect:({letter})=>`(Choice ${letter}, Correct)`,choiceCheckedIncorrect:({letter})=>`(Choice ${letter}, Checked, Incorrect)`,choiceIncorrect:({letter})=>`(Choice ${letter}, Incorrect)`,choiceChecked:({letter})=>`(Choice ${letter}, Checked)`,choice:({letter})=>`(Choice ${letter})`,notSelected:"not selected",choicesSelected:({num})=>num===1?`${num} choice selected`:`${num} choices selected`,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",scrollStart:"Scroll to view start of the content",scrollEnd:"Scroll to view the end of the content",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",pythonProgram:"Python program",computerScienceProgram:"Computer science program",embeddedContent:"Embedded content",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.",openInNewTab:"Open simulation in a new tab",fullscreen:"Fullscreen",exitFullscreen:"Exit fullscreen",selectAnAnswer:"Select an answer",srGraphInstructions:"Enable Forms or Focus mode and use the Tab key to move through the interactive elements in the graph. When an interactive element has focus, use Arrow keys to move it.",srUnlimitedGraphInstructions:"Press Shift + Enter to interact with the graph. Enable Forms or Focus mode and 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 Arrow keys 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",ungradedInteractiveGraph:"Use this graph to check your thinking, but it does not count as your answer.",srPointAtCoordinates:({pointLabel,x,y})=>`Point ${pointLabel} 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}.`,srCircleRadiusPointRightWithLabel:({pointLabel,radiusPointX,radiusPointY})=>`Right radius endpoint ${pointLabel} at ${radiusPointX} comma ${radiusPointY}.`,srCircleRadiusPointLeftWithLabel:({pointLabel,radiusPointX,radiusPointY})=>`Left radius endpoint ${pointLabel} 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:({pointLabel,x,y})=>`Point ${pointLabel}, starting side at ${x} comma ${y}.`,srAngleEndingSide:({pointLabel,x,y})=>`Point ${pointLabel}, ending side at ${x} comma ${y}.`,srAngleVertexWithAngleMeasure:({pointLabel,x,y,angleMeasure})=>`Point ${pointLabel}, 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:({pointLabel,x,y})=>`Endpoint ${pointLabel} at ${x} comma ${y}.`,srMultipleSegmentGraphEndpointAriaLabel:({pointLabel,x,y,indexOfSegment})=>`Endpoint ${pointLabel} 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,pointLabel,x,y})=>`Point ${pointLabel} 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}.`,srRayEndpointWithLabel:({pointLabel,x,y})=>`Endpoint ${pointLabel} at ${x} comma ${y}.`,srRayTerminalPoint:({x,y})=>`Through point at ${x} comma ${y}.`,srRayTerminalPointWithLabel:({pointLabel,x,y})=>`Through point ${pointLabel} at ${x} comma ${y}.`,srVectorGraph:"A vector on a coordinate plane.",srVectorPoints:({tailX,tailY,headX,headY})=>`The tail is at ${tailX} comma ${tailY} and the head is at ${headX} comma ${headY}.`,srVectorHeadPoint:({x,y})=>`Vector head at ${x} comma ${y}.`,srVectorMagnitudeDirection:({magnitude,direction})=>`The vector has a magnitude of ${magnitude} and a direction of ${direction} degrees.`,srVectorGrabHandle:({tailX,tailY,headX,headY})=>`Vector from ${tailX} comma ${tailY} to ${headX} comma ${headY}.`,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:({pointLabel})=>`Point ${pointLabel} on parabola at the origin.`,srQuadraticPointAxis:({pointLabel,x,y})=>`Point ${pointLabel} on parabola at ${x} comma ${y}.`,srQuadraticPointQuadrant:({pointLabel,x,y,quadrant})=>`Point ${pointLabel} 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}.`,srSinusoidRootPointWithLabel:({pointLabel,x,y})=>`Midline intersection point ${pointLabel} at ${x} comma ${y}.`,srSinusoidMaxPoint:({x,y})=>`Maximum point at ${x} comma ${y}.`,srSinusoidMaxPointWithLabel:({pointLabel,x,y})=>`Maximum point ${pointLabel} at ${x} comma ${y}.`,srSinusoidMinPoint:({x,y})=>`Minimum point at ${x} comma ${y}.`,srSinusoidMinPointWithLabel:({pointLabel,x,y})=>`Minimum point ${pointLabel} at ${x} comma ${y}.`,srSinusoidFlatPoint:({x,y})=>`Line through point at ${x} comma ${y}.`,srSinusoidFlatPointWithLabel:({pointLabel,x,y})=>`Line through point ${pointLabel} 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}.`,srExponentialGraph:"An exponential curve on a coordinate plane.",srExponentialPoint:({pointLabel,x,y})=>`Point ${pointLabel} on an exponential curve at ${x} comma ${y}.`,srExponentialDescriptionRightNeg:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches y equals ${asymptoteY} from the right and extends to negative infinity.`,srExponentialDescriptionLeftPos:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches y equals ${asymptoteY} from the left and extends to positive infinity.`,srExponentialAboveAsymptote:"The curve lies above the asymptote.",srExponentialBelowAsymptote:"The curve lies below the asymptote.",srExponentialNoCurve:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`No exponential curve can be drawn through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} with a horizontal asymptote at y equals ${asymptoteY}. Move both points to the same side of the asymptote to draw the curve.`,srExponentialIntercepts:({xIntercept,yIntercept})=>`The x-intercept is at ${xIntercept} comma 0. The y-intercept is at 0 comma ${yIntercept}.`,srExponentialYIntercept:({yIntercept})=>`The y-intercept is at 0 comma ${yIntercept}.`,srExponentialInteractiveElements:({point1X,point1Y,point2X,point2Y,asymptoteY})=>`Exponential graph with points at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, and a horizontal asymptote at y equals ${asymptoteY}.`,srExponentialAsymptote:({asymptoteY})=>`Horizontal asymptote at y equals ${asymptoteY}`,srLogarithmGraph:"A logarithmic curve on a coordinate plane.",srLogarithmPoint:({pointLabel,x,y})=>`Point ${pointLabel} on a logarithmic curve at ${x} comma ${y}.`,srLogarithmDescriptionRightNeg:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the right and extends to negative infinity.`,srLogarithmDescriptionRightPos:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the right and extends to positive infinity.`,srLogarithmDescriptionLeftNeg:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the left and extends to negative infinity.`,srLogarithmDescriptionLeftPos:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`The curve passes through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} as the curve approaches x equals ${asymptoteX} from the left and extends to positive infinity.`,srLogarithmToRightOfAsymptote:"The curve is to the right of the asymptote.",srLogarithmToLeftOfAsymptote:"The curve is to the left of the asymptote.",srLogarithmNoCurve:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`No curve can be drawn through ${point1X} comma ${point1Y} and ${point2X} comma ${point2Y} with a vertical asymptote at x equals ${asymptoteX}. Move both points to the same side of the asymptote to draw the curve.`,srLogarithmIntercepts:({xIntercept,yIntercept})=>`The x-intercept is at ${xIntercept} comma 0. The y-intercept is at 0 comma ${yIntercept}.`,srLogarithmXIntercept:({xIntercept})=>`The x-intercept is at ${xIntercept} comma 0.`,srLogarithmInteractiveElements:({point1X,point1Y,point2X,point2Y,asymptoteX})=>`Logarithmic graph with points at ${point1X} comma ${point1Y}, ${point2X} comma ${point2Y}, and a vertical asymptote at x equals ${asymptoteX}.`,srLogarithmAsymptote:({asymptoteX})=>`Vertical asymptote at x equals ${asymptoteX}.`,srAbsoluteValueGraph:"An absolute value on a coordinate plane.",srAbsoluteValueVertexPoint:({x,y})=>`Vertex point at ${x} comma ${y}.`,srAbsoluteValueVertexPointWithLabel:({pointLabel,x,y})=>`Vertex point ${pointLabel} at ${x} comma ${y}.`,srAbsoluteValueArmPoint:({x,y})=>`Point on arm at ${x} comma ${y}.`,srAbsoluteValueArmPointWithLabel:({pointLabel,x,y})=>`Point ${pointLabel} on arm at ${x} comma ${y}.`,srAbsoluteValueSlope:({slope})=>`The slope is ${slope}.`,srAbsoluteValueOpensUp:"The graph opens upward.",srAbsoluteValueOpensDown:"The graph opens downward.",srAbsoluteValueVertex:({x,y})=>`Vertex is at ${x} comma ${y}.`,srAbsoluteValueVertexOrigin:"Vertex is at the origin.",srAbsoluteValueTwoXIntercepts:({intercept1,intercept2})=>`The X-intercepts are at ${intercept1} comma 0 and ${intercept2} comma 0.`,srAbsoluteValueOneXIntercept:({intercept})=>`The X-intercept is at ${intercept} comma 0.`,srAbsoluteValueYIntercept:({intercept})=>`The Y-intercept is at 0 comma ${intercept}.`,srAbsoluteValueInteractiveElements:({point1X,point1Y,point2X,point2Y,slope})=>`Absolute value graph with vertex point at ${point1X} comma ${point1Y}, arm point at ${point2X} comma ${point2Y} and slope of ${slope}.`,srTangentGraph:"A tangent curve on a coordinate plane.",srTangentInflectionPoint:({x,y})=>`Inflection point at ${x} comma ${y}.`,srTangentInflectionPointWithLabel:({pointLabel,x,y})=>`Inflection point ${pointLabel} at ${x} comma ${y}.`,srTangentControlPoint:({x,y})=>`Control point at ${x} comma ${y}.`,srTangentControlPointWithLabel:({pointLabel,x,y})=>`Control point ${pointLabel} at ${x} comma ${y}.`,srTangentDescriptionPoints:({inflectionX,inflectionY,controlX,controlY})=>`The curve passes through an inflection point at ${inflectionX} comma ${inflectionY} and a control point at ${controlX} comma ${controlY}.`,srTangentIncreasing:({period})=>`The curve increases through the inflection point, repeating every ${period} units.`,srTangentDecreasing:({period})=>`The curve decreases through the inflection point, repeating every ${period} units.`,srTangentAsymptotes:({leftAsymptote,rightAsymptote})=>`The nearest vertical asymptotes are at x equals ${leftAsymptote} and x equals ${rightAsymptote}.`,srTangentInteractiveElements:({point1X,point1Y,point2X,point2Y})=>`Tangent graph with inflection point at ${point1X} comma ${point1Y} and control point at ${point2X} comma ${point2Y}.`,imageExploreButton:"Explore image",imageExploreButtonAriaLabel:"Explore image and description",imageAlternativeTitle:"Explore image and description",imageDescriptionLabel:"Description",imageZoomAriaLabel:"Make image bigger.",imageResetZoomAriaLabel:"Close image.",gifPlayButtonLabel:"Play Animation",gifPauseButtonLabel:"Pause Animation",definitionIdentifier:({word})=>`Definition of: ${word}`};const errorToString={APPROXIMATED_PI_ERROR:"APPROXIMATED_PI_ERROR",CHOOSE_CORRECT_NUM_ERROR:"chooseCorrectNum",EMPTY_RESPONSE_ERROR:"EMPTY_RESPONSE_ERROR",EXTRA_SYMBOLS_ERROR:"EXTRA_SYMBOLS_ERROR",FILL_ALL_CELLS_ERROR:"fillAllCells",INVALID_CHOICE_SELECTION:"INVALID_CHOICE_SELECTION",INVALID_SELECTION_ERROR:"invalidSelection",MISSING_PERCENT_ERROR:"MISSING_PERCENT_ERROR",MULTIPLICATION_SIGN_ERROR:"MULTIPLICATION_SIGN_ERROR",NEEDS_TO_BE_SIMPLIFIED_ERROR:"NEEDS_TO_BE_SIMPLFIED_ERROR",NOT_NONE_ABOVE_ERROR:"notNoneOfTheAbove",USER_INPUT_EMPTY:"USER_INPUT_EMPTY",USER_INPUT_TOO_LONG:"USER_INPUT_TOO_LONG",WRONG_CASE_ERROR:"WRONG_CASE_ERROR",WRONG_LETTER_ERROR:"WRONG_LETTER_ERROR"};function mapErrorToString(err,translatedStrings){if(!err){return err}return translatedStrings[errorToString[err]]||err}
|
|
1463
1465
|
|
|
1464
1466
|
const mockPerseusI18nContext={strings:mockStrings,locale:"en"};const PerseusI18nContext=React__namespace.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=()=>React.useContext(PerseusI18nContext);
|
|
1465
1467
|
|
|
@@ -1467,7 +1469,7 @@ var a11y = aphrodite.StyleSheet.create({srOnly:{border:0,clip:"rect(0,0,0,0)",he
|
|
|
1467
1469
|
|
|
1468
1470
|
const debounce=(func,delay)=>{let timer=null;return (...args)=>{if(timer){clearTimeout(timer);}timer=window.setTimeout(()=>{func(...args);},delay);}};
|
|
1469
1471
|
|
|
1470
|
-
class InnerMathInput extends React__namespace.Component{componentDidMount(){this.mathField()?.latex(this.props.value);}componentDidUpdate(prevProps){if(prevProps.value!==this.props.value){if(this.state.focused){return}const field=this.mathField();if(!field){return}const current=field.latex();if(this.props.value!==current){field.latex(this.props.value);}}}openKeypad(){if(this.props.buttonsVisible==="never"){return}this.setState({keypadOpen:true});}closeKeypad(){this.setState({keypadOpen:false});}render(){let className=classNames__default.default({"perseus-math-input":true,"mq-editable-field":true,"mq-math-mode":true});const popoverContentUniqueId=uuid.v4().slice(0,8);if(this.props.className){className=className+" "+this.props.className;}return jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:[styles$
|
|
1472
|
+
class InnerMathInput extends React__namespace.Component{componentDidMount(){this.mathField()?.latex(this.props.value);}componentDidUpdate(prevProps){if(prevProps.value!==this.props.value){if(this.state.focused){return}const field=this.mathField();if(!field){return}const current=field.latex();if(this.props.value!==current){field.latex(this.props.value);}}}openKeypad(){if(this.props.buttonsVisible==="never"){return}this.setState({keypadOpen:true});}closeKeypad(){this.setState({keypadOpen:false});}render(){let className=classNames__default.default({"perseus-math-input":true,"mq-editable-field":true,"mq-math-mode":true});const popoverContentUniqueId=uuid.v4().slice(0,8);if(this.props.className){className=className+" "+this.props.className;}return jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:[styles$C.outerWrapper,this.state.focused&&styles$C.wrapperFocused],children:jsxRuntimeExports.jsxs("div",{style:{display:"flex",padding:1},onClick:e=>{e.stopPropagation();const mathField=this.mathField();if(!mathField){return}this.setState({cursorContext:mathInput.getCursorContext(mathField)});},children:[jsxRuntimeExports.jsx("span",{className:className,ref:ref=>this.__mathFieldWrapperRef=ref,onFocus:()=>this.focus(),onBlur:()=>this.blur()}),jsxRuntimeExports.jsx(wonderBlocksPopover.Popover,{opened:this.state.keypadOpen,dismissEnabled:true,rootBoundary:"document","aria-label":this.context.strings.mathInputTitle,"aria-describedby":`popover-content-${popoverContentUniqueId}`,onClose:()=>this.closeKeypad(),content:()=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksTypography.Heading,{size:"large",id:`popover-content-${popoverContentUniqueId}`,style:a11y.srOnly,children:this.context.strings.mathInputDescription}),jsxRuntimeExports.jsx(wonderBlocksPopover.PopoverContentCore,{style:styles$C.popoverContent,children:jsxRuntimeExports.jsx(mathInput.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__default.default,{"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:mathInput.CursorContext.NONE},this.insert=value=>{const input=this.mathField();const{locale}=this.context;const customKeyTranslator={...mathInput.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(typeof value==="function"){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=mathInput.createMathField(this.__mathFieldWrapperRef,locale,this.props.mathInputStrings,baseConfig=>({...baseConfig,handlers:{edit:debounce(mathField=>{let value=mathField.latex();value=value.replace(/<>/g,"\\ne");if(mathInput.convertDotToTimesByLocale(locale,this.props.convertDotToTimes)){value=value.replace(/\\cdot/g,"\\times");const left=mathField.cursor()[mathInput.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:mathInput.getCursorContext(mathField)});},100),enter:()=>{if(this.__mathFieldWrapperRef){$__default.default(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)=>{if(key==="DISMISS"){this.closeKeypad();return}const{locale}=this.context;const translator=mathInput.getKeyTranslator(locale,this.context.strings)[key];const mathField=this.mathField();if(mathField){if(translator){translator(mathField,key);}this.setState({cursorContext:mathInput.getCursorContext(mathField)});}if(e?.type==="click"){this.focus();}};}}InnerMathInput.contextType=PerseusI18nContext;InnerMathInput.defaultProps={value:"",convertDotToTimes:false};class MathInput extends React__namespace.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__namespace.createRef();}}MathInput.contextType=mathInput.MathInputI18nContext;MathInput.defaultProps={ariaLabel:"Math input"};const MathInputIcon=({hovered,focused,active})=>{let fillColor;switch(true){case focused||active:fillColor=wonderBlocksTokens.semanticColor.action.primary.progressive.default.foreground;break;case hovered:fillColor=wonderBlocksTokens.semanticColor.action.primary.progressive.hover.background;break;default:fillColor=wonderBlocksTokens.semanticColor.core.foreground.neutral.strong;break}const dynamicClass=active||focused?styles$C.iconActive:styles$C.iconInactive;return jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:[styles$C.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:wonderBlocksTokens.semanticColor.core.border.instructive.default,margin:-1};const styles$C=aphrodite.StyleSheet.create({iconContainer:{display:"flex",justifyContent:"center",height:"100%",padding:wonderBlocksTokens.sizing.size_040,borderRadius:1},iconInactive:{border:"2px solid transparent",backgroundColor:wonderBlocksTokens.semanticColor.core.background.neutral.subtle},iconActive:{border:`2px solid ${wonderBlocksTokens.semanticColor.core.border.knockout.default}`,backgroundColor:wonderBlocksTokens.semanticColor.core.background.neutral.default},outerWrapper:{display:"inline-block",borderStyle:"solid",borderWidth:1,borderColor:wonderBlocksTokens.semanticColor.core.border.neutral.default,borderRadius:3,background:wonderBlocksTokens.semanticColor.core.background.base.default,":hover":inputFocused},wrapperFocused:inputFocused,popoverContent:{padding:0,paddingBottom:wonderBlocksTokens.sizing.size_060,maxWidth:"initial"}});
|
|
1471
1473
|
|
|
1472
1474
|
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__namespace.createContext({analytics:{onAnalyticsEvent:async()=>{}},generateUrl:()=>{throw new Error("generateUrl dependency not provided in Perseus dependencies")},useVideo:()=>{throw new Error("useVideo dependency not provided in Perseus dependencies")}});const useDependencies=()=>{const deps=React__namespace.useContext(DependenciesContext);return deps};
|
|
1473
1475
|
|
|
@@ -1483,41 +1485,37 @@ const ApiOptions={propTypes:PropTypes__default.default.shape({isArticle:PropType
|
|
|
1483
1485
|
|
|
1484
1486
|
const getPromptJSON$q=(label,userInput)=>{return {type:"expression",label,userInput:{value:userInput}}};
|
|
1485
1487
|
|
|
1486
|
-
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)};const defaultButtonSets=["basic","trig","prealgebra","logarithms"];const defaultOnFocus=()=>{};const defaultOnBlur=()=>{};const KeypadInputWithInterface=React__namespace.forwardRef(function KeypadInputWithInterface(props,ref){const keypadInputRef=React__namespace.useRef(null);const noopKeypadActivation=_keypadActive=>{};React__namespace.useImperativeHandle(ref,()=>({focus:(cb=noopKeypadActivation)=>keypadInputRef.current?.focus(cb),blur:()=>keypadInputRef.current?.blur(),insert:val=>{keypadInputRef.current?.mathField?.pressKey?.(val);}}));return jsxRuntimeExports.jsx(mathInput.KeypadInput,{ref:keypadInputRef,...props})});const Expression=React.forwardRef(function Expression({apiOptions=ApiOptions.defaults,buttonSets=defaultButtonSets,times=false,onFocus=defaultOnFocus,onBlur=defaultOnBlur,userInput="",visibleLabel,ariaLabel,keypadElement,extraKeys,handleUserInput,trackInteraction,widgetId,answerForms,...rest},ref){const{strings}=usePerseusI18n();const{analytics}=useDependencies();const{setKeypadActive}=React__namespace.useContext(keypadContext.KeypadContext);const textareaId=React.useId();const inputRef=React.useRef(null);const rootRef=React.useRef(null);React.useEffect(()=>{analytics?.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"expression",widgetId}});if(rootRef.current){const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=rootRef.current.querySelector(selector);if(inputElement instanceof HTMLElement){inputElement.setAttribute("id",textareaId);}}},[]);const handleFocus=()=>{analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});onFocus([]);};const handleBlur=()=>{onBlur([]);};const changeAndTrack=(value,cb)=>{const normalized=normalizeTex(value);handleUserInput(normalized,cb);trackInteraction();};const mobileHandleFocus=()=>{keypadElement?.configure(getKeypadConfiguration(),()=>{if(rootRef.current){handleFocus();}});};const getKeypadConfiguration=React.useCallback(()=>{return {keypadType:"EXPRESSION",extraKeys:extraKeys,times:times}},[extraKeys,times]);const getFocusTarget=React.useCallback(()=>{if(!rootRef.current){return null}const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const element=rootRef.current.querySelector(selector);return element instanceof HTMLElement?element:null},[apiOptions.customKeypad]);React.useImperativeHandle(ref,()=>({focus:()=>{const targetBefore=getFocusTarget();inputRef.current?.focus?.(setKeypadActive);const targetAfter=getFocusTarget()??targetBefore??(document.activeElement instanceof HTMLElement?document.activeElement:null);if(!targetAfter){return false}if(document.activeElement!==targetAfter){targetAfter.focus();}return document.activeElement===targetAfter},focusInputPath:path=>{inputRef.current?.focus?.(setKeypadActive);},blurInputPath:path=>{if(typeof inputRef.current?.blur==="function"){inputRef.current?.blur();}},insert:keyPressed=>{inputRef.current?.insert?.(keyPressed);},getInputPaths:()=>[[]],getUserInput:()=>{return normalizeTex(userInput)},getKeypadConfiguration,getPromptJSON:()=>{return getPromptJSON$q(visibleLabel,normalizeTex(userInput))},getSerializedState:()=>{return {...rest,value:userInput,keypadConfiguration:getKeypadConfiguration(),times,buttonSets}}}),[userInput,setKeypadActive,getKeypadConfiguration,getFocusTarget,rest,visibleLabel,buttonSets,times]);const keypadConfiguration=getKeypadConfiguration();if(apiOptions.customKeypad){return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{ref:rootRef,style:styles$
|
|
1487
|
-
|
|
1488
|
-
const getPromptJSON$p=widgetData=>{return {type:"numeric-input",label:widgetData.labelText,userInput:{value:widgetData.userInput.currentValue}}};
|
|
1488
|
+
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)};const defaultButtonSets=["basic","trig","prealgebra","logarithms"];const defaultOnFocus=()=>{};const defaultOnBlur=()=>{};const KeypadInputWithInterface=React__namespace.forwardRef(function KeypadInputWithInterface(props,ref){const keypadInputRef=React__namespace.useRef(null);const noopKeypadActivation=_keypadActive=>{};React__namespace.useImperativeHandle(ref,()=>({focus:(cb=noopKeypadActivation)=>keypadInputRef.current?.focus(cb),blur:()=>keypadInputRef.current?.blur(),insert:val=>{keypadInputRef.current?.mathField?.pressKey?.(val);}}));return jsxRuntimeExports.jsx(mathInput.KeypadInput,{ref:keypadInputRef,...props})});const Expression=React.forwardRef(function Expression({apiOptions=ApiOptions.defaults,buttonSets=defaultButtonSets,times=false,onFocus=defaultOnFocus,onBlur=defaultOnBlur,userInput="",visibleLabel,ariaLabel,keypadElement,extraKeys,handleUserInput,trackInteraction,widgetId,answerForms,...rest},ref){const{strings}=usePerseusI18n();const{analytics}=useDependencies();const{setKeypadActive}=React__namespace.useContext(keypadContext.KeypadContext);const textareaId=React.useId();const inputRef=React.useRef(null);const rootRef=React.useRef(null);React.useEffect(()=>{analytics?.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"expression",widgetId}});if(rootRef.current){const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const inputElement=rootRef.current.querySelector(selector);if(inputElement instanceof HTMLElement){inputElement.setAttribute("id",textareaId);}}},[]);const handleFocus=()=>{analytics?.onAnalyticsEvent({type:"perseus:expression-focused",payload:null});onFocus([]);};const handleBlur=()=>{onBlur([]);};const changeAndTrack=(value,cb)=>{const normalized=normalizeTex(value);handleUserInput(normalized,cb);trackInteraction();};const mobileHandleFocus=()=>{keypadElement?.configure(getKeypadConfiguration(),()=>{if(rootRef.current){handleFocus();}});};const getKeypadConfiguration=React.useCallback(()=>{return {keypadType:"EXPRESSION",extraKeys:extraKeys,times:times}},[extraKeys,times]);const getFocusTarget=React.useCallback(()=>{if(!rootRef.current){return null}const isMobile=apiOptions.customKeypad;const selector=isMobile?".mq-textarea > span":"textarea";const element=rootRef.current.querySelector(selector);return element instanceof HTMLElement?element:null},[apiOptions.customKeypad]);React.useImperativeHandle(ref,()=>({focus:()=>{const targetBefore=getFocusTarget();inputRef.current?.focus?.(setKeypadActive);const targetAfter=getFocusTarget()??targetBefore??(document.activeElement instanceof HTMLElement?document.activeElement:null);if(!targetAfter){return false}if(document.activeElement!==targetAfter){targetAfter.focus();}return document.activeElement===targetAfter},focusInputPath:path=>{inputRef.current?.focus?.(setKeypadActive);},blurInputPath:path=>{if(typeof inputRef.current?.blur==="function"){inputRef.current?.blur();}},insert:keyPressed=>{inputRef.current?.insert?.(keyPressed);},getInputPaths:()=>[[]],getUserInput:()=>{return normalizeTex(userInput)},getKeypadConfiguration,getPromptJSON:()=>{return getPromptJSON$q(visibleLabel,normalizeTex(userInput))},getSerializedState:()=>{return {...rest,value:userInput,keypadConfiguration:getKeypadConfiguration(),times,buttonSets}}}),[userInput,setKeypadActive,getKeypadConfiguration,getFocusTarget,rest,visibleLabel,buttonSets,times]);const keypadConfiguration=getKeypadConfiguration();if(apiOptions.customKeypad){return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{ref:rootRef,style:styles$B.mobileLabelInputWrapper,children:[!!visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",htmlFor:textareaId,tag:"label",children:visibleLabel}),jsxRuntimeExports.jsx(KeypadInputWithInterface,{ref:inputRef,ariaLabel:ariaLabel||strings.mathInputBox,value:userInput,keypadElement:keypadElement,onChange:changeAndTrack,onFocus:mobileHandleFocus,onBlur:handleBlur})]})}return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{ref:rootRef,style:styles$B.desktopLabelInputWrapper,children:[!!visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",htmlFor:textareaId,tag:"label",children:visibleLabel}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-expression",children:jsxRuntimeExports.jsx(MathInput,{ref:inputRef,value:userInput,onChange:changeAndTrack,convertDotToTimes:times,buttonSets:buttonSets,onFocus:handleFocus,onBlur:handleBlur,ariaLabel:ariaLabel||strings.mathInputBox,extraKeys:keypadConfiguration.extraKeys,onAnalyticsEvent:analytics?.onAnalyticsEvent??(async()=>{})})})]})});const styles$B=aphrodite.StyleSheet.create({mobileLabelInputWrapper:{padding:"15px 4px 0"},desktopLabelInputWrapper:{margin:"5px 5px 0"}});function getUserInputFromSerializedState$i(serializedState){return normalizeTex(serializedState.value)}function getStartUserInput$i(){return ""}function getOneCorrectAnswerFromRubric$1(rubric){const correctAnswers=(rubric.answerForms||[]).filter(answerForm=>answerForm.considered==="correct");if(correctAnswers.length===0){return}return correctAnswers[0].value}function getCorrectUserInput$9(options){for(const form of options.answerForms){if(form.considered==="correct"){return form.value}}return ""}var Expression$1 = {name:"expression",displayName:"Expression / Equation",widget:Expression,isLintable:true,getOneCorrectAnswerFromRubric: getOneCorrectAnswerFromRubric$1,getStartUserInput: getStartUserInput$i,getCorrectUserInput: getCorrectUserInput$9,getUserInputFromSerializedState: getUserInputFromSerializedState$i};
|
|
1489
1489
|
|
|
1490
1490
|
class SimpleKeypadInput extends React__namespace.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(mathInput.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__namespace.createRef();}}SimpleKeypadInput.contextType=keypadContext.KeypadContext;SimpleKeypadInput.propTypes={keypadElement:mathInput.keypadElementPropType,onFocus:PropTypes__default.default.func,value:PropTypes__default.default.oneOfType([PropTypes__default.default.string,PropTypes__default.default.number])};
|
|
1491
1491
|
|
|
1492
|
+
const getPromptJSON$p=widgetData=>{return {type:"numeric-input",label:widgetData.labelText??"",userInput:{value:widgetData.userInput.currentValue}}};
|
|
1493
|
+
|
|
1492
1494
|
let lastId=0;function uniqueIdForInput(prefix="input-"){lastId++;return `${prefix}${lastId}`}class TextInput extends React__namespace.Component{render(){const{labelText,value,onFocus,onBlur,disabled,placeholder,onKeyDown,style,className}=this.props;const formattedValue=value===null?"":value.toString();const ariaLabel=labelText||undefined;return jsxRuntimeExports.jsx(wonderBlocksForm.TextField,{ref:this.inputRef,className:className,style:style,disabled:disabled,id:this.id,value:formattedValue,type:"text","aria-label":ariaLabel,"aria-describedby":this.props["aria-describedby"],onChange:value=>this.props.onChange(value),placeholder:placeholder,testId:"input-with-examples",onFocus:onFocus,onBlur:onBlur,onKeyDown:onKeyDown,autoCorrect:"off",autoCapitalize:"off",autoComplete:"off"})}constructor(props){super(props),this.inputRef=React__namespace.createRef(),this._getInput=()=>{if(!this.inputRef.current){throw new perseusCore.PerseusError("Input ref accessed before set",perseusCore.Errors.Internal)}return this.inputRef.current},this.focus=()=>{this._getInput().focus();},this.blur=()=>{this._getInput().blur();},this.getValue=()=>{return this.inputRef.current?.value},this.getStringValue=()=>{return this.inputRef.current?.value.toString()},this.setSelectionRange=(selectionStart,selectionEnd)=>{this._getInput().setSelectionRange(selectionStart,selectionEnd);},this.getSelectionStart=()=>{return this._getInput().selectionStart},this.getSelectionEnd=()=>{return this._getInput().selectionEnd};if(props.id){this.id=props.id;}else {this.id=uniqueIdForInput();}}}TextInput.defaultProps={value:"",disabled:false};
|
|
1493
1495
|
|
|
1494
1496
|
const defaultContext$2={assetStatuses:{},setAssetStatus:(assetKey,loaded)=>{}};const context$1=React__namespace.createContext(defaultContext$2);
|
|
1495
1497
|
|
|
1496
|
-
let supportsPassive=false;const nestedMap$2=function(children,func,context){if(Array.isArray(children)){return
|
|
1498
|
+
let supportsPassive=false;const nestedMap$2=function(children,func,context){if(Array.isArray(children)){return children.map(function(child){return nestedMap$2(child,func)})}return func.call(context,children)};function inputPathsEqual(a,b){if(a==null||b==null){return a==null===(b==null)}return a.length===b.length&&a.every((item,index)=>{return b[index]===item})}const rWidgetRule=/^\[\[\u2603 (([a-z-]+) ([0-9]+))]]/;const rTypeFromWidgetId=/^([a-z-]+) ([0-9]+)$/;const rWidgetParts=new RegExp(rWidgetRule.source+"$");const snowman="☃";const isBlockWidgetNode=node=>node?.type==="widget"&&!perseusCore.CoreWidgetRegistry.getDefaultAlignment(node.widgetType).startsWith("inline");const isParagraphWithBlockWidget=node=>node?.type==="paragraph"&&Array.isArray(node.content)&&node.content.some(isBlockWidgetNode);const inlineWidgetsToExclude=node=>{const widgetsToExclude=["dropdown","explanation","expression"];return node?.type==="widget"&&widgetsToExclude.includes(node.widgetType)};const noParagraphForInlineWidget=node=>Array.isArray(node.content)&&node.content.some(inlineWidgetsToExclude);const isWhitespaceOnlyTextNode=node=>node?.type==="text"&&node.content.trim()==="";const trimEdgeWhitespaceNodes=nodes=>{let start=0;let end=nodes.length;while(start<end&&isWhitespaceOnlyTextNode(nodes[start])){start++;}while(end>start&&isWhitespaceOnlyTextNode(nodes[end-1])){end--;}return nodes.slice(start,end)};const mergeInlineNodes=(inlineNodes,blockNodes,referenceNode)=>{const trimmedContentNodes=trimEdgeWhitespaceNodes(inlineNodes);if(trimmedContentNodes.length>0){blockNodes.push({...referenceNode,content:trimmedContentNodes});}};function splitBlockWidgetsFromParagraphs(ast){if(!Array.isArray(ast)){return ast}return ast.flatMap(node=>{if(!isParagraphWithBlockWidget(node)){return node}const blockNodes=[];const inlineNodes=[];node.content.forEach(childNode=>{if(isBlockWidgetNode(childNode)){mergeInlineNodes(inlineNodes,blockNodes,node);blockNodes.push(childNode);inlineNodes.length=0;}else {inlineNodes.push(childNode);}});mergeInlineNodes(inlineNodes,blockNodes,node);return blockNodes})}function firstNumericalParse$1(text){let first;const val=perseusScore.KhanAnswerTypes.predicate.createValidatorFunctional(function(ans){first=ans;return true},{simplify:"optional",inexact:true,forms:"integer, proper, improper, pi, log, mixed, decimal"});val(text);return first}function stringArrayOfSize(size){return Array(size).fill("")}function stringArrayOfSize2D(opt){const{rows,columns}=opt;const rowArr=stringArrayOfSize(rows);return rowArr.map(()=>stringArrayOfSize(columns))}function gridDimensionConfig(absTickStep,extent,dimensionConstraint,gridStep){const scale=scaleFromExtent(extent,dimensionConstraint);const stepPx=absTickStep*scale;const unityLabel=stepPx>30;return {scale:scale,tickStep:absTickStep/gridStep,unityLabel:unityLabel}}function getGridStep(range,step,boxSize){return ___default.default(2).times(function(i){const scale=scaleFromExtent(range[i],boxSize);const gridStep=gridStepFromTickStep(step[i],scale);return gridStep})}function snapStepFromGridStep(gridStep){return [gridStep[0]/2,gridStep[1]/2]}function gridStepFromTickStep(tickStep,scale){const tickWidth=tickStep*scale;const x=tickStep;const y=Math.pow(10,Math.floor(Math.log(x)/Math.LN10));const leadingDigit=Math.floor(x/y);if(tickWidth<25){return tickStep}if(tickWidth<50){if(leadingDigit===5){return tickStep}return tickStep/2}if(leadingDigit===1){return tickStep/2}if(leadingDigit===2){return tickStep/4}if(leadingDigit===5){return tickStep/5}}function scaleFromExtent(extent,dimensionConstraint){const span=extent[1]-extent[0];const scale=dimensionConstraint/span;return scale}function tickStepFromExtent(extent,dimensionConstraint){const span=extent[1]-extent[0];let tickFactor;if(15<span&&span<=20){tickFactor=23;}else if(span>100||span<5){tickFactor=10;}else {tickFactor=16;}const constraintFactor=dimensionConstraint/500;const desiredNumTicks=tickFactor*constraintFactor;return tickStepFromNumTicks(span,desiredNumTicks)}function tickStepFromNumTicks(span,numTicks){let step=Math.pow(10,Math.floor(Math.log(span/numTicks)/Math.LN10));const err=numTicks/span*step;if(err<=.15){step*=10;}else if(err<=.35){step*=5;}else if(err<=.75){step*=2;}return step}const constrainTickStep=(step,range)=>{const span=range[1]-range[0];const numTicks=span/step;if(numTicks<=10){return step}if(numTicks<=20){return step*2}return tickStepFromNumTicks(span,10)};function constrainedTickStepsFromTickSteps(tickSteps,ranges){return [constrainTickStep(tickSteps[0],ranges[0]),constrainTickStep(tickSteps[1],ranges[1])]}function parseQueryString(query){query=query||window.location.search.substring(1);const urlParams={};const a=/\+/g;const r=/([^&=]+)=?([^&]*)/g;const d=function(s){return decodeURIComponent(s.replace(a," "))};let e;while(e=r.exec(query)){const m=e;urlParams[d(m[1])]=d(m[2]);}return urlParams}function updateQueryString$2(uri,key,value){value=encodeURIComponent(value);const re=new RegExp("([?&])"+key+"=.*?(&|$)","i");const separator=uri.indexOf("?")!==-1?"&":"?";if(uri.match(re)){return uri.replace(re,"$1"+key+"="+value+"$2")}return uri+separator+key+"="+value}function strongEncodeURIComponent(str){return encodeURIComponent(str).replace(/['()!]/g,window.escape).replace(/\*/g,"%2A")}const touchHandlers={pointerDown:false,currentTouchIdentifier:null};function resetTouchHandlers(){Object.assign(touchHandlers,{pointerDown:false,currentTouchIdentifier:null});}function extractPointerLocation(event){let touchOrEvent;if(touchHandlers.pointerDown){if(touchHandlers.currentTouchIdentifier!=null){const len=event.changedTouches?event.changedTouches.length:0;for(let i=0;i<len;i++){if(event.changedTouches[i].identifier===touchHandlers.currentTouchIdentifier){touchOrEvent=event.changedTouches[i];}}}else {touchOrEvent=event;}const isEndish=event.type==="touchend"||event.type==="touchcancel";if(touchOrEvent&&isEndish){touchHandlers.pointerDown=false;touchHandlers.currentTouchIdentifier=null;}}else {touchHandlers.pointerDown=true;if(event.changedTouches){touchOrEvent=event.changedTouches[0];touchHandlers.currentTouchIdentifier=touchOrEvent.identifier;}else {touchOrEvent=event;}}if(touchOrEvent){return {left:touchOrEvent.pageX,top:touchOrEvent.pageY}}}const supportsPassiveEvents=()=>{try{const opts=Object.defineProperty({},"passive",{get:function(){supportsPassive=true;}});window.addEventListener("testPassive",null,opts);window.removeEventListener("testPassive",null,opts);}catch{}return supportsPassive};function captureScratchpadTouchStart$2(e){e.stopPropagation();}function getImageSize(url,callback){const img=new Image;img.onload=function(){if(img.width===0&&img.height===0){document.body?.appendChild(img);___default.default.defer(function(){callback(img.clientWidth,img.clientHeight);document.body?.removeChild(img);});}else {callback(img.width,img.height);}};img.src=perseusCore.getRealImageUrl(url);}function getWordBeforeCursor(textarea){const text=textarea.value;const endPos=textarea.selectionStart-1;const startPos=Math.max(text.lastIndexOf("\n",endPos),text.lastIndexOf(" ",endPos))+1;return {string:text.substring(startPos,endPos+1),pos:{start:startPos,end:endPos}}}function moveCursor(textarea,pos){textarea.selectionStart=pos;textarea.selectionEnd=pos;}const textarea={getWordBeforeCursor,moveCursor};const unescapeMathMode$1=label=>label.startsWith("$")&&label.endsWith("$")?label.slice(1,-1):label;const Util={inputPathsEqual,nestedMap: nestedMap$2,rWidgetRule,rTypeFromWidgetId,rWidgetParts,snowman,splitBlockWidgetsFromParagraphs,firstNumericalParse: firstNumericalParse$1,stringArrayOfSize,stringArrayOfSize2D,gridDimensionConfig,getGridStep,snapStepFromGridStep,scaleFromExtent,tickStepFromExtent,gridStepFromTickStep,tickStepFromNumTicks,constrainedTickStepsFromTickSteps,parseQueryString,updateQueryString: updateQueryString$2,strongEncodeURIComponent,touchHandlers,resetTouchHandlers,extractPointerLocation,supportsPassiveEvents,captureScratchpadTouchStart: captureScratchpadTouchStart$2,getImageSize,getImageSizeModern:perseusCore.getImageSizeModern,getRealImageUrl:perseusCore.getRealImageUrl,isLabeledSVG:perseusCore.isLabeledSVG,getBaseUrl:perseusCore.getBaseUrl,getSvgUrl:perseusCore.getSvgUrl,getDataUrl:perseusCore.getDataUrl,textarea,unescapeMathMode: unescapeMathMode$1};
|
|
1497
1499
|
|
|
1498
1500
|
const Log={log:(message,extra)=>{getDependencies().Log.log(message,extra);},error:(message,kind,extra)=>{getDependencies().Log.error(message,kind,extra);}};
|
|
1499
1501
|
|
|
1500
1502
|
const svgLocalLabelsRegex=/^file\+graphie:/;const hashRegex=/\/([^/]+)$/;function getLocale(){const{JIPT,kaLocale}=getDependencies();return JIPT.useJIPT?"en-pt":kaLocale}function shouldUseLocalizedData(){return getLocale()!=="en"}const splitHashRegex=/\/(?=[^/]+$)/;function getLocalizedDataUrl(url){if(svgLocalLabelsRegex.test(url)){return Util.getDataUrl(url)}const[base,hash]=Util.getBaseUrl(url).split(splitHashRegex);return `${base}/${getLocale()}/${hash}-data.json`}function getUrlHash(url){const match=url.match(hashRegex);if(match==null){throw new perseusCore.PerseusError("not a valid URL",perseusCore.Errors.InvalidInput)}return match&&match[1]}function parseDataFromJSONP(graphieHash,graphieJSONP,errorCallback){const match=graphieJSONP.match(new RegExp(`^(?:svgData|svgOtherData)${graphieHash}\\((.+)\\);$`));const jsonToParse=match?match[1]:graphieJSONP;try{return JSON.parse(jsonToParse)}catch(error){errorCallback(error);return null}}let labelDataCache={};function loadGraphie(url,onDataLoaded){const hash=getUrlHash(url);const entry=labelDataCache[hash];if(entry!=null){if(entry.loaded){const{data,localized}=entry;onDataLoaded(data,localized);}else {entry.dataCallbacks.push(onDataLoaded);}}else {const cacheData={loaded:false,dataCallbacks:[onDataLoaded],localized:shouldUseLocalizedData()};labelDataCache[hash]=cacheData;const retrieveData=async(url,errorCallback)=>{const response=await fetch(url);if(!response?.ok){errorCallback();return}const jsonp=await response.text();const data=parseDataFromJSONP(hash,jsonp,error=>{Log.error("Failed to parse JSONP for svg-image",perseusCore.Errors.Service,{cause:error,loggedMetadata:{dataUrl:Util.getDataUrl(url),jsonp}});});if(!data){return}const newCacheEntry=labelDataCache[hash]={...labelDataCache[hash],loaded:true,data};newCacheEntry.dataCallbacks.forEach(callback=>{callback(newCacheEntry.data,cacheData.localized);});};const dataLoadErrorHandler=(x,status,error)=>{Log.error("Data load failed for svg-image",perseusCore.Errors.Service,{cause:error,loggedMetadata:{dataUrl:Util.getDataUrl(url),status}});};if(shouldUseLocalizedData()){retrieveData(getLocalizedDataUrl(url),()=>{cacheData.localized=false;retrieveData(Util.getDataUrl(url),dataLoadErrorHandler);});}else {retrieveData(Util.getDataUrl(url),dataLoadErrorHandler);}}}
|
|
1501
1503
|
|
|
1502
|
-
const baseFontFamily="'Lato', sans-serif";const boldFontFamily="'Lato-Bold', 'Lato', sans-serif";const
|
|
1504
|
+
const baseFontFamily="'Lato', sans-serif";const boldFontFamily="'Lato-Bold', 'Lato', sans-serif";const white="#FFFFFF";const gray76="#BABEC2";const gray68="#888D93";const gray17="#21242c";const pureSmMin="568px";const pureMdMin$1="768px";const pureLgMin$1="1024px";const pureXlMin="1280px";const pureXsMax$1="567px";const pureSmMax$1="767px";const pureMdMax$1="1023px";const pureLgMax$1="1279px";const phoneMargin=16;const negativePhoneMargin=-16;const hintBorderWidth=wonderBlocksTokens.sizing.size_040;const hintPaddingInlineStart=wonderBlocksTokens.sizing.size_160;const interactiveSizes$1={defaultBoxSize:400,defaultBoxSizeSmall:288};const circleSize$1=24;const radioMarginWidth$1=2;const warningColor="#f86700";const warningColorHover="#df5c00";const warningColorActive="#c75300";const publishBlockingErrorColor="#be2612";const articleMaxWidthInPx=688;const articleMaxWidthTableInPx=512;
|
|
1503
1505
|
|
|
1504
1506
|
var constants = /*#__PURE__*/Object.freeze({
|
|
1505
1507
|
__proto__: null,
|
|
1506
1508
|
articleMaxWidthInPx: articleMaxWidthInPx,
|
|
1507
1509
|
articleMaxWidthTableInPx: articleMaxWidthTableInPx,
|
|
1508
1510
|
baseFontFamily: baseFontFamily,
|
|
1509
|
-
baseUnitPx: baseUnitPx,
|
|
1510
1511
|
boldFontFamily: boldFontFamily,
|
|
1511
|
-
checkedColor: checkedColor$1,
|
|
1512
1512
|
circleSize: circleSize$1,
|
|
1513
1513
|
gray17: gray17,
|
|
1514
1514
|
gray68: gray68,
|
|
1515
1515
|
gray76: gray76,
|
|
1516
|
-
gray85: gray85,
|
|
1517
|
-
gray97: gray97,
|
|
1518
1516
|
hintBorderWidth: hintBorderWidth,
|
|
1517
|
+
hintPaddingInlineStart: hintPaddingInlineStart,
|
|
1519
1518
|
interactiveSizes: interactiveSizes$1,
|
|
1520
|
-
kaGreen: kaGreen,
|
|
1521
1519
|
negativePhoneMargin: negativePhoneMargin,
|
|
1522
1520
|
phoneMargin: phoneMargin,
|
|
1523
1521
|
publishBlockingErrorColor: publishBlockingErrorColor,
|
|
@@ -1529,7 +1527,6 @@ var constants = /*#__PURE__*/Object.freeze({
|
|
|
1529
1527
|
pureSmMin: pureSmMin,
|
|
1530
1528
|
pureXlMin: pureXlMin,
|
|
1531
1529
|
pureXsMax: pureXsMax$1,
|
|
1532
|
-
radioBorderColor: radioBorderColor$1,
|
|
1533
1530
|
radioMarginWidth: radioMarginWidth$1,
|
|
1534
1531
|
warningColor: warningColor,
|
|
1535
1532
|
warningColorActive: warningColorActive,
|
|
@@ -1541,9 +1538,9 @@ const MIN_VIEWPORT_HEIGHT=480;class FixedToResponsive extends React__namespace.C
|
|
|
1541
1538
|
|
|
1542
1539
|
const GifImage=props=>{const{alt,width,height,scale,isPlaying,onLoop,onLoad,gifFrames}=props;const framesRef=React__namespace.useRef([]);const canvasRef=React__namespace.useRef(null);const hiddenCanvasRef=React__namespace.useRef(null);const animationIdRef=React__namespace.useRef(null);const currentFrameIndexRef=React__namespace.useRef(0);const lastFrameTimeRef=React__namespace.useRef(null);const latestPropsRef=React__namespace.useRef({isPlaying,onLoop,onLoad});latestPropsRef.current={isPlaying,onLoop,onLoad};const drawPatch=React__namespace.useCallback(index=>{const frames=framesRef.current;const hiddenCtx=hiddenCanvasRef.current?.getContext("2d");const displayCtx=canvasRef.current?.getContext("2d");if(!hiddenCtx||!hiddenCanvasRef.current||!displayCtx||!canvasRef.current||frames.length===0){return}const frame=frames[index];const{dims}=frame;if(index>0){const prev=frames[index-1];if(prev.disposalType===2){displayCtx.clearRect(prev.dims.left,prev.dims.top,prev.dims.width,prev.dims.height);}}hiddenCanvasRef.current.width=dims.width;hiddenCanvasRef.current.height=dims.height;const imageData=new ImageData(new Uint8ClampedArray(frame.patch),dims.width,dims.height);hiddenCtx.putImageData(imageData,0,0);displayCtx.drawImage(hiddenCanvasRef.current,dims.left,dims.top);},[]);const drawFrame=React__namespace.useCallback((index=0)=>{const frames=framesRef.current;if(frames.length===0||!canvasRef.current||!hiddenCanvasRef.current){return}const targetIndex=Math.min(index,frames.length-1);currentFrameIndexRef.current=targetIndex;const{width:nativeWidth,height:nativeHeight}=frames[0].dims;canvasRef.current.width=nativeWidth;canvasRef.current.height=nativeHeight;for(let i=0;i<=targetIndex;i++){drawPatch(i);}},[drawPatch]);const pause=React__namespace.useCallback(()=>{if(animationIdRef.current!==null){cancelAnimationFrame(animationIdRef.current);animationIdRef.current=null;}},[]);const animate=React__namespace.useCallback(timestamp=>{const frames=framesRef.current;if(frames.length===0){return}if(lastFrameTimeRef.current===null){lastFrameTimeRef.current=timestamp;drawPatch(currentFrameIndexRef.current);}const frame=frames[currentFrameIndexRef.current];const delay=frame.delay<=0?10:frame.delay;if(timestamp-lastFrameTimeRef.current>=delay){currentFrameIndexRef.current++;if(currentFrameIndexRef.current>=frames.length){currentFrameIndexRef.current=0;animationIdRef.current=null;latestPropsRef.current.onLoop();return}drawPatch(currentFrameIndexRef.current);lastFrameTimeRef.current=lastFrameTimeRef.current+delay;}animationIdRef.current=requestAnimationFrame(animate);},[drawPatch]);const play=React__namespace.useCallback(()=>{if(framesRef.current.length===0){return}lastFrameTimeRef.current=null;animationIdRef.current=requestAnimationFrame(animate);},[animate]);const restart=React__namespace.useCallback(()=>{pause();drawFrame(0);},[pause,drawFrame]);React__namespace.useEffect(()=>{framesRef.current=gifFrames??[];currentFrameIndexRef.current=0;lastFrameTimeRef.current=null;drawFrame(0);latestPropsRef.current.onLoad?.();if(latestPropsRef.current.isPlaying){play();}return ()=>pause()},[gifFrames]);const prevIsPlayingRef=React__namespace.useRef(isPlaying);React__namespace.useEffect(()=>{const wasPlaying=prevIsPlayingRef.current;prevIsPlayingRef.current=isPlaying;if(isPlaying&&!wasPlaying){play();}if(!isPlaying&&wasPlaying){if(currentFrameIndexRef.current===0){restart();}else {pause();}}},[isPlaying,restart,play,pause,drawFrame]);const setCanvasRef=React__namespace.useCallback(canvas=>{canvasRef.current=canvas;if(canvas&&framesRef.current.length>0){drawFrame(0);}},[drawFrame]);const displayHeight=!width&&height?height*scale:undefined;const aspectRatio=width&&height?`${width} / ${height}`:undefined;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("canvas",{"aria-label":alt,role:"img",ref:setCanvasRef,"data-testid":"gif-canvas",style:{width:width?width*scale:undefined,maxWidth:"100%",aspectRatio:aspectRatio,height:displayHeight}}),jsxRuntimeExports.jsx("canvas",{"aria-hidden":true,tabIndex:-1,ref:hiddenCanvasRef,"data-testid":"gif-hidden-canvas",style:{display:"none"}})]})};
|
|
1543
1540
|
|
|
1544
|
-
function getKey$2(eventName,id){return eventName+":"+id}function getEventName$2(key){return key.split(":")[0]}const MovableHelperMethods={_fireEvent:function(listeners,...args){for(const listener of listeners){listener.call(this,...args);}},_applyConstraints:function(current,previous,extraOptions){let skipRemaining=false;return ___default.default.reduce(this.state.constraints,(memo,constraint)=>{if(memo===false){return false}if(skipRemaining){return memo}const result=constraint.call(this,memo,previous,{onSkipRemaining:()=>{skipRemaining=true;},...extraOptions});if(result===false){return false}if(kmath.point.is(result,2)){return result}if(result===true||result==null){return memo}throw new perseusCore.PerseusError("Constraint returned invalid result: "+result,perseusCore.Errors.Internal)},current,this)},draw:function(){const currState=this.cloneState();MovableHelperMethods._fireEvent.call(this,this.state.draw,currState,this.prevState);this.prevState=currState;},listen:function(eventName,id,func){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key]=this._listenerMap[key]||this.state[eventName].length;this.state[eventName][index]=func;},unlisten:function(eventName,id){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key];if(index!==undefined){this.state[eventName].splice(index,1);delete this._listenerMap[key];const keys=
|
|
1541
|
+
function getKey$2(eventName,id){return eventName+":"+id}function getEventName$2(key){return key.split(":")[0]}const MovableHelperMethods={_fireEvent:function(listeners,...args){for(const listener of listeners){listener.call(this,...args);}},_applyConstraints:function(current,previous,extraOptions){let skipRemaining=false;return ___default.default.reduce(this.state.constraints,(memo,constraint)=>{if(memo===false){return false}if(skipRemaining){return memo}const result=constraint.call(this,memo,previous,{onSkipRemaining:()=>{skipRemaining=true;},...extraOptions});if(result===false){return false}if(kmath.point.is(result,2)){return result}if(result===true||result==null){return memo}throw new perseusCore.PerseusError("Constraint returned invalid result: "+result,perseusCore.Errors.Internal)},current,this)},draw:function(){const currState=this.cloneState();MovableHelperMethods._fireEvent.call(this,this.state.draw,currState,this.prevState);this.prevState=currState;},listen:function(eventName,id,func){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key]=this._listenerMap[key]||this.state[eventName].length;this.state[eventName][index]=func;},unlisten:function(eventName,id){this._listenerMap=this._listenerMap||{};const key=getKey$2(eventName,id);const index=this._listenerMap[key];if(index!==undefined){this.state[eventName].splice(index,1);delete this._listenerMap[key];const keys=Object.keys(this._listenerMap);___default.default.each(keys,function(key){if(getEventName$2(key)===eventName&&this._listenerMap[key]>index){this._listenerMap[key]--;}},this);}}};
|
|
1545
1542
|
|
|
1546
|
-
let prefixedTransform=null;function computePrefixedTransform(){const el=document.createElement("div");const prefixes=["transform","msTransform","MozTransform","WebkitTransform","OTransform"];let correctPrefix=null;___default.default.each(prefixes,function(prefix){if(typeof el.style[prefix]!=="undefined"){correctPrefix=prefix;}});return correctPrefix}let canUse3dTransform=null;function computeCanUse3dTransform(){const el=document.createElement("div");const prefix=InteractiveUtil.getPrefixedTransform();el.style[prefix]="translateZ(0px)";return !!el.style[prefix]}const FUNCTION_ARRAY_OPTIONS=["add","modify","draw","remove","constraints","onMoveStart","onMove","onMoveEnd","onClick"];const InteractiveUtil={assert:function(isTrue,message){if(!isTrue){throw new perseusCore.PerseusError("Assertion Error"+(message?": "+message:""),perseusCore.Errors.Internal)}},createGettersFor:function(Class,defaults){___default.default.each(
|
|
1543
|
+
let prefixedTransform=null;function computePrefixedTransform(){const el=document.createElement("div");const prefixes=["transform","msTransform","MozTransform","WebkitTransform","OTransform"];let correctPrefix=null;___default.default.each(prefixes,function(prefix){if(typeof el.style[prefix]!=="undefined"){correctPrefix=prefix;}});return correctPrefix}let canUse3dTransform=null;function computeCanUse3dTransform(){const el=document.createElement("div");const prefix=InteractiveUtil.getPrefixedTransform();el.style[prefix]="translateZ(0px)";return !!el.style[prefix]}const FUNCTION_ARRAY_OPTIONS=["add","modify","draw","remove","constraints","onMoveStart","onMove","onMoveEnd","onClick"];const InteractiveUtil={assert:function(isTrue,message){if(!isTrue){throw new perseusCore.PerseusError("Assertion Error"+(message?": "+message:""),perseusCore.Errors.Internal)}},createGettersFor:function(Class,defaults){___default.default.each(Object.keys(defaults),function(key){if(Class.prototype[key]===undefined){Class.prototype[key]=function(){return this.state[key]};}});},addMovableHelperMethodsTo:function(Class){___default.default.each(MovableHelperMethods,function(methodFunc,methodName){if(Class.prototype[methodName]===undefined){Class.prototype[methodName]=methodFunc;}});},arrayify:function(funcOrArray){if(funcOrArray==null){return []}if(Array.isArray(funcOrArray)){return ___default.default.filter(___default.default.flatten(funcOrArray),___default.default.identity)}return [funcOrArray]},normalizeOptions:function(options){const result={...options};FUNCTION_ARRAY_OPTIONS.forEach(function(eventName){if(options[eventName]!==undefined){result[eventName]=InteractiveUtil.arrayify(options[eventName]);}});return result},getPrefixedTransform:function(){prefixedTransform=prefixedTransform||computePrefixedTransform();return prefixedTransform},getCanUse3dTransform:function(){if(canUse3dTransform==null){canUse3dTransform=computeCanUse3dTransform();}return canUse3dTransform}};
|
|
1547
1544
|
|
|
1548
1545
|
function _class_private_field_loose_base(receiver, privateKey) {
|
|
1549
1546
|
if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
|
|
@@ -1612,7 +1609,7 @@ const reactRootCache=new WeakMap;function render(element,container){const childr
|
|
|
1612
1609
|
|
|
1613
1610
|
function findChildOrAdd(elem,className){const $child=$__default.default(elem).find("."+className);if($child.length===0){return $__default.default("<span>").addClass(className).appendTo($__default.default(elem))}return $child}var Tex$1 = {processMath:async function(elem,text,force,callback){const $elem=$__default.default(elem);if($elem.attr("data-math-formula")==null||force){const $texHolder=findChildOrAdd($elem,"tex-holder");if(text==null&&$elem.attr("data-math-formula")){text=$elem.attr("data-math-formula");}text=text!=null?text+"":"";text=kmath.KhanMath.cleanMath(text);$elem.attr("data-math-formula",text);const{TeX}=await getDependencies();render(React__namespace.createElement(TeX,{children:text,onRender:callback}),$texHolder[0]);}}};
|
|
1614
1611
|
|
|
1615
|
-
const{processMath: processMath$1}=Tex$1;function polar$2(r,th){if(typeof r==="number"){r=[r,r];}th=th*Math.PI/180;return [r[0]*Math.cos(th),r[1]*Math.sin(th)]}var _bounds=/*#__PURE__*/_class_private_field_loose_key("_bounds"),_drawingTransform=/*#__PURE__*/_class_private_field_loose_key("_drawingTransform"),_labelElements=/*#__PURE__*/_class_private_field_loose_key("_labelElements"),_resizeObserver=/*#__PURE__*/_class_private_field_loose_key("_resizeObserver");let Graphie$1 = class Graphie{init(options){let scale=options.scale||[40,40];scale=typeof scale==="number"?[scale,scale]:scale;if(options.range==null){throw new perseusCore.PerseusError("range should be specified in graph init",perseusCore.Errors.Internal)}_class_private_field_loose_base(this,_bounds)[_bounds]=new GraphBounds(...options.range);_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]=new DrawingTransform(this.raphael,scale,this.bounds());const[w,h]=this.drawingTransform().canvasDimensions();$__default.default(this.el).css({width:w,height:h});this.range=options.range;this.scale=scale;this.dimensions=[w,h];this.xpixels=w;this.ypixels=h;this.isMobile=options.isMobile??false;return this}graphInit(options){options=options||{};for(const[prop,val]of wonderStuffCore.entries(options)){if(!prop.match(/.*Opacity$/)&&prop!=="range"&&typeof val==="number"){options[prop]=[val,val];}if(prop==="range"||prop==="gridRange"){options[prop]=normalizeRange(options[prop]);}}const range=normalizeRange(options.range||[[-10,10],[-10,10]]);const gridRange=normalizeRange(options.gridRange||range);const scale=options.scale||[20,20];const grid=options.grid!=null?options.grid:true;const gridOpacity=options.gridOpacity||.1;const gridStep=toPair(options.gridStep||[1,1]);const axes=options.axes!=null?options.axes:true;const axisArrows=options.axisArrows||"";const axisOpacity=options.axisOpacity||1;const axisCenter=options.axisCenter||[Math.min(Math.max(range[0][0],0),range[0][1]),Math.min(Math.max(range[1][0],0),range[1][1])];const axisLabels=options.axisLabels!=null?options.axisLabels:false;const ticks=options.ticks!=null?options.ticks:true;const tickStep=options.tickStep||[2,2];const tickLen=options.tickLen||[5,5];const tickOpacity=options.tickOpacity||1;const labels=options.labels||options.labelStep||false;const labelStep=options.labelStep||[1,1];const labelOpacity=options.labelOpacity||1;let unityLabels=options.unityLabels||false;const labelFormat=options.labelFormat||function(a){return a};let xLabelFormat=options.xLabelFormat||labelFormat;let yLabelFormat=options.yLabelFormat||labelFormat;const realRange=[[range[0][0]-(range[0][0]>0?1:0),range[0][1]+(range[0][1]<0?1:0)],[range[1][0]-(range[1][0]>0?1:0),range[1][1]+(range[1][1]<0?1:0)]];if(!Array.isArray(unityLabels)){unityLabels=[unityLabels,unityLabels];}const minusIgnorer=function(lf){return function(a){return (lf(a)+"").replace(/-(\d)/g,"\\llap{-}$1")}};xLabelFormat=minusIgnorer(xLabelFormat);yLabelFormat=minusIgnorer(yLabelFormat);this.init({range:realRange,scale:scale,isMobile:options.isMobile});if(grid){this.grid(gridRange[0],gridRange[1],{stroke:options.isMobile?KhanColors.GRAY_C:"#000000",opacity:options.isMobile?1:gridOpacity,step:gridStep,strokeWidth:options.isMobile?1:2});}if(axes){if(axisArrows==="<->"||axisArrows===true){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:axisOpacity,strokeWidth:options.isMobile?1:2,arrows:"->"},function(){if(range[1][0]<0&&range[1][1]>0){thisGraphie.path([axisCenter,[gridRange[0][0],axisCenter[1]]]);thisGraphie.path([axisCenter,[gridRange[0][1],axisCenter[1]]]);}if(range[0][0]<0&&range[0][1]>0){thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][0]]]);thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][1]]]);}});}else if(axisArrows==="->"||axisArrows===""){const thisGraphie=this;this.style({stroke:"#000000",opacity:axisOpacity,strokeWidth:2,arrows:axisArrows},function(){thisGraphie.path([[gridRange[0][0],axisCenter[1]],[gridRange[0][1],axisCenter[1]]]);thisGraphie.path([[axisCenter[0],gridRange[1][0]],[axisCenter[0],gridRange[1][1]]]);});}if(axisLabels&&axisLabels.length===2){this.label([gridRange[0][1],axisCenter[1]],axisLabels[0],"right");this.label([axisCenter[0],gridRange[1][1]],axisLabels[1],"above");}}if(ticks){const halfWidthTicks=options.isMobile;const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:tickOpacity,strokeWidth:1},()=>{let step=gridStep[0]*tickStep[0];let len=tickLen[0]/scale[1];let start=gridRange[0][0];let stop=gridRange[0][1];if(range[1][0]<0&&range[1][1]>0){for(let x=step+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}for(let x=-step+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}}step=gridStep[1]*tickStep[1];len=tickLen[1]/scale[0];start=gridRange[1][0];stop=gridRange[1][1];if(range[0][0]<0&&range[0][1]>0){for(let y=step+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}for(let y=-step+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}}});}if(labels){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:labelOpacity},function(){let step=gridStep[0]*tickStep[0]*labelStep[0];let start=gridRange[0][0];let stop=gridRange[0][1];const xAxisPosition=axisCenter[0]<0?"above":"below";const yAxisPosition=axisCenter[0]<0?"right":"left";const xShowZero=axisCenter[0]===0&&axisCenter[1]!==0;const yShowZero=axisCenter[0]!==0&&axisCenter[1]===0;const axisOffCenter=axisCenter[0]!==0||axisCenter[1]!==0;const showUnityX=unityLabels[0]||axisOffCenter;const showUnityY=unityLabels[1]||axisOffCenter;for(let x=(xShowZero?0:step)+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}for(let x=-step*(showUnityX?1:2)+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}step=gridStep[1]*tickStep[1]*labelStep[1];start=gridRange[1][0];stop=gridRange[1][1];for(let y=(yShowZero?0:step)+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}for(let y=-step*(showUnityY?1:2)+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}});}}drawingTransform(){if(_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]==null){throw new Error("Can't get drawingTransform of an uninitialized Graphie")}return _class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]}bounds(){if(_class_private_field_loose_base(this,_bounds)[_bounds]==null){throw new Error("Can't get bounds of an uninitialized Graphie")}return _class_private_field_loose_base(this,_bounds)[_bounds]}style(attrs,fn){const processed=this.processAttributes(attrs);if(typeof fn==="function"){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...processed};const result=fn.call(this);this.currentStyle=oldStyle;return result}Object.assign(this.currentStyle,processed);}grid(xr,yr,style){return this.withStyle(style,()=>{const step=this.currentStyle.step||[1,1];const set=this.raphael.set();let x=step[0]*Math.ceil(xr[0]/step[0]);for(;x<=xr[1];x+=step[0]){set.push(this.line([x,yr[0]],[x,yr[1]]));}let y=step[1]*Math.ceil(yr[0]/step[1]);for(;y<=yr[1];y+=step[1]){set.push(this.line([xr[0],y],[xr[1],y]));}return set})}arc(center,radius,startAngle,endAngle,sector,style){return this.withStyle(style,()=>{startAngle=(startAngle%360+360)%360;endAngle=(endAngle%360+360)%360;const cent=this.scalePoint(center);const radii=this.scaleVector(radius);const startVector=polar$2(radius,startAngle);const endVector=polar$2(radius,endAngle);const round=x=>kmath.number.round(x,6);const startPoint=this.scalePoint([round(center[0]+startVector[0]),round(center[1]+startVector[1])]);const endPoint=this.scalePoint([round(center[0]+endVector[0]),round(center[1]+endVector[1])]);const largeAngle=((endAngle-startAngle)%360+360)%360>180;return this.raphael.path("M"+startPoint.join(" ")+"A"+radii.join(" ")+" 0 "+(largeAngle?1:0)+" 0 "+endPoint.join(" ")+(sector?"L"+cent.join(" ")+"z":""))})}circle(center,radius,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center),...this.scaleVector([radius,radius])))}rect(x,y,width,height,style){return this.withStyle(style,()=>{const corner=this.scalePoint([x,y+height]);const dims=this.scaleVector([width,height]);const elem=this.raphael.rect(...corner.concat(dims));if(this.isMobile){elem.node.style.shapeRendering="crispEdges";}return elem})}ellipse(center,radii,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center).concat(this.scaleVector(radii))))}fixedEllipse(center,radii,maxScale,padding,style){return this.withStyle(style,()=>{const scaledPoint=this.scalePoint(center);const scaledRadii=this.scaleVector(radii);const width=2*scaledRadii[0]*maxScale+padding;const height=2*scaledRadii[1]*maxScale+padding;const left=scaledPoint[0]-width/2;const top=scaledPoint[1]-height/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px"});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.ellipse(width/2,height/2,scaledRadii[0],scaledRadii[1]);return {wrapper:wrapper,visibleShape:visibleShape}})}unstyledPath(points){const p=this.raphael.path(this.svgPath(points));p.graphiePath=points;return p}path(points,style){return this.withStyle(style,()=>{return this.unstyledPath(points)})}fixedPath(points,center,createPath){points=points.map(this.scalePoint);center=center?this.scalePoint(center):null;createPath=createPath||this.svgPath;const xs=points.map(p=>p[0]);const ys=points.map(p=>p[1]);const pathLeft=Math.min(...xs);const pathRight=Math.max(...xs);const pathTop=Math.min(...ys);const pathBottom=Math.max(...ys);const padding=[4,4];const topLeftOfBoundingBox=[pathLeft,pathTop];points=points.map(function(point){return kmath.vector.add(kmath.vector.subtract(point,topLeftOfBoundingBox),kmath.vector.scale(padding,.5))});const width=pathRight-pathLeft+padding[0];const height=pathBottom-pathTop+padding[1];const left=topLeftOfBoundingBox[0]-padding[0]/2;const top=topLeftOfBoundingBox[1]-padding[1]/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:center?width/2+center[0]+"px "+(height/2+center[1])+"px":null});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.path(createPath(points));return {wrapper:wrapper,visibleShape:visibleShape}}scaledPath(points,style){return this.withStyle(style,()=>{const p=this.raphael.path(this.svgPath(points,true));p.graphiePath=points;return p})}line(start,end,style){return this.withStyle(style,()=>{const l=this.unstyledPath([start,end]);if(this.isMobile){l.node.style.shapeRendering="crispEdges";}return l})}parabola(a,b,c,style){return this.withStyle(style,()=>this.raphael.path(this.svgParabolaPath(a,b,c)))}fixedLine(start,end,thickness){const padding=[thickness,thickness];start=this.scalePoint(start);end=this.scalePoint(end);const extraOffset=[Math.min(start[0],end[0]),Math.min(start[1],end[1])];start=kmath.vector.add(kmath.vector.subtract(start,extraOffset),kmath.vector.scale(padding,.5));end=kmath.vector.add(kmath.vector.subtract(end,extraOffset),kmath.vector.scale(padding,.5));const left=extraOffset[0]-padding[0]/2;const top=extraOffset[1]-padding[1]/2;const width=Math.abs(start[0]-end[0])+padding[0];const height=Math.abs(start[1]-end[1])+padding[1];const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:start[0]+"px "+start[1]+"px"});const localRaphael=Raphael$1(wrapper,width,height);const path="M"+start[0]+" "+start[1]+" "+"L"+end[0]+" "+end[1];const visibleShape=localRaphael.path(path);visibleShape.graphiePath=[start,end];return {wrapper:wrapper,visibleShape:visibleShape}}sinusoid(a,b,c,d,style){return this.withStyle(style,()=>this.raphael.path(this.svgSinusoidPath(a,b,c,d)))}plotParametric(fn,range,style){return this.withStyle(style,()=>{const clip=xy=>{if(Math.abs(xy[1])>5e5){return [xy[0],Math.min(Math.max(xy[1],-5e5),5e5)]}return xy};const clippedFn=x=>clip(fn(x));const min=range[0];const max=range[1];let step=(max-min)/(this.currentStyle["plot-points"]||800);if(step===0){step=1;}const paths=this.raphael.set();let points=[];let lastY=clippedFn(min)[1];for(let t=min;t<=max;t+=step){const point=clippedFn(t);const y=point[1];if(y>0!==lastY>0&&Math.abs(y-lastY)>2*this.drawingTransform().pixelsPerUnitY()||isNaN(y)){paths.push(this.unstyledPath(points));points=[];}else {points.push(point);}lastY=y;}paths.push(this.unstyledPath(points));return paths})}plot(fn,range,style){return this.withStyle(style,()=>{const min=range[0];const max=range[1];if(!this.currentStyle["plot-points"]){this.currentStyle["plot-points"]=2*(max-min)*this.drawingTransform().pixelsPerUnitX();}const parametricFn=x=>[x,fn(x)];return this.plotParametric(parametricFn,range)})}withStyle(style,fn){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...this.processAttributes(style)};const result=this.postprocessDrawingResult(fn());this.currentStyle=oldStyle;return result}postprocessDrawingResult(result){const type=result.constructor.prototype;if(type===Raphael$1.el||type===Raphael$1.st){result.attr(this.currentStyle);if(this.currentStyle.arrows){result=this.addArrowheads(result);}}else if(result instanceof $__default.default){result.css({...this.currentStyle,...SVG_SPECIFIC_STYLE_MASK});}return result}addArrowheads(path){const type=path.constructor.prototype;if(type===Raphael$1.el){if(path.type==="path"&&typeof path.arrowheadsDrawn==="undefined"){const w=path.attr("stroke-width");const s=.6+.4*w;const l=path.getTotalLength();const set=this.raphael.set();const head=this.raphael.path(this.isMobile?"M-4,4 C-4,4 -0.25,0 -0.25,0 C-0.25,0 -4,-4 -4,-4":"M-3 4 C-2.75 2.5 0 0.25 0.75 0C0 -0.25 -2.75 -2.5 -3 -4");const end=path.getPointAtLength(l-.4);const almostTheEnd=path.getPointAtLength(l-.75*s);const angle=Math.atan2(end.y-almostTheEnd.y,end.x-almostTheEnd.x)*180/Math.PI;const attrs=path.attr();delete attrs.path;let subpath=path.getSubpath(0,l-.75*s);subpath=this.raphael.path(subpath).attr(attrs);subpath.arrowheadsDrawn=true;path.remove();head.rotate(angle,this.isMobile?1e-5:.75,0).scale(s,s,.75,0).translate(almostTheEnd.x,almostTheEnd.y).attr(attrs).attr({"stroke-linejoin":"round","stroke-linecap":"round"});head.arrowheadsDrawn=true;set.push(subpath);set.push(head);return set}}else if(type===Raphael$1.st){for(let i=0,l=path.items.length;i<l;i++){this.addArrowheads(path.items[i]);}}return path}processAttributes(attrs){const transformers={scale:scale=>{this.drawingTransform().setScale(scale);},clipRect:pair=>{const point=pair[0];const size=pair[1];point[1]+=size[1];return {"clip-rect":this.scalePoint(point).concat(this.scaleVector(size)).join(" ")}},strokeWidth:function(val){return {"stroke-width":parseFloat(val)}},rx:val=>{return {rx:this.scaleVector([val,0])[0]}},ry:val=>{return {ry:this.scaleVector([0,val])[1]}},r:val=>{const scaled=this.scaleVector([val,val]);return {rx:scaled[0],ry:scaled[1]}}};const processed={};Object.entries(attrs||{}).forEach(function([key,value]){const transformer=transformers[key];if(typeof transformer==="function"){Object.assign(processed,transformer(value));}else {const dasherized=String(key).replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase();processed[dasherized]=value;}});return processed}addMouseLayer(options){const localOptions={allowScratchpad:false,...options};const mouselayerZIndex=2;this.mouselayer=Raphael$1(this.el,this.xpixels,this.ypixels);$__default.default(this.mouselayer.canvas).css("z-index",mouselayerZIndex);if(localOptions.onClick||localOptions.onMouseDown||localOptions.onMouseMove||localOptions.onMouseOver||localOptions.onMouseOut){const canvasClickTarget=this.mouselayer.rect(0,0,this.xpixels,this.ypixels).attr({fill:"#000",opacity:0});let isClickingCanvas=false;$__default.default(this.mouselayer.canvas).on("vmousedown",e=>{if(e.target===canvasClickTarget[0]){if(localOptions.onMouseDown){localOptions.onMouseDown(this.getMouseCoord(e));}isClickingCanvas=true;if(localOptions.onMouseMove){const handler=localOptions.onMouseMove;$__default.default(document).bind("vmousemove.mouseLayer",e=>{if(isClickingCanvas){e.preventDefault();handler(this.getMouseCoord(e));}});}$__default.default(document).bind("vmouseup.mouseLayer",e=>{$__default.default(document).unbind(".mouseLayer");if(isClickingCanvas&&localOptions.onClick){localOptions.onClick(this.getMouseCoord(e));}isClickingCanvas=false;});}});if(localOptions.onMouseOver){const handler=localOptions.onMouseOver;$__default.default(this.mouselayer.canvas).on("vmouseover",e=>{handler(this.getMouseCoord(e));});}if(localOptions.onMouseOut){const handler=localOptions.onMouseOut;$__default.default(this.mouselayer.canvas).on("vmouseout",e=>{handler(this.getMouseCoord(e));});}}this._mouselayerWrapper=document.createElement("div");$__default.default(this._mouselayerWrapper).css({position:"absolute",left:0,top:0,zIndex:mouselayerZIndex});this._visiblelayerWrapper=document.createElement("div");$__default.default(this._visiblelayerWrapper).css({position:"absolute",left:0,top:0});const el=this.el;el.appendChild(this._visiblelayerWrapper);el.appendChild(this._mouselayerWrapper);this.addToMouseLayerWrapper=el=>{this._mouselayerWrapper?.appendChild(el);};this.addToVisibleLayerWrapper=el=>{this._visiblelayerWrapper?.appendChild(el);};}addToMouseLayerWrapper(el){throw new Error("addToMouseLayerWrapper is not ready. Call addMouseLayer() first.")}addToVisibleLayerWrapper(el){throw new Error("addToVisibleLayerWrapper is not ready. Call addMouseLayer() first.")}getMousePx(event){const offset=$__default.default(this.el).offset();const mouseX=event.pageX-offset.left;const mouseY=event.pageY-offset.top;return [mouseX,mouseY]}getMouseCoord(event){return this.unscalePoint(this.getMousePx(event))}_ensureResizeObserver(){if(_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]!=null||typeof ResizeObserver==="undefined"){return}_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=new ResizeObserver(()=>{this._recalculateLabels();});_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver].observe(this.el);}_recalculateLabels(){_class_private_field_loose_base(this,_labelElements)[_labelElements].forEach(span=>{const originalSize=$__default.default(span).data("originalLabelSize");if(originalSize!=null){setLabelMargins(span,originalSize);}});}cleanup(){_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]?.disconnect();_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;_class_private_field_loose_base(this,_labelElements)[_labelElements].clear();}constructor(el){Object.defineProperty(this,_bounds,{writable:true,value:void 0});Object.defineProperty(this,_drawingTransform,{writable:true,value:void 0});Object.defineProperty(this,_labelElements,{writable:true,value:void 0});Object.defineProperty(this,_resizeObserver,{writable:true,value:void 0});_class_private_field_loose_base(this,_labelElements)[_labelElements]=new Set;_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;this.isMobile=false;this.currentStyle={"stroke-width":2,fill:"none"};this.label=(point,text,direction,arg4,arg5)=>{const style=typeof arg4==="object"?arg4:arg5;const latex=typeof arg4==="boolean"?arg4:true;return this.withStyle(style,()=>{const $span=$__default.default("<span>").addClass("graphie-label");const pad=this.currentStyle["label-distance"];$span.css({position:"absolute",padding:(pad!=null?pad:7)+"px",color:"black"}).data("labelDirection",direction).appendTo(this.el);$span.setPosition=point=>{const scaledPoint=this.scalePoint(point);$span.css({left:scaledPoint[0],top:scaledPoint[1]});};$span.setPosition(point);$span.css({"font-size":this.currentStyle["font-size"]});const span=$span[0];_class_private_field_loose_base(this,_labelElements)[_labelElements].add(span);$span.processMath=function(math,force){processMath$1(span,math,force,function(){const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);});};$span.processText=function(text){$span.html(text);const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);};if(latex){$span.processMath(text,false);}else {$span.processText(text);}this._ensureResizeObserver();return $span})};this.svgPath=(points,alreadyScaled)=>{return points.map((point,i)=>{if(point===true){return "z"}const scaled=alreadyScaled?point:this.scalePoint(point);return (i===0?"M":"L")+kmath.KhanMath.bound(scaled[0])+" "+kmath.KhanMath.bound(scaled[1])}).join("")};this.svgParabolaPath=(a,b,c)=>{const computeParabola=function(x){return (a*x+b)*x+c};if(a===0){const points=[[this.bounds().xMin,computeParabola(this.bounds().xMin)],[this.bounds().xMax,computeParabola(this.bounds().xMax)]];return this.svgPath(points)}const xVertex=-b/(2*a);const distToEdge=Math.max(Math.abs(xVertex-this.bounds().xMin),Math.abs(xVertex-this.bounds().xMax));const xPoint=xVertex+distToEdge;const vertex=[xVertex,computeParabola(xVertex)];const point=[xPoint,computeParabola(xPoint)];const control=[vertex[0],vertex[1]-(point[1]-vertex[1])];const dx=Math.abs(vertex[0]-point[0]);const left=[vertex[0]-dx,point[1]];const right=[vertex[0]+dx,point[1]];const points=[left,control,right].map(this.scalePoint);const values=points.flat().map(kmath.KhanMath.bound);return "M"+values[0]+","+values[1]+" Q"+values[2]+","+values[3]+" "+values[4]+","+values[5]};this.svgSinusoidPath=(a,b,c,d)=>{const quarterPeriod=Math.abs(Math.PI/(2*b));const computeSine=function(x){return a*Math.sin(b*x-c)+d};const computeDerivative=function(x){return a*b*Math.cos(c-b*x)};const coordsForOffset=(initial,i)=>{const x0=initial+quarterPeriod*i;const x1=x0+quarterPeriod;const xCoords=[x0,x0*2/3+x1*1/3,x0*1/3+x1*2/3,x1];const yCoords=[computeSine(x0),computeSine(x0)+computeDerivative(x0)*(x1-x0)/3,computeSine(x1)-computeDerivative(x1)*(x1-x0)/3,computeSine(x1)];const points=kmath.vector.zip(xCoords,yCoords);return points.map(this.scalePoint)};const extent=this.bounds().width();const numQuarterPeriods=Math.ceil(extent/quarterPeriod)+1;let initial=c/b;const distToEdge=initial-this.bounds().xMin;initial-=quarterPeriod*Math.ceil(distToEdge/quarterPeriod);let coords=coordsForOffset(initial,0);let path="M"+coords[0][0]+","+coords[0][1]+" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];for(let i=1;i<numQuarterPeriods;i++){coords=coordsForOffset(initial,i);path+=" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];}return path};this.scalePoint=point=>{return this.drawingTransform().scalePoint(point)};this.scaleVector=point=>{return this.drawingTransform().scaleVector(point)};this.unscalePoint=point=>{return this.drawingTransform().unscalePoint(point)};this.unscaleVector=point=>{return this.drawingTransform().unscaleVector(point)};this.el=el;$__default.default(el).css("position","relative");this.raphael=Raphael$1(el);$__default.default(el).attr("aria-hidden","true");$__default.default(el).children("div").css("position","absolute");}};const labelDirections={center:[-0.5,-0.5],above:[-0.5,-1],"above right":[0,-1],right:[0,-0.5],"below right":[0,0],below:[-0.5,0],"below left":[-1,0],left:[-1,-0.5],"above left":[-1,-1]};function normalizeRange(range){function normalizeInterval(magnitude){if(typeof magnitude==="number"){return [-magnitude,magnitude]}else {return magnitude}}function getXAndYRanges(range){if(Array.isArray(range)){return range}else {return [range,range]}}if(range==null){return range}const[xRange,yRange]=getXAndYRanges(range);return [normalizeInterval(xRange),normalizeInterval(yRange)]}function toPair(x){if(Array.isArray(x)){return x}return [x,x]}const SVG_SPECIFIC_STYLE_MASK={"stroke-width":null};const setLabelMargins=function(span,size){if(document.fonts?.status==="loading"){document.fonts.ready.then(()=>applyLabelMargins(span,size));return}applyLabelMargins(span,size);};const applyLabelMargins=function(span,size){const $span=$__default.default(span);const direction=$span.data("labelDirection");let[width,height]=size;if(width===0&&height===0){[width,height]=[1,1];Log.log("Label size was 0x0 in graphie.js; using 1x1 instead");}$span.css("visibility","");if(typeof direction==="number"){const x=Math.cos(direction);const y=Math.sin(direction);const scale=Math.min(width/2/Math.abs(x),height/2/Math.abs(y));$span.css({marginLeft:-width/2+x*scale,marginTop:-height/2-y*scale});if($span.data("originalLabelSize")==null){$span.data("originalLabelSize",[width,height]);}}else {const $svgImage=$span.closest(".svg-image");const $graphie=$span.closest(".graphie");const $container=$svgImage.length>0?$svgImage:$graphie;$container.css("line-height","normal");if($span.data("originalLabelSize")==null){height=span.scrollHeight;$span.data("originalLabelSize",[width,height]);}const widthValues=$container.css(["max-width","width"])??{"max-width":"0px"};const expectedWidth=widthValues["max-width"]!=="none"?widthValues["max-width"]:widthValues["width"];let scale=($container.width()??0)/parseInt(expectedWidth.replace(/px$/,""));if(isNaN(scale)){scale=1;}else if(scale===0){scale=1;}let rawPadding;const storedPadding=$span.data("originalPadding");if(storedPadding!=null){rawPadding=storedPadding;}else {const padding=$span.css("padding")??"0px";const currentPadding=padding!=="none"?padding:"0px";rawPadding=parseInt(currentPadding.replace(/px$/,""));$span.data("originalPadding",rawPadding);}let normalizedWidth=width;let normalizedHeight=height;const imageScale=Number($container.attr("data-scale"));const hasValidImageScale=!Number.isNaN(imageScale)&&imageScale>=0;if(hasValidImageScale){scale=scale*imageScale;const totalPadding=2*rawPadding;normalizedWidth=(width-totalPadding)/imageScale+totalPadding;normalizedHeight=(height-totalPadding)/imageScale+totalPadding;}const newPadding=rawPadding*scale;const multipliers=labelDirections[direction||"center"];const styling={marginLeft:normalizedWidth*multipliers[0]*scale,marginTop:normalizedHeight*multipliers[1]*scale,padding:`${newPadding}px`,fontSize:`${scale*100}%`};$span.css(styling);}};const GraphUtils={Graphie: Graphie$1,createGraphie:function(el){return new Graphie$1(el)},unscaledSvgPath:function(points){if(points[0]===true){return ""}return points.map(function(point,i){if(point===true){return "z"}return (i===0?"M":"L")+point[0]+" "+point[1]}).join("")},getDistance:function(point1,point2){return kmath.point.distanceToPoint(point1,point2)},findAngleDeprecated:function(point1,point2,vertex){if(vertex===undefined){const x=point1[0]-point2[0];const y=point1[1]-point2[1];if(!x&&!y){return 0}return (180+Math.atan2(-y,-x)*180/Math.PI+360)%360}return GraphUtils.findAngleDeprecated(point1,vertex)-GraphUtils.findAngleDeprecated(point2,vertex)},graphs:{}};
|
|
1612
|
+
const{processMath: processMath$1}=Tex$1;function polar$2(r,th){if(typeof r==="number"){r=[r,r];}th=th*Math.PI/180;return [r[0]*Math.cos(th),r[1]*Math.sin(th)]}var _bounds=/*#__PURE__*/_class_private_field_loose_key("_bounds"),_drawingTransform=/*#__PURE__*/_class_private_field_loose_key("_drawingTransform"),_labelElements=/*#__PURE__*/_class_private_field_loose_key("_labelElements"),_resizeObserver=/*#__PURE__*/_class_private_field_loose_key("_resizeObserver");let Graphie$1 = class Graphie{init(options){let scale=options.scale||[40,40];scale=typeof scale==="number"?[scale,scale]:scale;if(options.range==null){throw new perseusCore.PerseusError("range should be specified in graph init",perseusCore.Errors.Internal)}_class_private_field_loose_base(this,_bounds)[_bounds]=new GraphBounds(...options.range);_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]=new DrawingTransform(this.raphael,scale,this.bounds());const[w,h]=this.drawingTransform().canvasDimensions();$__default.default(this.el).css({width:w,height:h});this.range=options.range;this.scale=scale;this.dimensions=[w,h];this.xpixels=w;this.ypixels=h;this.isMobile=options.isMobile??false;return this}graphInit(options){options=options||{};for(const[prop,val]of wonderStuffCore.entries(options)){if(!prop.match(/.*Opacity$/)&&prop!=="range"&&typeof val==="number"){options[prop]=[val,val];}if(prop==="range"||prop==="gridRange"){options[prop]=normalizeRange(options[prop]);}}const range=normalizeRange(options.range||[[-10,10],[-10,10]]);const gridRange=normalizeRange(options.gridRange||range);const scale=options.scale||[20,20];const grid=options.grid!=null?options.grid:true;const gridOpacity=options.gridOpacity||.1;const gridStep=toPair(options.gridStep||[1,1]);const axes=options.axes!=null?options.axes:true;const axisArrows=options.axisArrows||"";const axisOpacity=options.axisOpacity||1;const axisCenter=options.axisCenter||[Math.min(Math.max(range[0][0],0),range[0][1]),Math.min(Math.max(range[1][0],0),range[1][1])];const axisLabels=options.axisLabels!=null?options.axisLabels:false;const ticks=options.ticks!=null?options.ticks:true;const tickStep=options.tickStep||[2,2];const tickLen=options.tickLen||[5,5];const tickOpacity=options.tickOpacity||1;const labels=options.labels||options.labelStep||false;const labelStep=options.labelStep||[1,1];const labelOpacity=options.labelOpacity||1;let unityLabels=options.unityLabels||false;const labelFormat=options.labelFormat||function(a){return a};let xLabelFormat=options.xLabelFormat||labelFormat;let yLabelFormat=options.yLabelFormat||labelFormat;const realRange=[[range[0][0]-(range[0][0]>0?1:0),range[0][1]+(range[0][1]<0?1:0)],[range[1][0]-(range[1][0]>0?1:0),range[1][1]+(range[1][1]<0?1:0)]];if(!Array.isArray(unityLabels)){unityLabels=[unityLabels,unityLabels];}const minusIgnorer=function(lf){return function(a){return (lf(a)+"").replace(/-(\d)/g,"\\llap{-}$1")}};xLabelFormat=minusIgnorer(xLabelFormat);yLabelFormat=minusIgnorer(yLabelFormat);this.init({range:realRange,scale:scale,isMobile:options.isMobile});if(grid){this.grid(gridRange[0],gridRange[1],{stroke:options.isMobile?KhanColors.GRAY_C:"#000000",opacity:options.isMobile?1:gridOpacity,step:gridStep,strokeWidth:options.isMobile?1:2});}if(axes){if(axisArrows==="<->"||axisArrows===true){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:axisOpacity,strokeWidth:options.isMobile?1:2,arrows:"->"},function(){if(range[1][0]<0&&range[1][1]>0){thisGraphie.path([axisCenter,[gridRange[0][0],axisCenter[1]]]);thisGraphie.path([axisCenter,[gridRange[0][1],axisCenter[1]]]);}if(range[0][0]<0&&range[0][1]>0){thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][0]]]);thisGraphie.path([axisCenter,[axisCenter[0],gridRange[1][1]]]);}});}else if(axisArrows==="->"||axisArrows===""){const thisGraphie=this;this.style({stroke:"#000000",opacity:axisOpacity,strokeWidth:2,arrows:axisArrows},function(){thisGraphie.path([[gridRange[0][0],axisCenter[1]],[gridRange[0][1],axisCenter[1]]]);thisGraphie.path([[axisCenter[0],gridRange[1][0]],[axisCenter[0],gridRange[1][1]]]);});}if(axisLabels&&axisLabels.length===2){this.label([gridRange[0][1],axisCenter[1]],axisLabels[0],"right");this.label([axisCenter[0],gridRange[1][1]],axisLabels[1],"above");}}if(ticks){const halfWidthTicks=options.isMobile;const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:tickOpacity,strokeWidth:1},()=>{let step=gridStep[0]*tickStep[0];let len=tickLen[0]/scale[1];let start=gridRange[0][0];let stop=gridRange[0][1];if(range[1][0]<0&&range[1][1]>0){for(let x=step+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}for(let x=-step+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.line([x,-len+axisCenter[1]],[x,halfWidthTicks?0:len+axisCenter[1]]);}}}step=gridStep[1]*tickStep[1];len=tickLen[1]/scale[0];start=gridRange[1][0];stop=gridRange[1][1];if(range[0][0]<0&&range[0][1]>0){for(let y=step+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}for(let y=-step+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){this.line([-len+axisCenter[0],y],[halfWidthTicks?0:len+axisCenter[0],y]);}}}});}if(labels){const thisGraphie=this;this.style({stroke:options.isMobile?KhanColors.GRAY_G:"#000000",opacity:options.isMobile?1:labelOpacity},function(){let step=gridStep[0]*tickStep[0]*labelStep[0];let start=gridRange[0][0];let stop=gridRange[0][1];const xAxisPosition=axisCenter[0]<0?"above":"below";const yAxisPosition=axisCenter[0]<0?"right":"left";const xShowZero=axisCenter[0]===0&&axisCenter[1]!==0;const yShowZero=axisCenter[0]!==0&&axisCenter[1]===0;const axisOffCenter=axisCenter[0]!==0||axisCenter[1]!==0;const showUnityX=unityLabels[0]||axisOffCenter;const showUnityY=unityLabels[1]||axisOffCenter;for(let x=(xShowZero?0:step)+axisCenter[0];x<=stop;x+=step){if(x<stop||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}for(let x=-step*(showUnityX?1:2)+axisCenter[0];x>=start;x-=step){if(x>start||!axisArrows){thisGraphie.label([x,axisCenter[1]],xLabelFormat(x),xAxisPosition);}}step=gridStep[1]*tickStep[1]*labelStep[1];start=gridRange[1][0];stop=gridRange[1][1];for(let y=(yShowZero?0:step)+axisCenter[1];y<=stop;y+=step){if(y<stop||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}for(let y=-step*(showUnityY?1:2)+axisCenter[1];y>=start;y-=step){if(y>start||!axisArrows){thisGraphie.label([axisCenter[0],y],yLabelFormat(y),yAxisPosition);}}});}}drawingTransform(){if(_class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]==null){throw new Error("Can't get drawingTransform of an uninitialized Graphie")}return _class_private_field_loose_base(this,_drawingTransform)[_drawingTransform]}bounds(){if(_class_private_field_loose_base(this,_bounds)[_bounds]==null){throw new Error("Can't get bounds of an uninitialized Graphie")}return _class_private_field_loose_base(this,_bounds)[_bounds]}style(attrs,fn){const processed=this.processAttributes(attrs);if(typeof fn==="function"){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...processed};const result=fn.call(this);this.currentStyle=oldStyle;return result}Object.assign(this.currentStyle,processed);}grid(xr,yr,style){return this.withStyle(style,()=>{const step=this.currentStyle.step||[1,1];const set=this.raphael.set();let x=step[0]*Math.ceil(xr[0]/step[0]);for(;x<=xr[1];x+=step[0]){set.push(this.line([x,yr[0]],[x,yr[1]]));}let y=step[1]*Math.ceil(yr[0]/step[1]);for(;y<=yr[1];y+=step[1]){set.push(this.line([xr[0],y],[xr[1],y]));}return set})}arc(center,radius,startAngle,endAngle,sector,style){return this.withStyle(style,()=>{startAngle=(startAngle%360+360)%360;endAngle=(endAngle%360+360)%360;const cent=this.scalePoint(center);const radii=this.scaleVector(radius);const startVector=polar$2(radius,startAngle);const endVector=polar$2(radius,endAngle);const round=x=>kmath.number.round(x,6);const startPoint=this.scalePoint([round(center[0]+startVector[0]),round(center[1]+startVector[1])]);const endPoint=this.scalePoint([round(center[0]+endVector[0]),round(center[1]+endVector[1])]);const largeAngle=((endAngle-startAngle)%360+360)%360>180;return this.raphael.path("M"+startPoint.join(" ")+"A"+radii.join(" ")+" 0 "+(largeAngle?1:0)+" 0 "+endPoint.join(" ")+(sector?"L"+cent.join(" ")+"z":""))})}circle(center,radius,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center),...this.scaleVector([radius,radius])))}rect(x,y,width,height,style){return this.withStyle(style,()=>{const corner=this.scalePoint([x,y+height]);const dims=this.scaleVector([width,height]);const elem=this.raphael.rect(...corner.concat(dims));if(this.isMobile){elem.node.style.shapeRendering="crispEdges";}return elem})}ellipse(center,radii,style){return this.withStyle(style,()=>this.raphael.ellipse(...this.scalePoint(center).concat(this.scaleVector(radii))))}fixedEllipse(center,radii,maxScale,padding,style){return this.withStyle(style,()=>{const scaledPoint=this.scalePoint(center);const scaledRadii=this.scaleVector(radii);const width=2*scaledRadii[0]*maxScale+padding;const height=2*scaledRadii[1]*maxScale+padding;const left=scaledPoint[0]-width/2;const top=scaledPoint[1]-height/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px"});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.ellipse(width/2,height/2,scaledRadii[0],scaledRadii[1]);return {wrapper:wrapper,visibleShape:visibleShape}})}unstyledPath(points){const p=this.raphael.path(this.svgPath(points));p.graphiePath=points;return p}path(points,style){return this.withStyle(style,()=>{return this.unstyledPath(points)})}fixedPath(points,center,createPath){points=points.map(this.scalePoint);center=center?this.scalePoint(center):null;createPath=createPath||this.svgPath;const xs=points.map(p=>p[0]);const ys=points.map(p=>p[1]);const pathLeft=Math.min(...xs);const pathRight=Math.max(...xs);const pathTop=Math.min(...ys);const pathBottom=Math.max(...ys);const padding=[4,4];const topLeftOfBoundingBox=[pathLeft,pathTop];points=points.map(function(point){return kmath.vector.add(kmath.vector.subtract(point,topLeftOfBoundingBox),kmath.vector.scale(padding,.5))});const width=pathRight-pathLeft+padding[0];const height=pathBottom-pathTop+padding[1];const left=topLeftOfBoundingBox[0]-padding[0]/2;const top=topLeftOfBoundingBox[1]-padding[1]/2;const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:center?width/2+center[0]+"px "+(height/2+center[1])+"px":null});const localRaphael=Raphael$1(wrapper,width,height);const visibleShape=localRaphael.path(createPath(points));return {wrapper:wrapper,visibleShape:visibleShape}}scaledPath(points,style){return this.withStyle(style,()=>{const p=this.raphael.path(this.svgPath(points,true));p.graphiePath=points;return p})}line(start,end,style){return this.withStyle(style,()=>{const l=this.unstyledPath([start,end]);if(this.isMobile){l.node.style.shapeRendering="crispEdges";}return l})}parabola(a,b,c,style){return this.withStyle(style,()=>this.raphael.path(this.svgParabolaPath(a,b,c)))}fixedLine(start,end,thickness){const padding=[thickness,thickness];start=this.scalePoint(start);end=this.scalePoint(end);const extraOffset=[Math.min(start[0],end[0]),Math.min(start[1],end[1])];start=kmath.vector.add(kmath.vector.subtract(start,extraOffset),kmath.vector.scale(padding,.5));end=kmath.vector.add(kmath.vector.subtract(end,extraOffset),kmath.vector.scale(padding,.5));const left=extraOffset[0]-padding[0]/2;const top=extraOffset[1]-padding[1]/2;const width=Math.abs(start[0]-end[0])+padding[0];const height=Math.abs(start[1]-end[1])+padding[1];const wrapper=document.createElement("div");$__default.default(wrapper).css({position:"absolute",width:width+"px",height:height+"px",left:left+"px",top:top+"px",transformOrigin:start[0]+"px "+start[1]+"px"});const localRaphael=Raphael$1(wrapper,width,height);const path="M"+start[0]+" "+start[1]+" "+"L"+end[0]+" "+end[1];const visibleShape=localRaphael.path(path);visibleShape.graphiePath=[start,end];return {wrapper:wrapper,visibleShape:visibleShape}}sinusoid(a,b,c,d,style){return this.withStyle(style,()=>this.raphael.path(this.svgSinusoidPath(a,b,c,d)))}plotParametric(fn,range,style){return this.withStyle(style,()=>{const clip=xy=>{if(Math.abs(xy[1])>5e5){return [xy[0],Math.min(Math.max(xy[1],-5e5),5e5)]}return xy};const clippedFn=x=>clip(fn(x));const min=range[0];const max=range[1];let step=(max-min)/(this.currentStyle["plot-points"]||800);if(step===0){step=1;}const paths=this.raphael.set();let points=[];let lastY=clippedFn(min)[1];for(let t=min;t<=max;t+=step){const point=clippedFn(t);const y=point[1];if(y>0!==lastY>0&&Math.abs(y-lastY)>2*this.drawingTransform().pixelsPerUnitY()||isNaN(y)){paths.push(this.unstyledPath(points));points=[];}else {points.push(point);}lastY=y;}paths.push(this.unstyledPath(points));return paths})}plot(fn,range,style){return this.withStyle(style,()=>{const min=range[0];const max=range[1];if(!this.currentStyle["plot-points"]){this.currentStyle["plot-points"]=2*(max-min)*this.drawingTransform().pixelsPerUnitX();}const parametricFn=x=>[x,fn(x)];return this.plotParametric(parametricFn,range)})}withStyle(style,fn){const oldStyle=this.currentStyle;this.currentStyle={...this.currentStyle,...this.processAttributes(style)};const result=this.postprocessDrawingResult(fn());this.currentStyle=oldStyle;return result}postprocessDrawingResult(result){const type=result.constructor.prototype;if(type===Raphael$1.el||type===Raphael$1.st){result.attr(this.currentStyle);if(this.currentStyle.arrows){result=this.addArrowheads(result);}}else if(result instanceof $__default.default){result.css({...this.currentStyle,...SVG_SPECIFIC_STYLE_MASK});}return result}addArrowheads(path){const type=path.constructor.prototype;if(type===Raphael$1.el){if(path.type==="path"&&typeof path.arrowheadsDrawn==="undefined"){const w=path.attr("stroke-width");const s=.6+.4*w;const l=path.getTotalLength();const set=this.raphael.set();const head=this.raphael.path(this.isMobile?"M-4,4 C-4,4 -0.25,0 -0.25,0 C-0.25,0 -4,-4 -4,-4":"M-3 4 C-2.75 2.5 0 0.25 0.75 0C0 -0.25 -2.75 -2.5 -3 -4");const end=path.getPointAtLength(l-.4);const almostTheEnd=path.getPointAtLength(l-.75*s);const angle=Math.atan2(end.y-almostTheEnd.y,end.x-almostTheEnd.x)*180/Math.PI;const attrs=path.attr();delete attrs.path;let subpath=path.getSubpath(0,l-.75*s);subpath=this.raphael.path(subpath).attr(attrs);subpath.arrowheadsDrawn=true;path.remove();head.rotate(angle,this.isMobile?1e-5:.75,0).scale(s,s,.75,0).translate(almostTheEnd.x,almostTheEnd.y).attr(attrs).attr({"stroke-linejoin":"round","stroke-linecap":"round"});head.arrowheadsDrawn=true;set.push(subpath);set.push(head);return set}}else if(type===Raphael$1.st){for(let i=0,l=path.items.length;i<l;i++){this.addArrowheads(path.items[i]);}}return path}processAttributes(attrs){const transformers={scale:scale=>{this.drawingTransform().setScale(scale);},clipRect:pair=>{const point=pair[0];const size=pair[1];point[1]+=size[1];return {"clip-rect":this.scalePoint(point).concat(this.scaleVector(size)).join(" ")}},strokeWidth:function(val){return {"stroke-width":parseFloat(val)}},rx:val=>{return {rx:this.scaleVector([val,0])[0]}},ry:val=>{return {ry:this.scaleVector([0,val])[1]}},r:val=>{const scaled=this.scaleVector([val,val]);return {rx:scaled[0],ry:scaled[1]}}};const processed={};Object.entries(attrs||{}).forEach(function([key,value]){const transformer=transformers[key];if(typeof transformer==="function"){Object.assign(processed,transformer(value));}else {const dasherized=String(key).replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase();processed[dasherized]=value;}});return processed}addMouseLayer(options){const localOptions={allowScratchpad:false,...options};const mouselayerZIndex=2;this.mouselayer=Raphael$1(this.el,this.xpixels,this.ypixels);$__default.default(this.mouselayer.canvas).css("z-index",mouselayerZIndex);if(localOptions.onClick||localOptions.onMouseDown||localOptions.onMouseMove||localOptions.onMouseOver||localOptions.onMouseOut){const canvasClickTarget=this.mouselayer.rect(0,0,this.xpixels,this.ypixels).attr({fill:"#000",opacity:0});let isClickingCanvas=false;$__default.default(this.mouselayer.canvas).on("vmousedown",e=>{if(e.target===canvasClickTarget[0]){if(localOptions.onMouseDown){localOptions.onMouseDown(this.getMouseCoord(e));}isClickingCanvas=true;if(localOptions.onMouseMove){const handler=localOptions.onMouseMove;$__default.default(document).on("vmousemove.mouseLayer",e=>{if(isClickingCanvas){e.preventDefault();handler(this.getMouseCoord(e));}});}$__default.default(document).on("vmouseup.mouseLayer",e=>{$__default.default(document).unbind(".mouseLayer");if(isClickingCanvas&&localOptions.onClick){localOptions.onClick(this.getMouseCoord(e));}isClickingCanvas=false;});}});if(localOptions.onMouseOver){const handler=localOptions.onMouseOver;$__default.default(this.mouselayer.canvas).on("vmouseover",e=>{handler(this.getMouseCoord(e));});}if(localOptions.onMouseOut){const handler=localOptions.onMouseOut;$__default.default(this.mouselayer.canvas).on("vmouseout",e=>{handler(this.getMouseCoord(e));});}}this._mouselayerWrapper=document.createElement("div");$__default.default(this._mouselayerWrapper).css({position:"absolute",left:0,top:0,zIndex:mouselayerZIndex});this._visiblelayerWrapper=document.createElement("div");$__default.default(this._visiblelayerWrapper).css({position:"absolute",left:0,top:0});const el=this.el;el.appendChild(this._visiblelayerWrapper);el.appendChild(this._mouselayerWrapper);this.addToMouseLayerWrapper=el=>{this._mouselayerWrapper?.appendChild(el);};this.addToVisibleLayerWrapper=el=>{this._visiblelayerWrapper?.appendChild(el);};}addToMouseLayerWrapper(el){throw new Error("addToMouseLayerWrapper is not ready. Call addMouseLayer() first.")}addToVisibleLayerWrapper(el){throw new Error("addToVisibleLayerWrapper is not ready. Call addMouseLayer() first.")}getMousePx(event){const offset=$__default.default(this.el).offset();const mouseX=event.pageX-offset.left;const mouseY=event.pageY-offset.top;return [mouseX,mouseY]}getMouseCoord(event){return this.unscalePoint(this.getMousePx(event))}_ensureResizeObserver(){if(_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]!=null||typeof ResizeObserver==="undefined"){return}_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=new ResizeObserver(()=>{this._recalculateLabels();});_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver].observe(this.el);}_recalculateLabels(){_class_private_field_loose_base(this,_labelElements)[_labelElements].forEach(span=>{const originalSize=$__default.default(span).data("originalLabelSize");if(originalSize!=null){setLabelMargins(span,originalSize);}});}cleanup(){_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]?.disconnect();_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;_class_private_field_loose_base(this,_labelElements)[_labelElements].clear();}constructor(el){Object.defineProperty(this,_bounds,{writable:true,value:void 0});Object.defineProperty(this,_drawingTransform,{writable:true,value:void 0});Object.defineProperty(this,_labelElements,{writable:true,value:void 0});Object.defineProperty(this,_resizeObserver,{writable:true,value:void 0});_class_private_field_loose_base(this,_labelElements)[_labelElements]=new Set;_class_private_field_loose_base(this,_resizeObserver)[_resizeObserver]=null;this.isMobile=false;this.currentStyle={"stroke-width":2,fill:"none"};this.label=(point,text,direction,arg4,arg5)=>{const style=typeof arg4==="object"?arg4:arg5;const latex=typeof arg4==="boolean"?arg4:true;return this.withStyle(style,()=>{const $span=$__default.default("<span>").addClass("graphie-label");const pad=this.currentStyle["label-distance"];$span.css({position:"absolute",padding:(pad!=null?pad:7)+"px",color:"black"}).data("labelDirection",direction).appendTo(this.el);$span.setPosition=point=>{const scaledPoint=this.scalePoint(point);$span.css({left:scaledPoint[0],top:scaledPoint[1]});};$span.setPosition(point);$span.css({"font-size":this.currentStyle["font-size"]});const span=$span[0];_class_private_field_loose_base(this,_labelElements)[_labelElements].add(span);$span.processMath=function(math,force){processMath$1(span,math,force,function(){const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);});};$span.processText=function(text){$span.html(text);const width=span.scrollWidth;const height=span.scrollHeight;setLabelMargins(span,[width,height]);};if(latex){$span.processMath(text,false);}else {$span.processText(text);}this._ensureResizeObserver();return $span})};this.svgPath=(points,alreadyScaled)=>{return points.map((point,i)=>{if(point===true){return "z"}const scaled=alreadyScaled?point:this.scalePoint(point);return (i===0?"M":"L")+kmath.KhanMath.bound(scaled[0])+" "+kmath.KhanMath.bound(scaled[1])}).join("")};this.svgParabolaPath=(a,b,c)=>{const computeParabola=function(x){return (a*x+b)*x+c};if(a===0){const points=[[this.bounds().xMin,computeParabola(this.bounds().xMin)],[this.bounds().xMax,computeParabola(this.bounds().xMax)]];return this.svgPath(points)}const xVertex=-b/(2*a);const distToEdge=Math.max(Math.abs(xVertex-this.bounds().xMin),Math.abs(xVertex-this.bounds().xMax));const xPoint=xVertex+distToEdge;const vertex=[xVertex,computeParabola(xVertex)];const point=[xPoint,computeParabola(xPoint)];const control=[vertex[0],vertex[1]-(point[1]-vertex[1])];const dx=Math.abs(vertex[0]-point[0]);const left=[vertex[0]-dx,point[1]];const right=[vertex[0]+dx,point[1]];const points=[left,control,right].map(this.scalePoint);const values=points.flat().map(kmath.KhanMath.bound);return "M"+values[0]+","+values[1]+" Q"+values[2]+","+values[3]+" "+values[4]+","+values[5]};this.svgSinusoidPath=(a,b,c,d)=>{const quarterPeriod=Math.abs(Math.PI/(2*b));const computeSine=function(x){return a*Math.sin(b*x-c)+d};const computeDerivative=function(x){return a*b*Math.cos(c-b*x)};const coordsForOffset=(initial,i)=>{const x0=initial+quarterPeriod*i;const x1=x0+quarterPeriod;const xCoords=[x0,x0*2/3+x1*1/3,x0*1/3+x1*2/3,x1];const yCoords=[computeSine(x0),computeSine(x0)+computeDerivative(x0)*(x1-x0)/3,computeSine(x1)-computeDerivative(x1)*(x1-x0)/3,computeSine(x1)];const points=kmath.vector.zip(xCoords,yCoords);return points.map(this.scalePoint)};const extent=this.bounds().width();const numQuarterPeriods=Math.ceil(extent/quarterPeriod)+1;let initial=c/b;const distToEdge=initial-this.bounds().xMin;initial-=quarterPeriod*Math.ceil(distToEdge/quarterPeriod);let coords=coordsForOffset(initial,0);let path="M"+coords[0][0]+","+coords[0][1]+" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];for(let i=1;i<numQuarterPeriods;i++){coords=coordsForOffset(initial,i);path+=" C"+coords[1][0]+","+coords[1][1]+" "+coords[2][0]+","+coords[2][1]+" "+coords[3][0]+","+coords[3][1];}return path};this.scalePoint=point=>{return this.drawingTransform().scalePoint(point)};this.scaleVector=point=>{return this.drawingTransform().scaleVector(point)};this.unscalePoint=point=>{return this.drawingTransform().unscalePoint(point)};this.unscaleVector=point=>{return this.drawingTransform().unscaleVector(point)};this.el=el;$__default.default(el).css("position","relative");this.raphael=Raphael$1(el);$__default.default(el).attr("aria-hidden","true");$__default.default(el).children("div").css("position","absolute");}};const labelDirections={center:[-0.5,-0.5],above:[-0.5,-1],"above right":[0,-1],right:[0,-0.5],"below right":[0,0],below:[-0.5,0],"below left":[-1,0],left:[-1,-0.5],"above left":[-1,-1]};function normalizeRange(range){function normalizeInterval(magnitude){if(typeof magnitude==="number"){return [-magnitude,magnitude]}else {return magnitude}}function getXAndYRanges(range){if(Array.isArray(range)){return range}else {return [range,range]}}if(range==null){return range}const[xRange,yRange]=getXAndYRanges(range);return [normalizeInterval(xRange),normalizeInterval(yRange)]}function toPair(x){if(Array.isArray(x)){return x}return [x,x]}const SVG_SPECIFIC_STYLE_MASK={"stroke-width":null};const setLabelMargins=function(span,size){if(document.fonts?.status==="loading"){document.fonts.ready.then(()=>applyLabelMargins(span,size));return}applyLabelMargins(span,size);};const applyLabelMargins=function(span,size){const $span=$__default.default(span);const direction=$span.data("labelDirection");let[width,height]=size;if(width===0&&height===0){[width,height]=[1,1];Log.log("Label size was 0x0 in graphie.js; using 1x1 instead");}$span.css("visibility","");if(typeof direction==="number"){const x=Math.cos(direction);const y=Math.sin(direction);const scale=Math.min(width/2/Math.abs(x),height/2/Math.abs(y));$span.css({marginLeft:-width/2+x*scale,marginTop:-height/2-y*scale});if($span.data("originalLabelSize")==null){$span.data("originalLabelSize",[width,height]);}}else {const $svgImage=$span.closest(".svg-image");const $graphie=$span.closest(".graphie");const $container=$svgImage.length>0?$svgImage:$graphie;$container.css("line-height","normal");if($span.data("originalLabelSize")==null){height=span.scrollHeight;$span.data("originalLabelSize",[width,height]);}const widthValues=$container.css(["max-width","width"])??{"max-width":"0px"};const expectedWidth=widthValues["max-width"]!=="none"?widthValues["max-width"]:widthValues["width"];let scale=($container.width()??0)/parseInt(expectedWidth.replace(/px$/,""));if(isNaN(scale)){scale=1;}else if(scale===0){scale=1;}let rawPadding;const storedPadding=$span.data("originalPadding");if(storedPadding!=null){rawPadding=storedPadding;}else {const padding=$span.css("padding")??"0px";const currentPadding=padding!=="none"?padding:"0px";rawPadding=parseInt(currentPadding.replace(/px$/,""));$span.data("originalPadding",rawPadding);}let normalizedWidth=width;let normalizedHeight=height;const imageScale=Number($container.attr("data-scale"));const hasValidImageScale=!Number.isNaN(imageScale)&&imageScale>=0;if(hasValidImageScale){scale=scale*imageScale;const totalPadding=2*rawPadding;normalizedWidth=(width-totalPadding)/imageScale+totalPadding;normalizedHeight=(height-totalPadding)/imageScale+totalPadding;}const newPadding=rawPadding*scale;const multipliers=labelDirections[direction||"center"];const styling={marginLeft:normalizedWidth*multipliers[0]*scale,marginTop:normalizedHeight*multipliers[1]*scale,padding:`${newPadding}px`,fontSize:`${scale*100}%`};$span.css(styling);}};const GraphUtils={Graphie: Graphie$1,createGraphie:function(el){return new Graphie$1(el)},unscaledSvgPath:function(points){if(points[0]===true){return ""}return points.map(function(point,i){if(point===true){return "z"}return (i===0?"M":"L")+point[0]+" "+point[1]}).join("")},getDistance:function(point1,point2){return kmath.point.distanceToPoint(point1,point2)},findAngleDeprecated:function(point1,point2,vertex){if(vertex===undefined){const x=point1[0]-point2[0];const y=point1[1]-point2[1];if(!x&&!y){return 0}return (180+Math.atan2(-y,-x)*180/Math.PI+360)%360}return GraphUtils.findAngleDeprecated(point1,vertex)-GraphUtils.findAngleDeprecated(point2,vertex)},graphs:{}};
|
|
1616
1613
|
|
|
1617
1614
|
(function($,window1,document1,undefined$1){if(typeof $==="undefined"){return}var dataPropertyName="virtualMouseBindings",touchTargetPropertyName="virtualTouchID",virtualEventNames="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),touchEventProps="clientX clientY pageX pageY screenX screenY".split(" "),mouseHookProps=$.event.mouseHooks?$.event.mouseHooks.props:[],mouseEventProps=$.event.props.concat(mouseHookProps),activeDocHandlers={},resetTimerID=0,startX=0,startY=0,didScroll=false,clickBlockList=[],blockMouseTriggers=false,blockTouchTriggers=false,eventCaptureSupported="addEventListener"in document1,$document=$(document1),nextTouchID=1,lastTouchID=0;$.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500};function getNativeEvent(event){while(event&&typeof event.originalEvent!=="undefined"){event=event.originalEvent;}return event}function createVirtualEvent(event,eventType){var t=event.type,oe,props,ne,prop,ct,touch,i,j,len;event=$.Event(event);event.type=eventType;oe=event.originalEvent;props=$.event.props;if(t.search(/mouse/)>-1){props=mouseEventProps;}if(oe){for(i=props.length,prop;i;){prop=props[--i];event[prop]=oe[prop];}}if(t.search(/mouse(down|up)|click/)>-1&&!event.which){event.which=1;}if(t.search(/^touch/)!==-1){ne=getNativeEvent(oe);t=ne.touches;ct=ne.changedTouches;touch=t&&t.length?t[0]:ct&&ct.length?ct[0]:undefined$1;if(touch){for(j=0,len=touchEventProps.length;j<len;j++){prop=touchEventProps[j];event[prop]=touch[prop];}}}return event}function getVirtualBindingFlags(element){var flags={},b,k;while(element){b=$.data(element,dataPropertyName);for(k in b){if(b[k]){flags[k]=flags.hasVirtualBinding=true;}}element=element.parentNode;}return flags}function getClosestElementWithVirtualBinding(element,eventType){var b;while(element){b=$.data(element,dataPropertyName);if(b&&(!eventType||b[eventType])){return element}element=element.parentNode;}return null}function enableTouchBindings(){blockTouchTriggers=false;}function disableTouchBindings(){blockTouchTriggers=true;}function enableMouseBindings(){lastTouchID=0;clickBlockList.length=0;blockMouseTriggers=false;disableTouchBindings();}function disableMouseBindings(){enableTouchBindings();}function startResetTimer(){clearResetTimer();resetTimerID=setTimeout(function(){resetTimerID=0;enableMouseBindings();},$.vmouse.resetTimerDuration);}function clearResetTimer(){if(resetTimerID){clearTimeout(resetTimerID);resetTimerID=0;}}function triggerVirtualEvent(eventType,event,flags){var ve;if(flags&&flags[eventType]||!flags&&getClosestElementWithVirtualBinding(event.target,eventType)){ve=createVirtualEvent(event,eventType);$(event.target).trigger(ve);}return ve}function mouseEventCallback(event){var touchID=$.data(event.target,touchTargetPropertyName);if(!blockMouseTriggers&&(!lastTouchID||lastTouchID!==touchID)){var ve=triggerVirtualEvent("v"+event.type,event);if(ve){if(ve.isDefaultPrevented()){event.preventDefault();}if(ve.isPropagationStopped()){event.stopPropagation();}if(ve.isImmediatePropagationStopped()){event.stopImmediatePropagation();}}}}function handleTouchStart(event){var touches=getNativeEvent(event).touches,target,flags;if(touches&&touches.length===1){target=event.target;flags=getVirtualBindingFlags(target);if(flags.hasVirtualBinding){lastTouchID=nextTouchID++;$.data(target,touchTargetPropertyName,lastTouchID);clearResetTimer();disableMouseBindings();didScroll=false;var t=getNativeEvent(event).touches[0];startX=t.pageX;startY=t.pageY;triggerVirtualEvent("vmouseover",event,flags);triggerVirtualEvent("vmousedown",event,flags);}}}function handleScroll(event){if(blockTouchTriggers){return}if(!didScroll){triggerVirtualEvent("vmousecancel",event,getVirtualBindingFlags(event.target));}didScroll=true;startResetTimer();}function handleTouchMove(event){if(blockTouchTriggers){return}var t=getNativeEvent(event).touches[0],didCancel=didScroll,moveThreshold=$.vmouse.moveDistanceThreshold,didScroll=didScroll||Math.abs(t.pageX-startX)>moveThreshold||Math.abs(t.pageY-startY)>moveThreshold,flags=getVirtualBindingFlags(event.target);if(didScroll&&!didCancel){triggerVirtualEvent("vmousecancel",event,flags);}triggerVirtualEvent("vmousemove",event,flags);startResetTimer();}function handleTouchEnd(event){if(blockTouchTriggers){return}disableTouchBindings();var flags=getVirtualBindingFlags(event.target),t;triggerVirtualEvent("vmouseup",event,flags);if(!didScroll){var ve=triggerVirtualEvent("vclick",event,flags);if(ve&&ve.isDefaultPrevented()){t=getNativeEvent(event).changedTouches[0];clickBlockList.push({touchID:lastTouchID,x:t.clientX,y:t.clientY});blockMouseTriggers=true;}}triggerVirtualEvent("vmouseout",event,flags);didScroll=false;startResetTimer();}function hasVirtualBindings(ele){var bindings=$.data(ele,dataPropertyName),k;if(bindings){for(k in bindings){if(bindings[k]){return true}}}return false}function dummyMouseHandler(){}function getSpecialEventObject(eventType){var realType=eventType.substr(1);return {setup:function(data,namespace){if(!hasVirtualBindings(this)){$.data(this,dataPropertyName,{});}var bindings=$.data(this,dataPropertyName);bindings[eventType]=true;activeDocHandlers[eventType]=(activeDocHandlers[eventType]||0)+1;if(activeDocHandlers[eventType]===1){$document.bind(realType,mouseEventCallback);}$(this).bind(realType,dummyMouseHandler);if(eventCaptureSupported){activeDocHandlers["touchstart"]=(activeDocHandlers["touchstart"]||0)+1;if(activeDocHandlers["touchstart"]===1){$document.bind("touchstart",handleTouchStart).bind("touchend",handleTouchEnd).bind("touchmove",handleTouchMove).bind("scroll",handleScroll);}}},teardown:function(data,namespace){--activeDocHandlers[eventType];if(!activeDocHandlers[eventType]){$document.unbind(realType,mouseEventCallback);}if(eventCaptureSupported){--activeDocHandlers["touchstart"];if(!activeDocHandlers["touchstart"]){$document.unbind("touchstart",handleTouchStart).unbind("touchmove",handleTouchMove).unbind("touchend",handleTouchEnd).unbind("scroll",handleScroll);}}var $this=$(this),bindings=$.data(this,dataPropertyName);if(bindings){bindings[eventType]=false;}$this.unbind(realType,dummyMouseHandler);if(!hasVirtualBindings(this)){$this.removeData(dataPropertyName);}}}}for(var i=0;i<virtualEventNames.length;i++){$.event.special[virtualEventNames[i]]=getSpecialEventObject(virtualEventNames[i]);}if(eventCaptureSupported){document1.addEventListener("click",function(e){var cnt=clickBlockList.length,target=e.target,x,y,ele,i,o;if(cnt){x=e.clientX;y=e.clientY;threshold=$.vmouse.clickDistanceThreshold;ele=target;while(ele){for(i=0;i<cnt;i++){o=clickBlockList[i];if(ele===target&&Math.abs(o.x-x)<threshold&&Math.abs(o.y-y)<threshold||$.data(ele,touchTargetPropertyName)===o.touchID){e.preventDefault();e.stopPropagation();return}}ele=ele.parentNode;}}},true);}})($__default.default,window,document);
|
|
1618
1615
|
|
|
@@ -1628,15 +1625,15 @@ const DEFAULT_OPTIONS$1={maxScale:1,mouselayer:false,shadow:false,disableMouseEv
|
|
|
1628
1625
|
|
|
1629
1626
|
const DEFAULT_OPTIONS={thickness:2,mouselayer:false};class WrappedLine extends WrappedDrawing{getMouseTarget(){return this.wrapper}moveTo(start,end){const scaledStart=this.graphie.scalePoint(start);const scaledEnd=this.graphie.scalePoint(end);const polarDiff=kmath.vector.polarDegFromCart(kmath.vector.subtract(scaledEnd,scaledStart));const lineLength=polarDiff[0];const angle=kmath.KhanMath.bound(polarDiff[1]);const delta=kmath.vector.subtract(scaledStart,this.initialPoint);const scale=kmath.KhanMath.bound(lineLength/this.initialLength);const do3dTransform=InteractiveUtil.getCanUse3dTransform();const transformation="translateX("+delta[0]+"px) "+"translateY("+delta[1]+"px) "+(do3dTransform?" translateZ(0)":"")+"rotate("+angle+"deg) "+"scaleX("+scale+") scaleY(1)";this.transform(transformation);}constructor(graphie,start,end,options){const initialStart=[graphie.range[0][0],0];const initialEnd=[graphie.range[0][1],0];const initialPoint=graphie.scalePoint(initialStart);super(graphie,initialPoint);options=___default.default.extend({},DEFAULT_OPTIONS,options);const fixedLine=graphie.fixedLine(initialStart,initialEnd,options.thickness);this.wrapper=fixedLine.wrapper;this.visibleShape=fixedLine.visibleShape;if(options.interactiveKindForTesting){this.wrapper.setAttribute("data-interactive-kind-for-testing",options.interactiveKindForTesting);}this.visibleShape.attr(options.normalStyle);this.initialPoint=initialPoint;this.initialLength=kmath.point.distanceToPoint(graphie.scalePoint(initialStart),graphie.scalePoint(initialEnd));if(options.mouselayer){this.wrapper.style.touchAction="none";this.graphie.addToMouseLayerWrapper(this.wrapper);}else {this.graphie.addToVisibleLayerWrapper(this.wrapper);}this.moveTo(start,end);}}
|
|
1630
1627
|
|
|
1631
|
-
const{clockwise: clockwise$3,reverseVector: reverseVector$1}=kmath.geometry;function scaledDistanceFromAngle(angle){const a=3.51470560176242*20;const b=.5687298702748785*20;const c=-0.037587715462826674;return (a-b)*Math.exp(c*angle)+b}function scaledPolarRad(radius,radians){return [radius*Math.cos(radians),radius*Math.sin(radians)*-1]}function scaledPolarDeg(radius,degrees){const radians=degrees*Math.PI/180;return scaledPolarRad(radius,radians)}let dragging=false;const InteractiveUtils={bogusShape:{animate:function(){},attr:function(){},remove:function(){}}};___default.default.extend(GraphUtils.Graphie.prototype,{labelAngle:function(options){const graphie=this;___default.default.defaults(options,{point1:[0,0],vertex:[0,0],point3:[0,0],label:null,numArcs:1,showRightAngleMarker:true,pushOut:0,clockwise:false,style:{}});let text=options.text===undefined?"":options.text;const vertex=options.vertex;const sVertex=graphie.scalePoint(vertex);let p1;let p3;if(options.clockwise){p1=options.point1;p3=options.point3;}else {p1=options.point3;p3=options.point1;}const startAngle=GraphUtils.findAngleDeprecated(p1,vertex);const endAngle=GraphUtils.findAngleDeprecated(p3,vertex);const angle=(endAngle+360-startAngle)%360;const halfAngle=(startAngle+angle/2)%360;const sPadding=5*options.pushOut;let sRadius=sPadding+scaledDistanceFromAngle(angle);const temp=[];if(Math.abs(angle-90)<1e-9&&options.showRightAngleMarker){const v1=kmath.vector.add(sVertex,scaledPolarDeg(sRadius,startAngle));const v2=kmath.vector.add(sVertex,scaledPolarDeg(sRadius,endAngle));sRadius*=Math.SQRT2;const v3=kmath.vector.add(sVertex,scaledPolarDeg(sRadius,halfAngle));___default.default.each([v1,v2],function(v){temp.push(graphie.scaledPath([v,v3],options.style));});}else {___default.default.times(options.numArcs,function(i){temp.push(graphie.arc(vertex,graphie.unscaleVector(sRadius),startAngle,endAngle,options.style));sRadius+=3;});}if(text){const match=text.match(/\$deg(\d)?/);if(match){const precision=match[1]||1;text=text.replace(match[0],kmath.KhanMath.toFixedApprox(angle,precision)+"^{\\circ}");}const sOffset=scaledPolarDeg(sRadius+15,halfAngle);const sPosition=kmath.vector.add(sVertex,sOffset);const position=graphie.unscalePoint(sPosition);if(options.label){options.label.setPosition(position);options.label.processMath(text,true);}else {graphie.label(position,text,"center",options.style);}}return temp},labelSide:function(options){const graphie=this;___default.default.defaults(options,{point1:[0,0],point2:[0,0],label:null,text:"",numTicks:0,numArrows:0,clockwise:false,style:{}});let p1;let p2;if(options.clockwise){p1=options.point1;p2=options.point2;}else {p1=options.point2;p2=options.point1;}const midpoint=[(p1[0]+p2[0])/2,(p1[1]+p2[1])/2];const sMidpoint=graphie.scalePoint(midpoint);const parallelAngle=Math.atan2(p2[1]-p1[1],p2[0]-p1[0]);const perpendicularAngle=parallelAngle+Math.PI/2;const temp=[];let sCumulativeOffset=0;if(options.numTicks){const n=options.numTicks;const sSpacing=5;const sHeight=5;const style=___default.default.extend({},options.style,{strokeWidth:2});___default.default.times(n,function(i){const sOffset=sSpacing*(i-(n-1)/2);const sOffsetVector=scaledPolarRad(sOffset,parallelAngle);const sHeightVector=scaledPolarRad(sHeight,perpendicularAngle);const sPath=[kmath.vector.add(sMidpoint,sOffsetVector,sHeightVector),kmath.vector.add(sMidpoint,sOffsetVector,reverseVector$1(sHeightVector))];temp.push(graphie.scaledPath(sPath,style));});sCumulativeOffset+=sSpacing*(n-1)+15;}if(options.numArrows){const n=options.numArrows;const start=[p1,p2].sort(function(a,b){if(a[1]===b[1]){return a[0]-b[0]}return a[1]-b[1]})[0];const sStart=graphie.scalePoint(start);const style=___default.default.extend({},options.style,{arrows:"->",strokeWidth:2});const sSpacing=5;___default.default.times(n,function(i){const sOffset=sCumulativeOffset+sSpacing*i;let sOffsetVector=scaledPolarRad(sOffset,parallelAngle);if(start!==p1){sOffsetVector=reverseVector$1(sOffsetVector);}const sEnd=kmath.vector.add(sMidpoint,sOffsetVector);temp.push(graphie.scaledPath([sStart,sEnd],style));});}let text=options.text;if(text){const match=text.match(/\$len(\d)?/);if(match){const distance=GraphUtils.getDistance(p1,p2);const precision=match[1]||1;text=text.replace(match[0],kmath.KhanMath.toFixedApprox(distance,precision));}const sOffset=20;const sOffsetVector=scaledPolarRad(sOffset,perpendicularAngle);const sPosition=kmath.vector.add(sMidpoint,sOffsetVector);const position=graphie.unscalePoint(sPosition);if(options.label){options.label.setPosition(position);options.label.processMath(text,true);}else {graphie.label(position,text,"center",options.style);}}return temp},labelVertex:function(options){const graphie=this;___default.default.defaults(options,{point1:null,vertex:[0,0],point3:null,label:null,text:"",clockwise:false,style:{}});if(!options.text){return}const vertex=options.vertex;const sVertex=graphie.scalePoint(vertex);let p1;let p3;if(options.clockwise){p1=options.point1;p3=options.point3;}else {p1=options.point3;p3=options.point1;}let angle=135;let halfAngle;if(p1&&p3){const startAngle=GraphUtils.findAngleDeprecated(p1,vertex);const endAngle=GraphUtils.findAngleDeprecated(p3,vertex);angle=(endAngle+360-startAngle)%360;halfAngle=(startAngle+angle/2+180)%360;}else if(p1){const parallelAngle=GraphUtils.findAngleDeprecated(vertex,p1);halfAngle=parallelAngle+90;}else if(p3){const parallelAngle=GraphUtils.findAngleDeprecated(p3,vertex);halfAngle=parallelAngle+90;}else {halfAngle=135;}const sRadius=10+scaledDistanceFromAngle(360-angle);const sOffsetVector=scaledPolarDeg(sRadius,halfAngle);const sPosition=kmath.vector.add(sVertex,sOffsetVector);const position=graphie.unscalePoint(sPosition);if(options.label){options.label.setPosition(position);options.label.processMath(options.text,true);}else {graphie.label(position,options.text,"center",options.style);}},addMovablePoint:function(options){const movablePoint=$__default.default.extend(true,{graph:this,coord:[0,0],snapX:0,snapY:0,pointSize:4,highlight:false,dragging:false,visible:true,bounded:true,constraints:{fixed:false,constrainX:false,constrainY:false,fixedAngle:{},fixedDistance:{}},lineStarts:[],lineEnds:[],polygonVertices:[],normalStyle:{},highlightStyle:{fill:KhanColors.INTERACTING,stroke:KhanColors.INTERACTING},labelStyle:{color:KhanColors.INTERACTIVE},vertexLabel:"",mouseTarget:null},options);const normalColor=movablePoint.constraints.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;movablePoint.normalStyle=___default.default.extend({},{fill:normalColor,stroke:normalColor},options.normalStyle);if(options.coordX!==undefined){movablePoint.coord[0]=options.coordX;}if(options.coordY!==undefined){movablePoint.coord[1]=options.coordY;}const graph=movablePoint.graph;const applySnapAndConstraints=function(coord){if(movablePoint.visible&&movablePoint.bounded&&!movablePoint.constraints.fixed){coord=graph.constrainToBounds(coord,10);}let coordX=coord[0];let coordY=coord[1];if(movablePoint.snapX!==0){coordX=Math.round(coordX/movablePoint.snapX)*movablePoint.snapX;}if(movablePoint.snapY!==0){coordY=Math.round(coordY/movablePoint.snapY)*movablePoint.snapY;}if(movablePoint.constraints.fixedDistance.snapPoints){const mouse=graph.scalePoint(coord);let mouseX=mouse[0];let mouseY=mouse[1];const snapRadians=2*Math.PI/movablePoint.constraints.fixedDistance.snapPoints;const radius=movablePoint.constraints.fixedDistance.dist;const centerCoord=movablePoint.constraints.fixedDistance.point;const centerX=(centerCoord[0]-graph.range[0][0])*graph.scale[0];const centerY=(-centerCoord[1]+graph.range[1][1])*graph.scale[1];let mouseXrel=mouseX-centerX;let mouseYrel=-mouseY+centerY;let radians=Math.atan(mouseYrel/mouseXrel);const outsideArcTanRange=mouseXrel<0;if(outsideArcTanRange){radians+=Math.PI;}radians=Math.round(radians/snapRadians)*snapRadians;mouseXrel=radius*Math.cos(radians);mouseYrel=radius*Math.sin(radians);mouseX=mouseXrel+centerX;mouseY=-mouseYrel+centerY;coordX=kmath.KhanMath.roundTo(5,mouseX/graph.scale[0]+graph.range[0][0]);coordY=kmath.KhanMath.roundTo(5,graph.range[1][1]-mouseY/graph.scale[1]);}const result=movablePoint.applyConstraint([coordX,coordY]);return result};movablePoint.applyConstraint=function(coord,extraConstraints,override){let newCoord=coord.slice();const constraints={};if(override){$__default.default.extend(constraints,{fixed:false,constrainX:false,constrainY:false,fixedAngle:{},fixedDistance:{}},extraConstraints);}else {$__default.default.extend(constraints,this.constraints,extraConstraints);}if(constraints.constrainX){newCoord=[this.coord[0],coord[1]];}else if(constraints.constrainY){newCoord=[coord[0],this.coord[1]];}else if(typeof constraints.fixedAngle.angle==="number"&&typeof constraints.fixedDistance.dist==="number"){const vertex=constraints.fixedAngle.vertex.coord||constraints.fixedAngle.vertex;const ref=constraints.fixedAngle.ref.coord||constraints.fixedAngle.ref;const distPoint=constraints.fixedDistance.point.coord||constraints.fixedDistance.point;const constrainedAngle=(constraints.fixedAngle.angle+GraphUtils.findAngleDeprecated(ref,vertex))*Math.PI/180;const length=constraints.fixedDistance.dist;newCoord[0]=length*Math.cos(constrainedAngle)+distPoint[0];newCoord[1]=length*Math.sin(constrainedAngle)+distPoint[1];}else if(typeof constraints.fixedAngle.angle==="number"){const vertex=constraints.fixedAngle.vertex.coord||constraints.fixedAngle.vertex;const ref=constraints.fixedAngle.ref.coord||constraints.fixedAngle.ref;const constrainedAngle=(constraints.fixedAngle.angle+GraphUtils.findAngleDeprecated(ref,vertex))*Math.PI/180;const angle=GraphUtils.findAngleDeprecated(coord,vertex)*Math.PI/180;const distance=GraphUtils.getDistance(coord,vertex);let length=distance*Math.cos(constrainedAngle-angle);length=length<1?1:length;newCoord[0]=length*Math.cos(constrainedAngle)+vertex[0];newCoord[1]=length*Math.sin(constrainedAngle)+vertex[1];}else if(typeof constraints.fixedDistance.dist==="number"){const distPoint=constraints.fixedDistance.point.coord||constraints.fixedDistance.point;let angle=GraphUtils.findAngleDeprecated(coord,distPoint);const length=constraints.fixedDistance.dist;angle=angle*Math.PI/180;newCoord[0]=length*Math.cos(angle)+distPoint[0];newCoord[1]=length*Math.sin(angle)+distPoint[1];}else if(constraints.fixed){newCoord=movablePoint.coord;}return newCoord};movablePoint.coord=applySnapAndConstraints(movablePoint.coord);const highlightScale=2;if(movablePoint.visible){graph.style(movablePoint.normalStyle,function(){const radii=[movablePoint.pointSize/graph.scale[0],movablePoint.pointSize/graph.scale[1]];const options={maxScale:highlightScale,padding:2};movablePoint.visibleShape=new WrappedEllipse(graph,movablePoint.coord,radii,options);movablePoint.visibleShape.attr(___default.default.omit(movablePoint.normalStyle,"scale"));movablePoint.visibleShape.toFront();});}movablePoint.normalStyle.scale=1;movablePoint.highlightStyle.scale=highlightScale;if(movablePoint.vertexLabel){movablePoint.labeledVertex=this.label([0,0],"","center",movablePoint.labelStyle);}movablePoint.drawLabel=function(){if(movablePoint.vertexLabel){movablePoint.graph.labelVertex({vertex:movablePoint.coord,label:movablePoint.labeledVertex,text:movablePoint.vertexLabel,style:movablePoint.labelStyle});}};movablePoint.drawLabel();movablePoint.grab=function(offset){offset=offset||[0,0];$__default.default(document).bind("vmousemove.point vmouseup.point",function(event){event.preventDefault();movablePoint.dragging=true;dragging=true;let coord=kmath.vector.add(graph.getMouseCoord(event),offset);coord=applySnapAndConstraints(coord);let coordX=coord[0];let coordY=coord[1];let mouseX;let mouseY;if(event.type==="vmousemove"){let doMove=true;if(___default.default.isFunction(movablePoint.onMove)){const result=movablePoint.onMove(coordX,coordY);if(result===false){doMove=false;}if(___default.default.isArray(result)){coordX=result[0];coordY=result[1];}}mouseX=(coordX-graph.range[0][0])*graph.scale[0];mouseY=(-coordY+graph.range[1][1])*graph.scale[1];if(doMove){const point=graph.unscalePoint([mouseX,mouseY]);movablePoint.visibleShape.moveTo(point);movablePoint.mouseTarget.moveTo(point);movablePoint.coord=[coordX,coordY];movablePoint.updateLineEnds();$__default.default(movablePoint).trigger("move");}movablePoint.drawLabel();}else if(event.type==="vmouseup"){$__default.default(document).unbind(".point");movablePoint.dragging=false;dragging=false;if(___default.default.isFunction(movablePoint.onMoveEnd)){const result=movablePoint.onMoveEnd(coordX,coordY);if(___default.default.isArray(result)){coordX=result[0];coordY=result[1];mouseX=(coordX-graph.range[0][0])*graph.scale[0];mouseY=(-coordY+graph.range[1][1])*graph.scale[1];const point=graph.unscalePoint([mouseX,mouseY]);movablePoint.visibleShape.moveTo(point);movablePoint.mouseTarget.moveTo(point);movablePoint.coord=[coordX,coordY];}}if(!movablePoint.highlight){movablePoint.visibleShape.animate(movablePoint.normalStyle,50);if(movablePoint.onUnhighlight){movablePoint.onUnhighlight();}}}});};if(movablePoint.visible&&!movablePoint.constraints.fixed){if(!movablePoint.mouseTarget){const radii=graph.unscaleVector(16);const options={mouselayer:true,padding:0,disableMouseEventsOnWrapper:true,interactiveKindForTesting:"movable-point"};movablePoint.mouseTarget=new WrappedEllipse(graph,movablePoint.coord,radii,options);movablePoint.mouseTarget.attr({fill:"#000",opacity:0});}const $mouseTarget=$__default.default(movablePoint.mouseTarget.getMouseTarget());$mouseTarget.css("cursor","move");$mouseTarget.bind("vmousedown vmouseover vmouseout",function(event){if(event.type==="vmouseover"){movablePoint.highlight=true;if(!dragging){movablePoint.visibleShape.animate(movablePoint.highlightStyle,50);if(movablePoint.onHighlight){movablePoint.onHighlight();}}}else if(event.type==="vmouseout"){movablePoint.highlight=false;if(!movablePoint.dragging&&!dragging){movablePoint.visibleShape.animate(movablePoint.normalStyle,50);if(movablePoint.onUnhighlight){movablePoint.onUnhighlight();}}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();const startCoord=movablePoint.coord;const startMouseCoord=graph.getMouseCoord(event);const isMouse=!("ontouchstart"in window);const touchOffset=isMouse?[0,0]:kmath.vector.subtract(startCoord,startMouseCoord);movablePoint.grab(touchOffset);}});}movablePoint.moveTo=function(coordX,coordY,updateLines){const distance=GraphUtils.getDistance(this.graph.scalePoint([coordX,coordY]),this.graph.scalePoint(this.coord));const time=distance*5;const cb=updateLines&&function(coord){movablePoint.coord=coord;movablePoint.updateLineEnds();};this.visibleShape.animateTo([coordX,coordY],time,cb);this.mouseTarget.animateTo([coordX,coordY],time,cb);this.coord=[coordX,coordY];if(___default.default.isFunction(this.onMove)){this.onMove(coordX,coordY);}};movablePoint.updateLineEnds=function(){$__default.default(this.lineStarts).each(function(){this.coordA=movablePoint.coord;this.transform();});$__default.default(this.lineEnds).each(function(){this.coordZ=movablePoint.coord;this.transform();});$__default.default(this.polygonVertices).each(function(){this.transform();});};movablePoint.setCoord=function(coord){if(this.visible){this.visibleShape.moveTo(coord);if(this.mouseTarget!=null){this.mouseTarget.moveTo(coord);}}this.coord=coord.slice();};movablePoint.setCoordConstrained=function(coord){this.setCoord(applySnapAndConstraints(coord));};movablePoint.toBack=function(){if(this.visible){if(this.mouseTarget!=null){this.mouseTarget.toBack();}this.visibleShape.toBack();}};movablePoint.toFront=function(){if(this.visible){if(this.mouseTarget!=null){this.mouseTarget.toFront();}this.visibleShape.toFront();}};movablePoint.remove=function(){if(this.visibleShape){this.visibleShape.remove();}if(this.mouseTarget){this.mouseTarget.remove();}if(this.labeledVertex){this.labeledVertex.remove();}};return movablePoint},addMovableLineSegment:function(options){const lineSegment=$__default.default.extend({graph:this,coordA:[0,0],coordZ:[1,1],snapX:0,snapY:0,fixed:false,ticks:0,normalStyle:{},highlightStyle:{stroke:KhanColors.INTERACTING,"stroke-width":6},labelStyle:{stroke:KhanColors.INTERACTIVE,color:KhanColors.INTERACTIVE},highlight:false,dragging:false,tick:[],extendLine:false,extendRay:false,constraints:{fixed:false,constrainX:false,constrainY:false},sideLabel:"",vertexLabels:[],numArrows:0,numTicks:0,movePointsWithLine:false},options);const normalColor=lineSegment.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;lineSegment.normalStyle=___default.default.extend({},{"stroke-width":2,stroke:normalColor},options.normalStyle);lineSegment.arrowStyle=___default.default.extend({},lineSegment.normalStyle,{color:lineSegment.normalStyle.stroke});if(options.pointA!==undefined){lineSegment.coordA=options.pointA.coord;lineSegment.pointA.lineStarts.push(lineSegment);}else if(options.coordA!==undefined){lineSegment.coordA=options.coordA.slice();}if(options.pointZ!==undefined){lineSegment.coordZ=options.pointZ.coord;lineSegment.pointZ.lineEnds.push(lineSegment);}else if(options.coordA!==undefined){lineSegment.coordA=lineSegment.coordA.slice();}const graph=lineSegment.graph;graph.style(lineSegment.normalStyle);for(let i=0;i<lineSegment.ticks;++i){lineSegment.tick[i]=InteractiveUtils.bogusShape;}let path=GraphUtils.unscaledSvgPath([[0,0],[1,0]]);for(let i=0;i<lineSegment.ticks;++i){const tickoffset=.5-(lineSegment.ticks-1+i*2)/graph.scale[0];path+=GraphUtils.unscaledSvgPath([[tickoffset,-7],[tickoffset,7]]);}options={thickness:Math.max(lineSegment.normalStyle["stroke-width"],lineSegment.highlightStyle["stroke-width"])};lineSegment.visibleLine=new WrappedLine(graph,[0,0],[1,0],options);lineSegment.visibleLine.attr(lineSegment.normalStyle);if(!lineSegment.fixed){const options={thickness:30,mouselayer:true,interactiveKindForTesting:"movable-line"};lineSegment.mouseTarget=new WrappedLine(graph,[0,0],[1,0],options);lineSegment.mouseTarget.attr({fill:"#000",opacity:0});}lineSegment.transform=function(syncToPoints){if(syncToPoints){if(typeof this.pointA==="object"){this.coordA=this.pointA.coord;}if(typeof this.pointZ==="object"){this.coordZ=this.pointZ.coord;}}const getScaledAngle=function(line){const scaledA=line.graph.scalePoint(line.coordA);const scaledZ=line.graph.scalePoint(line.coordZ);return kmath.vector.polarDegFromCart(kmath.vector.subtract(scaledZ,scaledA))[1]};const getClipPoint=function(graph,coord,angle){graph=lineSegment.graph;const xExtent=graph.range[0][1]-graph.range[0][0];const yExtent=graph.range[1][1]-graph.range[1][0];const distance=xExtent+yExtent;const angleVec=graph.unscaleVector(kmath.vector.cartFromPolarDeg(1,angle));const distVec=kmath.vector.scale(kmath.vector.normalize(angleVec),distance);const farCoord=kmath.vector.add(coord,distVec);const scaledAngle=kmath.vector.polarDegFromCart(angleVec)[1];const clipPoint=graph.constrainToBoundsOnAngle(farCoord,4,scaledAngle*Math.PI/180);return clipPoint};const angle=getScaledAngle(this);let start=this.coordA;let end=this.coordZ;if(this.extendLine){start=getClipPoint(graph,start,360-angle);end=getClipPoint(graph,end,(540-angle)%360);}else if(this.extendRay){end=getClipPoint(graph,start,360-angle);}const elements=[this.visibleLine];if(!this.fixed){elements.push(this.mouseTarget);}___default.default.each(elements,function(element){element.moveTo(start,end);});if(this._arrows==null){this._arrows=[];if(this.extendLine){this._arrows.push(new Arrowhead$1(graph,this.normalStyle));this._arrows.push(new Arrowhead$1(graph,this.normalStyle));}else if(this.extendRay){this._arrows.push(new Arrowhead$1(graph,this.normalStyle));}}const coordForArrow=[this.coordA,this.coordZ];const angleForArrow=[360-angle,(540-angle)%360];___default.default.each(this._arrows,function(arrow,i){arrow.toCoordAtAngle(coordForArrow[i],angleForArrow[i]);});___default.default.invoke(this.temp,"remove");this.temp=[];const isClockwise=this.coordA[0]<this.coordZ[0]||this.coordA[0]===this.coordZ[0]&&this.coordA[1]>this.coordZ[1];if(this.sideLabel){this.temp.push(this.graph.labelSide({point1:this.coordA,point2:this.coordZ,label:this.labeledSide,text:this.sideLabel,numArrows:this.numArrows,numTicks:this.numTicks,clockwise:isClockwise,style:this.labelStyle}));}if(this.vertexLabels.length){this.graph.labelVertex({vertex:this.coordA,point3:this.coordZ,label:this.labeledVertices[0],text:this.vertexLabels[0],clockwise:isClockwise,style:this.labelStyle});this.graph.labelVertex({point1:this.coordA,vertex:this.coordZ,label:this.labeledVertices[1],text:this.vertexLabels[1],clockwise:isClockwise,style:this.labelStyle});}this.temp=___default.default.flatten(this.temp);};lineSegment.toBack=function(){if(!lineSegment.fixed){lineSegment.mouseTarget.toBack();}lineSegment.visibleLine.toBack();};lineSegment.toFront=function(){if(!lineSegment.fixed){lineSegment.mouseTarget.toFront();}lineSegment.visibleLine.toFront();};lineSegment.remove=function(){if(!lineSegment.fixed){lineSegment.mouseTarget.remove();}lineSegment.visibleLine.remove();if(lineSegment.labeledSide){lineSegment.labeledSide.remove();}if(lineSegment.labeledVertices){___default.default.invoke(lineSegment.labeledVertices,"remove");}if(lineSegment._arrows){___default.default.invoke(lineSegment._arrows,"remove");}if(lineSegment.temp.length){___default.default.invoke(lineSegment.temp,"remove");}};lineSegment.hide=function(){lineSegment.visibleLine.hide();if(lineSegment.temp.length){___default.default.invoke(lineSegment.temp,"hide");}if(lineSegment._arrows){___default.default.invoke(lineSegment._arrows,"hide");}};lineSegment.show=function(){lineSegment.visibleLine.show();if(lineSegment.temp.length){___default.default.invoke(lineSegment.temp,"show");}if(lineSegment._arrows){___default.default.invoke(lineSegment._arrows,"show");}};if(lineSegment.sideLabel){lineSegment.labeledSide=this.label([0,0],"","center",lineSegment.labelStyle);}if(lineSegment.vertexLabels.length){lineSegment.labeledVertices=___default.default.map(lineSegment.vertexLabels,function(label){return this.label([0,0],"","center",lineSegment.labelStyle)},this);}if(!lineSegment.fixed&&!lineSegment.constraints.fixed){const $mouseTarget=$__default.default(lineSegment.mouseTarget.getMouseTarget());$mouseTarget.css("cursor","move");$mouseTarget.bind("vmousedown vmouseover vmouseout",function(event){if(event.type==="vmouseover"){if(!dragging){lineSegment.highlight=true;lineSegment.visibleLine.animate(lineSegment.highlightStyle,50);lineSegment.arrowStyle=___default.default.extend({},lineSegment.arrowStyle,{color:lineSegment.highlightStyle.stroke,stroke:lineSegment.highlightStyle.stroke});lineSegment.transform();}}else if(event.type==="vmouseout"){lineSegment.highlight=false;if(!lineSegment.dragging){lineSegment.visibleLine.animate(lineSegment.normalStyle,50);lineSegment.arrowStyle=___default.default.extend({},lineSegment.arrowStyle,{color:lineSegment.normalStyle.stroke,stroke:lineSegment.normalStyle.stroke});lineSegment.transform();}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();let coordX=(event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left)/graph.scale[0]+graph.range[0][0];let coordY=graph.range[1][1]-(event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top)/graph.scale[1];if(lineSegment.snapX>0){coordX=Math.round(coordX/lineSegment.snapX)*lineSegment.snapX;}if(lineSegment.snapY>0){coordY=Math.round(coordY/lineSegment.snapY)*lineSegment.snapY;}const mouseOffsetA=[lineSegment.coordA[0]-coordX,lineSegment.coordA[1]-coordY];const mouseOffsetZ=[lineSegment.coordZ[0]-coordX,lineSegment.coordZ[1]-coordY];const offsetLeft=-Math.min(graph.scaleVector(mouseOffsetA)[0],graph.scaleVector(mouseOffsetZ)[0]);const offsetRight=Math.max(graph.scaleVector(mouseOffsetA)[0],graph.scaleVector(mouseOffsetZ)[0]);const offsetTop=Math.max(graph.scaleVector(mouseOffsetA)[1],graph.scaleVector(mouseOffsetZ)[1]);const offsetBottom=-Math.min(graph.scaleVector(mouseOffsetA)[1],graph.scaleVector(mouseOffsetZ)[1]);$__default.default(document).bind("vmousemove.lineSegment vmouseup.lineSegment",function(event){event.preventDefault();lineSegment.dragging=true;dragging=true;let mouseX=event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top;mouseX=Math.max(offsetLeft+10,Math.min(graph.xpixels-10-offsetRight,mouseX));mouseY=Math.max(offsetTop+10,Math.min(graph.ypixels-10-offsetBottom,mouseY));let coordX=mouseX/graph.scale[0]+graph.range[0][0];let coordY=graph.range[1][1]-mouseY/graph.scale[1];if(lineSegment.snapX>0){coordX=Math.round(coordX/lineSegment.snapX)*lineSegment.snapX;}if(lineSegment.snapY>0){coordY=Math.round(coordY/lineSegment.snapY)*lineSegment.snapY;}if(event.type==="vmousemove"){if(lineSegment.constraints.constrainX){coordX=lineSegment.coordA[0]-mouseOffsetA[0];}if(lineSegment.constraints.constrainY){coordY=lineSegment.coordA[1]-mouseOffsetA[1];}const dX=coordX+mouseOffsetA[0]-lineSegment.coordA[0];const dY=coordY+mouseOffsetA[1]-lineSegment.coordA[1];lineSegment.coordA=[coordX+mouseOffsetA[0],coordY+mouseOffsetA[1]];lineSegment.coordZ=[coordX+mouseOffsetZ[0],coordY+mouseOffsetZ[1]];lineSegment.transform();if(lineSegment.movePointsWithLine){if(typeof lineSegment.pointA==="object"){lineSegment.pointA.setCoord([lineSegment.pointA.coord[0]+dX,lineSegment.pointA.coord[1]+dY]);}if(typeof lineSegment.pointZ==="object"){lineSegment.pointZ.setCoord([lineSegment.pointZ.coord[0]+dX,lineSegment.pointZ.coord[1]+dY]);}}if(___default.default.isFunction(lineSegment.onMove)){lineSegment.onMove(dX,dY);}}else if(event.type==="vmouseup"){$__default.default(document).unbind(".lineSegment");lineSegment.dragging=false;dragging=false;if(!lineSegment.highlight){lineSegment.visibleLine.animate(lineSegment.normalStyle,50);lineSegment.arrowStyle=___default.default.extend({},lineSegment.arrowStyle,{color:lineSegment.normalStyle.stroke,stroke:lineSegment.normalStyle.stroke});lineSegment.transform();}if(___default.default.isFunction(lineSegment.onMoveEnd)){lineSegment.onMoveEnd();}}$__default.default(lineSegment).trigger("move");});}});}if(lineSegment.pointA!==undefined){lineSegment.pointA.toFront();}if(lineSegment.pointZ!==undefined){lineSegment.pointZ.toFront();}lineSegment.transform();return lineSegment},addMovablePolygon:function(options){const graphie=this;const polygon=$__default.default.extend({snapX:0,snapY:0,fixed:false,constrainToGraph:true,normalStyle:{},highlightStyle:{stroke:KhanColors.INTERACTING,"stroke-width":2,fill:KhanColors.INTERACTING,"fill-opacity":.05},pointHighlightStyle:{fill:KhanColors.INTERACTING,stroke:KhanColors.INTERACTING},labelStyle:{stroke:KhanColors.DYNAMIC,"stroke-width":1,color:KhanColors.DYNAMIC},angleLabels:[],showRightAngleMarkers:[],sideLabels:[],vertexLabels:[],numArcs:[],numArrows:[],numTicks:[],updateOnPointMove:true,closed:true},___default.default.omit(options,"points"));const normalColor=polygon.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;polygon.normalStyle=___default.default.extend({"stroke-width":2,"fill-opacity":0,fill:normalColor,stroke:normalColor},options.normalStyle);polygon.points=options.points;const isPoint=function(coordOrPoint){return !___default.default.isArray(coordOrPoint)};polygon.update=function(){const n=polygon.points.length;polygon.coords=___default.default.map(polygon.points,function(coordOrPoint,i){if(isPoint(coordOrPoint)){return coordOrPoint.coord}return coordOrPoint});polygon.left=___default.default.min(___default.default.pluck(polygon.coords,0));polygon.right=___default.default.max(___default.default.pluck(polygon.coords,0));polygon.top=___default.default.max(___default.default.pluck(polygon.coords,1));polygon.bottom=___default.default.min(___default.default.pluck(polygon.coords,1));let scaledCoords=___default.default.map(polygon.coords,function(coord){return graphie.scalePoint(coord)});if(polygon.closed){scaledCoords.push(true);}else {scaledCoords=scaledCoords.concat(___default.default.clone(scaledCoords).reverse());}polygon.path=GraphUtils.unscaledSvgPath(scaledCoords);___default.default.invoke(polygon.temp,"remove");polygon.temp=[];const isClockwise=clockwise$3(polygon.coords);if(polygon.angleLabels.length||polygon.showRightAngleMarkers.length){___default.default.each(polygon.labeledAngles,function(label,i){polygon.temp.push(graphie.labelAngle({point1:polygon.coords[(i-1+n)%n],vertex:polygon.coords[i],point3:polygon.coords[(i+1)%n],label:label,text:polygon.angleLabels[i],showRightAngleMarker:polygon.showRightAngleMarkers[i],numArcs:polygon.numArcs[i],clockwise:isClockwise,style:polygon.labelStyle}));});}if(polygon.sideLabels.length){___default.default.each(polygon.labeledSides,function(label,i){polygon.temp.push(graphie.labelSide({point1:polygon.coords[i],point2:polygon.coords[(i+1)%n],label:label,text:polygon.sideLabels[i],numArrows:polygon.numArrows[i],numTicks:polygon.numTicks[i],clockwise:isClockwise,style:polygon.labelStyle}));});}if(polygon.vertexLabels.length){___default.default.each(polygon.labeledVertices,function(label,i){graphie.labelVertex({point1:polygon.coords[(i-1+n)%n],vertex:polygon.coords[i],point3:polygon.coords[(i+1)%n],label:label,text:polygon.vertexLabels[i],clockwise:isClockwise,style:polygon.labelStyle});});}polygon.temp=___default.default.flatten(polygon.temp);};polygon.transform=function(){polygon.update();polygon.visibleShape.attr({path:polygon.path});if(!polygon.fixed){polygon.mouseTarget.attr({path:polygon.path});}};polygon.remove=function(){polygon.visibleShape.remove();if(!polygon.fixed){polygon.mouseTarget.remove();}if(polygon.labeledAngles){___default.default.invoke(polygon.labeledAngles,"remove");}if(polygon.labeledSides){___default.default.invoke(polygon.labeledSides,"remove");}if(polygon.labeledVertices){___default.default.invoke(polygon.labeledVertices,"remove");}if(polygon.temp.length){___default.default.invoke(polygon.temp,"remove");}};polygon.toBack=function(){if(!polygon.fixed){polygon.mouseTarget.toBack();}polygon.visibleShape.toBack();};polygon.toFront=function(){if(!polygon.fixed){polygon.mouseTarget.toFront();}polygon.visibleShape.toFront();};if(polygon.updateOnPointMove){___default.default.each(___default.default.filter(polygon.points,isPoint),function(coordOrPoint){coordOrPoint.polygonVertices.push(polygon);});}polygon.coords=new Array(polygon.points.length);if(polygon.angleLabels.length){const numLabels=Math.max(polygon.angleLabels.length,polygon.showRightAngleMarkers.length);polygon.labeledAngles=___default.default.times(numLabels,function(){return this.label([0,0],"","center",polygon.labelStyle)},this);}if(polygon.sideLabels.length){polygon.labeledSides=___default.default.map(polygon.sideLabels,function(label){return this.label([0,0],"","center",polygon.labelStyle)},this);}if(polygon.vertexLabels.length){polygon.labeledVertices=___default.default.map(polygon.vertexLabels,function(label){return this.label([0,0],"","center",polygon.labelStyle)},this);}polygon.update();polygon.visibleShape=graphie.raphael.path(polygon.path);polygon.visibleShape.attr(polygon.normalStyle);if(!polygon.fixed){polygon.mouseTarget=graphie.mouselayer.path(polygon.path);polygon.mouseTarget.attr({fill:"#000",opacity:0,cursor:"move"});$__default.default(polygon.mouseTarget[0]).bind("vmousedown vmouseover vmouseout",function(event){if(event.type==="vmouseover"){if(!dragging||polygon.dragging){polygon.highlight=true;polygon.visibleShape.animate(polygon.highlightStyle,50);___default.default.each(___default.default.filter(polygon.points,isPoint),function(point){point.visibleShape.animate(polygon.pointHighlightStyle,50);});}}else if(event.type==="vmouseout"){polygon.highlight=false;if(!polygon.dragging){polygon.visibleShape.animate(polygon.normalStyle,50);const points=___default.default.filter(polygon.points,isPoint);if(!___default.default.any(___default.default.pluck(points,"dragging"))){___default.default.each(points,function(point){point.visibleShape.animate(point.normalStyle,50);});}}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();___default.default.each(___default.default.filter(polygon.points,isPoint),function(point){point.dragging=true;});let startX=(event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left)/graphie.scale[0]+graphie.range[0][0];let startY=graphie.range[1][1]-(event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top)/graphie.scale[1];if(polygon.snapX>0){startX=Math.round(startX/polygon.snapX)*polygon.snapX;}if(polygon.snapY>0){startY=Math.round(startY/polygon.snapY)*polygon.snapY;}let lastX=startX;let lastY=startY;const polygonCoords=polygon.coords.slice();const offsetLeft=(startX-polygon.left)*graphie.scale[0];const offsetRight=(polygon.right-startX)*graphie.scale[0];const offsetTop=(polygon.top-startY)*graphie.scale[1];const offsetBottom=(startY-polygon.bottom)*graphie.scale[1];$__default.default(document).bind("vmousemove.polygon vmouseup.polygon",function(event){event.preventDefault();polygon.dragging=true;dragging=true;let mouseX=event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top;if(polygon.constrainToGraph){mouseX=Math.max(offsetLeft+10,Math.min(graphie.xpixels-10-offsetRight,mouseX));mouseY=Math.max(offsetTop+10,Math.min(graphie.ypixels-10-offsetBottom,mouseY));}let currentX=mouseX/graphie.scale[0]+graphie.range[0][0];let currentY=graphie.range[1][1]-mouseY/graphie.scale[1];if(polygon.snapX>0){currentX=Math.round(currentX/polygon.snapX)*polygon.snapX;}if(polygon.snapY>0){currentY=Math.round(currentY/polygon.snapY)*polygon.snapY;}if(event.type==="vmousemove"){let dX=currentX-startX;let dY=currentY-startY;let doMove=true;if(___default.default.isFunction(polygon.onMove)){const onMoveResult=polygon.onMove(dX,dY);if(onMoveResult===false){doMove=false;}else if(___default.default.isArray(onMoveResult)){dX=onMoveResult[0];dY=onMoveResult[1];currentX=startX+dX;currentY=startY+dY;}}const increment=function(i){return [polygonCoords[i][0]+dX,polygonCoords[i][1]+dY]};if(doMove){___default.default.each(polygon.points,function(coordOrPoint,i){if(isPoint(coordOrPoint)){coordOrPoint.setCoord(increment(i));}else {polygon.points[i]=increment(i);}});polygon.transform();$__default.default(polygon).trigger("move");lastX=currentX;lastY=currentY;}}else if(event.type==="vmouseup"){$__default.default(document).unbind(".polygon");const points=___default.default.filter(polygon.points,isPoint);___default.default.each(points,function(point){point.dragging=false;});polygon.dragging=false;dragging=false;if(!polygon.highlight){polygon.visibleShape.animate(polygon.normalStyle,50);___default.default.each(points,function(point){point.visibleShape.animate(point.normalStyle,50);});}if(___default.default.isFunction(polygon.onMoveEnd)){polygon.onMoveEnd(lastX-startX,lastY-startY);}}});}});}___default.default.invoke(___default.default.filter(polygon.points,isPoint),"toFront");return polygon},constrainToBounds:function(point,padding){const lower=this.unscalePoint([padding,this.ypixels-padding]);const upper=this.unscalePoint([this.xpixels-padding,padding]);const coordX=Math.max(lower[0],Math.min(upper[0],point[0]));const coordY=Math.max(lower[1],Math.min(upper[1],point[1]));return [coordX,coordY]},constrainToBoundsOnAngle:function(point,padding,angle){const lower=this.unscalePoint([padding,this.ypixels-padding]);const upper=this.unscalePoint([this.xpixels-padding,padding]);let result=point.slice();if(result[0]<lower[0]){result=[lower[0],result[1]+(lower[0]-result[0])*Math.tan(angle)];}else if(result[0]>upper[0]){result=[upper[0],result[1]-(result[0]-upper[0])*Math.tan(angle)];}if(result[1]<lower[1]){result=[result[0]+(lower[1]-result[1])/Math.tan(angle),lower[1]];}else if(result[1]>upper[1]){result=[result[0]-(result[1]-upper[1])/Math.tan(angle),upper[1]];}return result},addMovableAngle:function(options){return new MovableAngle(this,options)},addCircleGraph:function(options){const graphie=this;const circle=$__default.default.extend({center:[0,0],radius:2,snapX:.5,snapY:.5,snapRadius:.5,minRadius:1,centerConstraints:{},centerNormalStyle:{},centerHighlightStyle:{stroke:KhanColors.INTERACTING,fill:KhanColors.INTERACTING},circleNormalStyle:{stroke:KhanColors.INTERACTIVE,"fill-opacity":0},circleHighlightStyle:{stroke:KhanColors.INTERACTING,fill:KhanColors.INTERACTING,"fill-opacity":.05}},options);const normalColor=circle.centerConstraints.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;const centerNormalStyle=options?options.centerNormalStyle:null;circle.centerNormalStyle=___default.default.extend({},{fill:normalColor,stroke:normalColor},centerNormalStyle);circle.centerPoint=graphie.addMovablePoint({graph:graphie,coord:circle.center,normalStyle:circle.centerNormalStyle,snapX:circle.snapX,snapY:circle.snapY,constraints:circle.centerConstraints});circle.circ=graphie.circle(circle.center,circle.radius,circle.circleNormalStyle);circle.perim=graphie.mouselayer.circle(graphie.scalePoint(circle.center)[0],graphie.scalePoint(circle.center)[1],graphie.scaleVector(circle.radius)[0]).attr({"stroke-width":20,opacity:.002});if(!circle.centerConstraints.fixed){$__default.default(circle.centerPoint.mouseTarget.getMouseTarget()).on("vmouseover vmouseout",function(event){if(circle.centerPoint.highlight||circle.centerPoint.dragging){circle.circ.animate(circle.circleHighlightStyle,50);}else {circle.circ.animate(circle.circleNormalStyle,50);}});}circle.toFront=function(){circle.circ.toFront();circle.perim.toFront();circle.centerPoint.visibleShape.toFront();if(!circle.centerConstraints.fixed){circle.centerPoint.mouseTarget.toFront();}};circle.centerPoint.onMove=function(x,y){circle.toFront();circle.circ.attr({cx:graphie.scalePoint(x)[0],cy:graphie.scalePoint(y)[1]});circle.perim.attr({cx:graphie.scalePoint(x)[0],cy:graphie.scalePoint(y)[1]});if(circle.onMove){circle.onMove(x,y);}};$__default.default(circle.centerPoint).on("move",function(){circle.center=this.coord;$__default.default(circle).trigger("move");});circle.setCenter=function(x,y){circle.centerPoint.setCoord([x,y]);circle.centerPoint.onMove(x,y);circle.center=[x,y];};circle.setRadius=function(r){circle.radius=r;circle.perim.attr({r:graphie.scaleVector(r)[0]});circle.circ.attr({rx:graphie.scaleVector(r)[0],ry:graphie.scaleVector(r)[1]});};circle.remove=function(){circle.centerPoint.remove();circle.circ.remove();circle.perim.remove();};const cursorAxes=[[Math.PI*-1,Math.PI*-0.875,"ew-resize"],[Math.PI*-0.875,Math.PI*-0.625,"nesw-resize"],[Math.PI*-0.625,Math.PI*-0.375,"ns-resize"],[Math.PI*-0.375,Math.PI*-0.125,"nwse-resize"],[Math.PI*-0.125,Math.PI*.125,"ew-resize"],[Math.PI*.125,Math.PI*.375,"nesw-resize"],[Math.PI*.375,Math.PI*.625,"ns-resize"],[Math.PI*.625,Math.PI*.875,"nwse-resize"],[Math.PI*.875,Math.PI*1,"ew-resize"]];$__default.default(circle.perim.node).on("vmousemove",event=>{let[x,y]=this.getMouseCoord(event);x-=circle.center[0];y-=circle.center[1];const theta=Math.atan2(y,x);cursorAxes.forEach(function(axes){const[min,max,cursorName]=axes;if(theta>=min&&theta<max){$__default.default(circle.perim.node).css("cursor",cursorName);}});});$__default.default(circle.perim.node).css("cursor","nesw-resize");circle.perim.node.addEventListener("touchstart",function(event){event.preventDefault();},{passive:false});$__default.default(circle.perim.node).on("vmouseover vmouseout vmousedown",function(event){if(event.type==="vmouseover"){circle.highlight=true;if(!dragging){circle.circ.animate(circle.circleHighlightStyle,50);circle.centerPoint.visibleShape.animate(circle.centerHighlightStyle,50);}}else if(event.type==="vmouseout"){circle.highlight=false;if(!circle.dragging&&!circle.centerPoint.dragging){circle.circ.animate(circle.circleNormalStyle,50);circle.centerPoint.visibleShape.animate(circle.centerNormalStyle,50);}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();circle.toFront();const startRadius=circle.radius;$__default.default(document).on("vmousemove vmouseup",function(event){event.preventDefault();circle.dragging=true;dragging=true;if(event.type==="vmousemove"){const coord=graphie.constrainToBounds(graphie.getMouseCoord(event),10);let radius=GraphUtils.getDistance(circle.centerPoint.coord,coord);radius=Math.max(circle.minRadius,Math.round(radius/circle.snapRadius)*circle.snapRadius);const oldRadius=circle.radius;let doResize=true;if(circle.onResize){const onResizeResult=circle.onResize(radius,oldRadius);if(___default.default.isNumber(onResizeResult)){radius=onResizeResult;}else if(onResizeResult===false){doResize=false;}}if(doResize){circle.setRadius(radius);$__default.default(circle).trigger("move");}}else if(event.type==="vmouseup"){$__default.default(document).off("vmousemove vmouseup");circle.dragging=false;dragging=false;if(circle.onResizeEnd){circle.onResizeEnd(circle.radius,startRadius);}}});}});return circle},addRotateHandle:function(){const drawRotateHandle=function(graphie,center,radius,halfWidth,lengthAngle,angle,interacting){const getRotateHandlePoint=function(offset,distanceFromArrowMidline){const distFromRotationCenter=radius+distanceFromArrowMidline;const vec=kmath.vector.cartFromPolarDeg(distFromRotationCenter,angle+offset);const absolute=kmath.vector.add(center,vec);const pixels=graphie.scalePoint(absolute);return pixels[0]+","+pixels[1]};const innerR=graphie.scaleVector(radius-halfWidth);const outerR=graphie.scaleVector(radius+halfWidth);return graphie.raphael.path(" M"+getRotateHandlePoint(lengthAngle,-halfWidth)+" L"+getRotateHandlePoint(lengthAngle,-3*halfWidth)+" L"+getRotateHandlePoint(2*lengthAngle,0)+" L"+getRotateHandlePoint(lengthAngle,3*halfWidth)+" L"+getRotateHandlePoint(lengthAngle,halfWidth)+" A"+outerR[0]+","+outerR[1]+",0,0,1,"+getRotateHandlePoint(-lengthAngle,halfWidth)+" L"+getRotateHandlePoint(-lengthAngle,3*halfWidth)+" L"+getRotateHandlePoint(-2*lengthAngle,0)+" L"+getRotateHandlePoint(-lengthAngle,-3*halfWidth)+" L"+getRotateHandlePoint(-lengthAngle,-halfWidth)+" A"+innerR[0]+","+innerR[1]+",0,0,0,"+getRotateHandlePoint(lengthAngle,-halfWidth)+" Z").attr({stroke:null,fill:interacting?KhanColors.INTERACTING:KhanColors.INTERACTIVE})};return function(options){const graph=this;let rotatePoint=options.center;const radius=options.radius;const lengthAngle=options.lengthAngle||30;const hideArrow=options.hideArrow||false;const mouseTarget=options.mouseTarget;const id=___default.default.uniqueId("rotateHandle");if(___default.default.isArray(rotatePoint)){rotatePoint={coord:rotatePoint};}const rotateHandle=graph.addMovablePoint({coord:kmath.point.addVector(rotatePoint.coord,kmath.vector.cartFromPolarDeg(radius,options.angleDeg||0)),constraints:{fixedDistance:{dist:radius,point:rotatePoint}},mouseTarget:mouseTarget});rotatePoint.toFront();let rotatePointPrevCoord=rotatePoint.coord;let rotateHandlePrevCoord=rotateHandle.coord;let rotateHandleStartCoord=rotateHandlePrevCoord;let isRotating=false;let isHovering=false;let drawnRotateHandle;const redrawRotateHandle=function(handleCoord){if(hideArrow){return}const handleVec=kmath.vector.subtract(handleCoord,rotatePoint.coord);const handlePolar=kmath.vector.polarDegFromCart(handleVec);const angle=handlePolar[1];if(drawnRotateHandle){drawnRotateHandle.remove();}drawnRotateHandle=drawRotateHandle(graph,rotatePoint.coord,options.radius,isRotating||isHovering?options.hoverWidth/2:options.width/2,lengthAngle,angle,isRotating||isHovering);};$__default.default(rotatePoint).on("move."+id,function(){const delta=kmath.vector.subtract(rotatePoint.coord,rotatePointPrevCoord);rotateHandle.setCoord(kmath.vector.add(rotateHandle.coord,delta));redrawRotateHandle(rotateHandle.coord);rotatePointPrevCoord=rotatePoint.coord;rotateHandle.constraints.fixedDistance.point=rotatePoint;rotateHandlePrevCoord=rotateHandle.coord;});rotateHandle.onMove=function(x,y){if(!isRotating){rotateHandleStartCoord=rotateHandlePrevCoord;isRotating=true;}let coord=[x,y];if(options.onMove){const oldPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(rotateHandlePrevCoord,rotatePoint.coord));const newPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(coord,rotatePoint.coord));const oldAngle=oldPolar[1];const newAngle=newPolar[1];let result=options.onMove(newAngle,oldAngle);if(result!=null&&result!==true){if(result===false){result=oldAngle;}coord=kmath.vector.add(rotatePoint.coord,kmath.vector.cartFromPolarDeg(oldPolar[0],result));}}redrawRotateHandle(coord);rotateHandlePrevCoord=coord;return coord};rotateHandle.onMoveEnd=function(){isRotating=false;redrawRotateHandle(rotateHandle.coord);if(options.onMoveEnd){const oldPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(rotateHandleStartCoord,rotatePoint.coord));const newPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(rotateHandle.coord,rotatePoint.coord));options.onMoveEnd(newPolar[1],oldPolar[1]);}};rotateHandle.visibleShape.remove();if(!mouseTarget){rotateHandle.mouseTarget.attr({scale:2});}const $mouseTarget=$__default.default(rotateHandle.mouseTarget.getMouseTarget());$mouseTarget.bind("vmouseover",function(e){isHovering=true;redrawRotateHandle(rotateHandle.coord);});$mouseTarget.bind("vmouseout",function(e){isHovering=false;redrawRotateHandle(rotateHandle.coord);});redrawRotateHandle(rotateHandle.coord);const oldRemove=rotateHandle.remove;rotateHandle.remove=function(){oldRemove.call(rotateHandle);if(drawnRotateHandle){drawnRotateHandle.remove();}$__default.default(rotatePoint).off("move."+id);};rotateHandle.update=function(){redrawRotateHandle(rotateHandle.coord);};return rotateHandle}}(),addReflectButton:function(){const drawButton=function(graphie,buttonCoord,lineCoords,size,distanceFromCenter,leftStyle,rightStyle){if(kmath.point.equal(lineCoords[0],lineCoords[1])){lineCoords=[lineCoords[0],kmath.point.addVector(lineCoords[0],[1,1])];}const lineDirection=kmath.vector.normalize(kmath.vector.subtract(lineCoords[1],lineCoords[0]));const lineVec=kmath.vector.scale(lineDirection,size/2);const centerVec=kmath.vector.scale(lineDirection,distanceFromCenter);const leftCenterVec=kmath.vector.rotateDeg(centerVec,90);const rightCenterVec=kmath.vector.rotateDeg(centerVec,-90);const negLineVec=kmath.vector.negate(lineVec);const leftVec=kmath.vector.rotateDeg(lineVec,90);const rightVec=kmath.vector.rotateDeg(lineVec,-90);const leftCenter=kmath.point.addVectors(buttonCoord,leftCenterVec);const rightCenter=kmath.point.addVectors(buttonCoord,rightCenterVec);const leftCoord1=kmath.point.addVectors(buttonCoord,leftCenterVec,lineVec,leftVec);const leftCoord2=kmath.point.addVectors(buttonCoord,leftCenterVec,negLineVec,leftVec);const rightCoord1=kmath.point.addVectors(buttonCoord,rightCenterVec,lineVec,rightVec);const rightCoord2=kmath.point.addVectors(buttonCoord,rightCenterVec,negLineVec,rightVec);const leftButton=graphie.path([leftCenter,leftCoord1,leftCoord2,true],leftStyle);const rightButton=graphie.path([rightCenter,rightCoord1,rightCoord2,true],rightStyle);return {remove:function(){leftButton.remove();rightButton.remove();}}};return function(options){const graphie=this;const line=options.line;const button=graphie.addMovablePoint({constraints:options.constraints,coord:kmath.line.midpoint([line.pointA.coord,line.pointZ.coord]),snapX:graphie.snap[0],snapY:graphie.snap[1],onMove:function(x,y){return false},onMoveEnd:function(x,y){if(options.onMoveEnd){options.onMoveEnd.call(this,x,y);}}});let isHovering=false;let isFlipped=false;let currentlyDrawnButton;const isHighlight=function(){return isHovering};const styles=___default.default.map([0,1],function(isHighlight){const baseStyle=isHighlight?options.highlightStyle:options.normalStyle;return ___default.default.map([0,1],function(opacity){return ___default.default.defaults({"fill-opacity":opacity},baseStyle)})});const getStyle=function(isRight){if(isFlipped){isRight=!isRight;}return styles[+isHighlight()][+isRight]};const redraw=function(coord,lineCoords){if(currentlyDrawnButton){currentlyDrawnButton.remove();}currentlyDrawnButton=drawButton(graphie,coord,lineCoords,isHighlight()?options.size*1.5:options.size,isHighlight()?options.size*.125:.25,getStyle(0),getStyle(1));};const update=function(coordA,coordZ){coordA=coordA||line.pointA.coord;coordZ=coordZ||line.pointZ.coord;const buttonCoord=kmath.line.midpoint([coordA,coordZ]);button.setCoord(buttonCoord);redraw(buttonCoord,[coordA,coordZ]);};$__default.default(line).on("move",___default.default.bind(update,button,null,null));const $mouseTarget=$__default.default(button.mouseTarget.getMouseTarget());$mouseTarget.on("vclick",function(){const result=options.onClick();if(result!==false){isFlipped=!isFlipped;redraw(button.coord,[line.pointA.coord,line.pointZ.coord]);}});line.pointA.toFront();line.pointZ.toFront();button.visibleShape.remove();const pointScale=graphie.scaleVector(options.size)[0]/20;button.mouseTarget.attr({scale:1.5*pointScale});$mouseTarget.css("cursor","pointer");$mouseTarget.bind("vmouseover",function(e){isHovering=true;redraw(button.coord,[line.pointA.coord,line.pointZ.coord]);});$mouseTarget.bind("vmouseout",function(e){isHovering=false;redraw(button.coord,[line.pointA.coord,line.pointZ.coord]);});const oldButtonRemove=button.remove;button.remove=function(){currentlyDrawnButton.remove();oldButtonRemove.call(button);};button.update=update;button.isFlipped=function(){return isFlipped};update();return button}}(),protractor:function(center){return new Protractor$1(this,center)},ruler:function(options){return new Ruler(this,options||{})},addPoints:kmath.vector.add});function Protractor$1(graph,center){this.set=graph.raphael.set();this.cx=center[0];this.cy=center[1];const pro=this;const r=graph.unscaleVector(180.5)[0];const imgPos=graph.scalePoint([this.cx-r,this.cy+r-graph.unscaleVector(10.5)[1]]);const image=graph.mouselayer.image("https://ka-perseus-graphie.s3.amazonaws.com/e9d032f2ab8b95979f674fbfa67056442ba1ff6a.png",imgPos[0],imgPos[1],360,180);this.set.push(image);image.node.addEventListener("touchstart",function(event){event.preventDefault();},{passive:false});const arrowHelper=function(angle,pixelsFromEdge){const scaledRadius=graph.scaleVector(r);scaledRadius[0]-=16;scaledRadius[1]-=16;const scaledCenter=graph.scalePoint(center);const x=Math.sin((angle+90)*Math.PI/180)*(scaledRadius[0]+pixelsFromEdge)+scaledCenter[0];const y=Math.cos((angle+90)*Math.PI/180)*(scaledRadius[1]+pixelsFromEdge)+scaledCenter[1];return x+","+y};const arrow=graph.raphael.path(" M"+arrowHelper(180,6)+" L"+arrowHelper(180,2)+" L"+arrowHelper(183,10)+" L"+arrowHelper(180,18)+" L"+arrowHelper(180,14)+" A"+(graph.scaleVector(r)[0]+10)+","+(graph.scaleVector(r)[1]+10)+",0,0,1,"+arrowHelper(170,14)+" L"+arrowHelper(170,18)+" L"+arrowHelper(167,10)+" L"+arrowHelper(170,2)+" L"+arrowHelper(170,6)+" A"+(graph.scaleVector(r)[0]+10)+","+(graph.scaleVector(r)[1]+10)+",0,0,0,"+arrowHelper(180,6)+" Z").attr({stroke:null,fill:KhanColors.INTERACTIVE});this.set.push(arrow);this.centerPoint=graph.addMovablePoint({coord:center,visible:false});this.rotateHandle=graph.addMovablePoint({bounded:false,coord:[Math.sin(275*Math.PI/180)*r+this.cx,Math.cos(275*Math.PI/180)*r+this.cy],onMove:function(x,y){const angle=Math.atan2(pro.centerPoint.coord[1]-y,pro.centerPoint.coord[0]-x)*180/Math.PI;pro.rotate(-angle-5,true);}});this.rotateHandle.constraints.fixedDistance.dist=r;this.rotateHandle.constraints.fixedDistance.point=this.centerPoint;this.rotateHandle.visibleShape.remove();this.rotateHandle.mouseTarget.attr({scale:2});let isDragging=false;let isHovering=false;const isHighlight=function(){return isHovering||isDragging};const self=this;const $mouseTarget=$__default.default(self.rotateHandle.mouseTarget.getMouseTarget());$mouseTarget.bind("vmousedown",function(event){isDragging=true;$mouseTarget.css("cursor","-webkit-grabbing");$mouseTarget.css("cursor","grabbing");arrow.animate({scale:1.5,fill:KhanColors.INTERACTING},50);$__default.default(document).bind("vmouseup.rotateHandle",function(event){isDragging=false;$mouseTarget.css("cursor","-webkit-grab");$mouseTarget.css("cursor","grab");if(!isHighlight()){arrow.animate({scale:1,fill:KhanColors.INTERACTIVE},50);}$__default.default(document).unbind("vmouseup.rotateHandle");});});$mouseTarget.bind("vmouseover",function(event){isHovering=true;arrow.animate({scale:1.5,fill:KhanColors.INTERACTING},50);});$mouseTarget.bind("vmouseout",function(event){isHovering=false;if(!isHighlight()){arrow.animate({scale:1,fill:KhanColors.INTERACTIVE},50);}});const setNodes=$__default.default.map(this.set,function(el){return el.node});this.makeTranslatable=function makeTranslatable(){$__default.default(setNodes).css("cursor","move");$mouseTarget.css("cursor","-webkit-grab");$mouseTarget.css("cursor","grab");$__default.default(setNodes).bind("vmousedown",function(event){event.preventDefault();let startx=event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left;let starty=event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top;$__default.default(document).bind("vmousemove.protractor",function(event){let mouseX=event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top;mouseX=Math.max(10,Math.min(graph.xpixels-10,mouseX));mouseY=Math.max(10,Math.min(graph.ypixels-10,mouseY));const dx=mouseX-startx;const dy=mouseY-starty;$__default.default.each(pro.set.items,function(){this.translate(dx,dy);});pro.centerPoint.setCoord([pro.centerPoint.coord[0]+dx/graph.scale[0],pro.centerPoint.coord[1]-dy/graph.scale[1]]);pro.rotateHandle.setCoord([pro.rotateHandle.coord[0]+dx/graph.scale[0],pro.rotateHandle.coord[1]-dy/graph.scale[1]]);startx=mouseX;starty=mouseY;});$__default.default(document).one("vmouseup",function(event){$__default.default(document).unbind("vmousemove.protractor");});});};this.rotation=0;this.rotate=function(offset,absolute){const center=graph.scalePoint(this.centerPoint.coord);if(absolute){this.rotation=0;}this.set.rotate(this.rotation+offset,center[0],center[1]);this.rotation=this.rotation+offset;return this};this.moveTo=function moveTo(x,y){const start=graph.scalePoint(pro.centerPoint.coord);const end=graph.scalePoint([x,y]);const time=GraphUtils.getDistance(start,end)*2;$__default.default({x:start[0],y:start[1]}).animate({x:end[0],y:end[1]},{duration:time,step:function(now,fx){let dx=0;let dy=0;if(fx.prop==="x"){dx=now-graph.scalePoint(pro.centerPoint.coord)[0];}else if(fx.prop==="y"){dy=now-graph.scalePoint(pro.centerPoint.coord)[1];}$__default.default.each(pro.set.items,function(){this.translate(dx,dy);});pro.centerPoint.setCoord([pro.centerPoint.coord[0]+dx/graph.scale[0],pro.centerPoint.coord[1]-dy/graph.scale[1]]);pro.rotateHandle.setCoord([pro.rotateHandle.coord[0]+dx/graph.scale[0],pro.rotateHandle.coord[1]-dy/graph.scale[1]]);}});};this.rotateTo=function rotateTo(angle){if(Math.abs(this.rotation-angle)>180){this.rotation+=360;}const time=Math.abs(this.rotation-angle)*5;$__default.default({0:this.rotation}).animate({0:angle},{duration:time,step:function(now,fx){pro.rotate(now,true);pro.rotateHandle.setCoord([Math.sin((now+275)*Math.PI/180)*r+pro.centerPoint.coord[0],Math.cos((now+275)*Math.PI/180)*r+pro.centerPoint.coord[1]]);}});};this.remove=function(){this.set.remove();};this.makeTranslatable();return this}function Ruler(graphie,options){___default.default.defaults(options,{center:[0,0],pixelsPerUnit:40,ticksPerUnit:10,units:10,label:"",style:{fill:null,stroke:KhanColors.GRAY}});const light=___default.default.extend({},options.style,{strokeWidth:1});const bold=___default.default.extend({},options.style,{strokeWidth:2});const width=options.units*options.pixelsPerUnit;const height=50;const leftBottom=graphie.unscalePoint(kmath.vector.subtract(graphie.scalePoint(options.center),kmath.vector.scale([width,-50],.5)));const graphieUnitsPerUnit=options.pixelsPerUnit/graphie.scale[0];const graphieUnitsHeight=height/graphie.scale[0];const rightTop=kmath.vector.add(leftBottom,[options.units*graphieUnitsPerUnit,graphieUnitsHeight]);const tickHeight=1;let tickHeightMap;if(options.ticksPerUnit===10){tickHeightMap={10:tickHeight,5:tickHeight*.55,1:tickHeight*.35};}else {const sizes=[1,.6,.45,.3];tickHeightMap={};for(let i=options.ticksPerUnit;i>=1;i/=2){tickHeightMap[i]=tickHeight*(sizes.shift()||.2);}}const tickFrequencies=___default.default.keys(tickHeightMap).sort(function(a,b){return b-a});function getTickHeight(i){for(let k=0;k<tickFrequencies.length;k++){const key=tickFrequencies[k];if(i%key===0){return tickHeightMap[key]}}return 0}const left=leftBottom[0];const bottom=leftBottom[1];const right=rightTop[0];const top=rightTop[1];const numTicks=options.units*options.ticksPerUnit+1;const set=graphie.raphael.set();const px=1/graphie.scale[0];set.push(graphie.line([left-px,bottom],[right+px,bottom],bold));set.push(graphie.line([left-px,top],[right+px,top],bold));___default.default.times(numTicks,function(i){const n=i/options.ticksPerUnit;const x=left+n*graphieUnitsPerUnit;const height=getTickHeight(i)*graphieUnitsHeight;const style=i===0||i===numTicks-1?bold:light;set.push(graphie.line([x,bottom],[x,bottom+height],style));if(n%1===0){const coord=graphie.scalePoint([x,top]);let text;let offset;if(n===0){text=options.label;offset=({mm:13,cm:11,m:8,km:11,in:8,ft:8,yd:10,mi:10})[text]||3*text.toString().length;}else {text=n;offset=-3*(n.toString().length+1);}const label=graphie.raphael.text(coord[0]+offset,coord[1]+10,text);label.attr({"font-family":"KaTeX_Main","font-size":"12px",color:"#444"});set.push(label);}});const mouseTarget=graphie.mouselayer.path(graphie.svgPath([leftBottom,[left,top],rightTop,[right,bottom],true]));mouseTarget.attr({fill:"#000",opacity:0,stroke:"#000","stroke-width":2});set.push(mouseTarget);mouseTarget.node.addEventListener("touchstart",function(event){event.preventDefault();},{passive:false});const setNodes=$__default.default.map(set,function(el){return el.node});$__default.default(setNodes).css("cursor","move");$__default.default(setNodes).bind("vmousedown",function(event){event.preventDefault();let startx=event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left;let starty=event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top;$__default.default(document).bind("vmousemove.ruler",function(event){let mouseX=event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top;mouseX=Math.max(10,Math.min(graphie.xpixels-10,mouseX));mouseY=Math.max(10,Math.min(graphie.ypixels-10,mouseY));const dx=mouseX-startx;const dy=mouseY-starty;set.translate(dx,dy);leftBottomHandle.setCoord([leftBottomHandle.coord[0]+dx/graphie.scale[0],leftBottomHandle.coord[1]-dy/graphie.scale[1]]);rightBottomHandle.setCoord([rightBottomHandle.coord[0]+dx/graphie.scale[0],rightBottomHandle.coord[1]-dy/graphie.scale[1]]);startx=mouseX;starty=mouseY;});$__default.default(document).one("vmouseup",function(event){$__default.default(document).unbind("vmousemove.ruler");});});const leftBottomHandle=graphie.addMovablePoint({coord:leftBottom,normalStyle:{fill:KhanColors.INTERACTIVE,"fill-opacity":0,stroke:KhanColors.INTERACTIVE},highlightStyle:{fill:KhanColors.INTERACTING,"fill-opacity":.1,stroke:KhanColors.INTERACTING},pointSize:6,onMove:function(x,y){const dy=rightBottomHandle.coord[1]-y;const dx=rightBottomHandle.coord[0]-x;const angle=Math.atan2(dy,dx)*180/Math.PI;const center=kmath.vector.scale(kmath.vector.add([x,y],rightBottomHandle.coord),.5);const scaledCenter=graphie.scalePoint(center);const oldCenter=kmath.vector.scale(kmath.vector.add(leftBottomHandle.coord,rightBottomHandle.coord),.5);const scaledOldCenter=graphie.scalePoint(oldCenter);const diff=kmath.vector.subtract(scaledCenter,scaledOldCenter);set.rotate(-angle,scaledOldCenter[0],scaledOldCenter[1]);set.translate(diff[0],diff[1]);}});const rightBottomHandle=graphie.addMovablePoint({coord:[right,bottom],normalStyle:{fill:KhanColors.INTERACTIVE,"fill-opacity":0,stroke:KhanColors.INTERACTIVE},highlightStyle:{fill:KhanColors.INTERACTING,"fill-opacity":.1,stroke:KhanColors.INTERACTING},pointSize:6,onMove:function(x,y){const dy=y-leftBottomHandle.coord[1];const dx=x-leftBottomHandle.coord[0];const angle=Math.atan2(dy,dx)*180/Math.PI;const center=kmath.vector.scale(kmath.vector.add([x,y],leftBottomHandle.coord),.5);const scaledCenter=graphie.scalePoint(center);const oldCenter=kmath.vector.scale(kmath.vector.add(leftBottomHandle.coord,rightBottomHandle.coord),.5);const scaledOldCenter=graphie.scalePoint(oldCenter);const diff=kmath.vector.subtract(scaledCenter,scaledOldCenter);set.rotate(-angle,scaledOldCenter[0],scaledOldCenter[1]);set.translate(diff[0],diff[1]);}});leftBottomHandle.constraints.fixedDistance.dist=width/graphie.scale[0];leftBottomHandle.constraints.fixedDistance.point=rightBottomHandle;rightBottomHandle.constraints.fixedDistance.dist=width/graphie.scale[0];rightBottomHandle.constraints.fixedDistance.point=leftBottomHandle;this.remove=function(){set.remove();leftBottomHandle.remove();rightBottomHandle.remove();};return this}function MovableAngle(graphie,options){this.graphie=graphie;___default.default.extend(this,options);___default.default.defaults(this,{normalStyle:{stroke:KhanColors.INTERACTIVE,"stroke-width":2,fill:KhanColors.INTERACTIVE},highlightStyle:{stroke:KhanColors.INTERACTING,"stroke-width":2,fill:KhanColors.INTERACTING},labelStyle:{stroke:KhanColors.DYNAMIC,"stroke-width":1,color:KhanColors.DYNAMIC},angleStyle:{stroke:KhanColors.DYNAMIC,"stroke-width":1,color:KhanColors.DYNAMIC},allowReflex:true});if(!this.points||this.points.length!==3){throw new perseusCore.PerseusError("MovableAngle requires 3 points",perseusCore.Errors.InvalidInput)}this.points=___default.default.map(options.points,function(point){if(___default.default.isArray(point)){return graphie.addMovablePoint({coord:point,visible:false,constraints:{fixed:true},normalStyle:this.normalStyle})}return point},this);this.coords=___default.default.pluck(this.points,"coord");if(this.reflex==null){if(this.allowReflex){this.reflex=this._getClockwiseAngle(this.coords)>180;}else {this.reflex=false;}}this.rays=___default.default.map([0,2],function(i){return graphie.addMovableLineSegment({pointA:this.points[1],pointZ:this.points[i],fixed:true,extendRay:true})},this);this.temp=[];this.labeledAngle=graphie.label([0,0],"","center",this.labelStyle);if(!this.fixed){this.addMoveHandlers();this.addHighlightHandlers();}this.update();}___default.default.extend(MovableAngle.prototype,{points:[],snapDegrees:0,snapOffsetDeg:0,angleLabel:"",numArcs:1,pushOut:0,fixed:false,addMoveHandlers:function(){const graphie=this.graphie;function tooClose(point1,point2){const safeDistance=30;const distance=GraphUtils.getDistance(graphie.scalePoint(point1),graphie.scalePoint(point2));return distance<safeDistance}const points=this.points;points[1].onMove=function(x,y){const oldVertex=points[1].coord;const newVertex=[x,y];const delta=kmath.vector.add(newVertex,reverseVector$1(oldVertex));let valid=true;const newPoints={};___default.default.each([0,2],function(i){const oldPoint=points[i].coord;let newPoint=kmath.vector.add(oldPoint,delta);let angle=GraphUtils.findAngleDeprecated(newVertex,newPoint);angle*=Math.PI/180;newPoint=graphie.constrainToBoundsOnAngle(newPoint,10,angle);newPoints[i]=newPoint;if(tooClose(newVertex,newPoint)){valid=false;}});if(valid){___default.default.each(newPoints,function(newPoint,i){points[i].setCoord(newPoint);});}return valid};const snap=this.snapDegrees;const snapOffset=this.snapOffsetDeg;___default.default.each([0,2],function(i){points[i].onMove=function(x,y){const newPoint=[x,y];const vertex=points[1].coord;if(tooClose(vertex,newPoint)){return false}if(snap){let angle=GraphUtils.findAngleDeprecated(newPoint,vertex);angle=Math.round((angle-snapOffset)/snap)*snap+snapOffset;const distance=GraphUtils.getDistance(newPoint,vertex);return kmath.vector.add(vertex,polar$2(distance,angle))}return true};});$__default.default(points).on("move",(function(){this.update();$__default.default(this).trigger("move");}).bind(this));},addHighlightHandlers:function(){const vertex=this.points[1];vertex.onHighlight=(function(){___default.default.each(this.points,function(point){point.visibleShape.animate(this.highlightStyle,50);},this);___default.default.each(this.rays,function(ray){ray.visibleLine.animate(this.highlightStyle,50);ray.arrowStyle=___default.default.extend({},ray.arrowStyle,{color:this.highlightStyle.stroke,stroke:this.highlightStyle.stroke});},this);this.angleStyle=___default.default.extend({},this.angleStyle,{color:this.highlightStyle.stroke,stroke:this.highlightStyle.stroke});this.update();}).bind(this);vertex.onUnhighlight=(function(){___default.default.each(this.points,function(point){point.visibleShape.animate(this.normalStyle,50);},this);___default.default.each(this.rays,function(ray){ray.visibleLine.animate(ray.normalStyle,50);ray.arrowStyle=___default.default.extend({},ray.arrowStyle,{color:ray.normalStyle.stroke,stroke:ray.normalStyle.stroke});},this);this.angleStyle=___default.default.extend({},this.angleStyle,{color:KhanColors.DYNAMIC,stroke:KhanColors.DYNAMIC});this.update();}).bind(this);},_getClockwiseAngle:function(coords){const rawAngle=GraphUtils.findAngleDeprecated(coords[2],coords[0],coords[1]);const clockwiseAngle=rawAngle+360%360;return clockwiseAngle},isReflex:function(){return this.reflex},isClockwise:function(){const clockwiseReflexive=this._getClockwiseAngle(this.coords)>180;return clockwiseReflexive===this.reflex},getClockwiseCoords:function(){if(this.isClockwise()){return ___default.default.clone(this.coords)}return ___default.default.clone(this.coords).reverse()},update:function(shouldChangeReflexivity){const prevCoords=this.coords;this.coords=___default.default.pluck(this.points,"coord");___default.default.invoke(this.points,"updateLineEnds");const prevAngle=this._getClockwiseAngle(prevCoords);const angle=this._getClockwiseAngle(this.coords);const prevClockwiseReflexive=prevAngle>180;const clockwiseReflexive=angle>180;if(this.allowReflex){if(shouldChangeReflexivity==null){shouldChangeReflexivity=prevClockwiseReflexive!==clockwiseReflexive&&Math.abs(angle-prevAngle)<180;}if(shouldChangeReflexivity){this.reflex=!this.reflex;}}___default.default.invoke(this.temp,"remove");this.temp=this.graphie.labelAngle({point1:this.coords[0],vertex:this.coords[1],point3:this.coords[2],label:this.labeledAngle,text:this.angleLabel,numArcs:this.numArcs,pushOut:this.pushOut,clockwise:this.reflex===clockwiseReflexive,style:this.angleStyle});},remove:function(){___default.default.invoke(this.rays,"remove");___default.default.invoke(this.temp,"remove");this.labeledAngle.remove();}});
|
|
1628
|
+
const{clockwise: clockwise$3,reverseVector: reverseVector$1}=kmath.geometry;function scaledDistanceFromAngle(angle){const a=3.51470560176242*20;const b=.5687298702748785*20;const c=-0.037587715462826674;return (a-b)*Math.exp(c*angle)+b}function scaledPolarRad(radius,radians){return [radius*Math.cos(radians),radius*Math.sin(radians)*-1]}function scaledPolarDeg(radius,degrees){const radians=degrees*Math.PI/180;return scaledPolarRad(radius,radians)}let dragging=false;const InteractiveUtils={bogusShape:{animate:function(){},attr:function(){},remove:function(){}}};___default.default.extend(GraphUtils.Graphie.prototype,{labelAngle:function(options){const graphie=this;___default.default.defaults(options,{point1:[0,0],vertex:[0,0],point3:[0,0],label:null,numArcs:1,showRightAngleMarker:true,pushOut:0,clockwise:false,style:{}});let text=options.text===undefined?"":options.text;const vertex=options.vertex;const sVertex=graphie.scalePoint(vertex);let p1;let p3;if(options.clockwise){p1=options.point1;p3=options.point3;}else {p1=options.point3;p3=options.point1;}const startAngle=GraphUtils.findAngleDeprecated(p1,vertex);const endAngle=GraphUtils.findAngleDeprecated(p3,vertex);const angle=(endAngle+360-startAngle)%360;const halfAngle=(startAngle+angle/2)%360;const sPadding=5*options.pushOut;let sRadius=sPadding+scaledDistanceFromAngle(angle);const temp=[];if(Math.abs(angle-90)<1e-9&&options.showRightAngleMarker){const v1=kmath.vector.add(sVertex,scaledPolarDeg(sRadius,startAngle));const v2=kmath.vector.add(sVertex,scaledPolarDeg(sRadius,endAngle));sRadius*=Math.SQRT2;const v3=kmath.vector.add(sVertex,scaledPolarDeg(sRadius,halfAngle));[v1,v2].forEach(function(v){temp.push(graphie.scaledPath([v,v3],options.style));});}else {for(let i=0;i<options.numArcs;i++){temp.push(graphie.arc(vertex,graphie.unscaleVector(sRadius),startAngle,endAngle,options.style));sRadius+=3;}}if(text){const match=text.match(/\$deg(\d)?/);if(match){const precision=match[1]||1;text=text.replace(match[0],kmath.KhanMath.toFixedApprox(angle,precision)+"^{\\circ}");}const sOffset=scaledPolarDeg(sRadius+15,halfAngle);const sPosition=kmath.vector.add(sVertex,sOffset);const position=graphie.unscalePoint(sPosition);if(options.label){options.label.setPosition(position);options.label.processMath(text,true);}else {graphie.label(position,text,"center",options.style);}}return temp},labelSide:function(options){const graphie=this;___default.default.defaults(options,{point1:[0,0],point2:[0,0],label:null,text:"",numTicks:0,numArrows:0,clockwise:false,style:{}});let p1;let p2;if(options.clockwise){p1=options.point1;p2=options.point2;}else {p1=options.point2;p2=options.point1;}const midpoint=[(p1[0]+p2[0])/2,(p1[1]+p2[1])/2];const sMidpoint=graphie.scalePoint(midpoint);const parallelAngle=Math.atan2(p2[1]-p1[1],p2[0]-p1[0]);const perpendicularAngle=parallelAngle+Math.PI/2;const temp=[];let sCumulativeOffset=0;if(options.numTicks){const n=options.numTicks;const sSpacing=5;const sHeight=5;const style={...options.style,strokeWidth:2};for(let i=0;i<n;i++){const sOffset=sSpacing*(i-(n-1)/2);const sOffsetVector=scaledPolarRad(sOffset,parallelAngle);const sHeightVector=scaledPolarRad(sHeight,perpendicularAngle);const sPath=[kmath.vector.add(sMidpoint,sOffsetVector,sHeightVector),kmath.vector.add(sMidpoint,sOffsetVector,reverseVector$1(sHeightVector))];temp.push(graphie.scaledPath(sPath,style));}sCumulativeOffset+=sSpacing*(n-1)+15;}if(options.numArrows){const n=options.numArrows;const start=[p1,p2].sort(function(a,b){if(a[1]===b[1]){return a[0]-b[0]}return a[1]-b[1]})[0];const sStart=graphie.scalePoint(start);const style={...options.style,arrows:"->",strokeWidth:2};const sSpacing=5;for(let i=0;i<n;i++){const sOffset=sCumulativeOffset+sSpacing*i;let sOffsetVector=scaledPolarRad(sOffset,parallelAngle);if(start!==p1){sOffsetVector=reverseVector$1(sOffsetVector);}const sEnd=kmath.vector.add(sMidpoint,sOffsetVector);temp.push(graphie.scaledPath([sStart,sEnd],style));}}let text=options.text;if(text){const match=text.match(/\$len(\d)?/);if(match){const distance=GraphUtils.getDistance(p1,p2);const precision=match[1]||1;text=text.replace(match[0],kmath.KhanMath.toFixedApprox(distance,precision));}const sOffset=20;const sOffsetVector=scaledPolarRad(sOffset,perpendicularAngle);const sPosition=kmath.vector.add(sMidpoint,sOffsetVector);const position=graphie.unscalePoint(sPosition);if(options.label){options.label.setPosition(position);options.label.processMath(text,true);}else {graphie.label(position,text,"center",options.style);}}return temp},labelVertex:function(options){const graphie=this;___default.default.defaults(options,{point1:null,vertex:[0,0],point3:null,label:null,text:"",clockwise:false,style:{}});if(!options.text){return}const vertex=options.vertex;const sVertex=graphie.scalePoint(vertex);let p1;let p3;if(options.clockwise){p1=options.point1;p3=options.point3;}else {p1=options.point3;p3=options.point1;}let angle=135;let halfAngle;if(p1&&p3){const startAngle=GraphUtils.findAngleDeprecated(p1,vertex);const endAngle=GraphUtils.findAngleDeprecated(p3,vertex);angle=(endAngle+360-startAngle)%360;halfAngle=(startAngle+angle/2+180)%360;}else if(p1){const parallelAngle=GraphUtils.findAngleDeprecated(vertex,p1);halfAngle=parallelAngle+90;}else if(p3){const parallelAngle=GraphUtils.findAngleDeprecated(p3,vertex);halfAngle=parallelAngle+90;}else {halfAngle=135;}const sRadius=10+scaledDistanceFromAngle(360-angle);const sOffsetVector=scaledPolarDeg(sRadius,halfAngle);const sPosition=kmath.vector.add(sVertex,sOffsetVector);const position=graphie.unscalePoint(sPosition);if(options.label){options.label.setPosition(position);options.label.processMath(options.text,true);}else {graphie.label(position,options.text,"center",options.style);}},addMovablePoint:function(options){const movablePoint=$__default.default.extend(true,{graph:this,coord:[0,0],snapX:0,snapY:0,pointSize:4,highlight:false,dragging:false,visible:true,bounded:true,constraints:{fixed:false,constrainX:false,constrainY:false,fixedAngle:{},fixedDistance:{}},lineStarts:[],lineEnds:[],polygonVertices:[],normalStyle:{},highlightStyle:{fill:KhanColors.INTERACTING,stroke:KhanColors.INTERACTING},labelStyle:{color:KhanColors.INTERACTIVE},vertexLabel:"",mouseTarget:null},options);const normalColor=movablePoint.constraints.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;movablePoint.normalStyle={fill:normalColor,stroke:normalColor,...options.normalStyle};if(options.coordX!==undefined){movablePoint.coord[0]=options.coordX;}if(options.coordY!==undefined){movablePoint.coord[1]=options.coordY;}const graph=movablePoint.graph;const applySnapAndConstraints=function(coord){if(movablePoint.visible&&movablePoint.bounded&&!movablePoint.constraints.fixed){coord=graph.constrainToBounds(coord,10);}let coordX=coord[0];let coordY=coord[1];if(movablePoint.snapX!==0){coordX=Math.round(coordX/movablePoint.snapX)*movablePoint.snapX;}if(movablePoint.snapY!==0){coordY=Math.round(coordY/movablePoint.snapY)*movablePoint.snapY;}if(movablePoint.constraints.fixedDistance.snapPoints){const mouse=graph.scalePoint(coord);let mouseX=mouse[0];let mouseY=mouse[1];const snapRadians=2*Math.PI/movablePoint.constraints.fixedDistance.snapPoints;const radius=movablePoint.constraints.fixedDistance.dist;const centerCoord=movablePoint.constraints.fixedDistance.point;const centerX=(centerCoord[0]-graph.range[0][0])*graph.scale[0];const centerY=(-centerCoord[1]+graph.range[1][1])*graph.scale[1];let mouseXrel=mouseX-centerX;let mouseYrel=-mouseY+centerY;let radians=Math.atan(mouseYrel/mouseXrel);const outsideArcTanRange=mouseXrel<0;if(outsideArcTanRange){radians+=Math.PI;}radians=Math.round(radians/snapRadians)*snapRadians;mouseXrel=radius*Math.cos(radians);mouseYrel=radius*Math.sin(radians);mouseX=mouseXrel+centerX;mouseY=-mouseYrel+centerY;coordX=kmath.KhanMath.roundTo(5,mouseX/graph.scale[0]+graph.range[0][0]);coordY=kmath.KhanMath.roundTo(5,graph.range[1][1]-mouseY/graph.scale[1]);}const result=movablePoint.applyConstraint([coordX,coordY]);return result};movablePoint.applyConstraint=function(coord,extraConstraints,override){let newCoord=coord.slice();const constraints={};if(override){$__default.default.extend(constraints,{fixed:false,constrainX:false,constrainY:false,fixedAngle:{},fixedDistance:{}},extraConstraints);}else {$__default.default.extend(constraints,this.constraints,extraConstraints);}if(constraints.constrainX){newCoord=[this.coord[0],coord[1]];}else if(constraints.constrainY){newCoord=[coord[0],this.coord[1]];}else if(typeof constraints.fixedAngle.angle==="number"&&typeof constraints.fixedDistance.dist==="number"){const vertex=constraints.fixedAngle.vertex.coord||constraints.fixedAngle.vertex;const ref=constraints.fixedAngle.ref.coord||constraints.fixedAngle.ref;const distPoint=constraints.fixedDistance.point.coord||constraints.fixedDistance.point;const constrainedAngle=(constraints.fixedAngle.angle+GraphUtils.findAngleDeprecated(ref,vertex))*Math.PI/180;const length=constraints.fixedDistance.dist;newCoord[0]=length*Math.cos(constrainedAngle)+distPoint[0];newCoord[1]=length*Math.sin(constrainedAngle)+distPoint[1];}else if(typeof constraints.fixedAngle.angle==="number"){const vertex=constraints.fixedAngle.vertex.coord||constraints.fixedAngle.vertex;const ref=constraints.fixedAngle.ref.coord||constraints.fixedAngle.ref;const constrainedAngle=(constraints.fixedAngle.angle+GraphUtils.findAngleDeprecated(ref,vertex))*Math.PI/180;const angle=GraphUtils.findAngleDeprecated(coord,vertex)*Math.PI/180;const distance=GraphUtils.getDistance(coord,vertex);let length=distance*Math.cos(constrainedAngle-angle);length=length<1?1:length;newCoord[0]=length*Math.cos(constrainedAngle)+vertex[0];newCoord[1]=length*Math.sin(constrainedAngle)+vertex[1];}else if(typeof constraints.fixedDistance.dist==="number"){const distPoint=constraints.fixedDistance.point.coord||constraints.fixedDistance.point;let angle=GraphUtils.findAngleDeprecated(coord,distPoint);const length=constraints.fixedDistance.dist;angle=angle*Math.PI/180;newCoord[0]=length*Math.cos(angle)+distPoint[0];newCoord[1]=length*Math.sin(angle)+distPoint[1];}else if(constraints.fixed){newCoord=movablePoint.coord;}return newCoord};movablePoint.coord=applySnapAndConstraints(movablePoint.coord);const highlightScale=2;if(movablePoint.visible){graph.style(movablePoint.normalStyle,function(){const radii=[movablePoint.pointSize/graph.scale[0],movablePoint.pointSize/graph.scale[1]];const options={maxScale:highlightScale,padding:2};movablePoint.visibleShape=new WrappedEllipse(graph,movablePoint.coord,radii,options);const{scale,...styleWithoutScale}=movablePoint.normalStyle;movablePoint.visibleShape.attr(styleWithoutScale);movablePoint.visibleShape.toFront();});}movablePoint.normalStyle.scale=1;movablePoint.highlightStyle.scale=highlightScale;if(movablePoint.vertexLabel){movablePoint.labeledVertex=this.label([0,0],"","center",movablePoint.labelStyle);}movablePoint.drawLabel=function(){if(movablePoint.vertexLabel){movablePoint.graph.labelVertex({vertex:movablePoint.coord,label:movablePoint.labeledVertex,text:movablePoint.vertexLabel,style:movablePoint.labelStyle});}};movablePoint.drawLabel();movablePoint.grab=function(offset){offset=offset||[0,0];$__default.default(document).on("vmousemove.point vmouseup.point",function(event){event.preventDefault();movablePoint.dragging=true;dragging=true;let coord=kmath.vector.add(graph.getMouseCoord(event),offset);coord=applySnapAndConstraints(coord);let coordX=coord[0];let coordY=coord[1];let mouseX;let mouseY;if(event.type==="vmousemove"){let doMove=true;if(typeof movablePoint.onMove==="function"){const result=movablePoint.onMove(coordX,coordY);if(result===false){doMove=false;}if(Array.isArray(result)){coordX=result[0];coordY=result[1];}}mouseX=(coordX-graph.range[0][0])*graph.scale[0];mouseY=(-coordY+graph.range[1][1])*graph.scale[1];if(doMove){const point=graph.unscalePoint([mouseX,mouseY]);movablePoint.visibleShape.moveTo(point);movablePoint.mouseTarget.moveTo(point);movablePoint.coord=[coordX,coordY];movablePoint.updateLineEnds();$__default.default(movablePoint).trigger("move");}movablePoint.drawLabel();}else if(event.type==="vmouseup"){$__default.default(document).unbind(".point");movablePoint.dragging=false;dragging=false;if(typeof movablePoint.onMoveEnd==="function"){const result=movablePoint.onMoveEnd(coordX,coordY);if(Array.isArray(result)){coordX=result[0];coordY=result[1];mouseX=(coordX-graph.range[0][0])*graph.scale[0];mouseY=(-coordY+graph.range[1][1])*graph.scale[1];const point=graph.unscalePoint([mouseX,mouseY]);movablePoint.visibleShape.moveTo(point);movablePoint.mouseTarget.moveTo(point);movablePoint.coord=[coordX,coordY];}}if(!movablePoint.highlight){movablePoint.visibleShape.animate(movablePoint.normalStyle,50);if(movablePoint.onUnhighlight){movablePoint.onUnhighlight();}}}});};if(movablePoint.visible&&!movablePoint.constraints.fixed){if(!movablePoint.mouseTarget){const radii=graph.unscaleVector(16);const options={mouselayer:true,padding:0,disableMouseEventsOnWrapper:true,interactiveKindForTesting:"movable-point"};movablePoint.mouseTarget=new WrappedEllipse(graph,movablePoint.coord,radii,options);movablePoint.mouseTarget.attr({fill:"#000",opacity:0});}const $mouseTarget=$__default.default(movablePoint.mouseTarget.getMouseTarget());$mouseTarget.css("cursor","move");$mouseTarget.on("vmousedown vmouseover vmouseout",function(event){if(event.type==="vmouseover"){movablePoint.highlight=true;if(!dragging){movablePoint.visibleShape.animate(movablePoint.highlightStyle,50);if(movablePoint.onHighlight){movablePoint.onHighlight();}}}else if(event.type==="vmouseout"){movablePoint.highlight=false;if(!movablePoint.dragging&&!dragging){movablePoint.visibleShape.animate(movablePoint.normalStyle,50);if(movablePoint.onUnhighlight){movablePoint.onUnhighlight();}}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();const startCoord=movablePoint.coord;const startMouseCoord=graph.getMouseCoord(event);const isMouse=!("ontouchstart"in window);const touchOffset=isMouse?[0,0]:kmath.vector.subtract(startCoord,startMouseCoord);movablePoint.grab(touchOffset);}});}movablePoint.moveTo=function(coordX,coordY,updateLines){const distance=GraphUtils.getDistance(this.graph.scalePoint([coordX,coordY]),this.graph.scalePoint(this.coord));const time=distance*5;const cb=updateLines&&function(coord){movablePoint.coord=coord;movablePoint.updateLineEnds();};this.visibleShape.animateTo([coordX,coordY],time,cb);this.mouseTarget.animateTo([coordX,coordY],time,cb);this.coord=[coordX,coordY];if(typeof this.onMove==="function"){this.onMove(coordX,coordY);}};movablePoint.updateLineEnds=function(){$__default.default(this.lineStarts).each(function(){this.coordA=movablePoint.coord;this.transform();});$__default.default(this.lineEnds).each(function(){this.coordZ=movablePoint.coord;this.transform();});$__default.default(this.polygonVertices).each(function(){this.transform();});};movablePoint.setCoord=function(coord){if(this.visible){this.visibleShape.moveTo(coord);if(this.mouseTarget!=null){this.mouseTarget.moveTo(coord);}}this.coord=coord.slice();};movablePoint.setCoordConstrained=function(coord){this.setCoord(applySnapAndConstraints(coord));};movablePoint.toBack=function(){if(this.visible){if(this.mouseTarget!=null){this.mouseTarget.toBack();}this.visibleShape.toBack();}};movablePoint.toFront=function(){if(this.visible){if(this.mouseTarget!=null){this.mouseTarget.toFront();}this.visibleShape.toFront();}};movablePoint.remove=function(){if(this.visibleShape){this.visibleShape.remove();}if(this.mouseTarget){this.mouseTarget.remove();}if(this.labeledVertex){this.labeledVertex.remove();}};return movablePoint},addMovableLineSegment:function(options){const lineSegment=$__default.default.extend({graph:this,coordA:[0,0],coordZ:[1,1],snapX:0,snapY:0,fixed:false,ticks:0,normalStyle:{},highlightStyle:{stroke:KhanColors.INTERACTING,"stroke-width":6},labelStyle:{stroke:KhanColors.INTERACTIVE,color:KhanColors.INTERACTIVE},highlight:false,dragging:false,tick:[],extendLine:false,extendRay:false,constraints:{fixed:false,constrainX:false,constrainY:false},sideLabel:"",vertexLabels:[],numArrows:0,numTicks:0,movePointsWithLine:false},options);const normalColor=lineSegment.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;lineSegment.normalStyle={"stroke-width":2,stroke:normalColor,...options.normalStyle};lineSegment.arrowStyle={...lineSegment.normalStyle,color:lineSegment.normalStyle.stroke};if(options.pointA!==undefined){lineSegment.coordA=options.pointA.coord;lineSegment.pointA.lineStarts.push(lineSegment);}else if(options.coordA!==undefined){lineSegment.coordA=options.coordA.slice();}if(options.pointZ!==undefined){lineSegment.coordZ=options.pointZ.coord;lineSegment.pointZ.lineEnds.push(lineSegment);}else if(options.coordA!==undefined){lineSegment.coordA=lineSegment.coordA.slice();}const graph=lineSegment.graph;graph.style(lineSegment.normalStyle);for(let i=0;i<lineSegment.ticks;++i){lineSegment.tick[i]=InteractiveUtils.bogusShape;}let path=GraphUtils.unscaledSvgPath([[0,0],[1,0]]);for(let i=0;i<lineSegment.ticks;++i){const tickoffset=.5-(lineSegment.ticks-1+i*2)/graph.scale[0];path+=GraphUtils.unscaledSvgPath([[tickoffset,-7],[tickoffset,7]]);}options={thickness:Math.max(lineSegment.normalStyle["stroke-width"],lineSegment.highlightStyle["stroke-width"])};lineSegment.visibleLine=new WrappedLine(graph,[0,0],[1,0],options);lineSegment.visibleLine.attr(lineSegment.normalStyle);if(!lineSegment.fixed){const options={thickness:30,mouselayer:true,interactiveKindForTesting:"movable-line"};lineSegment.mouseTarget=new WrappedLine(graph,[0,0],[1,0],options);lineSegment.mouseTarget.attr({fill:"#000",opacity:0});}lineSegment.transform=function(syncToPoints){if(syncToPoints){if(typeof this.pointA==="object"){this.coordA=this.pointA.coord;}if(typeof this.pointZ==="object"){this.coordZ=this.pointZ.coord;}}const getScaledAngle=function(line){const scaledA=line.graph.scalePoint(line.coordA);const scaledZ=line.graph.scalePoint(line.coordZ);return kmath.vector.polarDegFromCart(kmath.vector.subtract(scaledZ,scaledA))[1]};const getClipPoint=function(graph,coord,angle){graph=lineSegment.graph;const xExtent=graph.range[0][1]-graph.range[0][0];const yExtent=graph.range[1][1]-graph.range[1][0];const distance=xExtent+yExtent;const angleVec=graph.unscaleVector(kmath.vector.cartFromPolarDeg(1,angle));const distVec=kmath.vector.scale(kmath.vector.normalize(angleVec),distance);const farCoord=kmath.vector.add(coord,distVec);const scaledAngle=kmath.vector.polarDegFromCart(angleVec)[1];const clipPoint=graph.constrainToBoundsOnAngle(farCoord,4,scaledAngle*Math.PI/180);return clipPoint};const angle=getScaledAngle(this);let start=this.coordA;let end=this.coordZ;if(this.extendLine){start=getClipPoint(graph,start,360-angle);end=getClipPoint(graph,end,(540-angle)%360);}else if(this.extendRay){end=getClipPoint(graph,start,360-angle);}const elements=[this.visibleLine];if(!this.fixed){elements.push(this.mouseTarget);}elements.forEach(function(element){element.moveTo(start,end);});if(this._arrows==null){this._arrows=[];if(this.extendLine){this._arrows.push(new Arrowhead$1(graph,this.normalStyle));this._arrows.push(new Arrowhead$1(graph,this.normalStyle));}else if(this.extendRay){this._arrows.push(new Arrowhead$1(graph,this.normalStyle));}}const coordForArrow=[this.coordA,this.coordZ];const angleForArrow=[360-angle,(540-angle)%360];this._arrows.forEach(function(arrow,i){arrow.toCoordAtAngle(coordForArrow[i],angleForArrow[i]);});___default.default.invoke(this.temp,"remove");this.temp=[];const isClockwise=this.coordA[0]<this.coordZ[0]||this.coordA[0]===this.coordZ[0]&&this.coordA[1]>this.coordZ[1];if(this.sideLabel){this.temp.push(this.graph.labelSide({point1:this.coordA,point2:this.coordZ,label:this.labeledSide,text:this.sideLabel,numArrows:this.numArrows,numTicks:this.numTicks,clockwise:isClockwise,style:this.labelStyle}));}if(this.vertexLabels.length){this.graph.labelVertex({vertex:this.coordA,point3:this.coordZ,label:this.labeledVertices[0],text:this.vertexLabels[0],clockwise:isClockwise,style:this.labelStyle});this.graph.labelVertex({point1:this.coordA,vertex:this.coordZ,label:this.labeledVertices[1],text:this.vertexLabels[1],clockwise:isClockwise,style:this.labelStyle});}this.temp=this.temp.flat(Infinity);};lineSegment.toBack=function(){if(!lineSegment.fixed){lineSegment.mouseTarget.toBack();}lineSegment.visibleLine.toBack();};lineSegment.toFront=function(){if(!lineSegment.fixed){lineSegment.mouseTarget.toFront();}lineSegment.visibleLine.toFront();};lineSegment.remove=function(){if(!lineSegment.fixed){lineSegment.mouseTarget.remove();}lineSegment.visibleLine.remove();if(lineSegment.labeledSide){lineSegment.labeledSide.remove();}if(lineSegment.labeledVertices){___default.default.invoke(lineSegment.labeledVertices,"remove");}if(lineSegment._arrows){___default.default.invoke(lineSegment._arrows,"remove");}if(lineSegment.temp.length){___default.default.invoke(lineSegment.temp,"remove");}};lineSegment.hide=function(){lineSegment.visibleLine.hide();if(lineSegment.temp.length){___default.default.invoke(lineSegment.temp,"hide");}if(lineSegment._arrows){___default.default.invoke(lineSegment._arrows,"hide");}};lineSegment.show=function(){lineSegment.visibleLine.show();if(lineSegment.temp.length){___default.default.invoke(lineSegment.temp,"show");}if(lineSegment._arrows){___default.default.invoke(lineSegment._arrows,"show");}};if(lineSegment.sideLabel){lineSegment.labeledSide=this.label([0,0],"","center",lineSegment.labelStyle);}if(lineSegment.vertexLabels.length){lineSegment.labeledVertices=lineSegment.vertexLabels.map(label=>{return this.label([0,0],"","center",lineSegment.labelStyle)});}if(!lineSegment.fixed&&!lineSegment.constraints.fixed){const $mouseTarget=$__default.default(lineSegment.mouseTarget.getMouseTarget());$mouseTarget.css("cursor","move");$mouseTarget.on("vmousedown vmouseover vmouseout",function(event){if(event.type==="vmouseover"){if(!dragging){lineSegment.highlight=true;lineSegment.visibleLine.animate(lineSegment.highlightStyle,50);lineSegment.arrowStyle={...lineSegment.arrowStyle,color:lineSegment.highlightStyle.stroke,stroke:lineSegment.highlightStyle.stroke};lineSegment.transform();}}else if(event.type==="vmouseout"){lineSegment.highlight=false;if(!lineSegment.dragging){lineSegment.visibleLine.animate(lineSegment.normalStyle,50);lineSegment.arrowStyle={...lineSegment.arrowStyle,color:lineSegment.normalStyle.stroke,stroke:lineSegment.normalStyle.stroke};lineSegment.transform();}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();let coordX=(event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left)/graph.scale[0]+graph.range[0][0];let coordY=graph.range[1][1]-(event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top)/graph.scale[1];if(lineSegment.snapX>0){coordX=Math.round(coordX/lineSegment.snapX)*lineSegment.snapX;}if(lineSegment.snapY>0){coordY=Math.round(coordY/lineSegment.snapY)*lineSegment.snapY;}const mouseOffsetA=[lineSegment.coordA[0]-coordX,lineSegment.coordA[1]-coordY];const mouseOffsetZ=[lineSegment.coordZ[0]-coordX,lineSegment.coordZ[1]-coordY];const offsetLeft=-Math.min(graph.scaleVector(mouseOffsetA)[0],graph.scaleVector(mouseOffsetZ)[0]);const offsetRight=Math.max(graph.scaleVector(mouseOffsetA)[0],graph.scaleVector(mouseOffsetZ)[0]);const offsetTop=Math.max(graph.scaleVector(mouseOffsetA)[1],graph.scaleVector(mouseOffsetZ)[1]);const offsetBottom=-Math.min(graph.scaleVector(mouseOffsetA)[1],graph.scaleVector(mouseOffsetZ)[1]);$__default.default(document).on("vmousemove.lineSegment vmouseup.lineSegment",function(event){event.preventDefault();lineSegment.dragging=true;dragging=true;let mouseX=event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top;mouseX=Math.max(offsetLeft+10,Math.min(graph.xpixels-10-offsetRight,mouseX));mouseY=Math.max(offsetTop+10,Math.min(graph.ypixels-10-offsetBottom,mouseY));let coordX=mouseX/graph.scale[0]+graph.range[0][0];let coordY=graph.range[1][1]-mouseY/graph.scale[1];if(lineSegment.snapX>0){coordX=Math.round(coordX/lineSegment.snapX)*lineSegment.snapX;}if(lineSegment.snapY>0){coordY=Math.round(coordY/lineSegment.snapY)*lineSegment.snapY;}if(event.type==="vmousemove"){if(lineSegment.constraints.constrainX){coordX=lineSegment.coordA[0]-mouseOffsetA[0];}if(lineSegment.constraints.constrainY){coordY=lineSegment.coordA[1]-mouseOffsetA[1];}const dX=coordX+mouseOffsetA[0]-lineSegment.coordA[0];const dY=coordY+mouseOffsetA[1]-lineSegment.coordA[1];lineSegment.coordA=[coordX+mouseOffsetA[0],coordY+mouseOffsetA[1]];lineSegment.coordZ=[coordX+mouseOffsetZ[0],coordY+mouseOffsetZ[1]];lineSegment.transform();if(lineSegment.movePointsWithLine){if(typeof lineSegment.pointA==="object"){lineSegment.pointA.setCoord([lineSegment.pointA.coord[0]+dX,lineSegment.pointA.coord[1]+dY]);}if(typeof lineSegment.pointZ==="object"){lineSegment.pointZ.setCoord([lineSegment.pointZ.coord[0]+dX,lineSegment.pointZ.coord[1]+dY]);}}if(typeof lineSegment.onMove==="function"){lineSegment.onMove(dX,dY);}}else if(event.type==="vmouseup"){$__default.default(document).unbind(".lineSegment");lineSegment.dragging=false;dragging=false;if(!lineSegment.highlight){lineSegment.visibleLine.animate(lineSegment.normalStyle,50);lineSegment.arrowStyle={...lineSegment.arrowStyle,color:lineSegment.normalStyle.stroke,stroke:lineSegment.normalStyle.stroke};lineSegment.transform();}if(typeof lineSegment.onMoveEnd==="function"){lineSegment.onMoveEnd();}}$__default.default(lineSegment).trigger("move");});}});}if(lineSegment.pointA!==undefined){lineSegment.pointA.toFront();}if(lineSegment.pointZ!==undefined){lineSegment.pointZ.toFront();}lineSegment.transform();return lineSegment},addMovablePolygon:function(options){const graphie=this;const{points,...optionsWithoutPoints}=options;const polygon=$__default.default.extend({snapX:0,snapY:0,fixed:false,constrainToGraph:true,normalStyle:{},highlightStyle:{stroke:KhanColors.INTERACTING,"stroke-width":2,fill:KhanColors.INTERACTING,"fill-opacity":.05},pointHighlightStyle:{fill:KhanColors.INTERACTING,stroke:KhanColors.INTERACTING},labelStyle:{stroke:KhanColors.DYNAMIC,"stroke-width":1,color:KhanColors.DYNAMIC},angleLabels:[],showRightAngleMarkers:[],sideLabels:[],vertexLabels:[],numArcs:[],numArrows:[],numTicks:[],updateOnPointMove:true,closed:true},optionsWithoutPoints);const normalColor=polygon.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;polygon.normalStyle={"stroke-width":2,"fill-opacity":0,fill:normalColor,stroke:normalColor,...options.normalStyle};polygon.points=options.points;const isPoint=function(coordOrPoint){return !Array.isArray(coordOrPoint)};polygon.update=function(){const n=polygon.points.length;polygon.coords=polygon.points.map(function(coordOrPoint,i){if(isPoint(coordOrPoint)){return coordOrPoint.coord}return coordOrPoint});polygon.left=Math.min(...polygon.coords.map(coord=>coord[0]));polygon.right=Math.max(...polygon.coords.map(coord=>coord[0]));polygon.top=Math.max(...polygon.coords.map(coord=>coord[1]));polygon.bottom=Math.min(...polygon.coords.map(coord=>coord[1]));let scaledCoords=polygon.coords.map(function(coord){return graphie.scalePoint(coord)});if(polygon.closed){scaledCoords.push(true);}else {scaledCoords=scaledCoords.concat([...scaledCoords].reverse());}polygon.path=GraphUtils.unscaledSvgPath(scaledCoords);___default.default.invoke(polygon.temp,"remove");polygon.temp=[];const isClockwise=clockwise$3(polygon.coords);if(polygon.angleLabels.length||polygon.showRightAngleMarkers.length){polygon.labeledAngles.forEach(function(label,i){polygon.temp.push(graphie.labelAngle({point1:polygon.coords[(i-1+n)%n],vertex:polygon.coords[i],point3:polygon.coords[(i+1)%n],label:label,text:polygon.angleLabels[i],showRightAngleMarker:polygon.showRightAngleMarkers[i],numArcs:polygon.numArcs[i],clockwise:isClockwise,style:polygon.labelStyle}));});}if(polygon.sideLabels.length){polygon.labeledSides.forEach(function(label,i){polygon.temp.push(graphie.labelSide({point1:polygon.coords[i],point2:polygon.coords[(i+1)%n],label:label,text:polygon.sideLabels[i],numArrows:polygon.numArrows[i],numTicks:polygon.numTicks[i],clockwise:isClockwise,style:polygon.labelStyle}));});}if(polygon.vertexLabels.length){polygon.labeledVertices.forEach(function(label,i){graphie.labelVertex({point1:polygon.coords[(i-1+n)%n],vertex:polygon.coords[i],point3:polygon.coords[(i+1)%n],label:label,text:polygon.vertexLabels[i],clockwise:isClockwise,style:polygon.labelStyle});});}polygon.temp=polygon.temp.flat(Infinity);};polygon.transform=function(){polygon.update();polygon.visibleShape.attr({path:polygon.path});if(!polygon.fixed){polygon.mouseTarget.attr({path:polygon.path});}};polygon.remove=function(){polygon.visibleShape.remove();if(!polygon.fixed){polygon.mouseTarget.remove();}if(polygon.labeledAngles){___default.default.invoke(polygon.labeledAngles,"remove");}if(polygon.labeledSides){___default.default.invoke(polygon.labeledSides,"remove");}if(polygon.labeledVertices){___default.default.invoke(polygon.labeledVertices,"remove");}if(polygon.temp.length){___default.default.invoke(polygon.temp,"remove");}};polygon.toBack=function(){if(!polygon.fixed){polygon.mouseTarget.toBack();}polygon.visibleShape.toBack();};polygon.toFront=function(){if(!polygon.fixed){polygon.mouseTarget.toFront();}polygon.visibleShape.toFront();};if(polygon.updateOnPointMove){polygon.points.filter(isPoint).forEach(function(coordOrPoint){coordOrPoint.polygonVertices.push(polygon);});}polygon.coords=new Array(polygon.points.length);if(polygon.angleLabels.length){const numLabels=Math.max(polygon.angleLabels.length,polygon.showRightAngleMarkers.length);polygon.labeledAngles=Array.from({length:numLabels},()=>{return this.label([0,0],"","center",polygon.labelStyle)});}if(polygon.sideLabels.length){polygon.labeledSides=polygon.sideLabels.map(label=>{return this.label([0,0],"","center",polygon.labelStyle)});}if(polygon.vertexLabels.length){polygon.labeledVertices=polygon.vertexLabels.map(label=>{return this.label([0,0],"","center",polygon.labelStyle)});}polygon.update();polygon.visibleShape=graphie.raphael.path(polygon.path);polygon.visibleShape.attr(polygon.normalStyle);if(!polygon.fixed){polygon.mouseTarget=graphie.mouselayer.path(polygon.path);polygon.mouseTarget.attr({fill:"#000",opacity:0,cursor:"move"});$__default.default(polygon.mouseTarget[0]).on("vmousedown vmouseover vmouseout",function(event){if(event.type==="vmouseover"){if(!dragging||polygon.dragging){polygon.highlight=true;polygon.visibleShape.animate(polygon.highlightStyle,50);polygon.points.filter(isPoint).forEach(function(point){point.visibleShape.animate(polygon.pointHighlightStyle,50);});}}else if(event.type==="vmouseout"){polygon.highlight=false;if(!polygon.dragging){polygon.visibleShape.animate(polygon.normalStyle,50);const points=polygon.points.filter(isPoint);if(!points.some(point=>point.dragging)){points.forEach(function(point){point.visibleShape.animate(point.normalStyle,50);});}}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();polygon.points.filter(isPoint).forEach(function(point){point.dragging=true;});let startX=(event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left)/graphie.scale[0]+graphie.range[0][0];let startY=graphie.range[1][1]-(event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top)/graphie.scale[1];if(polygon.snapX>0){startX=Math.round(startX/polygon.snapX)*polygon.snapX;}if(polygon.snapY>0){startY=Math.round(startY/polygon.snapY)*polygon.snapY;}let lastX=startX;let lastY=startY;const polygonCoords=polygon.coords.slice();const offsetLeft=(startX-polygon.left)*graphie.scale[0];const offsetRight=(polygon.right-startX)*graphie.scale[0];const offsetTop=(polygon.top-startY)*graphie.scale[1];const offsetBottom=(startY-polygon.bottom)*graphie.scale[1];$__default.default(document).on("vmousemove.polygon vmouseup.polygon",function(event){event.preventDefault();polygon.dragging=true;dragging=true;let mouseX=event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top;if(polygon.constrainToGraph){mouseX=Math.max(offsetLeft+10,Math.min(graphie.xpixels-10-offsetRight,mouseX));mouseY=Math.max(offsetTop+10,Math.min(graphie.ypixels-10-offsetBottom,mouseY));}let currentX=mouseX/graphie.scale[0]+graphie.range[0][0];let currentY=graphie.range[1][1]-mouseY/graphie.scale[1];if(polygon.snapX>0){currentX=Math.round(currentX/polygon.snapX)*polygon.snapX;}if(polygon.snapY>0){currentY=Math.round(currentY/polygon.snapY)*polygon.snapY;}if(event.type==="vmousemove"){let dX=currentX-startX;let dY=currentY-startY;let doMove=true;if(typeof polygon.onMove==="function"){const onMoveResult=polygon.onMove(dX,dY);if(onMoveResult===false){doMove=false;}else if(Array.isArray(onMoveResult)){dX=onMoveResult[0];dY=onMoveResult[1];currentX=startX+dX;currentY=startY+dY;}}const increment=function(i){return [polygonCoords[i][0]+dX,polygonCoords[i][1]+dY]};if(doMove){polygon.points.forEach(function(coordOrPoint,i){if(isPoint(coordOrPoint)){coordOrPoint.setCoord(increment(i));}else {polygon.points[i]=increment(i);}});polygon.transform();$__default.default(polygon).trigger("move");lastX=currentX;lastY=currentY;}}else if(event.type==="vmouseup"){$__default.default(document).unbind(".polygon");const points=polygon.points.filter(isPoint);points.forEach(function(point){point.dragging=false;});polygon.dragging=false;dragging=false;if(!polygon.highlight){polygon.visibleShape.animate(polygon.normalStyle,50);points.forEach(function(point){point.visibleShape.animate(point.normalStyle,50);});}if(typeof polygon.onMoveEnd==="function"){polygon.onMoveEnd(lastX-startX,lastY-startY);}}});}});}___default.default.invoke(polygon.points.filter(isPoint),"toFront");return polygon},constrainToBounds:function(point,padding){const lower=this.unscalePoint([padding,this.ypixels-padding]);const upper=this.unscalePoint([this.xpixels-padding,padding]);const coordX=Math.max(lower[0],Math.min(upper[0],point[0]));const coordY=Math.max(lower[1],Math.min(upper[1],point[1]));return [coordX,coordY]},constrainToBoundsOnAngle:function(point,padding,angle){const lower=this.unscalePoint([padding,this.ypixels-padding]);const upper=this.unscalePoint([this.xpixels-padding,padding]);let result=point.slice();if(result[0]<lower[0]){result=[lower[0],result[1]+(lower[0]-result[0])*Math.tan(angle)];}else if(result[0]>upper[0]){result=[upper[0],result[1]-(result[0]-upper[0])*Math.tan(angle)];}if(result[1]<lower[1]){result=[result[0]+(lower[1]-result[1])/Math.tan(angle),lower[1]];}else if(result[1]>upper[1]){result=[result[0]-(result[1]-upper[1])/Math.tan(angle),upper[1]];}return result},addMovableAngle:function(options){return new MovableAngle(this,options)},addCircleGraph:function(options){const graphie=this;const circle=$__default.default.extend({center:[0,0],radius:2,snapX:.5,snapY:.5,snapRadius:.5,minRadius:1,centerConstraints:{},centerNormalStyle:{},centerHighlightStyle:{stroke:KhanColors.INTERACTING,fill:KhanColors.INTERACTING},circleNormalStyle:{stroke:KhanColors.INTERACTIVE,"fill-opacity":0},circleHighlightStyle:{stroke:KhanColors.INTERACTING,fill:KhanColors.INTERACTING,"fill-opacity":.05}},options);const normalColor=circle.centerConstraints.fixed?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;const centerNormalStyle=options?options.centerNormalStyle:null;circle.centerNormalStyle={fill:normalColor,stroke:normalColor,...centerNormalStyle};circle.centerPoint=graphie.addMovablePoint({graph:graphie,coord:circle.center,normalStyle:circle.centerNormalStyle,snapX:circle.snapX,snapY:circle.snapY,constraints:circle.centerConstraints});circle.circ=graphie.circle(circle.center,circle.radius,circle.circleNormalStyle);circle.perim=graphie.mouselayer.circle(graphie.scalePoint(circle.center)[0],graphie.scalePoint(circle.center)[1],graphie.scaleVector(circle.radius)[0]).attr({"stroke-width":20,opacity:.002});if(!circle.centerConstraints.fixed){$__default.default(circle.centerPoint.mouseTarget.getMouseTarget()).on("vmouseover vmouseout",function(event){if(circle.centerPoint.highlight||circle.centerPoint.dragging){circle.circ.animate(circle.circleHighlightStyle,50);}else {circle.circ.animate(circle.circleNormalStyle,50);}});}circle.toFront=function(){circle.circ.toFront();circle.perim.toFront();circle.centerPoint.visibleShape.toFront();if(!circle.centerConstraints.fixed){circle.centerPoint.mouseTarget.toFront();}};circle.centerPoint.onMove=function(x,y){circle.toFront();circle.circ.attr({cx:graphie.scalePoint(x)[0],cy:graphie.scalePoint(y)[1]});circle.perim.attr({cx:graphie.scalePoint(x)[0],cy:graphie.scalePoint(y)[1]});if(circle.onMove){circle.onMove(x,y);}};$__default.default(circle.centerPoint).on("move",function(){circle.center=this.coord;$__default.default(circle).trigger("move");});circle.setCenter=function(x,y){circle.centerPoint.setCoord([x,y]);circle.centerPoint.onMove(x,y);circle.center=[x,y];};circle.setRadius=function(r){circle.radius=r;circle.perim.attr({r:graphie.scaleVector(r)[0]});circle.circ.attr({rx:graphie.scaleVector(r)[0],ry:graphie.scaleVector(r)[1]});};circle.remove=function(){circle.centerPoint.remove();circle.circ.remove();circle.perim.remove();};const cursorAxes=[[Math.PI*-1,Math.PI*-0.875,"ew-resize"],[Math.PI*-0.875,Math.PI*-0.625,"nesw-resize"],[Math.PI*-0.625,Math.PI*-0.375,"ns-resize"],[Math.PI*-0.375,Math.PI*-0.125,"nwse-resize"],[Math.PI*-0.125,Math.PI*.125,"ew-resize"],[Math.PI*.125,Math.PI*.375,"nesw-resize"],[Math.PI*.375,Math.PI*.625,"ns-resize"],[Math.PI*.625,Math.PI*.875,"nwse-resize"],[Math.PI*.875,Math.PI*1,"ew-resize"]];$__default.default(circle.perim.node).on("vmousemove",event=>{let[x,y]=this.getMouseCoord(event);x-=circle.center[0];y-=circle.center[1];const theta=Math.atan2(y,x);cursorAxes.forEach(function(axes){const[min,max,cursorName]=axes;if(theta>=min&&theta<max){$__default.default(circle.perim.node).css("cursor",cursorName);}});});$__default.default(circle.perim.node).css("cursor","nesw-resize");circle.perim.node.addEventListener("touchstart",function(event){event.preventDefault();},{passive:false});$__default.default(circle.perim.node).on("vmouseover vmouseout vmousedown",function(event){if(event.type==="vmouseover"){circle.highlight=true;if(!dragging){circle.circ.animate(circle.circleHighlightStyle,50);circle.centerPoint.visibleShape.animate(circle.centerHighlightStyle,50);}}else if(event.type==="vmouseout"){circle.highlight=false;if(!circle.dragging&&!circle.centerPoint.dragging){circle.circ.animate(circle.circleNormalStyle,50);circle.centerPoint.visibleShape.animate(circle.centerNormalStyle,50);}}else if(event.type==="vmousedown"&&(event.which===1||event.which===0)){event.preventDefault();circle.toFront();const startRadius=circle.radius;$__default.default(document).on("vmousemove vmouseup",function(event){event.preventDefault();circle.dragging=true;dragging=true;if(event.type==="vmousemove"){const coord=graphie.constrainToBounds(graphie.getMouseCoord(event),10);let radius=GraphUtils.getDistance(circle.centerPoint.coord,coord);radius=Math.max(circle.minRadius,Math.round(radius/circle.snapRadius)*circle.snapRadius);const oldRadius=circle.radius;let doResize=true;if(circle.onResize){const onResizeResult=circle.onResize(radius,oldRadius);if(typeof onResizeResult==="number"){radius=onResizeResult;}else if(onResizeResult===false){doResize=false;}}if(doResize){circle.setRadius(radius);$__default.default(circle).trigger("move");}}else if(event.type==="vmouseup"){$__default.default(document).off("vmousemove vmouseup");circle.dragging=false;dragging=false;if(circle.onResizeEnd){circle.onResizeEnd(circle.radius,startRadius);}}});}});return circle},addRotateHandle:function(){const drawRotateHandle=function(graphie,center,radius,halfWidth,lengthAngle,angle,interacting){const getRotateHandlePoint=function(offset,distanceFromArrowMidline){const distFromRotationCenter=radius+distanceFromArrowMidline;const vec=kmath.vector.cartFromPolarDeg(distFromRotationCenter,angle+offset);const absolute=kmath.vector.add(center,vec);const pixels=graphie.scalePoint(absolute);return pixels[0]+","+pixels[1]};const innerR=graphie.scaleVector(radius-halfWidth);const outerR=graphie.scaleVector(radius+halfWidth);return graphie.raphael.path(" M"+getRotateHandlePoint(lengthAngle,-halfWidth)+" L"+getRotateHandlePoint(lengthAngle,-3*halfWidth)+" L"+getRotateHandlePoint(2*lengthAngle,0)+" L"+getRotateHandlePoint(lengthAngle,3*halfWidth)+" L"+getRotateHandlePoint(lengthAngle,halfWidth)+" A"+outerR[0]+","+outerR[1]+",0,0,1,"+getRotateHandlePoint(-lengthAngle,halfWidth)+" L"+getRotateHandlePoint(-lengthAngle,3*halfWidth)+" L"+getRotateHandlePoint(-2*lengthAngle,0)+" L"+getRotateHandlePoint(-lengthAngle,-3*halfWidth)+" L"+getRotateHandlePoint(-lengthAngle,-halfWidth)+" A"+innerR[0]+","+innerR[1]+",0,0,0,"+getRotateHandlePoint(lengthAngle,-halfWidth)+" Z").attr({stroke:null,fill:interacting?KhanColors.INTERACTING:KhanColors.INTERACTIVE})};return function(options){const graph=this;let rotatePoint=options.center;const radius=options.radius;const lengthAngle=options.lengthAngle||30;const hideArrow=options.hideArrow||false;const mouseTarget=options.mouseTarget;const id=___default.default.uniqueId("rotateHandle");if(Array.isArray(rotatePoint)){rotatePoint={coord:rotatePoint};}const rotateHandle=graph.addMovablePoint({coord:kmath.point.addVector(rotatePoint.coord,kmath.vector.cartFromPolarDeg(radius,options.angleDeg||0)),constraints:{fixedDistance:{dist:radius,point:rotatePoint}},mouseTarget:mouseTarget});rotatePoint.toFront();let rotatePointPrevCoord=rotatePoint.coord;let rotateHandlePrevCoord=rotateHandle.coord;let rotateHandleStartCoord=rotateHandlePrevCoord;let isRotating=false;let isHovering=false;let drawnRotateHandle;const redrawRotateHandle=function(handleCoord){if(hideArrow){return}const handleVec=kmath.vector.subtract(handleCoord,rotatePoint.coord);const handlePolar=kmath.vector.polarDegFromCart(handleVec);const angle=handlePolar[1];if(drawnRotateHandle){drawnRotateHandle.remove();}drawnRotateHandle=drawRotateHandle(graph,rotatePoint.coord,options.radius,isRotating||isHovering?options.hoverWidth/2:options.width/2,lengthAngle,angle,isRotating||isHovering);};$__default.default(rotatePoint).on("move."+id,function(){const delta=kmath.vector.subtract(rotatePoint.coord,rotatePointPrevCoord);rotateHandle.setCoord(kmath.vector.add(rotateHandle.coord,delta));redrawRotateHandle(rotateHandle.coord);rotatePointPrevCoord=rotatePoint.coord;rotateHandle.constraints.fixedDistance.point=rotatePoint;rotateHandlePrevCoord=rotateHandle.coord;});rotateHandle.onMove=function(x,y){if(!isRotating){rotateHandleStartCoord=rotateHandlePrevCoord;isRotating=true;}let coord=[x,y];if(options.onMove){const oldPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(rotateHandlePrevCoord,rotatePoint.coord));const newPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(coord,rotatePoint.coord));const oldAngle=oldPolar[1];const newAngle=newPolar[1];let result=options.onMove(newAngle,oldAngle);if(result!=null&&result!==true){if(result===false){result=oldAngle;}coord=kmath.vector.add(rotatePoint.coord,kmath.vector.cartFromPolarDeg(oldPolar[0],result));}}redrawRotateHandle(coord);rotateHandlePrevCoord=coord;return coord};rotateHandle.onMoveEnd=function(){isRotating=false;redrawRotateHandle(rotateHandle.coord);if(options.onMoveEnd){const oldPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(rotateHandleStartCoord,rotatePoint.coord));const newPolar=kmath.vector.polarDegFromCart(kmath.vector.subtract(rotateHandle.coord,rotatePoint.coord));options.onMoveEnd(newPolar[1],oldPolar[1]);}};rotateHandle.visibleShape.remove();if(!mouseTarget){rotateHandle.mouseTarget.attr({scale:2});}const $mouseTarget=$__default.default(rotateHandle.mouseTarget.getMouseTarget());$mouseTarget.on("vmouseover",function(e){isHovering=true;redrawRotateHandle(rotateHandle.coord);});$mouseTarget.on("vmouseout",function(e){isHovering=false;redrawRotateHandle(rotateHandle.coord);});redrawRotateHandle(rotateHandle.coord);const oldRemove=rotateHandle.remove;rotateHandle.remove=function(){oldRemove.call(rotateHandle);if(drawnRotateHandle){drawnRotateHandle.remove();}$__default.default(rotatePoint).off("move."+id);};rotateHandle.update=function(){redrawRotateHandle(rotateHandle.coord);};return rotateHandle}}(),addReflectButton:function(){const drawButton=function(graphie,buttonCoord,lineCoords,size,distanceFromCenter,leftStyle,rightStyle){if(kmath.point.equal(lineCoords[0],lineCoords[1])){lineCoords=[lineCoords[0],kmath.point.addVector(lineCoords[0],[1,1])];}const lineDirection=kmath.vector.normalize(kmath.vector.subtract(lineCoords[1],lineCoords[0]));const lineVec=kmath.vector.scale(lineDirection,size/2);const centerVec=kmath.vector.scale(lineDirection,distanceFromCenter);const leftCenterVec=kmath.vector.rotateDeg(centerVec,90);const rightCenterVec=kmath.vector.rotateDeg(centerVec,-90);const negLineVec=kmath.vector.negate(lineVec);const leftVec=kmath.vector.rotateDeg(lineVec,90);const rightVec=kmath.vector.rotateDeg(lineVec,-90);const leftCenter=kmath.point.addVectors(buttonCoord,leftCenterVec);const rightCenter=kmath.point.addVectors(buttonCoord,rightCenterVec);const leftCoord1=kmath.point.addVectors(buttonCoord,leftCenterVec,lineVec,leftVec);const leftCoord2=kmath.point.addVectors(buttonCoord,leftCenterVec,negLineVec,leftVec);const rightCoord1=kmath.point.addVectors(buttonCoord,rightCenterVec,lineVec,rightVec);const rightCoord2=kmath.point.addVectors(buttonCoord,rightCenterVec,negLineVec,rightVec);const leftButton=graphie.path([leftCenter,leftCoord1,leftCoord2,true],leftStyle);const rightButton=graphie.path([rightCenter,rightCoord1,rightCoord2,true],rightStyle);return {remove:function(){leftButton.remove();rightButton.remove();}}};return function(options){const graphie=this;const line=options.line;const button=graphie.addMovablePoint({constraints:options.constraints,coord:kmath.line.midpoint([line.pointA.coord,line.pointZ.coord]),snapX:graphie.snap[0],snapY:graphie.snap[1],onMove:function(x,y){return false},onMoveEnd:function(x,y){if(options.onMoveEnd){options.onMoveEnd.call(this,x,y);}}});let isHovering=false;let isFlipped=false;let currentlyDrawnButton;const isHighlight=function(){return isHovering};const styles=[0,1].map(function(isHighlight){const baseStyle=isHighlight?options.highlightStyle:options.normalStyle;return [0,1].map(function(opacity){return ___default.default.defaults({"fill-opacity":opacity},baseStyle)})});const getStyle=function(isRight){if(isFlipped){isRight=!isRight;}return styles[+isHighlight()][+isRight]};const redraw=function(coord,lineCoords){if(currentlyDrawnButton){currentlyDrawnButton.remove();}currentlyDrawnButton=drawButton(graphie,coord,lineCoords,isHighlight()?options.size*1.5:options.size,isHighlight()?options.size*.125:.25,getStyle(0),getStyle(1));};const update=function(coordA,coordZ){coordA=coordA||line.pointA.coord;coordZ=coordZ||line.pointZ.coord;const buttonCoord=kmath.line.midpoint([coordA,coordZ]);button.setCoord(buttonCoord);redraw(buttonCoord,[coordA,coordZ]);};$__default.default(line).on("move",()=>update(null,null));const $mouseTarget=$__default.default(button.mouseTarget.getMouseTarget());$mouseTarget.on("vclick",function(){const result=options.onClick();if(result!==false){isFlipped=!isFlipped;redraw(button.coord,[line.pointA.coord,line.pointZ.coord]);}});line.pointA.toFront();line.pointZ.toFront();button.visibleShape.remove();const pointScale=graphie.scaleVector(options.size)[0]/20;button.mouseTarget.attr({scale:1.5*pointScale});$mouseTarget.css("cursor","pointer");$mouseTarget.on("vmouseover",function(e){isHovering=true;redraw(button.coord,[line.pointA.coord,line.pointZ.coord]);});$mouseTarget.on("vmouseout",function(e){isHovering=false;redraw(button.coord,[line.pointA.coord,line.pointZ.coord]);});const oldButtonRemove=button.remove;button.remove=function(){currentlyDrawnButton.remove();oldButtonRemove.call(button);};button.update=update;button.isFlipped=function(){return isFlipped};update();return button}}(),protractor:function(center){return new Protractor$1(this,center)},ruler:function(options){return new Ruler(this,options||{})},addPoints:kmath.vector.add});function Protractor$1(graph,center){this.set=graph.raphael.set();this.cx=center[0];this.cy=center[1];const pro=this;const r=graph.unscaleVector(180.5)[0];const imgPos=graph.scalePoint([this.cx-r,this.cy+r-graph.unscaleVector(10.5)[1]]);const image=graph.mouselayer.image("https://ka-perseus-graphie.s3.amazonaws.com/e9d032f2ab8b95979f674fbfa67056442ba1ff6a.png",imgPos[0],imgPos[1],360,180);this.set.push(image);image.node.addEventListener("touchstart",function(event){event.preventDefault();},{passive:false});const arrowHelper=function(angle,pixelsFromEdge){const scaledRadius=graph.scaleVector(r);scaledRadius[0]-=16;scaledRadius[1]-=16;const scaledCenter=graph.scalePoint(center);const x=Math.sin((angle+90)*Math.PI/180)*(scaledRadius[0]+pixelsFromEdge)+scaledCenter[0];const y=Math.cos((angle+90)*Math.PI/180)*(scaledRadius[1]+pixelsFromEdge)+scaledCenter[1];return x+","+y};const arrow=graph.raphael.path(" M"+arrowHelper(180,6)+" L"+arrowHelper(180,2)+" L"+arrowHelper(183,10)+" L"+arrowHelper(180,18)+" L"+arrowHelper(180,14)+" A"+(graph.scaleVector(r)[0]+10)+","+(graph.scaleVector(r)[1]+10)+",0,0,1,"+arrowHelper(170,14)+" L"+arrowHelper(170,18)+" L"+arrowHelper(167,10)+" L"+arrowHelper(170,2)+" L"+arrowHelper(170,6)+" A"+(graph.scaleVector(r)[0]+10)+","+(graph.scaleVector(r)[1]+10)+",0,0,0,"+arrowHelper(180,6)+" Z").attr({stroke:null,fill:KhanColors.INTERACTIVE});this.set.push(arrow);this.centerPoint=graph.addMovablePoint({coord:center,visible:false});this.rotateHandle=graph.addMovablePoint({bounded:false,coord:[Math.sin(275*Math.PI/180)*r+this.cx,Math.cos(275*Math.PI/180)*r+this.cy],onMove:function(x,y){const angle=Math.atan2(pro.centerPoint.coord[1]-y,pro.centerPoint.coord[0]-x)*180/Math.PI;pro.rotate(-angle-5,true);}});this.rotateHandle.constraints.fixedDistance.dist=r;this.rotateHandle.constraints.fixedDistance.point=this.centerPoint;this.rotateHandle.visibleShape.remove();this.rotateHandle.mouseTarget.attr({scale:2});let isDragging=false;let isHovering=false;const isHighlight=function(){return isHovering||isDragging};const self=this;const $mouseTarget=$__default.default(self.rotateHandle.mouseTarget.getMouseTarget());$mouseTarget.on("vmousedown",function(event){isDragging=true;$mouseTarget.css("cursor","-webkit-grabbing");$mouseTarget.css("cursor","grabbing");arrow.animate({scale:1.5,fill:KhanColors.INTERACTING},50);$__default.default(document).on("vmouseup.rotateHandle",function(event){isDragging=false;$mouseTarget.css("cursor","-webkit-grab");$mouseTarget.css("cursor","grab");if(!isHighlight()){arrow.animate({scale:1,fill:KhanColors.INTERACTIVE},50);}$__default.default(document).unbind("vmouseup.rotateHandle");});});$mouseTarget.on("vmouseover",function(event){isHovering=true;arrow.animate({scale:1.5,fill:KhanColors.INTERACTING},50);});$mouseTarget.on("vmouseout",function(event){isHovering=false;if(!isHighlight()){arrow.animate({scale:1,fill:KhanColors.INTERACTIVE},50);}});const setNodes=$__default.default.map(this.set,function(el){return el.node});this.makeTranslatable=function makeTranslatable(){$__default.default(setNodes).css("cursor","move");$mouseTarget.css("cursor","-webkit-grab");$mouseTarget.css("cursor","grab");$__default.default(setNodes).on("vmousedown",function(event){event.preventDefault();let startx=event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left;let starty=event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top;$__default.default(document).on("vmousemove.protractor",function(event){let mouseX=event.pageX-$__default.default(graph.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graph.raphael.canvas.parentNode).offset().top;mouseX=Math.max(10,Math.min(graph.xpixels-10,mouseX));mouseY=Math.max(10,Math.min(graph.ypixels-10,mouseY));const dx=mouseX-startx;const dy=mouseY-starty;$__default.default.each(pro.set.items,function(){this.translate(dx,dy);});pro.centerPoint.setCoord([pro.centerPoint.coord[0]+dx/graph.scale[0],pro.centerPoint.coord[1]-dy/graph.scale[1]]);pro.rotateHandle.setCoord([pro.rotateHandle.coord[0]+dx/graph.scale[0],pro.rotateHandle.coord[1]-dy/graph.scale[1]]);startx=mouseX;starty=mouseY;});$__default.default(document).one("vmouseup",function(event){$__default.default(document).unbind("vmousemove.protractor");});});};this.rotation=0;this.rotate=function(offset,absolute){const center=graph.scalePoint(this.centerPoint.coord);if(absolute){this.rotation=0;}this.set.rotate(this.rotation+offset,center[0],center[1]);this.rotation=this.rotation+offset;return this};this.moveTo=function moveTo(x,y){const start=graph.scalePoint(pro.centerPoint.coord);const end=graph.scalePoint([x,y]);const time=GraphUtils.getDistance(start,end)*2;$__default.default({x:start[0],y:start[1]}).animate({x:end[0],y:end[1]},{duration:time,step:function(now,fx){let dx=0;let dy=0;if(fx.prop==="x"){dx=now-graph.scalePoint(pro.centerPoint.coord)[0];}else if(fx.prop==="y"){dy=now-graph.scalePoint(pro.centerPoint.coord)[1];}$__default.default.each(pro.set.items,function(){this.translate(dx,dy);});pro.centerPoint.setCoord([pro.centerPoint.coord[0]+dx/graph.scale[0],pro.centerPoint.coord[1]-dy/graph.scale[1]]);pro.rotateHandle.setCoord([pro.rotateHandle.coord[0]+dx/graph.scale[0],pro.rotateHandle.coord[1]-dy/graph.scale[1]]);}});};this.rotateTo=function rotateTo(angle){if(Math.abs(this.rotation-angle)>180){this.rotation+=360;}const time=Math.abs(this.rotation-angle)*5;$__default.default({0:this.rotation}).animate({0:angle},{duration:time,step:function(now,fx){pro.rotate(now,true);pro.rotateHandle.setCoord([Math.sin((now+275)*Math.PI/180)*r+pro.centerPoint.coord[0],Math.cos((now+275)*Math.PI/180)*r+pro.centerPoint.coord[1]]);}});};this.remove=function(){this.set.remove();};this.makeTranslatable();return this}function Ruler(graphie,options){___default.default.defaults(options,{center:[0,0],pixelsPerUnit:40,ticksPerUnit:10,units:10,label:"",style:{fill:null,stroke:KhanColors.GRAY}});const light={...options.style,strokeWidth:1};const bold={...options.style,strokeWidth:2};const width=options.units*options.pixelsPerUnit;const height=50;const leftBottom=graphie.unscalePoint(kmath.vector.subtract(graphie.scalePoint(options.center),kmath.vector.scale([width,-50],.5)));const graphieUnitsPerUnit=options.pixelsPerUnit/graphie.scale[0];const graphieUnitsHeight=height/graphie.scale[0];const rightTop=kmath.vector.add(leftBottom,[options.units*graphieUnitsPerUnit,graphieUnitsHeight]);const tickHeight=1;let tickHeightMap;if(options.ticksPerUnit===10){tickHeightMap={10:tickHeight,5:tickHeight*.55,1:tickHeight*.35};}else {const sizes=[1,.6,.45,.3];tickHeightMap={};for(let i=options.ticksPerUnit;i>=1;i/=2){tickHeightMap[i]=tickHeight*(sizes.shift()||.2);}}const tickFrequencies=Object.keys(tickHeightMap).sort(function(a,b){return b-a});function getTickHeight(i){for(let k=0;k<tickFrequencies.length;k++){const key=tickFrequencies[k];if(i%key===0){return tickHeightMap[key]}}return 0}const left=leftBottom[0];const bottom=leftBottom[1];const right=rightTop[0];const top=rightTop[1];const numTicks=options.units*options.ticksPerUnit+1;const set=graphie.raphael.set();const px=1/graphie.scale[0];set.push(graphie.line([left-px,bottom],[right+px,bottom],bold));set.push(graphie.line([left-px,top],[right+px,top],bold));for(let i=0;i<numTicks;i++){const n=i/options.ticksPerUnit;const x=left+n*graphieUnitsPerUnit;const height=getTickHeight(i)*graphieUnitsHeight;const style=i===0||i===numTicks-1?bold:light;set.push(graphie.line([x,bottom],[x,bottom+height],style));if(n%1===0){const coord=graphie.scalePoint([x,top]);let text;let offset;if(n===0){text=options.label;offset=({mm:13,cm:11,m:8,km:11,in:8,ft:8,yd:10,mi:10})[text]||3*text.toString().length;}else {text=n;offset=-3*(n.toString().length+1);}const label=graphie.raphael.text(coord[0]+offset,coord[1]+10,text);label.attr({"font-family":"KaTeX_Main","font-size":"12px",color:"#444"});set.push(label);}}const mouseTarget=graphie.mouselayer.path(graphie.svgPath([leftBottom,[left,top],rightTop,[right,bottom],true]));mouseTarget.attr({fill:"#000",opacity:0,stroke:"#000","stroke-width":2});set.push(mouseTarget);mouseTarget.node.addEventListener("touchstart",function(event){event.preventDefault();},{passive:false});const setNodes=$__default.default.map(set,function(el){return el.node});$__default.default(setNodes).css("cursor","move");$__default.default(setNodes).on("vmousedown",function(event){event.preventDefault();let startx=event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left;let starty=event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top;$__default.default(document).on("vmousemove.ruler",function(event){let mouseX=event.pageX-$__default.default(graphie.raphael.canvas.parentNode).offset().left;let mouseY=event.pageY-$__default.default(graphie.raphael.canvas.parentNode).offset().top;mouseX=Math.max(10,Math.min(graphie.xpixels-10,mouseX));mouseY=Math.max(10,Math.min(graphie.ypixels-10,mouseY));const dx=mouseX-startx;const dy=mouseY-starty;set.translate(dx,dy);leftBottomHandle.setCoord([leftBottomHandle.coord[0]+dx/graphie.scale[0],leftBottomHandle.coord[1]-dy/graphie.scale[1]]);rightBottomHandle.setCoord([rightBottomHandle.coord[0]+dx/graphie.scale[0],rightBottomHandle.coord[1]-dy/graphie.scale[1]]);startx=mouseX;starty=mouseY;});$__default.default(document).one("vmouseup",function(event){$__default.default(document).unbind("vmousemove.ruler");});});const leftBottomHandle=graphie.addMovablePoint({coord:leftBottom,normalStyle:{fill:KhanColors.INTERACTIVE,"fill-opacity":0,stroke:KhanColors.INTERACTIVE},highlightStyle:{fill:KhanColors.INTERACTING,"fill-opacity":.1,stroke:KhanColors.INTERACTING},pointSize:6,onMove:function(x,y){const dy=rightBottomHandle.coord[1]-y;const dx=rightBottomHandle.coord[0]-x;const angle=Math.atan2(dy,dx)*180/Math.PI;const center=kmath.vector.scale(kmath.vector.add([x,y],rightBottomHandle.coord),.5);const scaledCenter=graphie.scalePoint(center);const oldCenter=kmath.vector.scale(kmath.vector.add(leftBottomHandle.coord,rightBottomHandle.coord),.5);const scaledOldCenter=graphie.scalePoint(oldCenter);const diff=kmath.vector.subtract(scaledCenter,scaledOldCenter);set.rotate(-angle,scaledOldCenter[0],scaledOldCenter[1]);set.translate(diff[0],diff[1]);}});const rightBottomHandle=graphie.addMovablePoint({coord:[right,bottom],normalStyle:{fill:KhanColors.INTERACTIVE,"fill-opacity":0,stroke:KhanColors.INTERACTIVE},highlightStyle:{fill:KhanColors.INTERACTING,"fill-opacity":.1,stroke:KhanColors.INTERACTING},pointSize:6,onMove:function(x,y){const dy=y-leftBottomHandle.coord[1];const dx=x-leftBottomHandle.coord[0];const angle=Math.atan2(dy,dx)*180/Math.PI;const center=kmath.vector.scale(kmath.vector.add([x,y],leftBottomHandle.coord),.5);const scaledCenter=graphie.scalePoint(center);const oldCenter=kmath.vector.scale(kmath.vector.add(leftBottomHandle.coord,rightBottomHandle.coord),.5);const scaledOldCenter=graphie.scalePoint(oldCenter);const diff=kmath.vector.subtract(scaledCenter,scaledOldCenter);set.rotate(-angle,scaledOldCenter[0],scaledOldCenter[1]);set.translate(diff[0],diff[1]);}});leftBottomHandle.constraints.fixedDistance.dist=width/graphie.scale[0];leftBottomHandle.constraints.fixedDistance.point=rightBottomHandle;rightBottomHandle.constraints.fixedDistance.dist=width/graphie.scale[0];rightBottomHandle.constraints.fixedDistance.point=leftBottomHandle;this.remove=function(){set.remove();leftBottomHandle.remove();rightBottomHandle.remove();};return this}function MovableAngle(graphie,options){this.graphie=graphie;Object.assign(this,options);___default.default.defaults(this,{normalStyle:{stroke:KhanColors.INTERACTIVE,"stroke-width":2,fill:KhanColors.INTERACTIVE},highlightStyle:{stroke:KhanColors.INTERACTING,"stroke-width":2,fill:KhanColors.INTERACTING},labelStyle:{stroke:KhanColors.DYNAMIC,"stroke-width":1,color:KhanColors.DYNAMIC},angleStyle:{stroke:KhanColors.DYNAMIC,"stroke-width":1,color:KhanColors.DYNAMIC},allowReflex:true});if(!this.points||this.points.length!==3){throw new perseusCore.PerseusError("MovableAngle requires 3 points",perseusCore.Errors.InvalidInput)}this.points=options.points.map(point=>{if(Array.isArray(point)){return graphie.addMovablePoint({coord:point,visible:false,constraints:{fixed:true},normalStyle:this.normalStyle})}return point});this.coords=this.points.map(point=>point.coord);if(this.reflex==null){if(this.allowReflex){this.reflex=this._getClockwiseAngle(this.coords)>180;}else {this.reflex=false;}}this.rays=[0,2].map(i=>{return graphie.addMovableLineSegment({pointA:this.points[1],pointZ:this.points[i],fixed:true,extendRay:true})});this.temp=[];this.labeledAngle=graphie.label([0,0],"","center",this.labelStyle);if(!this.fixed){this.addMoveHandlers();this.addHighlightHandlers();}this.update();}___default.default.extend(MovableAngle.prototype,{points:[],snapDegrees:0,snapOffsetDeg:0,angleLabel:"",numArcs:1,pushOut:0,fixed:false,addMoveHandlers:function(){const graphie=this.graphie;function tooClose(point1,point2){const safeDistance=30;const distance=GraphUtils.getDistance(graphie.scalePoint(point1),graphie.scalePoint(point2));return distance<safeDistance}const points=this.points;points[1].onMove=function(x,y){const oldVertex=points[1].coord;const newVertex=[x,y];const delta=kmath.vector.add(newVertex,reverseVector$1(oldVertex));let valid=true;const newPoints={};[0,2].forEach(function(i){const oldPoint=points[i].coord;let newPoint=kmath.vector.add(oldPoint,delta);let angle=GraphUtils.findAngleDeprecated(newVertex,newPoint);angle*=Math.PI/180;newPoint=graphie.constrainToBoundsOnAngle(newPoint,10,angle);newPoints[i]=newPoint;if(tooClose(newVertex,newPoint)){valid=false;}});if(valid){Object.entries(newPoints).forEach(function([i,newPoint]){points[i].setCoord(newPoint);});}return valid};const snap=this.snapDegrees;const snapOffset=this.snapOffsetDeg;[0,2].forEach(function(i){points[i].onMove=function(x,y){const newPoint=[x,y];const vertex=points[1].coord;if(tooClose(vertex,newPoint)){return false}if(snap){let angle=GraphUtils.findAngleDeprecated(newPoint,vertex);angle=Math.round((angle-snapOffset)/snap)*snap+snapOffset;const distance=GraphUtils.getDistance(newPoint,vertex);return kmath.vector.add(vertex,polar$2(distance,angle))}return true};});$__default.default(points).on("move",()=>{this.update();$__default.default(this).trigger("move");});},addHighlightHandlers:function(){const vertex=this.points[1];vertex.onHighlight=()=>{this.points.forEach(point=>{point.visibleShape.animate(this.highlightStyle,50);});this.rays.forEach(ray=>{ray.visibleLine.animate(this.highlightStyle,50);ray.arrowStyle={...ray.arrowStyle,color:this.highlightStyle.stroke,stroke:this.highlightStyle.stroke};});this.angleStyle={...this.angleStyle,color:this.highlightStyle.stroke,stroke:this.highlightStyle.stroke};this.update();};vertex.onUnhighlight=()=>{this.points.forEach(point=>{point.visibleShape.animate(this.normalStyle,50);});this.rays.forEach(ray=>{ray.visibleLine.animate(ray.normalStyle,50);ray.arrowStyle={...ray.arrowStyle,color:ray.normalStyle.stroke,stroke:ray.normalStyle.stroke};});this.angleStyle={...this.angleStyle,color:KhanColors.DYNAMIC,stroke:KhanColors.DYNAMIC};this.update();};},_getClockwiseAngle:function(coords){const rawAngle=GraphUtils.findAngleDeprecated(coords[2],coords[0],coords[1]);const clockwiseAngle=rawAngle+360%360;return clockwiseAngle},isReflex:function(){return this.reflex},isClockwise:function(){const clockwiseReflexive=this._getClockwiseAngle(this.coords)>180;return clockwiseReflexive===this.reflex},getClockwiseCoords:function(){if(this.isClockwise()){return [...this.coords]}return [...this.coords].reverse()},update:function(shouldChangeReflexivity){const prevCoords=this.coords;this.coords=this.points.map(point=>point.coord);___default.default.invoke(this.points,"updateLineEnds");const prevAngle=this._getClockwiseAngle(prevCoords);const angle=this._getClockwiseAngle(this.coords);const prevClockwiseReflexive=prevAngle>180;const clockwiseReflexive=angle>180;if(this.allowReflex){if(shouldChangeReflexivity==null){shouldChangeReflexivity=prevClockwiseReflexive!==clockwiseReflexive&&Math.abs(angle-prevAngle)<180;}if(shouldChangeReflexivity){this.reflex=!this.reflex;}}___default.default.invoke(this.temp,"remove");this.temp=this.graphie.labelAngle({point1:this.coords[0],vertex:this.coords[1],point3:this.coords[2],label:this.labeledAngle,text:this.angleLabel,numArcs:this.numArcs,pushOut:this.pushOut,clockwise:this.reflex===clockwiseReflexive,style:this.angleStyle});},remove:function(){___default.default.invoke(this.rays,"remove");___default.default.invoke(this.temp,"remove");this.labeledAngle.remove();}});
|
|
1632
1629
|
|
|
1633
|
-
const nestedMap$1=Util.nestedMap;function GraphieMovable$1(descriptor){___default.default.extend(this,descriptor);}const abstractMethod=function(){throw new perseusCore.PerseusError("Abstract method! Must be implemented by Graphie Movable"+this.constructor.displayName,perseusCore.Errors.NotAllowed)};___default.default.extend(GraphieMovable$1.prototype,{movableProps:[],add:abstractMethod,modify:abstractMethod,remove:abstractMethod,toFront:function(){},componentDidMount:function(){}});const rewriteProps=function(props,childrenArray){return ___default.default.extend({},props,{children:___default.default.filter(___default.default.flatten(childrenArray),___default.default.identity)})};const createClass=function(spec){const GraphieClass=function(props){if(!(this instanceof GraphieClass)){throw new perseusCore.PerseusError("Use createElement or JSX with graphie movables",perseusCore.Errors.NotAllowed)}this.props=rewriteProps(props,props.children||[]);return this};spec.displayName=spec.displayName||___default.default.uniqueId("GraphieClass");GraphieClass.displayName=spec.displayName;GraphieClass.prototype=new GraphieMovable$1(spec);GraphieClass.prototype.constructor=GraphieClass;return GraphieClass};const createSimpleClass=function(addFunction){return createClass({displayName:addFunction.name||___default.default.uniqueId("GraphieSimpleClass"),movableProps:["children"],add:function(graphie){this._elements=addFunction(graphie,this.props);this._prevProps=this.props;},modify:function(graphie){if(!perseusCore.approximateDeepEqual(this.props,this._prevProps)){this.remove();this.add(graphie);this._prevProps=this.props;return "reordered"}},remove:function(){nestedMap$1(this._elements,elem=>{if(elem){elem.remove();}});this._elements=null;this._prevProps=null;},toFront:function(){nestedMap$1(this._elements,elem=>{if(elem&&
|
|
1630
|
+
const nestedMap$1=Util.nestedMap;function GraphieMovable$1(descriptor){___default.default.extend(this,descriptor);}const abstractMethod=function(){throw new perseusCore.PerseusError("Abstract method! Must be implemented by Graphie Movable"+this.constructor.displayName,perseusCore.Errors.NotAllowed)};___default.default.extend(GraphieMovable$1.prototype,{movableProps:[],add:abstractMethod,modify:abstractMethod,remove:abstractMethod,toFront:function(){},componentDidMount:function(){}});const rewriteProps=function(props,childrenArray){return ___default.default.extend({},props,{children:___default.default.filter(___default.default.flatten(childrenArray),___default.default.identity)})};const createClass=function(spec){const GraphieClass=function(props){if(!(this instanceof GraphieClass)){throw new perseusCore.PerseusError("Use createElement or JSX with graphie movables",perseusCore.Errors.NotAllowed)}this.props=rewriteProps(props,props.children||[]);return this};spec.displayName=spec.displayName||___default.default.uniqueId("GraphieClass");GraphieClass.displayName=spec.displayName;GraphieClass.prototype=new GraphieMovable$1(spec);GraphieClass.prototype.constructor=GraphieClass;return GraphieClass};const createSimpleClass=function(addFunction){return createClass({displayName:addFunction.name||___default.default.uniqueId("GraphieSimpleClass"),movableProps:["children"],add:function(graphie){this._elements=addFunction(graphie,this.props);this._prevProps=this.props;},modify:function(graphie){if(!perseusCore.approximateDeepEqual(this.props,this._prevProps)){this.remove();this.add(graphie);this._prevProps=this.props;return "reordered"}},remove:function(){nestedMap$1(this._elements,elem=>{if(elem){elem.remove();}});this._elements=null;this._prevProps=null;},toFront:function(){nestedMap$1(this._elements,elem=>{if(elem&&typeof elem.toFront==="function"){elem.toFront();}});}})};var GraphieClasses = {GraphieMovable:GraphieMovable$1,createClass:createClass,createSimpleClass:createSimpleClass};
|
|
1634
1631
|
|
|
1635
|
-
const normalizeOptions$3=InteractiveUtil.normalizeOptions;const assert$
|
|
1632
|
+
const normalizeOptions$3=InteractiveUtil.normalizeOptions;const assert$6=InteractiveUtil.assert;const DEFAULT_PROPS$3={cursor:null};const DEFAULT_STATE$3={added:false,isHovering:false,isMouseOver:false,isDragging:false,mouseTarget:null};class Movable{modify(options){this.update({...this._createDefaultState(),...options});}_createDefaultState(){return {id:this.state.id,add:[],modify:[],draw:[],remove:[],onMoveStart:[],onMove:[],onMoveEnd:[],onClick:[],...DEFAULT_PROPS$3}}update(options){const graphie=this.graphie;const prevState=this.cloneState();const state=Object.assign(this.state,normalizeOptions$3(options));if(state.mouseTarget&&!prevState.mouseTarget){let $mouseTarget;if(state.mouseTarget.getMouseTarget){$mouseTarget=$__default.default(state.mouseTarget.getMouseTarget());}else {$mouseTarget=$__default.default(state.mouseTarget[0]);}const isMouse=!("ontouchstart"in window);if(isMouse){$mouseTarget.on("vmouseover",()=>{state.isMouseOver=true;if(!graphie.isDragging){state.isHovering=true;}if(this.state.added){this.draw();}});$mouseTarget.on("vmouseout",()=>{state.isMouseOver=false;if(!state.isDragging){state.isHovering=false;}if(this.state.added){this.draw();}});}$mouseTarget[0].addEventListener("touchstart",function(event){event.preventDefault();},{passive:false});$mouseTarget.on("vmousedown",e=>{if(e.which!==0&&e.which!==1){return}e.preventDefault();const mouseCoord=graphie.getMouseCoord(e);this.grab(mouseCoord);});}if(state.mouseTarget&&state.cursor!==undefined){let $mouseTarget;if(state.mouseTarget.getMouseTarget){$mouseTarget=$__default.default(state.mouseTarget.getMouseTarget());}else {$mouseTarget=$__default.default(state.mouseTarget[0]);}$mouseTarget.css("cursor",state.cursor||"");}if(!state.added){this._fireEvent(state.modify,this.cloneState(),{});state.added=true;this.prevState=this.cloneState();}this._fireEvent(state.modify,this.cloneState(),this.prevState);}cloneState(){return {...this.state}}_fireEvent(listeners,...args){if(listeners==null){return}for(const listener of listeners){listener.call(this,...args);}}draw(){const currState=this.cloneState();this._fireEvent(this.state.draw,currState,this.prevState);this.prevState=currState;}grab(coord){assert$6(kmath.point.is(coord));const graphie=this.graphie;const state=this.state;state.isHovering=true;state.isDragging=true;graphie.isDragging=true;const startMouseCoord=coord;let prevMouseCoord=startMouseCoord;this._fireEvent(state.onMoveStart,startMouseCoord,startMouseCoord);const moveHandler=e=>{e.preventDefault();const mouseCoord=graphie.getMouseCoord(e);this._fireEvent(state.onMove,mouseCoord,prevMouseCoord);this.draw();prevMouseCoord=mouseCoord;};const upHandler=()=>{$__default.default(document).unbind("vmousemove",moveHandler);$__default.default(document).unbind("vmouseup",upHandler);if(state.isHovering){this._fireEvent(state.onClick,prevMouseCoord,startMouseCoord);}state.isHovering=this.state.isMouseOver;state.isDragging=false;graphie.isDragging=false;this._fireEvent(state.onMoveEnd,prevMouseCoord,startMouseCoord);this.draw();};$__default.default(document).on("vmousemove",moveHandler);$__default.default(document).on("vmouseup",upHandler);}_applyConstraints(current,previous,extraOptions){let skipRemaining=false;return (this.state.constraints??[]).reduce((memo,constraint)=>{if(memo===false){return false}if(skipRemaining){return memo}const result=constraint.call(this,memo,previous,{onSkipRemaining:()=>{skipRemaining=true;},...extraOptions});if(result===false){return false}if(kmath.point.is(result,2)){return result}if(result===true||result==null){return memo}throw new perseusCore.PerseusError("Constraint returned invalid result: "+result,perseusCore.Errors.Internal)},current)}toBack(){if(this.state.mouseTarget){this.state.mouseTarget.toBack();}}toFront(){if(this.state.mouseTarget){this.state.mouseTarget.toFront();}}listen(eventName,id,func){this._listenerMap=this._listenerMap||{};const key=getKey$1(eventName,id);const index=this._listenerMap[key]=this._listenerMap[key]||this.state[eventName].length;this.state[eventName][index]=func;}unlisten(eventName,id){this._listenerMap=this._listenerMap||{};const key=getKey$1(eventName,id);const index=this._listenerMap[key];if(index!==undefined){this.state[eventName].splice(index,1);delete this._listenerMap[key];const keys=Object.keys(this._listenerMap);keys.forEach(key=>{if(getEventName$1(key)===eventName&&this._listenerMap[key]>index){this._listenerMap[key]--;}});}}remove(){this.state.added=false;this._fireEvent(this.state.remove);if(this.state.mouseTarget){$__default.default(this.state.mouseTarget).off();this.state.mouseTarget.remove();this.state.mouseTarget=null;}}cursor(){return this.state.cursor}added(){return this.state.added}isHovering(){return this.state.isHovering}isMouseOver(){return this.state.isMouseOver}isDragging(){return this.state.isDragging}mouseTarget(){return this.state.mouseTarget}constructor(graphie,options){this._listenerMap={};this.graphie=graphie;this.state={id:___default.default.uniqueId("movable")};this.modify({...DEFAULT_STATE$3,...options});}}function getKey$1(eventName,id){return eventName+":"+id}function getEventName$1(key){return key.split(":")[0]}
|
|
1636
1633
|
|
|
1637
|
-
const getScaledAngle=function(line){const scaledA=line.graphie.scalePoint(line.coord(0));const scaledZ=line.graphie.scalePoint(line.coord(1));return kmath.vector.polarDegFromCart(kmath.vector.subtract(scaledZ,scaledA))[1]};const add$2={draw:function(){this.draw();},pointsToFront:function(state){___default.default.invoke(state.points,"toFront");}};add$2.standard=[add$2.draw,add$2.pointsToFront];const modify$2={draw:function(){this.draw();}};modify$2.standard=[modify$2.draw];const draw$2={basic:function(state){const graphie=this.graphie;let start=this.coord(0);let end=this.coord(1);if(!this.state.visibleShape){const options={thickness:10};this.state.visibleShape=new WrappedLine(graphie,start,end,options);this.state.visibleShape.attr(this.normalStyle());this.state.visibleShape.toFront();if(this.mouseTarget()){this.mouseTarget().toFront();}}const angle=getScaledAngle(this);if(state.extendLine){start=getClipPoint(graphie,start,360-angle);end=getClipPoint(graphie,end,(540-angle)%360);}else if(state.extendRay){end=getClipPoint(graphie,end,360-angle);}const elements=[this.state.visibleShape];if(this.mouseTarget()){elements.push(this.mouseTarget());}___default.default.each(elements,function(element){element.moveTo(start,end);});},arrows:function(state){if(this._arrows==null){this._arrows=[];if(state.extendLine){this._arrows.push(new Arrowhead$1(this.graphie,this.normalStyle()));this._arrows.push(new Arrowhead$1(this.graphie,this.normalStyle()));}else if(state.extendRay){this._arrows.push(new Arrowhead$1(this.graphie,this.normalStyle()));}}const angle=getScaledAngle(this);const angleForArrow=[360-angle,(540-angle)%360];___default.default.each(this._arrows,function(arrow,i){arrow.toCoordAtAngle(this.coord(i),angleForArrow[i]);},this);},highlight:function(state,prevState){if(state.isHovering&&!prevState.isHovering){state.visibleShape.animate(state.highlightStyle,50);}else if(!state.isHovering&&prevState.isHovering){state.visibleShape.animate(state.normalStyle,50);}}};draw$2.standard=[draw$2.basic,draw$2.arrows,draw$2.highlight];const remove$2={basic:function(){if(this.state.visibleShape){this.state.visibleShape.remove();}},arrows:function(){if(this._arrows!=null){___default.default.invoke(this._arrows,"remove");}this._arrows=null;}};remove$2.standard=[remove$2.basic,remove$2.arrows];const constraints$2={fixed:function(){return function(){return false}},snap:function(snap){return function(coord,prevCoord){if(snap===null){return true}let delta=kmath.vector.subtract(coord,prevCoord);snap=snap||this.graphie.snap;delta=kmath.point.roundTo(delta,snap);return kmath.vector.add(prevCoord,delta)}},bound:function(range,snap,paddingPx){if(paddingPx===undefined){if(range===undefined){paddingPx=10;}else {paddingPx=0;}}return function(coord,prevCoord){const graphie=this.graphie;const delta=kmath.vector.subtract(coord,prevCoord);range=range||graphie.range;if(snap===undefined){snap=graphie.snap;}let absoluteLower=graphie.unscalePoint([paddingPx,graphie.ypixels-paddingPx]);let absoluteUpper=graphie.unscalePoint([graphie.xpixels-paddingPx,paddingPx]);if(snap){absoluteLower=kmath.point.ceilTo(absoluteLower,snap);absoluteUpper=kmath.point.floorTo(absoluteUpper,snap);}const deltaBounds=
|
|
1634
|
+
const getScaledAngle=function(line){const scaledA=line.graphie.scalePoint(line.coord(0));const scaledZ=line.graphie.scalePoint(line.coord(1));return kmath.vector.polarDegFromCart(kmath.vector.subtract(scaledZ,scaledA))[1]};const add$2={draw:function(){this.draw();},pointsToFront:function(state){___default.default.invoke(state.points,"toFront");}};add$2.standard=[add$2.draw,add$2.pointsToFront];const modify$2={draw:function(){this.draw();}};modify$2.standard=[modify$2.draw];const draw$2={basic:function(state){const graphie=this.graphie;let start=this.coord(0);let end=this.coord(1);if(!this.state.visibleShape){const options={thickness:10};this.state.visibleShape=new WrappedLine(graphie,start,end,options);this.state.visibleShape.attr(this.normalStyle());this.state.visibleShape.toFront();if(this.mouseTarget()){this.mouseTarget().toFront();}}const angle=getScaledAngle(this);if(state.extendLine){start=getClipPoint(graphie,start,360-angle);end=getClipPoint(graphie,end,(540-angle)%360);}else if(state.extendRay){end=getClipPoint(graphie,end,360-angle);}const elements=[this.state.visibleShape];if(this.mouseTarget()){elements.push(this.mouseTarget());}___default.default.each(elements,function(element){element.moveTo(start,end);});},arrows:function(state){if(this._arrows==null){this._arrows=[];if(state.extendLine){this._arrows.push(new Arrowhead$1(this.graphie,this.normalStyle()));this._arrows.push(new Arrowhead$1(this.graphie,this.normalStyle()));}else if(state.extendRay){this._arrows.push(new Arrowhead$1(this.graphie,this.normalStyle()));}}const angle=getScaledAngle(this);const angleForArrow=[360-angle,(540-angle)%360];___default.default.each(this._arrows,function(arrow,i){arrow.toCoordAtAngle(this.coord(i),angleForArrow[i]);},this);},highlight:function(state,prevState){if(state.isHovering&&!prevState.isHovering){state.visibleShape.animate(state.highlightStyle,50);}else if(!state.isHovering&&prevState.isHovering){state.visibleShape.animate(state.normalStyle,50);}}};draw$2.standard=[draw$2.basic,draw$2.arrows,draw$2.highlight];const remove$2={basic:function(){if(this.state.visibleShape){this.state.visibleShape.remove();}},arrows:function(){if(this._arrows!=null){___default.default.invoke(this._arrows,"remove");}this._arrows=null;}};remove$2.standard=[remove$2.basic,remove$2.arrows];const constraints$2={fixed:function(){return function(){return false}},snap:function(snap){return function(coord,prevCoord){if(snap===null){return true}let delta=kmath.vector.subtract(coord,prevCoord);snap=snap||this.graphie.snap;delta=kmath.point.roundTo(delta,snap);return kmath.vector.add(prevCoord,delta)}},bound:function(range,snap,paddingPx){if(paddingPx===undefined){if(range===undefined){paddingPx=10;}else {paddingPx=0;}}return function(coord,prevCoord){const graphie=this.graphie;const delta=kmath.vector.subtract(coord,prevCoord);range=range||graphie.range;if(snap===undefined){snap=graphie.snap;}let absoluteLower=graphie.unscalePoint([paddingPx,graphie.ypixels-paddingPx]);let absoluteUpper=graphie.unscalePoint([graphie.xpixels-paddingPx,paddingPx]);if(snap){absoluteLower=kmath.point.ceilTo(absoluteLower,snap);absoluteUpper=kmath.point.floorTo(absoluteUpper,snap);}const deltaBounds=this.coords().map(function(coord,i){const max=kmath.vector.subtract(absoluteUpper,coord);const min=kmath.vector.subtract(absoluteLower,coord);return [min,max]});const boundedDelta=___default.default.reduce(deltaBounds,function(delta,bound){const lower=bound[0];const upper=bound[1];const deltaX=Math.max(lower[0],Math.min(upper[0],delta[0]));const deltaY=Math.max(lower[1],Math.min(upper[1],delta[1]));return [deltaX,deltaY]},delta);return kmath.vector.add(prevCoord,boundedDelta)}}};constraints$2.standard=null;const onMove$1={updatePoints:function(coord,prevCoord){const actualDelta=kmath.vector.subtract(coord,prevCoord);___default.default.each(this.state.points,function(point){point.setCoord(kmath.vector.add(point.coord(),actualDelta));});}};onMove$1.standard=null;var MovableLineOptions = {add:add$2,modify:modify$2,draw:draw$2,remove:remove$2,onMoveStart:{standard:null},constraints:constraints$2,onMove:onMove$1,onMoveEnd:{standard:null}};
|
|
1638
1635
|
|
|
1639
|
-
const assert$
|
|
1636
|
+
const assert$5=InteractiveUtil.assert;const normalizeOptions$2=InteractiveUtil.normalizeOptions;const DEFAULT_PROPS$2={points:null,static:false,cursor:"move",normalStyle:null,highlightStyle:null,extendLine:false,extendRay:false};const DEFAULT_STATE$2={visibleShape:null,mouseTarget:null};const MovableLine$4=function(graphie,movable,options){assert$5(graphie!=null);assert$5(options!=null);___default.default.extend(this,{graphie:graphie,movable:movable,state:{id:___default.default.uniqueId("movableLine")}});this.modify(___default.default.extend({},DEFAULT_STATE$2,options));};___default.default.extend(MovableLine$4,MovableLineOptions);InteractiveUtil.createGettersFor(MovableLine$4,___default.default.extend({},DEFAULT_PROPS$2,DEFAULT_STATE$2));InteractiveUtil.addMovableHelperMethodsTo(MovableLine$4);___default.default.extend(MovableLine$4.prototype,{cloneState:function(){return ___default.default.extend(this.movable.cloneState(),{coords:this.coords()},this.state)},_createDefaultState:function(){return ___default.default.extend({id:this.state.id},normalizeOptions$2(perseusCore.pluck(MovableLineOptions,"standard")),DEFAULT_PROPS$2)},modify:function(options){this.update(___default.default.extend(this._createDefaultState(),options));},update:function(options){const self=this;const graphie=this.graphie;const state=self.state=___default.default.extend(self.state,normalizeOptions$2(options));const movableColor=wonderBlocksTokens.tokenValue(state.static?wonderBlocksTokens.semanticColor.core.foreground.disabled.strong:wonderBlocksTokens.semanticColor.core.foreground.instructive.default);state.normalStyle=___default.default.extend({stroke:movableColor,"stroke-width":2},state.normalStyle);state.highlightStyle=___default.default.extend({stroke:movableColor,"stroke-width":3},state.highlightStyle);if(!state.static){if(!state.mouseTarget){const options={thickness:30,mouselayer:true,interactiveKindForTesting:"movable-line"};state.mouseTarget=new WrappedLine(graphie,this.coord(0),this.coord(1),options);state.mouseTarget.attr({fill:"#000",opacity:0});}}if(state.static&&state.mouseTarget){state.mouseTarget.remove();state.mouseTarget=null;}self.movable.modify(___default.default.extend({},state,{mouseTarget:state.mouseTarget,add:null,modify:null,draw:self.draw.bind(self),remove:null,onMoveStart:function(){self._initialRefCoord=self.coord(0);self._prevRefCoord=self._initialRefCoord;self._totalDelta=[0,0];self._fireEvent(self.state.onMoveStart,self.coord(0),self.coord(0));},onMove:function(mouseCoord,prevMouseCoord){const delta=kmath.vector.subtract(mouseCoord,prevMouseCoord);self._totalDelta=kmath.vector.add(self._totalDelta,delta);let refCoord=kmath.vector.add(self._initialRefCoord,self._totalDelta);refCoord=self._applyConstraints(refCoord,self._prevRefCoord);if(refCoord===false){return}self._fireEvent(self.state.onMove,refCoord,self._prevRefCoord);self._prevRefCoord=refCoord;},onMoveEnd:function(){self._fireEvent(self.state.onMoveEnd,self._prevRefCoord,self._initialRefCoord);}}));if(!state.added){self.prevState={};self._fireEvent(state.add,self.cloneState(),self.prevState);state.added=true;___default.default.invoke(state.points,"listen","onMove",state.id,self.draw.bind(self));self.prevState=self.cloneState();}self._fireEvent(state.modify,self.cloneState(),self.prevState);},coords:function(){return ___default.default.invoke(this.state.points,"coord")},point:function(index){return this.state.points[index]},coord:function(index){return this.point(index).coord()},remove:function(){this.state.added=false;this._fireEvent(this.state.remove);if(this.points){___default.default.invoke(this.points,"unlisten","onMove",this.state.id);}if(this.movable){this.movable.remove();}},toBack:function(){this.movable.toBack();if(this.state.visibleShape){this.state.visibleShape.toBack();}},toFront:function(){if(this.state.visibleShape){this.state.visibleShape.toFront();}this.movable.toFront();},isHovering:function(){return this.movable.isHovering()},isDragging:function(){return this.movable.isDragging()},mouseTarget:function(){return this.movable.mouseTarget()}});
|
|
1640
1637
|
|
|
1641
1638
|
const InlineIcon=({path,width,height,style={},title})=>jsxRuntimeExports.jsxs("svg",{role:"img","aria-hidden":!title,style:{verticalAlign:"middle",...style},width:`${width/height}em`,height:"1em",viewBox:`0 0 ${width} ${height}`,children:[!!title&&jsxRuntimeExports.jsx("title",{children:title}),jsxRuntimeExports.jsx("path",{d:path,fill:"currentColor"})]});
|
|
1642
1639
|
|
|
@@ -1644,17 +1641,17 @@ const iconCheck={path:`M8.70710678,12.2928932 C8.31658249,11.9023689 7.68341751,
|
|
|
1644
1641
|
|
|
1645
1642
|
const add$1={constrain:function(){this.constrain();}};add$1.standard=[add$1.constrain];const modify$1={draw:function(){this.draw();}};modify$1.standard=[modify$1.draw];const draw$1={basic:function(state,prevState){const graphie=this.graphie;if(!this.state.visibleShape){const radii=[this.pointSize()/graphie.scale[0],this.pointSize()/graphie.scale[1]];const options={maxScale:Math.max(this.highlightStyle().scale,this.normalStyle().scale),padding:10,shadow:state.shadow};this.state.visibleShape=new WrappedEllipse(graphie,this.coord(),radii,options);this.state.visibleShape.attr(___default.default.omit(this.normalStyle(),"scale"));this.state.visibleShape.toFront();if(this.mouseTarget()){this.mouseTarget().toFront();}}if(state.normalStyle!==prevState.normalStyle&&!___default.default.isEqual(state.normalStyle,prevState.normalStyle)){this.state.visibleShape.attr(this.normalStyle());}this.state.visibleShape.moveTo(this.coord());if(this.mouseTarget()){this.mouseTarget().moveTo(this.coord());}},highlight:function(state,prevState){if(state.isHovering&&!prevState.isHovering){state.visibleShape.animate(this.highlightStyle(),50);}else if(!state.isHovering&&prevState.isHovering){state.visibleShape.animate(this.normalStyle(),50);}}};draw$1.standard=[draw$1.basic,draw$1.highlight];const remove$1={basic:function(){if(this.state.visibleShape){this.state.visibleShape.remove();this.state.visibleShape=null;}}};remove$1.standard=remove$1.basic;const constraints$1={fixed:function(){return function(){return false}},snap:function(snap){return function(coord){if(snap===null){return true}return kmath.point.roundTo(coord,snap||this.graphie.snap)}},bound:function(range,snap,optionalPaddingPx){const paddingPx=(()=>{if(optionalPaddingPx===undefined){if(range===undefined){return 10}else {return 0}}else {return optionalPaddingPx}})();return function(coord,prev,options){const graphie=this.graphie;range=range||graphie.range;if(snap===undefined){snap=graphie.snap;}let lower=graphie.unscalePoint([paddingPx,graphie.ypixels-paddingPx]);let upper=graphie.unscalePoint([graphie.xpixels-paddingPx,paddingPx]);if(snap){lower=kmath.point.ceilTo(lower,snap);upper=kmath.point.floorTo(upper,snap);}if(!!options&&!!options.onOutOfBounds){if(coord[0]>upper[0]||coord[0]<lower[0]||coord[1]>upper[1]||coord[1]<lower[1]){options.onSkipRemaining();options.onOutOfBounds();}return coord}const coordX=Math.max(lower[0],Math.min(upper[0],coord[0]));const coordY=Math.max(lower[1],Math.min(upper[1],coord[1]));return [coordX,coordY]}}};constraints$1.standard=null;var MovablePointOptions = {add:add$1,modify:modify$1,draw:draw$1,remove:remove$1,onMoveStart:{standard:null},constraints:constraints$1,onMove:{standard:null},onMoveEnd:{standard:null},onClick:{standard:null}};
|
|
1646
1643
|
|
|
1647
|
-
const assert$
|
|
1644
|
+
const assert$4=InteractiveUtil.assert;const normalizeOptions$1=InteractiveUtil.normalizeOptions;const{processMath}=Tex$1;const DEFAULT_PROPS$1={coord:[0,0],pointSize:4,static:false,cursor:"move",normalStyle:null,highlightStyle:null,shadow:false,tooltip:false};const DEFAULT_STATE$1={added:false,hasMoved:false,visibleShape:null,outOfBounds:false,mouseTarget:null,touchOffset:null};const tooltipResetFunctions=[];let MovablePoint$5 = class MovablePoint{modify(options){this.update(___default.default.extend(this._createDefaultState(),options));}_createDefaultState(){return {id:this.state.id,...normalizeOptions$1(perseusCore.pluck(MovablePointOptions,"standard")),...DEFAULT_PROPS$1}}cloneState(){return {...this.movable.cloneState(),...this.state}}update(options){const self=this;const graphie=self.graphie;const state=___default.default.extend(self.state,normalizeOptions$1(options));assert$4(kmath.point.is(state.coord));const movableColor=wonderBlocksTokens.tokenValue(state.static?wonderBlocksTokens.semanticColor.core.foreground.disabled.strong:wonderBlocksTokens.semanticColor.core.foreground.instructive.default);state.normalStyle=___default.default.extend({fill:movableColor,stroke:movableColor,scale:1},state.normalStyle);state.highlightStyle=___default.default.extend({fill:movableColor,stroke:movableColor,scale:2},state.highlightStyle);if(!state.static){if(!state.mouseTarget){const center=self.state.coord;const radii=graphie.unscaleVector(24);const options={mouselayer:true,padding:0,interactiveKindForTesting:"movable-point"};state.mouseTarget=new WrappedEllipse(graphie,center,radii,options);state.mouseTarget.attr({fill:"#000",opacity:0});}}const showTrashTooltip=()=>{this._showTooltip(container=>{render(jsxRuntimeExports.jsx("span",{style:{fontSize:"2em"},children:jsxRuntimeExports.jsx(InlineIcon,{...iconTrash,style:{position:"static",color:movableColor,marginLeft:9,marginRight:9}})}),container);});};let startCoord=state.coord;self.movable.modify(___default.default.extend({},state,{add:null,modify:null,draw:self.draw.bind(self),remove:null,onMoveStart:startMouseCoord=>{state.hasMoved=false;startCoord=state.coord;if(state.touchOffset==null){const isMouse=!("ontouchstart"in window);state.touchOffset=isMouse?[0,0]:kmath.vector.subtract(startCoord,startMouseCoord);}const svgElem=state.visibleShape.wrapper;if(state.shadow){const filter="none";svgElem.style.filter=filter;}if(state.showHairlines){state.showHairlines(state.coord);}tooltipResetFunctions.forEach(f=>f());if(state.tooltip){if(state.xOnlyTooltip){this._showTooltip(`${state.coord[0]}`);}else {this._showTooltip(`(${state.coord[0]}, ${state.coord[1]})`);}if(state.shadow){const content=svgElem.getElementsByClassName("tooltip-content")[0];const filter="drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";content.style.filter=filter;}}self._fireEvent(state.onMoveStart,startCoord,startCoord);self.draw();},onMove:(mouseCoord,prevMouseCoord)=>{const transformedCoord=kmath.vector.add(mouseCoord,state.touchOffset);self.moveTo(transformedCoord);if(state.showHairlines){if(!this.state.outOfBounds){state.showHairlines(state.coord);}else {state.hideHairlines();}}if(state.tooltip){if(!this.state.outOfBounds){if(state.xOnlyTooltip){this._showTooltip(`${state.coord[0]}`);}else {this._showTooltip(`(${state.coord[0]}, ${state.coord[1]})`);}}}if(state.onRemove&&this.state.outOfBounds){showTrashTooltip();}},onMoveEnd:()=>{if(self.isHovering()&&!state.hasMoved){self._fireEvent(state.onClick,state.coord,startCoord);}const svgElem=state.visibleShape.wrapper;if(state.shadow){const filter="drop-shadow(0px 0px 5px rgba(0, 0, 0, 0.5))";svgElem.style.filter=filter;}if(state.hideHairlines){state.hideHairlines();}if(state.hasMoved){this._hideTooltip();}else if(state.onRemove){showTrashTooltip();const content=svgElem.getElementsByClassName("tooltip-content")[0];content.style.filter="none";this._tooltip.firstChild.addEventListener("touchstart",e=>{e.stopPropagation();},true);this._tooltip.firstChild.addEventListener("touchend",e=>{state.onRemove();e.stopPropagation();},true);}else if(state.tooltip){this._hideTooltip();}if(state.outOfBounds){state.onRemove();}self._fireEvent(state.onMoveEnd,state.coord,startCoord);state.hasMoved=false;state.touchOffset=null;self.draw();}}));if(!state.added){self.prevState={};self._fireEvent(state.add,self.cloneState(),self.prevState);state.added=true;self.prevState=self.cloneState();}self._fireEvent(state.modify,self.cloneState(),self.prevState);}draw(){const currState=this.cloneState();this._fireEvent(this.state.draw,currState,this.prevState);this.prevState=currState;}constrain(){const result=this._applyConstraints(this.coord(),this.coord());if(kmath.point.is(result)){this.setCoord(result);}return result!==false}_fireEvent(listeners,...args){for(const listener of listeners){listener.call(this,...args);}}_applyConstraints(current,previous,extraOptions){let skipRemaining=false;return this.state.constraints.reduce((memo,constraint)=>{if(memo===false){return false}if(skipRemaining){return memo}const result=constraint.call(this,memo,previous,{onSkipRemaining:()=>{skipRemaining=true;},...extraOptions});if(result===false){return false}if(kmath.point.is(result,2)){return result}if(result===true||result==null){return memo}throw new perseusCore.PerseusError("Constraint returned invalid result: "+result,perseusCore.Errors.Internal)},current)}_showTooltip(contents){if(!this._tooltip){this._tooltip=document.createElement("div");this._tooltip.className="tooltip-content";this.state.visibleShape.wrapper.className="tooltip";this.state.visibleShape.wrapper.appendChild(this._tooltip);tooltipResetFunctions.push(()=>{if(this.state.added){this._hideTooltip();}});}if(this._tooltip.firstChild){this._tooltip.removeChild(this._tooltip.firstChild);}this.state.visibleShape.wrapper.className="tooltip visible";this._tooltip.appendChild(document.createElement("span"));if(typeof contents==="string"){processMath(this._tooltip.firstChild,contents,false);}else if(typeof contents==="function"){contents(this._tooltip.firstChild);}else {this._tooltip.firstChild.appendChild(contents);}}_hideTooltip(){if(this._tooltip){this.state.visibleShape.wrapper.className="tooltip";}}coord(){return this.state.coord}setCoord(coord){assert$4(kmath.point.is(coord,2));this.state.coord=___default.default.clone(coord);this.draw();}setCoordConstrained(coord){assert$4(kmath.point.is(coord,2));const result=this._applyConstraints(coord,this.coord());if(result!==false){this.state.coord=___default.default.clone(result);this.draw();}}listen(eventName,id,func){this._listenerMap=this._listenerMap||{};const key=getKey(eventName,id);const index=this._listenerMap[key]=this._listenerMap[key]||this.state[eventName].length;this.state[eventName][index]=func;}unlisten(eventName,id){this._listenerMap=this._listenerMap||{};const key=getKey(eventName,id);const index=this._listenerMap[key];if(index!==undefined){this.state[eventName].splice(index,1);delete this._listenerMap[key];const keys=Object.keys(this._listenerMap);___default.default.each(keys,key=>{if(getEventName(key)===eventName&&this._listenerMap[key]>index){this._listenerMap[key]--;}},this);}}grab(coord){this.state.touchOffset=[0,0];this.movable.grab(coord);this.moveTo(coord);}moveTo(coord){const state=this.state;this.state.outOfBounds=false;const result=this._applyConstraints(coord,state.coord,state.onRemove?{onOutOfBounds:()=>{this.state.outOfBounds=true;},onSkipRemaining:()=>{}}:{onSkipRemaining:()=>{}});if(result===false){return}if(kmath.point.is(result)){coord=result;}if(!kmath.point.equal(coord,state.coord)){const prevCoord=state.coord;state.coord=coord;state.hasMoved=true;this._fireEvent(state.onMove,state.coord,prevCoord);this.draw();}}remove(){this.state.added=false;this._fireEvent(this.state.remove);if(this.movable){this.movable.remove();}this.state.mouseTarget=null;}pointSize(){return this.state.pointSize}static(){return this.state.static}cursor(){return this.state.cursor}normalStyle(){return this.state.normalStyle}highlightStyle(){return this.state.highlightStyle}shadow(){return this.state.shadow}tooltip(){return this.state.tooltip}added(){return this.state.added}hasMoved(){return this.state.hasMoved}visibleShape(){return this.state.visibleShape}outOfBounds(){return this.state.outOfBounds}mouseTarget(){return this.state.mouseTarget}touchOffset(){return this.state.touchOffset}isHovering(){return this.movable.isHovering()}isDragging(){return this.movable.isDragging()}toBack(){this.movable.toBack();if(this.state.visibleShape){this.state.visibleShape.toBack();}}toFront(){if(this.state.visibleShape){this.state.visibleShape.toFront();}this.movable.toFront();}constructor(graphie,movable,options){this._listenerMap={};this.graphie=graphie;this.movable=movable;this.state={id:___default.default.uniqueId("movablePoint")};this.modify({...DEFAULT_STATE$1,...options});}};MovablePoint$5.add=MovablePointOptions.add;MovablePoint$5.modify=MovablePointOptions.modify;MovablePoint$5.draw=MovablePointOptions.draw;MovablePoint$5.remove=MovablePointOptions.remove;MovablePoint$5.onMoveStart=MovablePointOptions.onMoveStart;MovablePoint$5.constraints=MovablePointOptions.constraints;MovablePoint$5.onMove=MovablePointOptions.onMove;MovablePoint$5.onMoveEnd=MovablePointOptions.onMoveEnd;MovablePoint$5.onClick=MovablePointOptions.onClick;function getKey(eventName,id){return eventName+":"+id}function getEventName(key){return key.split(":")[0]}
|
|
1648
1645
|
|
|
1649
|
-
function sum(array){return ___default.default.reduce(array,function(memo,arg){return memo+arg},0)}function clockwise$2(points){const segments=___default.default.zip(points,points.slice(1).concat(points.slice(0,1)));const areas=
|
|
1646
|
+
function sum(array){return ___default.default.reduce(array,function(memo,arg){return memo+arg},0)}function clockwise$2(points){const segments=___default.default.zip(points,points.slice(1).concat(points.slice(0,1)));const areas=segments.map(function(segment){const p1=segment[0];const p2=segment[1];return (p2[0]-p1[0])*(p2[1]+p1[1])});return sum(areas)>0}const add={constrain:function(){this.constrain();},pointsToFront:function(state){___default.default.invoke(state.points,"toFront");}};add.standard=[add.constrain,add.pointsToFront];const modify={draw:function(){this.draw();}};modify.standard=[modify.draw];const draw={basic:function(state,prevState){const graphie=this.graphie;const path=this.path(state);if(!this.state.visibleShape){this.state.visibleShape=graphie.raphael.path(path);this.state.visibleShape.attr(this.normalStyle());}if(state.normalStyle!==prevState.normalStyle&&!___default.default.isEqual(state.normalStyle,prevState.normalStyle)){this.state.visibleShape.attr(this.normalStyle());}this.state.visibleShape.attr({path:path});if(this.mouseTarget()){this.mouseTarget().attr({path:path});}},labels:function(state,prevState){const graphie=this.graphie;const self=this;const coords=___default.default.invoke(state.points,"coord");const isClockwise=clockwise$2(coords);const n=coords.length;if(self.state._labelCache!=null){___default.default.invoke(self.state._labelCache,"remove");}self.state._labelCache=[];if(state.angleLabels.length||state.showRightAngleMarkers.length){if(self.state._labeledAngles==null){self.state._labeledAngles=___default.default.times(Math.max(state.angleLabels.length,state.showRightAngleMarkers.length),function(){return graphie.label([0,0],"","center",state.labelStyle)});}___default.default.each(self.state._labeledAngles,function(label,i){self.state._labelCache.push(graphie.labelAngle({point1:coords[(i-1+n)%n],vertex:coords[i],point3:coords[(i+1)%n],label:label,text:state.angleLabels[i],showRightAngleMarker:state.showRightAngleMarkers[i],numArcs:state.numArcs[i],clockwise:isClockwise,style:state.labelStyle}));});}if(state.sideLabels.length){if(self.state._labeledSides==null){self.state._labeledSides=state.sideLabels.map(function(label){return graphie.label([0,0],"","center",state.labelStyle)});}___default.default.each(self.state._labeledSides,function(label,i){self.state._labelCache.push(graphie.labelSide({point1:coords[i],point2:coords[(i+1)%n],label:label,text:state.sideLabels[i],numArrows:state.numArrows[i],numTicks:state.numTicks[i],clockwise:isClockwise,style:state.labelStyle}));});}if(state.vertexLabels.length){if(self.state._labeledVertices==null){self.state._labeledVertices=state.vertexLabels.map(function(label){return graphie.label([0,0],"","center",state.labelStyle)});}___default.default.each(self.state._labeledVertices,function(label,i){self.state._labelCache.push(graphie.labelVertex({point1:coords[(i-1+n)%n],vertex:coords[i],point3:coords[(i+1)%n],label:label,text:state.vertexLabels[i],clockwise:isClockwise,style:state.labelStyle}));});}self.state._labelCache=___default.default.flatten(self.state._labelCache);},highlight:function(state,prevState){if(state.isHovering&&!prevState.isHovering){state.visibleShape.animate(this.highlightStyle(),50);}else if(!state.isHovering&&prevState.isHovering){state.visibleShape.animate(this.normalStyle(),50);}}};draw.standard=[draw.basic,draw.labels,draw.highlight];const remove={basic:function(){if(this.state.visibleShape){this.state.visibleShape.remove();}},labels:function(){const labels=[this.state._labeledSides,this.state._labeledVertices,this.state._labeledAngles,this.state._labelCache];___default.default.each(labels,function(labelType){if(labelType!=null&&labelType.length){___default.default.invoke(labelType,"remove");}});}};remove.standard=[remove.basic,remove.labels];const constraints={fixed:function(){return function(){return false}},snap:function(snap){return function(coord){if(snap===null){return true}snap=snap||this.graphie.snap;return kmath.point.roundTo(coord,snap)}},bound:function(range,snap,paddingPx){if(paddingPx===undefined){if(range===undefined){paddingPx=10;}else {paddingPx=0;}}return function(coord,prevCoord){const graphie=this.graphie;const delta=kmath.vector.subtract(coord,prevCoord);range=range||graphie.range;if(snap===undefined){snap=graphie.snap;}let absoluteLower=graphie.unscalePoint([paddingPx,graphie.ypixels-paddingPx]);let absoluteUpper=graphie.unscalePoint([graphie.xpixels-paddingPx,paddingPx]);if(snap){absoluteLower=kmath.point.ceilTo(absoluteLower,snap);absoluteUpper=kmath.point.floorTo(absoluteUpper,snap);}const deltaBounds=this.coords().map(function(coord,i){const max=kmath.vector.subtract(absoluteUpper,coord);const min=kmath.vector.subtract(absoluteLower,coord);return [min,max]});const boundedDelta=___default.default.reduce(deltaBounds,function(delta,bound){const lower=bound[0];const upper=bound[1];const deltaX=Math.max(lower[0],Math.min(upper[0],delta[0]));const deltaY=Math.max(lower[1],Math.min(upper[1],delta[1]));return [deltaX,deltaY]},delta);return kmath.vector.add(prevCoord,boundedDelta)}}};constraints.standard=null;const onMove={updatePoints:function(coord,prevCoord){const actualDelta=kmath.vector.subtract(coord,prevCoord);___default.default.each(this.state.points,function(point){point.setCoord(kmath.vector.add(point.coord(),actualDelta));});}};onMove.standard=null;var MovablePolygonOptions = {add:add,modify:modify,draw:draw,remove:remove,onMoveStart:{standard:null},constraints:constraints,onMove:onMove,onMoveEnd:{standard:null},onClick:{standard:null}};
|
|
1650
1647
|
|
|
1651
|
-
const assert$
|
|
1648
|
+
const assert$3=InteractiveUtil.assert;const normalizeOptions=InteractiveUtil.normalizeOptions;const DEFAULT_PROPS={points:null,angleLabels:[],showRightAngleMarkers:[],sideLabels:[],vertexLabels:[],numArcs:[],numArrows:[],numTicks:[],closed:true,static:false,cursor:"move",normalStyle:null,highlightStyle:null,labelStyle:null};const DEFAULT_STATE={added:false,hasMoved:false,visibleShape:null,mouseTarget:null};const MovablePolygon=function(graphie,movable,options){assert$3(graphie!=null);assert$3(options!=null);___default.default.extend(this,{graphie:graphie,movable:movable,state:{id:___default.default.uniqueId("movablePolygon")}});this.modify(___default.default.extend({},DEFAULT_STATE,options));};___default.default.extend(MovablePolygon,MovablePolygonOptions);InteractiveUtil.createGettersFor(MovablePolygon,___default.default.extend({},DEFAULT_PROPS,DEFAULT_STATE));InteractiveUtil.addMovableHelperMethodsTo(MovablePolygon);___default.default.extend(MovablePolygon.prototype,{cloneState:function(){return ___default.default.extend(this.movable.cloneState(),this.state)},_createDefaultState:function(){return ___default.default.extend({id:this.state.id},normalizeOptions(perseusCore.pluck(MovablePolygonOptions,"standard")),DEFAULT_PROPS)},modify:function(options){this.update(___default.default.extend(this._createDefaultState(),options));},update:function(options){const self=this;const graphie=self.graphie;const state=___default.default.extend(self.state,normalizeOptions(options));const normalColor=state.static?KhanColors.DYNAMIC:KhanColors.INTERACTIVE;state.normalStyle=___default.default.extend({},state.normalStyle,{"stroke-width":2,"fill-opacity":0,fill:normalColor,stroke:normalColor},options.normalStyle);state.highlightStyle=___default.default.extend({},{stroke:KhanColors.INTERACTING,"stroke-width":2,fill:KhanColors.INTERACTING,"fill-opacity":.05},state.highlightStyle);state.labelStyle=___default.default.extend({},{stroke:KhanColors.DYNAMIC,"stroke-width":1,color:KhanColors.DYNAMIC},state.labelStyle);if(!state.static){if(!state.mouseTarget){state.mouseTarget=graphie.mouselayer.path(this.path());state.mouseTarget.attr({fill:"#000",opacity:0,cursor:"move"});}}self.movable.modify(___default.default.extend({},state,{modify:null,draw:self.draw.bind(self),remove:null,onMoveStart:function(){self._initialRefCoord=self.coord(0);self._prevRefCoord=self._initialRefCoord;self._totalDelta=[0,0];self._fireEvent(self.state.onMoveStart,self.coord(0),self.coord(0));},onMove:function(mouseCoord,prevMouseCoord){const delta=kmath.vector.subtract(mouseCoord,prevMouseCoord);self._totalDelta=kmath.vector.add(self._totalDelta,delta);let refCoord=kmath.vector.add(self._initialRefCoord,self._totalDelta);refCoord=self._applyConstraints(refCoord,self._prevRefCoord);if(refCoord===false){return}self._fireEvent(self.state.onMove,refCoord,self._prevRefCoord);self._prevRefCoord=refCoord;},onMoveEnd:function(){self._fireEvent(self.state.onMoveEnd,self._prevRefCoord,self._initialRefCoord);}}));___default.default.invoke(state.points,"listen","onMove",state.id,self.draw.bind(self));if(!state.added){self.prevState={};self._fireEvent(state.add,self.cloneState(),self.prevState);state.added=true;self.prevState=self.cloneState();}self._fireEvent(state.modify,self.cloneState(),self.prevState);},path:function(state){const graphie=this.graphie;state=state||this.state;let coords=state.points.map(function(point){return graphie.scalePoint(point.coord())});if(state.closed){coords.push(true);}else {coords=coords.concat(___default.default.clone(coords).reverse());}return GraphUtils.unscaledSvgPath(coords)},coords:function(){return ___default.default.invoke(this.state.points,"coord")},point:function(index){return this.state.points[index]},coord:function(index){return this.point(index).coord()},remove:function(){this.state.added=false;this._fireEvent(this.state.remove);if(this.state.points){___default.default.invoke(this.state.points,"unlisten","onMove",this.state.id);}if(this.movable){this.movable.remove();}this.state.mouseTarget=null;},constrain:function(){if(this.points==null||this.points.length===0){return}const prevRefCoord=this.coord(0);const refCoord=this._applyConstraints(prevRefCoord,prevRefCoord);if(refCoord!==false){this._fireEvent(this.state.onMove,refCoord,prevRefCoord);}},normalStyle:function(){return ___default.default.clone(this.state.normalStyle)},highlightStyle:function(){return ___default.default.clone(this.state.highlightStyle)},toBack:function(){this.movable.toBack();if(this.state.visibleShape){this.state.visibleShape.toBack();}},toFront:function(){if(this.state.visibleShape){this.state.visibleShape.toFront();}this.movable.toFront();},isHovering:function(){return this.movable.isHovering()},isDragging:function(){return this.movable.isDragging()},mouseTarget:function(){return this.movable.mouseTarget()}});
|
|
1652
1649
|
|
|
1653
1650
|
const Interactive2={MovablePoint:MovablePoint$5,addMovablePoint:function(graphie,options){const movable=new Movable(graphie,{});return new MovablePoint$5(graphie,movable,options)},MovableLine:MovableLine$4,addMovableLine:function(graphie,options){const movable=new Movable(graphie,{});return new MovableLine$4(graphie,movable,options)},MovablePolygon:MovablePolygon,addMovablePolygon:function(graphie,options){const movable=new Movable(graphie,{});return new MovablePolygon(graphie,movable,options)},addMaybeMobileMovablePoint:function(widget,extraProps){const isMobile=widget.props.apiOptions.isMobile;const commonStyle=isMobile?{stroke:"#ffffff","stroke-width":3,fill:KhanColors.INTERACTIVE}:{stroke:KhanColors.INTERACTIVE,fill:KhanColors.INTERACTIVE};const normalStyle=Object.assign(commonStyle,extraProps.normalStyle);const highlightStyle=Object.assign(isMobile?{...commonStyle,"stroke-width":0,scale:.75}:{},extraProps.highlightStyle);const props=Object.assign({normalStyle:normalStyle,highlightStyle:highlightStyle,shadow:isMobile,tooltip:isMobile&&widget.props.showTooltips,showHairlines:widget.showHairlines,hideHairlines:widget.hideHairlines},isMobile?{pointSize:7}:{});return Interactive2.addMovablePoint(widget.graphie,Object.assign(extraProps,props))}};
|
|
1654
1651
|
|
|
1655
1652
|
const MovablePoint$4=GraphieClasses.createClass({displayName:"MovablePoint",movableProps:["children"],_getProps:function(){if(!this.props.isMobile){return this.props}const interactiveColor=wonderBlocksTokens.tokenValue(wonderBlocksTokens.semanticColor.core.foreground.instructive.default);const commonStyle={stroke:wonderBlocksTokens.tokenValue(wonderBlocksTokens.semanticColor.core.foreground.knockout.default),"stroke-width":3,fill:interactiveColor};return Object.assign(this.props,{normalStyle:{...commonStyle,...this.props.mobileStyleOverride||{}},highlightStyle:{...commonStyle,"stroke-width":0,scale:.75},shadow:true,tooltip:this.props.showTooltips,pointSize:7})},add:function(graphie){this.point=Interactive2.addMovablePoint(graphie,this._getProps());},modify:function(){this.point.modify(this._getProps());},remove:function(){this.point.remove();},toFront:function(){this.point.toFront();},grab:function(coord){this.point.grab(coord);}});___default.default.extend(MovablePoint$4,Interactive2.MovablePoint);const MovableLine$3=GraphieClasses.createClass({displayName:"MovableLine",movableProps:["children"],add:function(graphie){const points=___default.default.pluck(this.props.children,"point");const props=___default.default.extend({},this.props,{points:points});this.line=Interactive2.addMovableLine(graphie,props);},modify:function(){const points=___default.default.pluck(this.props.children,"point");const props=___default.default.extend({},this.props,{points:points});this.line.modify(props);},remove:function(){this.line.remove();},toFront:function(){this.line.toFront();}});___default.default.extend(MovableLine$3,Interactive2.MovableLine);const Label$1=GraphieClasses.createSimpleClass((graphie,props)=>{let coord=props.coord;if(props.unscaled){coord=graphie.unscalePoint(coord);}let elem;if(getDependencies().JIPT.useJIPT){elem=graphie.label(coord,props.text,props.direction,false,props.style);getDependencies().graphieMovablesJiptLabels.addLabel(elem,props.tex);}else {elem=graphie.label(coord,props.text,props.direction,props.tex,props.style);}return elem});const Line$3=GraphieClasses.createClass({displayName:"Line",movableProps:["children"],add:function(graphie){const props=this.props;this.graphie=graphie;this.line=this.graphie.line(props.start,props.end,props.style);},modify:function(){const props=this.props;const path=this.graphie.svgPath([props.start,props.end]);this.line.attr(___default.default.extend({},props.style,{path:path}));},remove:function(){this.line.remove();},toFront:function(){this.line.toFront();}});const Parabola=GraphieClasses.createClass({displayName:"Parabola",movableProps:["children"],add:function(graphie){const props=this.props;this.graphie=graphie;this.parabola=this.graphie.parabola(props.a,props.b,props.c,props.style);},modify:function(){const props=this.props;const path=this.graphie.svgParabolaPath(props.a,props.b,props.c);this.parabola.attr(___default.default.extend({},props.style,{path:path}));},remove:function(){this.parabola.remove();},toFront:function(){this.parabola.toFront();}});const Sinusoid=GraphieClasses.createClass({displayName:"Sinusoid",movableProps:["children"],add:function(graphie){const props=this.props;this.graphie=graphie;this.sinusoid=this.graphie.sinusoid(props.a,props.b,props.c,props.d,props.style);},modify:function(){const props=this.props;const path=this.graphie.svgSinusoidPath(props.a,props.b,props.c,props.d);this.sinusoid.attr(___default.default.extend({},props.style,{path:path}));},remove:function(){this.sinusoid.remove();},toFront:function(){this.sinusoid.toFront();}});const Plot$1=GraphieClasses.createSimpleClass((graphie,props)=>{return graphie.plot(props.fn,props.range,props.style)});const PlotParametric$1=GraphieClasses.createSimpleClass((graphie,props)=>{return graphie.plotParametric(props.fn,props.range,props.style)});const Point$1=GraphieClasses.createSimpleClass((graphie,props)=>{const neutralColor=wonderBlocksTokens.tokenValue(wonderBlocksTokens.semanticColor.core.foreground.neutral.strong);return graphie.ellipse(props.coord,graphie.unscaleVector([4,4]),{fill:props.color||neutralColor,stroke:props.color||neutralColor})});const Path=GraphieClasses.createClass({displayName:"Path",movableProps:["children"],add:function(graphie){const props=this.props;this.graphie=graphie;this.path=this.graphie.path(props.coords,props.style);},modify:function(){const props=this.props;const path=this.graphie.svgPath(props.coords);this.path.attr({path:path});},remove:function(){this.path.remove();},toFront:function(){this.path.toFront();}});const Arc$1=GraphieClasses.createSimpleClass((graphie,props)=>{let center=props.center;let radius=props.radius;if(props.unscaled){center=graphie.unscalePoint(center);radius=graphie.unscaleVector(radius);}return graphie.arc(center,radius,props.startAngle,props.endAngle,props.sector,props.style)});const Circle=GraphieClasses.createSimpleClass((graphie,props)=>{return graphie.circle(props.center,props.radius,props.style)});const Rect$1=GraphieClasses.createSimpleClass((graphie,props)=>{return graphie.rect(props.x,props.y,props.width,props.height,props.style)});var Movables = {Arc:Arc$1,Circle:Circle,Label:Label$1,Line:Line$3,MovableLine:MovableLine$3,MovablePoint:MovablePoint$4,Parabola:Parabola,Path:Path,Plot:Plot$1,PlotParametric:PlotParametric$1,Point:Point$1,Sinusoid:Sinusoid,Rect:Rect$1};
|
|
1656
1653
|
|
|
1657
|
-
const GraphieMovable=GraphieClasses.GraphieMovable;const createGraphie=GraphUtils.createGraphie;const{nestedMap}=Util;const{assert: assert$
|
|
1654
|
+
const GraphieMovable=GraphieClasses.GraphieMovable;const createGraphie=GraphUtils.createGraphie;const{nestedMap}=Util;const{assert: assert$2}=InteractiveUtil;class Graphie extends React__namespace.Component{componentDidMount(){this._setupGraphie();this._updateMovables();}shouldComponentUpdate(nextProps){return !___default.default.isEqual(this.props,nextProps)}componentDidUpdate(prevProps){if(this.props.setup!==prevProps.setup){Log.error("<Graphie> was given a new setup function. "+"This is a bad idea; please refactor your code to give "+"the same setup function reference to <Graphie> on "+"every render.",perseusCore.Errors.Internal);}if(!perseusCore.approximateDeepEqual(this.props.options,prevProps.options)||!perseusCore.approximateDeepEqual(this.props.box,prevProps.box)||!perseusCore.approximateDeepEqual(this.props.range,prevProps.range)){this._setupGraphie();}this._updateMovables();}componentWillUnmount(){this._removeMovables();this._graphie.cleanup();}render(){return jsxRuntimeExports.jsx("div",{className:"graphie-container",children:jsxRuntimeExports.jsx("div",{className:"graphie",ref:this.graphieDivRef})})}constructor(...args){super(...args),this.graphieDivRef=React__namespace.createRef(),this._graphie=new Graphie$1(document.createElement("div")),this._movables={},this.movables={},this.getGraphie=()=>{return this._graphie},this._range=()=>{const boundsCheckRange=range=>{if(range[0]>=range[1]){return [-10,10]}return range};return [boundsCheckRange(this.props.range[0]),boundsCheckRange(this.props.range[1])]},this._box=()=>{const ensureMinSize=pixelDim=>{return pixelDim>0?pixelDim:340};return [ensureMinSize(this.props.box[0]),ensureMinSize(this.props.box[1])]},this._scale=()=>{const box=this._box();const range=this._range();return box.map((pixelDim,i)=>{const unitDim=range[i][1]-range[i][0];return pixelDim/unitDim})},this._setupGraphie=()=>{this._graphie.cleanup();this._removeMovables();const graphieDiv=this.graphieDivRef.current;if(graphieDiv==null||graphieDiv instanceof Text){throw new Error("No graphie container div found")}graphieDiv.innerHTML="";const graphie=this._graphie=createGraphie(graphieDiv);graphie.init({range:this._range(),scale:this._scale(),isMobile:this.props.isMobile});if(this.props.addMouseLayer){graphie.addMouseLayer({onClick:this.props.onClick,onMouseDown:this.props.onMouseDown,onMouseMove:this.props.onMouseMove});}graphie.snap=this.props.options.snapStep||[1,1];if(this.props.responsive){$__default.default(graphieDiv).css({width:"100%",height:"100%"});graphie.raphael.setSize("100%","100%");}this.props.setup(graphie,___default.default.extend({range:this._range(),scale:this._scale()},this.props.options));},this._removeMovables=()=>{___default.default.invoke(this._movables,"remove");this._movables={};},this._renderMovables=(children,options)=>{const graphie=options.graphie;const oldMovables=options.oldMovables;const newMovables=options.newMovables;const renderChildren=elem=>{___default.default.each(elem.movableProps,prop=>{elem.props[prop]=this._renderMovables(elem.props[prop],options);});};let areMovablesOutOfOrder=false;return nestedMap(children,childDescriptor=>{if(!childDescriptor){options.nextKey++;return childDescriptor}const child=new childDescriptor.type(childDescriptor.props);assert$2(child instanceof GraphieMovable,"All children of a Graphie component must be Graphie "+"movables");const keyProp=childDescriptor.key;const key=keyProp==null?"_no_id_"+options.nextKey:keyProp;options.nextKey++;const ref=childDescriptor.ref;renderChildren(child);const prevMovable=oldMovables[key];if(!prevMovable){child.add(graphie);areMovablesOutOfOrder=true;newMovables[key]=child;}else if(child.constructor===prevMovable.constructor){prevMovable.props=child.props;const modifyResult=prevMovable.modify(graphie);if(modifyResult==="reordered"){areMovablesOutOfOrder=true;}newMovables[key]=prevMovable;}else {if(keyProp==null){Log.error("Replacing a <Graphie> child with a "+"child of a different type. Please add keys "+"to your <Graphie> children",perseusCore.Errors.Internal);}prevMovable.remove();child.add(graphie);areMovablesOutOfOrder=true;newMovables[key]=child;}if(areMovablesOutOfOrder){newMovables[key].toFront();}if(ref){this.movables[ref]=newMovables[key];}return newMovables[key]})},this._updateMovables=()=>{const graphie=this._graphie;const oldMovables=this._movables;const newMovables={};this._movables=newMovables;this.movables={};this._renderMovables(this.props.children,{nextKey:1,graphie:graphie,oldMovables:oldMovables,newMovables:newMovables});___default.default.each(oldMovables,(oldMovable,key)=>{if(!newMovables[key]){oldMovable.remove();}});};}}Graphie.defaultProps={range:[[-10,10],[-10,10]],options:{},responsive:false,addMouseLayer:true};___default.default.extend(Graphie,GraphieClasses);___default.default.extend(Graphie,Movables);
|
|
1658
1655
|
|
|
1659
1656
|
function withDependencies(WrappedComponent){const WithDependenciesComponent=React__namespace.default.forwardRef((props,ref)=>{const dependencies=useDependencies();return jsxRuntimeExports.jsx(WrappedComponent,{...props,dependencies:dependencies,ref:ref})});WithDependenciesComponent.displayName=`withDependencies(${WrappedComponent.displayName||WrappedComponent.name||"Component"})`;return WithDependenciesComponent}
|
|
1660
1657
|
|
|
@@ -1662,9 +1659,9 @@ const Status={PENDING:"pending",LOADING:"loading",LOADED:"loaded",FAILED:"failed
|
|
|
1662
1659
|
|
|
1663
1660
|
function isGif(url){return url.endsWith(".gif")}async function decodeGifFrames(src){const res=await fetch(src);if(!res.ok){return []}const buffer=await res.arrayBuffer();const gif=gifuctJs.parseGIF(buffer);return gifuctJs.decompressFrames(gif,true)}function isSvg(url){const hasSvgExtension=url.endsWith(".svg");const hasGraphieUrl=perseusCore.isLabeledSVG(url);return hasSvgExtension||hasGraphieUrl}
|
|
1664
1661
|
|
|
1665
|
-
var styles$
|
|
1662
|
+
var styles$A = {"contentWrapper":"perseus_NqTCZY3N","imageContainer":"perseus_Ctn3miye"};
|
|
1666
1663
|
|
|
1667
|
-
const WB_MODAL_PADDING_TOTAL=64;const ZoomedImageView=props=>{const i18n=usePerseusI18n();const{initialFocusId,onClose,...svgProps}=props;const width=props.width;const height=props.height;const contentScale=props.scale;const imageIsSvg=isSvg(props.src);const scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);const maxAvailableWidth=window.innerWidth-WB_MODAL_PADDING_TOTAL;const maxAvailableHeight=window.innerHeight-WB_MODAL_PADDING_TOTAL;const scaleWidth=maxAvailableWidth/(width*scale);const scaleHeight=maxAvailableHeight/(height*scale);const fitRatio=Math.min(scaleWidth,scaleHeight,1);const constrainedDisplayWidth=width*fitRatio*scale;return jsxRuntimeExports.jsx(wonderBlocksModal.ModalDialog,{"aria-labelledby":"",style:wbStyles$2.dialog,children:jsxRuntimeExports.jsx(wonderBlocksModal.ModalPanel,{closeButtonVisible:false,content:jsxRuntimeExports.jsxs("div",{className:styles$
|
|
1664
|
+
const WB_MODAL_PADDING_TOTAL=64;const ZoomedImageView=props=>{const i18n=usePerseusI18n();const{initialFocusId,onClose,...svgProps}=props;const width=props.width;const height=props.height;const contentScale=props.scale;const imageIsSvg=isSvg(props.src);const scale=imageIsSvg?Math.max(contentScale,2):Math.max(contentScale,1);const maxAvailableWidth=window.innerWidth-WB_MODAL_PADDING_TOTAL;const maxAvailableHeight=window.innerHeight-WB_MODAL_PADDING_TOTAL;const scaleWidth=maxAvailableWidth/(width*scale);const scaleHeight=maxAvailableHeight/(height*scale);const fitRatio=Math.min(scaleWidth,scaleHeight,1);const constrainedDisplayWidth=width*fitRatio*scale;return jsxRuntimeExports.jsx(wonderBlocksModal.ModalDialog,{"aria-labelledby":"",style:wbStyles$2.dialog,children:jsxRuntimeExports.jsx(wonderBlocksModal.ModalPanel,{closeButtonVisible:false,content:jsxRuntimeExports.jsxs("div",{className:styles$A.contentWrapper,children:[jsxRuntimeExports.jsx("div",{className:styles$A.imageContainer,style:{width:constrainedDisplayWidth},children:jsxRuntimeExports.jsx("div",{className:"framework-perseus",tabIndex:0,id:initialFocusId,children:jsxRuntimeExports.jsx(SvgImage,{...svgProps,allowZoom:false,width:width,height:height,scale:scale})})}),jsxRuntimeExports.jsx(IconButton__default.default,{icon:closeIcon__default.default,onClick:onClose,"aria-label":i18n.strings.imageResetZoomAriaLabel,kind:"primary",style:wbStyles$2.closeButton})]})})})};const wbStyles$2=aphrodite.StyleSheet.create({dialog:{width:"auto",height:"auto",margin:wonderBlocksTokens.sizing.size_320,"@media (max-width: 767px)":{margin:0}},closeButton:{position:"absolute",top:wonderBlocksTokens.border.width.medium,right:wonderBlocksTokens.border.width.medium,opacity:0,":hover":{opacity:1},":focus":{opacity:1}}});
|
|
1668
1665
|
|
|
1669
1666
|
const ZoomImageButton=props=>{const{imgSrc}=props;const i18n=usePerseusI18n();const uniqueId=React__namespace.useId().replace(/:/g,"");const zoomedImageUniqueId=`zoomed-image-${uniqueId}`;const handleClick=(event,openModal)=>{const mouseEvent=event;if(mouseEvent.metaKey||mouseEvent.ctrlKey){window.open(imgSrc,"_blank");}else {openModal();}};return jsxRuntimeExports.jsx(wonderBlocksModal.ModalLauncher,{initialFocusId:zoomedImageUniqueId,modal:({closeModal})=>jsxRuntimeExports.jsx(ZoomedImageView,{...props,initialFocusId:zoomedImageUniqueId,onClose:closeModal}),children:({openModal})=>jsxRuntimeExports.jsx(Clickable__default.default,{"aria-label":i18n.strings.imageZoomAriaLabel,onClick:event=>handleClick(event,openModal),style:{position:"absolute",width:"100%",height:"100%",overflow:"hidden",cursor:"zoom-in"},children:()=>{return jsxRuntimeExports.jsx(React__namespace.Fragment,{})}})})};
|
|
1670
1667
|
|
|
@@ -1688,11 +1685,11 @@ const arrayRules={fence:{match:SimpleMarkdown__default.default.defaultRules.fenc
|
|
|
1688
1685
|
|
|
1689
1686
|
const denylist=["key","ref","containerSizeClass","widgetId","onChange","problemNum","apiOptions","widgetIsOpen","findWidgets","onRemove","id","onBlur","onFocus","trackInteraction","keypadElement","linterContext","handleUserInput","analytics","showSolutions","reviewMode","widgetIndex","graded"];function excludeDenylistKeys(obj){if(obj==null){return obj}const rv={};for(const k of Object.keys(obj)){if(!denylist.includes(k)){rv[k]=obj[k];}}return rv}
|
|
1690
1687
|
|
|
1691
|
-
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__namespace.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:aphrodite.css(styles$
|
|
1688
|
+
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__namespace.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:aphrodite.css(styles$z.lintContainer,styles$z.lintContainerBlock),children:[this.renderLink(styles$z.radioWidgetHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}if(inline){return jsxRuntimeExports.jsxs("span",{className:aphrodite.css(styles$z.lintContainer),children:[this.renderLink(styles$z.inlineHoverTarget),jsxRuntimeExports.jsx("span",{children:children})]})}return jsxRuntimeExports.jsxs("div",{className:aphrodite.css(styles$z.lintContainer),children:[this.renderLink(styles$z.hoverTarget),jsxRuntimeExports.jsx("div",{children:children})]})}constructor(...args){super(...args),this.state={tooltipAbove:true},this.getPosition=()=>{const rect=ReactDOM__namespace.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$z.indicatorError;warningText="Error";warningTextStyle=styles$z.publishBlockingError;}else if(this.props.severity===2){severityStyle=styles$z.indicatorWarning;warningText="Warning";warningTextStyle=styles$z.warning;}else {severityStyle=styles$z.indicatorGuideline;warningText="Recommendation";warningTextStyle=styles$z.warning;}return jsxRuntimeExports.jsxs("a",{href:`https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,target:"lint-help-window",className:aphrodite.css(style),children:[jsxRuntimeExports.jsx("span",{className:aphrodite.css(styles$z.indicator,severityStyle),children:this.props.severity===1&&jsxRuntimeExports.jsx(InlineIcon,{...exclamationIcon})}),jsxRuntimeExports.jsxs("div",{className:aphrodite.css(styles$z.tooltip,tooltipAbove&&styles$z.tooltipAbove),children:[this.props.message.split("\n\n").map((m,i)=>jsxRuntimeExports.jsxs("p",{className:aphrodite.css(styles$z.tooltipParagraph),children:[jsxRuntimeExports.jsxs("span",{className:aphrodite.css(warningTextStyle),children:[warningText,":"," "]}),m]},i)),jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$z.tail,tooltipAbove&&styles$z.tailAbove)})]})]})};}}const styles$z=aphrodite.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}});
|
|
1692
1689
|
|
|
1693
|
-
const rules$1={...pureMarkdown.pureMarkdownRules,columns:{...pureMarkdown.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:{...pureMarkdown.pureMarkdownRules.crowdinId,react:(node,output,state)=>node.id},table:{...pureMarkdown.pureMarkdownRules.table,react:function(node,output,state){const table=SimpleMarkdown__default.default.defaultRules.table.react(node,output,state);if(!state.isMobile){return table}return React__namespace.cloneElement(table,{tabIndex:0})}},titledTable:{...pureMarkdown.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__default.default.defaultRules.table.react(node.table,output,state);const caption=jsxRuntimeExports.jsx("caption",{className:"perseus-table-title",children:output(node.title,state)},"caption");contents=React__namespace.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:{...pureMarkdown.pureMarkdownRules.widget,react:(node,output,state)=>{return jsxRuntimeExports.jsx("em",{children:`[Widget: ${node.id}]`},state.key)}},blockMath:{...pureMarkdown.pureMarkdownRules.blockMath,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},math:{...pureMarkdown.pureMarkdownRules.math,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},unescapedDollar:{...pureMarkdown.pureMarkdownRules.unescapedDollar,react:(node,output,state)=>{return "$"}},link:{...pureMarkdown.pureMarkdownRules.link,react:function(node,output,state){const link=SimpleMarkdown__default.default.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__namespace.cloneElement(link,newProps)}},codeBlock:{...pureMarkdown.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__default.default.defaultRules.codeBlock.react(node,output,state)}},lint:{...pureMarkdown.pureMarkdownRules.lint,react:(node,output,state)=>{return jsxRuntimeExports.jsx(Lint,{message:node.message,ruleName:node.ruleName,inline:isInline$1(node.content),blockHighlight:node.blockHighlight,insideTable:node.insideTable,severity:node.severity,children:output(node.content,state)})}}};function isInline$1(node){return !!(node&&node.type&&inlineNodeTypes$1.hasOwnProperty(node.type))}const inlineNodeTypes$1={text:true,math:true,unescapedDollar:true,link:true,img:true,strong:true,u:true,em:true,del:true,code:true};const builtParser$1=SimpleMarkdown__default.default.parserFor(rules$1);const parse$1=(source,state)=>{const paragraphedSource=source+"\n\n";return builtParser$1(paragraphedSource,{...state,inline:false})};const inlineParser$1=(source,state)=>{return builtParser$1(source,{...state,inline:true})};const getContent$1=ast=>{if(
|
|
1690
|
+
const rules$1={...pureMarkdown.pureMarkdownRules,columns:{...pureMarkdown.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:{...pureMarkdown.pureMarkdownRules.crowdinId,react:(node,output,state)=>node.id},table:{...pureMarkdown.pureMarkdownRules.table,react:function(node,output,state){const table=SimpleMarkdown__default.default.defaultRules.table.react(node,output,state);if(!state.isMobile){return table}return React__namespace.cloneElement(table,{tabIndex:0})}},titledTable:{...pureMarkdown.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__default.default.defaultRules.table.react(node.table,output,state);const caption=jsxRuntimeExports.jsx("caption",{className:"perseus-table-title",children:output(node.title,state)},"caption");contents=React__namespace.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:{...pureMarkdown.pureMarkdownRules.widget,react:(node,output,state)=>{return jsxRuntimeExports.jsx("em",{children:`[Widget: ${node.id}]`},state.key)}},blockMath:{...pureMarkdown.pureMarkdownRules.blockMath,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},math:{...pureMarkdown.pureMarkdownRules.math,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},unescapedDollar:{...pureMarkdown.pureMarkdownRules.unescapedDollar,react:(node,output,state)=>{return "$"}},link:{...pureMarkdown.pureMarkdownRules.link,react:function(node,output,state){const link=SimpleMarkdown__default.default.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__namespace.cloneElement(link,newProps)}},codeBlock:{...pureMarkdown.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__default.default.defaultRules.codeBlock.react(node,output,state)}},lint:{...pureMarkdown.pureMarkdownRules.lint,react:(node,output,state)=>{return jsxRuntimeExports.jsx(Lint,{message:node.message,ruleName:node.ruleName,inline:isInline$1(node.content),blockHighlight:node.blockHighlight,insideTable:node.insideTable,severity:node.severity,children:output(node.content,state)})}},paragraph:{...pureMarkdown.pureMarkdownRules.paragraph,react:(node,output,state)=>{if(noParagraphForInlineWidget(node)){return output(node.content,state)}else {return jsxRuntimeExports.jsx("p",{children:output(node.content,state)})}}}};function isInline$1(node){return !!(node&&node.type&&inlineNodeTypes$1.hasOwnProperty(node.type))}const inlineNodeTypes$1={text:true,math:true,unescapedDollar:true,link:true,img:true,strong:true,u:true,em:true,del:true,code:true};const builtParser$1=SimpleMarkdown__default.default.parserFor(rules$1);const parse$1=(source,state)=>{const paragraphedSource=source+"\n\n";return builtParser$1(paragraphedSource,{...state,inline:false})};const inlineParser$1=(source,state)=>{return builtParser$1(source,{...state,inline:true})};const getContent$1=ast=>{if(Array.isArray(ast)){return ___default.default.flatten(ast.map(getContent$1))}if(ast.content&&typeof ast.content==="string"){if(ast.type.toLowerCase().indexOf("code")!==-1){return ["",ast.content,""]}return [ast.content.replace(/\s+/g," ")]}const children=___default.default.chain(ast).values().flatten().filter(object=>object!=null&&___default.default.has(object,"type")).value();if(!children.length){return []}const nestedContent=getContent$1(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$1=source=>{const ast=parse$1(source);const content=getContent$1(ast).join("");return content.length};var PerseusMarkdown$1 = {characterCount:characterCount$1,traverseContent:pureMarkdown.traverseContent,parse:parse$1,parseInline:inlineParser$1,reactFor:SimpleMarkdown__default.default.reactFor,ruleOutput:SimpleMarkdown__default.default.ruleOutput(rules$1,"react"),basicOutput:SimpleMarkdown__default.default.reactFor(SimpleMarkdown__default.default.ruleOutput(rules$1,"react")),sanitizeUrl:SimpleMarkdown__default.default.sanitizeUrl};
|
|
1694
1691
|
|
|
1695
|
-
|
|
1692
|
+
const QuestionParagraph$1=({className,translationIndex,paragraphIndex,children})=>{const isJIPT=translationIndex!=null;const resolvedClassName=className&&className.trim().length>0?className:undefined;if(!isJIPT&&resolvedClassName==null){return children}return jsxRuntimeExports.jsx("div",{className:resolvedClassName,"data-perseus-component-index":translationIndex,"data-perseus-paragraph-index":isJIPT?paragraphIndex:undefined,children:children})};
|
|
1696
1693
|
|
|
1697
1694
|
const DEBOUNCE_TIMEOUT=1e3;class TranslationLinter{applyLintErrors(parsedMarkdown,translationLintErrors){if(translationLintErrors.length){const errorText=translationLintErrors.join("\n\n");parsedMarkdown.unshift({content:{type:"text",content:""},insideTable:false,message:errorText,ruleName:"legacy-error",severity:PerseusLinter.Rule.Severity.ERROR,type:"lint"});}}constructor(){this.previousContent=null;this.runLinter=_.debounce((perseusStr,onLintErrorsGenerated)=>{if(typeof KA==="undefined"){return}if(perseusStr===this.previousContent){return}this.previousContent=perseusStr;if(perseusStr===""){onLintErrorsGenerated([]);return}fetch("/api/internal/translations/lint_poentry?preview=1&lang=en",{headers:{"Content-Type":"application/json"},body:JSON.stringify({msgid:perseusStr,msgstr:perseusStr,format:"perseus_text",filename:""}),method:"POST"}).then(response=>{if(response.status>=400){return {status:"error",message:"Could not run i18n linter."}}return response.json()},rejection=>{return {status:"error",message:"Could not run i18n linter."}}).then(json=>{if(json.status==="error"){onLintErrorsGenerated(["Some part of this text makes it untranslatable. "+"The specific message from the i18n linter was: "+json.message.replace(/\n/g," ")]);}else {onLintErrorsGenerated([]);}});},DEBOUNCE_TIMEOUT);}}
|
|
1698
1695
|
|
|
@@ -1724,13 +1721,17 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
1724
1721
|
supportsUngraded: supportsUngraded
|
|
1725
1722
|
});
|
|
1726
1723
|
|
|
1727
|
-
class WidgetContainer extends React__namespace.Component{componentDidMount(){if(this.props.widgetProps.apiOptions.isMobile){const containerWidth=ReactDOM__namespace.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.")}}render(){let className=classNames__default.default({"perseus-widget-container":true,"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})}const subType=getWidgetSubType(type,this.props.widgetProps)??"null";let alignment=this.props.widgetProps.alignment;if(alignment==="default"){alignment=perseusCore.CoreWidgetRegistry.getDefaultAlignment(type);}className+=perseusCore.CoreWidgetRegistry.getAlignmentClassName(type,alignment);const apiOptions=this.props.widgetProps.apiOptions;const isStatic=this.props.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(
|
|
1724
|
+
class WidgetContainer extends React__namespace.Component{componentDidMount(){if(this.props.widgetProps.apiOptions.isMobile){const containerWidth=ReactDOM__namespace.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.")}}render(){let className=classNames__default.default({"perseus-widget-container":true,"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})}const subType=getWidgetSubType(type,this.props.widgetProps)??"null";let alignment=this.props.widgetProps.alignment;if(alignment==null||alignment==="default"){alignment=perseusCore.CoreWidgetRegistry.getDefaultAlignment(type);}className+=perseusCore.CoreWidgetRegistry.getAlignmentClassName(type,alignment);const Container=alignment.startsWith("inline")?"span":"div";const apiOptions=this.props.widgetProps.apiOptions;const isStatic=this.props.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(Container,{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,stack:error.stack??"No stack trace available",userAgent:userAgent}});},children:[jsxRuntimeExports.jsx(WidgetType,{...this.props.widgetProps,linterContext:linterContext,containerSizeClass:this.state.sizeClass,ref:this.widgetRef}),isStatic&&jsxRuntimeExports.jsx("div",{style:staticOverlayStyles})]})})})}constructor(...args){super(...args),this.widgetRef=React__namespace.createRef(),this.state={sizeClass:containerSizeClass.MEDIUM},this.getWidget=()=>{return this.widgetRef.current};}}WidgetContainer.defaultProps={linterContext:PerseusLinter.linterContextDefault};
|
|
1725
|
+
|
|
1726
|
+
const rContainsNonWhitespace$1=/\S/;const rImageURL$1=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender$1=()=>{};const makeContainerId$1=id=>"container:"+id;const isIdPathPrefix$1=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return ___default.default.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return ___default.default.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion$1(propsA,propsB){function makeItem(props){return perseusCore.splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:perseusCore.getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!___default.default.isEqual(makeItem(propsA),makeItem(propsB))}let Renderer$2 = class Renderer extends React__namespace.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion$1(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!___default.default.isEqual(this.state,nextState);const propsChanged=!___default.default.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput&&!___default.default.isEqual(this.props.userInput,prevProps.userInput)){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_isAnswerable(){if(this.props.userInput){return this.emptyWidgets().length===0}return false}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",perseusCore.Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];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,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,graded:widgetInfo?.graded,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,showSolutions:this.props.showSolutions,onFocus:___default.default.partial(this._onWidgetFocus,widgetId),onBlur:___default.default.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.apiOptions?.interactionCallback?.(updatedUserInput);},trackInteraction:interactionTracker.track}}getSerializedState(){return perseusCore.mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}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)});}}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}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(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=perseusScore.scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=perseusScore.flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();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;let parsedMarkdown=this.props.inline?PerseusMarkdown$1.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown$1.parse(content,{isJipt:this.translationIndex!=null});parsedMarkdown=Util.splitBlockWidgetsFromParagraphs(parsedMarkdown);if(this.props.linterContext.highlightLint){const fullLinterContext={content:this.props.content,widgets:this.props.widgets,...this.props.linterContext};PerseusLinter__namespace.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__default.default({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=perseusCore.applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},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;return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId$1(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,widgetProps:this.getWidgetProps(id),linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"widget")},makeContainerId$1(id))}return null},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$1(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!Array.isArray(focusPath)){throw new perseusCore.PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),perseusCore.Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!___default.default.isEqual(fullPath,blurringFocusPath)){return}___default.default.defer(()=>{if(___default.default.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.outputMarkdown=(ast,state)=>{if(Array.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__default.default({"perseus-paragraph-centered":!this._foundTextNodes,"perseus-paragraph-full-width":state.foundFullWidth&&ast.content?.length===1});}return jsxRuntimeExports.jsx(QuestionParagraph$1,{className:className,translationIndex:this.translationIndex,paragraphIndex:state.paragraphIndex,children:jsxRuntimeExports.jsx(ErrorBoundary,{children:output})},state.key)},this.outputNested=(ast,state)=>{if(Array.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$y.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=___default.default.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,{allowZoom:true,setAssetStatus:setAssetStatus,src:PerseusMarkdown$1.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$1.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace$1.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL$1.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown$1.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$y.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$1.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender$1||oldOnRender!==noopOnRender$1){const $images=$__default.default(ReactDOM__namespace.default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender$1){$images.off("load",oldOnRender);}if(onRender!==noopOnRender$1){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix$1(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'",perseusCore.Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){const container=this._widgetContainers.get(makeContainerId$1(widgetId));if(container){return ReactDOM__namespace.default.findDOMNode(container)}return ReactDOM__namespace.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(___default.default.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!___default.default.isEqual(this._currentFocus,path)){return}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.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={};___default.default.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!___default.default.isEmpty(s)){state[id]=s;}},this);return state},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:[],...this._getInitialWidgetState(props)};}};Renderer$2.contextType=PerseusI18nContext;Renderer$2.defaultProps={content:"",widgets:{},images:{},showSolutions:"none",onRender:noopOnRender$1,findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter__namespace.linterContextDefault};const styles$y={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
|
|
1728
1727
|
|
|
1729
|
-
const rContainsNonWhitespace$1=/\S/;const rImageURL$1=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender$1=()=>{};const makeContainerId$1=id=>"container:"+id;const isIdPathPrefix$1=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return ___default.default.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return ___default.default.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion$1(propsA,propsB){function makeItem(props){return perseusCore.splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:perseusCore.getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!___default.default.isEqual(makeItem(propsA),makeItem(propsB))}let Renderer$2 = class Renderer extends React__namespace.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion$1(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!___default.default.isEqual(this.state,nextState);const propsChanged=!___default.default.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput&&!___default.default.isEqual(this.props.userInput,prevProps.userInput)){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_isAnswerable(){if(this.props.userInput){return this.emptyWidgets().length===0}return false}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",perseusCore.Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];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,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,graded:widgetInfo?.graded,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,showSolutions:this.props.showSolutions,onFocus:___default.default.partial(this._onWidgetFocus,widgetId),onBlur:___default.default.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.apiOptions?.interactionCallback?.(updatedUserInput);},trackInteraction:interactionTracker.track}}getSerializedState(){return perseusCore.mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}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)});}}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}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(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=perseusScore.scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=perseusScore.flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();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$1.parseInline(content,{isJipt:this.translationIndex!=null}):PerseusMarkdown$1.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__namespace.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__default.default({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=perseusCore.applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},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;return jsxRuntimeExports.jsx(WidgetContainer,{id:id,ref:node=>{const containerId=makeContainerId$1(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,widgetProps:this.getWidgetProps(id),linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"widget")},makeContainerId$1(id))}return null},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$1(id));if(!ref){return null}return ref.getWidget()},this._onWidgetFocus=(id,focusPath=[])=>{if(!___default.default.isArray(focusPath)){throw new perseusCore.PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),perseusCore.Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!___default.default.isEqual(fullPath,blurringFocusPath)){return}___default.default.defer(()=>{if(___default.default.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.outputMarkdown=(ast,state)=>{if(___default.default.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__default.default({"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(___default.default.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$z.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=___default.default.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,{allowZoom:true,setAssetStatus:setAssetStatus,src:PerseusMarkdown$1.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$1.ruleOutput(node,nestedOutput,state)},state.key)}if(node.type==="text"){if(rContainsNonWhitespace$1.test(node.content)){this._foundTextNodes=true;}if(imagePlaceholder&&rImageURL$1.test(node.content)){return imagePlaceholder}return node.content}if(node.type==="table"||node.type==="titledTable"){const output=PerseusMarkdown$1.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$z.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$1.ruleOutput(node,nestedOutput,state)},state.key)},this.handleRender=prevProps=>{const onRender=this.props.onRender;const oldOnRender=prevProps.onRender;if(onRender!==noopOnRender$1||oldOnRender!==noopOnRender$1){const $images=$__default.default(ReactDOM__namespace.default.findDOMNode(this)).find("img");if(oldOnRender!==noopOnRender$1){$images.off("load",oldOnRender);}if(onRender!==noopOnRender$1){$images.on("load",onRender);}}onRender();},this._setCurrentFocus=path=>{const apiOptions=this.getApiOptions();if(!isIdPathPrefix$1(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'",perseusCore.Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){const container=this._widgetContainers.get(makeContainerId$1(widgetId));if(container){return ReactDOM__namespace.default.findDOMNode(container)}return ReactDOM__namespace.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(___default.default.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!___default.default.isEqual(this._currentFocus,path)){return}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.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={};___default.default.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!___default.default.isEmpty(s)){state[id]=s;}},this);return state},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:[],...this._getInitialWidgetState(props)};}};Renderer$2.contextType=PerseusI18nContext;Renderer$2.defaultProps={content:"",widgets:{},images:{},showSolutions:"none",onRender:noopOnRender$1,findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter__namespace.linterContextDefault};const styles$z={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
|
|
1728
|
+
const rules={...pureMarkdown.pureMarkdownRules,columns:{...pureMarkdown.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:{...pureMarkdown.pureMarkdownRules.crowdinId,react:(node,output,state)=>node.id},table:{...pureMarkdown.pureMarkdownRules.table,react:function(node,output,state){const table=SimpleMarkdown__default.default.defaultRules.table.react(node,output,state);if(!state.isMobile){return table}return React__namespace.cloneElement(table,{tabIndex:0})}},titledTable:{...pureMarkdown.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.lint.react({...node.table,content:{...node,table:node.table.content}},output,{...state,unwrapTitledTableContents:true});}else {contents=rules.lint.react(node.table,output,state);}}else {const tableOutput=SimpleMarkdown__default.default.defaultRules.table.react(node.table,output,state);const caption=jsxRuntimeExports.jsx("caption",{className:"perseus-table-title",children:output(node.title,state)},"caption");contents=React__namespace.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:{...pureMarkdown.pureMarkdownRules.widget,react:(node,output,state)=>{return jsxRuntimeExports.jsx("em",{children:`[Widget: ${node.id}]`},state.key)}},blockMath:{...pureMarkdown.pureMarkdownRules.blockMath,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},math:{...pureMarkdown.pureMarkdownRules.math,react:(node,output,state)=>{const{TeX}=getDependencies();return jsxRuntimeExports.jsx(TeX,{children:node.content},state.key)}},unescapedDollar:{...pureMarkdown.pureMarkdownRules.unescapedDollar,react:(node,output,state)=>{return "$"}},link:{...pureMarkdown.pureMarkdownRules.link,react:function(node,output,state){const link=SimpleMarkdown__default.default.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__namespace.cloneElement(link,newProps)}},codeBlock:{...pureMarkdown.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__default.default.defaultRules.codeBlock.react(node,output,state)}},lint:{...pureMarkdown.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=SimpleMarkdown__default.default.parserFor(rules);const parse=(source,state)=>{const paragraphedSource=source+"\n\n";return builtParser(paragraphedSource,{...state,inline:false})};const inlineParser=(source,state)=>{return builtParser(source,{...state,inline:true})};const getContent=ast=>{if(Array.isArray(ast)){return ___default.default.flatten(ast.map(getContent))}if(ast.content&&typeof ast.content==="string"){if(ast.type.toLowerCase().indexOf("code")!==-1){return ["",ast.content,""]}return [ast.content.replace(/\s+/g," ")]}const children=___default.default.chain(ast).values().flatten().filter(object=>object!=null&&___default.default.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(source);const content=getContent(ast).join("");return content.length};var PerseusMarkdown = {characterCount:characterCount,traverseContent:pureMarkdown.traverseContent,parse:parse,parseInline:inlineParser,reactFor:SimpleMarkdown__default.default.reactFor,ruleOutput:SimpleMarkdown__default.default.ruleOutput(rules,"react"),basicOutput:SimpleMarkdown__default.default.reactFor(SimpleMarkdown__default.default.ruleOutput(rules,"react")),sanitizeUrl:SimpleMarkdown__default.default.sanitizeUrl};
|
|
1729
|
+
|
|
1730
|
+
class QuestionParagraph extends React__namespace.Component{render(){const className=this.props.className?"paragraph "+this.props.className:"paragraph";return jsxRuntimeExports.jsx("div",{className:this.props.inline?this.props.className??undefined:className,"data-perseus-component-index":this.props.translationIndex,"data-perseus-paragraph-index":this.props.paragraphIndex,children:this.props.children})}}
|
|
1730
1731
|
|
|
1731
|
-
|
|
1732
|
+
class WidgetContainerOld extends React__namespace.Component{componentDidMount(){if(this.props.widgetProps.apiOptions.isMobile){const containerWidth=ReactDOM__namespace.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.")}}render(){let className=classNames__default.default({"perseus-widget-container":true,"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})}const subType=getWidgetSubType(type,this.props.widgetProps)??"null";let alignment=this.props.widgetProps.alignment;if(alignment==="default"){alignment=perseusCore.CoreWidgetRegistry.getDefaultAlignment(type);}className+=perseusCore.CoreWidgetRegistry.getAlignmentClassName(type,alignment);const apiOptions=this.props.widgetProps.apiOptions;const isStatic=this.props.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,stack:error.stack??"No stack trace available",userAgent:userAgent}});},children:[jsxRuntimeExports.jsx(WidgetType,{...this.props.widgetProps,linterContext:linterContext,containerSizeClass:this.state.sizeClass,ref:this.widgetRef}),isStatic&&jsxRuntimeExports.jsx("div",{style:staticOverlayStyles})]})})})}constructor(...args){super(...args),this.widgetRef=React__namespace.createRef(),this.state={sizeClass:containerSizeClass.MEDIUM},this.getWidget=()=>{return this.widgetRef.current};}}WidgetContainerOld.defaultProps={linterContext:PerseusLinter.linterContextDefault};
|
|
1732
1733
|
|
|
1733
|
-
const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return ___default.default.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return ___default.default.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion(propsA,propsB){function makeItem(props){return perseusCore.splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:perseusCore.getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!___default.default.isEqual(makeItem(propsA),makeItem(propsB))}let Renderer$1 = class Renderer extends React__namespace.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!___default.default.isEqual(this.state,nextState);const propsChanged=!___default.default.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput&&!___default.default.isEqual(this.props.userInput,prevProps.userInput)){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_isAnswerable(){if(this.props.userInput){return this.emptyWidgets().length===0}return false}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",perseusCore.Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];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,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,graded:widgetInfo?.graded,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,showSolutions:this.props.showSolutions,onFocus:___default.default.partial(this._onWidgetFocus,widgetId),onBlur:___default.default.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.apiOptions?.interactionCallback?.(updatedUserInput);},trackInteraction:interactionTracker.track}}getSerializedState(){return perseusCore.mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}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)});}}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}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(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=perseusScore.scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=perseusScore.flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();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__namespace.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__default.default({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=perseusCore.applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},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;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,widgetProps:this.getWidgetProps(id),linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},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(!___default.default.isArray(focusPath)){throw new perseusCore.PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),perseusCore.Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!___default.default.isEqual(fullPath,blurringFocusPath)){return}___default.default.defer(()=>{if(___default.default.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.outputMarkdown=(ast,state)=>{if(___default.default.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__default.default({"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(___default.default.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$y.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=___default.default.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,{allowZoom:true,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$y.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=$__default.default(ReactDOM__namespace.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'",perseusCore.Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){const container=this._widgetContainers.get(makeContainerId(widgetId));if(container){return ReactDOM__namespace.default.findDOMNode(container)}return ReactDOM__namespace.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(___default.default.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!___default.default.isEqual(this._currentFocus,path)){return}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.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={};___default.default.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!___default.default.isEmpty(s)){state[id]=s;}},this);return state},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:[],...this._getInitialWidgetState(props)};}};Renderer$1.contextType=PerseusI18nContext;Renderer$1.defaultProps={content:"",widgets:{},images:{},showSolutions:"none",onRender:noopOnRender,findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter__namespace.linterContextDefault};const styles$y={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
|
|
1734
|
+
const rContainsNonWhitespace=/\S/;const rImageURL=/(web\+graphie|https):\/\/[^\s]*/;const noopOnRender=()=>{};const makeContainerId=id=>"container:"+id;const isIdPathPrefix=function(prefixArray,wholeArray){if(prefixArray===null||wholeArray===null){return prefixArray===wholeArray}return ___default.default.every(prefixArray,(elem,i)=>{if(wholeArray!=null){return ___default.default.isEqual(elem,wholeArray[i])}})};function isDifferentQuestion(propsA,propsB){function makeItem(props){return perseusCore.splitPerseusItem({question:{content:props.content,widgets:props.widgets,images:{}},hints:[],answerArea:perseusCore.getDefaultAnswerArea()})}return propsA.problemNum!==propsB.problemNum||!___default.default.isEqual(makeItem(propsA),makeItem(propsB))}let Renderer$1 = class Renderer extends React__namespace.Component{componentDidMount(){this._isMounted=true;this.handleRender({});this._currentFocus=null;this.props.initializeUserInput?.(this.props.widgets,this.props.problemNum??0);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}UNSAFE_componentWillReceiveProps(nextProps){if(isDifferentQuestion(this.props,nextProps)){this.props.initializeUserInput?.(nextProps.widgets,nextProps.problemNum??0);this.setState(this._getInitialWidgetState(nextProps));}}shouldComponentUpdate(nextProps,nextState){if(this.props.alwaysUpdate){return true}const stateChanged=!___default.default.isEqual(this.state,nextState);const propsChanged=!___default.default.isEqual(this.props,nextProps);return propsChanged||stateChanged}componentDidUpdate(prevProps,prevState){this.handleRender(prevProps);if(this.props.linterContext.highlightLint){this._translationLinter.runLinter(this.props.content,this.handletranslationLintErrors);}if(this.props.userInput&&!___default.default.isEqual(this.props.userInput,prevProps.userInput)){this.props.apiOptions?.answerableCallback?.(this._isAnswerable());}}componentWillUnmount(){this.widgetIds=[];if(this.translationIndex!=null){getDependencies().rendererTranslationComponents.removeComponentAtIndex(this.translationIndex);}this._isMounted=false;}_isAnswerable(){if(this.props.userInput){return this.emptyWidgets().length===0}return false}_getWidgetIndexById(id){const widgetIndex=this.widgetIds.indexOf(id);if(widgetIndex<0){Log.error("Unable to get widget index in _getWidgetIndexById",perseusCore.Errors.Internal,{loggedMetadata:{widgets:JSON.stringify(this.props.widgets),widgetId:JSON.stringify(id)}});return 0}return widgetIndex}getWidgetProps(widgetId){const apiOptions=this.getApiOptions();const widgetProps=this.props.widgets[widgetId].options;const widgetInfo=this.state.widgetInfo[widgetId];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,userInput:this.props.userInput?.[widgetId],widgetId:widgetId,widgetIndex:this._getWidgetIndexById(widgetId),alignment:widgetInfo&&widgetInfo.alignment,static:widgetInfo?.static,graded:widgetInfo?.graded,problemNum:this.props.problemNum,apiOptions:this.getApiOptions(),keypadElement:this.props.keypadElement,showSolutions:this.props.showSolutions,onFocus:___default.default.partial(this._onWidgetFocus,widgetId),onBlur:___default.default.partial(this._onWidgetBlur,widgetId),findWidgets:this.findWidgets,reviewMode:this.props.reviewMode,handleUserInput:newUserInput=>{const updatedUserInput={...this.props.userInput,[widgetId]:newUserInput};const emptyWidgetIds=perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,updatedUserInput,this.context.locale);const widgetsEmpty=emptyWidgetIds.length>0;this.props.handleUserInput?.(widgetId,newUserInput,widgetsEmpty);this.props.apiOptions?.interactionCallback?.(updatedUserInput);},trackInteraction:interactionTracker.track}}getSerializedState(){return perseusCore.mapObject(this.props.widgets,(widgetData,widgetId)=>{const widget=this.getWidgetInstance(widgetId);if(widget&&widget.getSerializedState){return excludeDenylistKeys(widget.getSerializedState())}return widgetData.options})}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)});}}emptyWidgets(){if(!this.props.userInput){throw new Error(`emptyWidgets called without providing userInput to Renderer`)}return perseusScore.emptyWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale)}getUserInputMap(){const userInput=this.props.userInput;if(!userInput){throw new Error(`getUserInputMap called without providing userInput to Renderer`)}return userInput}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(){if(!this.props.userInput){throw new Error(`score called without providing userInput to Renderer`)}const scores=perseusScore.scoreWidgetsFunctional(this.state.widgetInfo,this.widgetIds,this.props.userInput,this.context.locale);const combinedScore=perseusScore.flattenScores(scores);return combinedScore}render(){const apiOptions=this.getApiOptions();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__namespace.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__default.default({[ClassNames.RENDERER]:true,[ClassNames.RESPONSIVE_RENDERER]:true,[ClassNames.TWO_COLUMN_RENDERER]:this._isTwoColumn});return jsxRuntimeExports.jsx(DefinitionProvider,{children:jsxRuntimeExports.jsx("div",{className:className,children:markdownContents})})}constructor(props){super(props),this._widgetContainers=new Map,this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions}},this._getInitialWidgetState=props=>{const allWidgetInfo=perseusCore.applyDefaultsToWidgets(props.widgets);return {widgetInfo:allWidgetInfo}},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;return jsxRuntimeExports.jsx(WidgetContainerOld,{id:id,ref:node=>{const containerId=makeContainerId(id);if(node!=null){this._widgetContainers.set(containerId,node);}else {this._widgetContainers.delete(containerId);}},type:type,widgetProps:this.getWidgetProps(id),linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"widget")},makeContainerId(id))}return null},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(!Array.isArray(focusPath)){throw new perseusCore.PerseusError("widget props.onFocus focusPath must be an Array, "+"but was"+JSON.stringify(focusPath),perseusCore.Errors.Internal)}this._setCurrentFocus([id].concat(focusPath));},this._onWidgetBlur=(id,blurPath)=>{const blurringFocusPath=this._currentFocus;const fullPath=[id].concat(blurPath);if(!___default.default.isEqual(fullPath,blurringFocusPath)){return}___default.default.defer(()=>{if(___default.default.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.outputMarkdown=(ast,state)=>{if(Array.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__default.default({"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(Array.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$x.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=___default.default.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,{allowZoom:true,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$x.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=$__default.default(ReactDOM__namespace.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'",perseusCore.Errors.Internal,{loggedMetadata:{focusResult:JSON.stringify(focusResult)}});}else {path=[id];}this._setCurrentFocus(path);return true}},this.getDOMNodeForPath=path=>{const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const widget=this.getWidgetInstance(widgetId);if(widget?.getDOMNodeForPath){return widget.getDOMNodeForPath(interWidgetPath)}if(interWidgetPath.length===0){const container=this._widgetContainers.get(makeContainerId(widgetId));if(container){return ReactDOM__namespace.default.findDOMNode(container)}return ReactDOM__namespace.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(___default.default.isEqual(this._currentFocus,path)){return}if(this._currentFocus){this.blurPath(this._currentFocus);}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.rest(path);const focusWidget=this.getWidgetInstance(widgetId);focusWidget?.focusInputPath?.(interWidgetPath);},this.blurPath=path=>{if(!___default.default.isEqual(this._currentFocus,path)){return}const widgetId=___default.default.first(path);const interWidgetPath=___default.default.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={};___default.default.each(this.state.widgetInfo,function(info,id){const widget=this.getWidgetInstance(id);const s=widget.serialize();if(!___default.default.isEmpty(s)){state[id]=s;}},this);return state},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:[],...this._getInitialWidgetState(props)};}};Renderer$1.contextType=PerseusI18nContext;Renderer$1.defaultProps={content:"",widgets:{},images:{},showSolutions:"none",onRender:noopOnRender,findExternalWidgets:()=>[],alwaysUpdate:false,reviewMode:false,linterContext:PerseusLinter__namespace.linterContextDefault};const styles$x={mobileZoomableParentFix:{transform:"translate3d(0,0,0)"}};
|
|
1734
1735
|
|
|
1735
1736
|
const Renderer=React__namespace.forwardRef(function Renderer(props,ref){const rendererFF=perseusCore.isFeatureOn({apiOptions:props.apiOptions},"perseus-renderer-upgrade");return rendererFF?jsxRuntimeExports.jsx(Renderer$2,{ref:ref,...props}):jsxRuntimeExports.jsx(Renderer$1,{ref:ref,...props})});
|
|
1736
1737
|
|
|
@@ -1738,15 +1739,13 @@ const{captureScratchpadTouchStart: captureScratchpadTouchStart$1}=Util;const Inp
|
|
|
1738
1739
|
${props.examples.slice(1).join(", or\n")}`.replace(/\*/g,"").replace(/\$/g,"").replace(/\\ \\text{pi}/g," pi").replace(/\\ /g," 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$1,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(Tooltip.TooltipContent,{children:jsxRuntimeExports.jsx("div",{id:id,className:"input-with-examples-tooltip",children:jsxRuntimeExports.jsx(Renderer,{content:examplesContent,linterContext:PerseusLinter__namespace.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}
|
|
1739
1740
|
`:`- ${example}`}).join("\n");const showExamplesTooltip=shouldShowExamples&&inputFocused;return jsxRuntimeExports.jsx(Tooltip__default.default,{content:renderTooltipContent(),opened:showExamplesTooltip,placement:"bottom",children:renderInput()})});
|
|
1740
1741
|
|
|
1741
|
-
var styles$
|
|
1742
|
+
var styles$w = {"inputWithExamples":"perseus_QUlWSKE-","isFocused":"perseus_8i8MUC5K","rightAlign":"perseus_9cRSmuw9","centerAlign":"perseus_L-8sB566","sizeSmall":"perseus_LbMErCm0"};
|
|
1742
1743
|
|
|
1743
|
-
const styles$
|
|
1744
|
+
const styles$v={inputWithExamples:{borderRadius:"0.3rem",borderWidth:"var(--wb-border-width-thin)",direction:"ltr",display:"inline-block",fontFamily:'Symbola, "Times New Roman", serif',fontSize:"1.8rem",height:"3.2rem",lineHeight:"1.8rem",padding:"0.4rem 0.5rem",textAlign:"left",width:"8rem"},isFocused:{borderWidth:"var(--wb-border-width-medium)",padding:"0.4rem"},rightAlign:{textAlign:"right"},centerAlign:{textAlign:"center"},sizeSmall:{width:"4rem"}};
|
|
1744
1745
|
|
|
1745
|
-
const NumericExampleStrings={integer:(form,strings)=>strings.integerExample,proper:(form,strings)=>form.simplify==="optional"?strings.properExample:strings.simplifiedProperExample,improper:(form,strings)=>form.simplify==="optional"?strings.improperExample:strings.simplifiedImproperExample,mixed:(form,strings)=>strings.mixedExample,decimal:(form,strings)=>strings.decimalExample,percent:(form,strings)=>strings.percentExample,pi:(form,strings)=>strings.piExample};const generateExamples=(answerForms,strings)=>{if(answerForms.length===0){return []}const uniqueForms=getUniqueAnswerForms(answerForms);const examples=uniqueForms.map(form=>{return NumericExampleStrings[form.name](form,strings)});return [strings.yourAnswer].concat(examples)};const shouldShowExamples=answerForms=>{if(answerForms.length===0){return false}const answerFormNames=getUniqueAnswerForms(answerForms).map(form=>form.name);const allFormsAccepted=answerFormNames.length>=Object.keys(NumericExampleStrings).length;return !allFormsAccepted};const getUniqueAnswerForms=function(list){const foundForms=new Set;return list.filter(form=>{if(foundForms.has(form.name)){return false}foundForms.add(form.name);return true})};const unionAnswerForms=function(answerFormsList){const allForms=answerFormsList.flat();const uniqueForms=getUniqueAnswerForms(allForms);const formExampleKeys=Object.keys(NumericExampleStrings);return uniqueForms.sort((a,b)=>{return formExampleKeys.indexOf(a.name)-formExampleKeys.indexOf(b.name)})};function normalizeCorrectAnswerForms(answers){if(answers==null){return []}return unionAnswerForms(answers.filter(answer=>answer.status==="correct").map(answer=>{return (answer.answerForms||[]).map(form=>{return {simplify:answer.simplify,name:form}})}))}
|
|
1746
|
+
const NumericExampleStrings={integer:(form,strings)=>strings.integerExample,proper:(form,strings)=>form.simplify==="optional"?strings.properExample:strings.simplifiedProperExample,improper:(form,strings)=>form.simplify==="optional"?strings.improperExample:strings.simplifiedImproperExample,mixed:(form,strings)=>strings.mixedExample,decimal:(form,strings)=>strings.decimalExample,percent:(form,strings)=>strings.percentExample,pi:(form,strings)=>strings.piExample};const generateExamples=(answerForms,strings)=>{if(answerForms.length===0){return []}const uniqueForms=getUniqueAnswerForms(answerForms);const examples=uniqueForms.map(form=>{return NumericExampleStrings[form.name](form,strings)});return [strings.yourAnswer].concat(examples)};const shouldShowExamples=answerForms=>{if(answerForms.length===0){return false}const answerFormNames=getUniqueAnswerForms(answerForms).map(form=>form.name);const allFormsAccepted=answerFormNames.length>=Object.keys(NumericExampleStrings).length;return !allFormsAccepted};const getUniqueAnswerForms=function(list){const foundForms=new Set;return list.filter(form=>{if(foundForms.has(form.name)){return false}foundForms.add(form.name);return true})};const unionAnswerForms=function(answerFormsList){const allForms=answerFormsList.flat();const uniqueForms=getUniqueAnswerForms(allForms);const formExampleKeys=Object.keys(NumericExampleStrings);return uniqueForms.sort((a,b)=>{return formExampleKeys.indexOf(a.name)-formExampleKeys.indexOf(b.name)})};function normalizeCorrectAnswerForms(answers){if(answers==null){return []}return unionAnswerForms(answers.filter(answer=>answer.status==="correct").map(answer=>{return (answer.answerForms||[]).map(form=>{return {simplify:answer.simplify,name:form}})}))}function getStartUserInput$h(){return {currentValue:""}}function getUserInputFromSerializedState$h(serializedState){return {currentValue:serializedState.currentValue}}function findPrecision(value){for(let i=0;i<10;i++){if(value===+value.toFixed(i)){return i}}return 10}function findCommonFractions(value){const whole=Math.floor(value);if(value===whole){return}const decimal=value-whole;const precision=findPrecision(decimal);for(let num=1;num<100;num++){for(let denom=2;denom<100;denom++){if(+(num/denom).toFixed(precision)===decimal){return {num:num+whole*denom,denom}}}}}function getCorrectUserInput$8(options){for(const answer of options.answers){if(answer.status==="correct"&&answer.value!=null){if(answer.answerForms?.includes("decimal")){return {currentValue:answer.value.toString()}}if(answer.answerForms?.includes("improper")){const frac=findCommonFractions(answer.value);if(frac){return {currentValue:`${frac.num}/${frac.denom}`}}}if(answer.answerForms?.includes("proper")){const frac=findCommonFractions(answer.value);if(frac){const{num,denom}=frac;if(num>denom){const whole=Math.floor(num/denom);const remainder=num-whole*denom;return {currentValue:`${whole} ${remainder}/${denom}`}}else {return {currentValue:`${num}/${denom}`}}}}return {currentValue:answer.value.toString()}}}return {currentValue:""}}function getOneCorrectAnswerFromRubric(rubric){const correctAnswers=rubric.answers.filter(answer=>answer.status==="correct");const answerStrings=correctAnswers.map(answer=>{const format=answer.answerForms&&answer.answerForms[0]?answer.answerForms[0]:"decimal";let answerString=kmath.KhanMath.toNumericString(answer.value,format);if(answer.maxError){answerString+=" ± "+kmath.KhanMath.toNumericString(answer.maxError,format);}return answerString});if(answerStrings.length===0){return}return answerStrings[0]}
|
|
1746
1747
|
|
|
1747
|
-
const
|
|
1748
|
-
|
|
1749
|
-
class NumericInput extends React__namespace.Component{getPromptJSON(){return getPromptJSON$p(this.props)}getSerializedState(){const{userInput,answers:_,...rest}=this.props;return {...rest,currentValue:userInput.currentValue}}render(){return jsxRuntimeExports.jsx(NumericInputComponent,{...this.props,answerForms:normalizeCorrectAnswerForms(this.props.answers),ref:this.inputRef})}constructor(...args){super(...args),this.inputRef=React__namespace.createRef(),this.focus=()=>{this.inputRef.current?.focus();return true},this.blur=()=>{this.inputRef.current?.blur();},this.focusInputPath=()=>{this.inputRef.current?.focus();},this.blurInputPath=()=>{this.inputRef.current?.blur();},this.getInputPaths=()=>{return [[]]};}}NumericInput.defaultProps={size:"normal",apiOptions:ApiOptions.defaults,coefficient:false,answerForms:[],labelText:"",linterContext:PerseusLinter.linterContextDefault,userInput:{currentValue:""}};function getStartUserInput$h(){return {currentValue:""}}function getUserInputFromSerializedState$h(serializedState){return {currentValue:serializedState.currentValue}}function findPrecision(value){for(let i=0;i<10;i++){if(value===+value.toFixed(i)){return i}}return 10}function findCommonFractions(value){const whole=Math.floor(value);if(value===whole){return}const decimal=value-whole;const precision=findPrecision(decimal);for(let num=1;num<100;num++){for(let denom=2;denom<100;denom++){if(+(num/denom).toFixed(precision)===decimal){return {num:num+whole*denom,denom}}}}}function getCorrectUserInput$8(options){for(const answer of options.answers){if(answer.status==="correct"&&answer.value!=null){if(answer.answerForms?.includes("decimal")){return {currentValue:answer.value.toString()}}if(answer.answerForms?.includes("improper")){const frac=findCommonFractions(answer.value);if(frac){return {currentValue:`${frac.num}/${frac.denom}`}}}if(answer.answerForms?.includes("proper")){const frac=findCommonFractions(answer.value);if(frac){const{num,denom}=frac;if(num>denom){const whole=Math.floor(num/denom);const remainder=num-whole*denom;return {currentValue:`${whole} ${remainder}/${denom}`}}else {return {currentValue:`${num}/${denom}`}}}}return {currentValue:answer.value.toString()}}}return {currentValue:""}}var NumericInput$1 = {name:"numeric-input",displayName:"Numeric input",widget:NumericInput,isLintable:true,getCorrectUserInput: getCorrectUserInput$8,getOneCorrectAnswerFromRubric(rubric){const correctAnswers=rubric.answers.filter(answer=>answer.status==="correct");const answerStrings=correctAnswers.map(answer=>{const format=answer.answerForms&&answer.answerForms[0]?answer.answerForms[0]:"decimal";let answerString=kmath.KhanMath.toNumericString(answer.value,format);if(answer.maxError){answerString+=" ± "+kmath.KhanMath.toNumericString(answer.maxError,format);}return answerString});if(answerStrings.length===0){return}return answerStrings[0]},getStartUserInput: getStartUserInput$h,getUserInputFromSerializedState: getUserInputFromSerializedState$h};
|
|
1748
|
+
const NumericInput=React.forwardRef(function NumericInput(props,ref){const{analytics}=useDependencies();const context=React.useContext(PerseusI18nContext);const inputRef=React.useRef(null);const[isFocused,setIsFocused]=React.useState(false);wonderBlocksCore.useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"numeric-input",widgetId:props.widgetId}});});React.useImperativeHandle(ref,()=>({focus(){if(inputRef.current){inputRef.current.focus();setIsFocused(true);}return true},focusInputPath(){if(inputRef.current){inputRef.current.focus();setIsFocused(true);}},blurInputPath(){if(inputRef.current){inputRef.current.blur();setIsFocused(false);}},getInputPaths:()=>[[]],getPromptJSON:()=>getPromptJSON$p(props),getSerializedState(){const{userInput,labelText,answers,...rest}=props;return {...rest,answerForms:[],labelText:labelText??"",currentValue:userInput.currentValue}}}));const answerForms=normalizeCorrectAnswerForms(props.answers);const handleChange=newValue=>{props.handleUserInput({currentValue:newValue});props.trackInteraction();};const handleFocus=()=>{props.onFocus([]);setIsFocused(true);};const handleBlur=()=>{props.onBlur([]);setIsFocused(false);};const alignmentStyles=props.textAlign==="center"?styles$v.centerAlign:props.textAlign==="right"?styles$v.rightAlign:{};const legacyStylesToUse={...styles$v.inputWithExamples,...isFocused?styles$v.isFocused:{},...alignmentStyles,...props.size==="small"?styles$v.sizeSmall:{}};const classesToUse=[styles$w.inputWithExamples];if(isFocused){classesToUse.push(styles$w.isFocused);}if(props.textAlign!=="left"){const alignmentClass=props.textAlign==="center"?styles$w.centerAlign:styles$w.rightAlign;classesToUse.push(alignmentClass);}if(props.size==="small"){classesToUse.push(styles$w.sizeSmall);}if(props.apiOptions.customKeypad){const alignmentClass=props.textAlign==="center"?"perseus-input-center-align":props.textAlign==="right"?"perseus-input-right-align":undefined;return jsxRuntimeExports.jsx("div",{className:alignmentClass,children:jsxRuntimeExports.jsx(SimpleKeypadInput,{ref:inputRef,value:props.userInput.currentValue,keypadElement:props.keypadElement,onChange:handleChange,onFocus:handleFocus,onBlur:handleBlur})})}return jsxRuntimeExports.jsx(InputWithExamples,{ref:inputRef,value:props.userInput.currentValue,onChange:handleChange,labelText:props.labelText||context.strings.yourAnswerLabel,examples:generateExamples(answerForms,context.strings),shouldShowExamples:shouldShowExamples(answerForms),onFocus:handleFocus,onBlur:handleBlur,id:props.widgetId,disabled:props.apiOptions.readOnly,style:legacyStylesToUse,className:classesToUse.join(" ")})});var NumericInput$1 = {name:"numeric-input",displayName:"Numeric input",widget:NumericInput,isLintable:true,getCorrectUserInput: getCorrectUserInput$8,getOneCorrectAnswerFromRubric,getStartUserInput: getStartUserInput$h,getUserInputFromSerializedState: getUserInputFromSerializedState$h};
|
|
1750
1749
|
|
|
1751
1750
|
function getUserInputFromSerializedState$g(serializedState){return {currentValue:serializedState.currentValue}}var InputNumber = {name:"input-number",displayName:"Input number (deprecated - use numeric input instead)",hidden:true,widget:NumericInput$1.widget,isLintable:true,getOneCorrectAnswerFromRubric:NumericInput$1.getOneCorrectAnswerFromRubric,getStartUserInput:NumericInput$1.getStartUserInput,getCorrectUserInput:NumericInput$1.getCorrectUserInput,getUserInputFromSerializedState: getUserInputFromSerializedState$g};
|
|
1752
1751
|
|
|
@@ -1754,29 +1753,29 @@ const MathRenderingContext=React__namespace.createContext({shouldAddAriaLabels:f
|
|
|
1754
1753
|
|
|
1755
1754
|
const getPromptJSON$o=(widgetData,userInput)=>{const choices=widgetData.choices||[];const options=choices.map(choice=>{const option={value:choice.content,id:choice.id};if(choice.rationale){option.rationale=choice.rationale;}return option});const hasNoneOfTheAbove=choices.some(choice=>choice.isNoneOfTheAbove);return {type:"radio",hasNoneOfTheAbove,options,userInput:{selectedOptions:userInput?.selectedChoiceIds??[]}}};
|
|
1756
1755
|
|
|
1757
|
-
var styles$
|
|
1756
|
+
var styles$u = {"scrollButtonsContainer":"perseus_kjDHiWdD"};
|
|
1758
1757
|
|
|
1759
|
-
const SCROLL_DISTANCE=100;const scrollInstances=new Map;function ScrollableArea({overflowX,overflowY,children,className,scrollDescription,style,role="group",id:providedId,...additionalProps}){const{strings}=usePerseusI18n();const containerRef=React.useRef(null);const[isScrollable,setIsScrollable]=React.useState(false);const[isScrolling,setIsScrolling]=React.useState(false);const generatedId=React__namespace.useId();const id=providedId||generatedId;const scrollableThreshold=React__namespace.useMemo(()=>{return window.innerWidth<=767?8:5},[]);const scroll=React__namespace.useCallback(direction=>{if(!containerRef.current||isScrolling){return}setIsScrolling(true);const contentIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const scrollNegative=contentIsRtl&&direction==="end"||!contentIsRtl&&direction==="start";const scrollAmount=scrollNegative?-100:SCROLL_DISTANCE;containerRef.current.scrollBy({left:scrollAmount,behavior:"smooth"});setTimeout(()=>{setIsScrolling(false);},150);},[isScrolling]);const updateScrollState=React__namespace.useCallback(()=>{if(!containerRef.current){return}const{scrollLeft,scrollWidth,clientWidth}=containerRef.current;const newIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const newIsScrollable=scrollWidth>clientWidth+scrollableThreshold;setIsScrollable(newIsScrollable);let newCanScrollStart;let newCanScrollEnd;if(newIsRtl){newCanScrollStart=scrollLeft<-scrollableThreshold;newCanScrollEnd=Math.abs(scrollLeft)<scrollWidth-clientWidth-scrollableThreshold;}else {newCanScrollStart=scrollLeft>scrollableThreshold;newCanScrollEnd=scrollLeft+clientWidth<scrollWidth-scrollableThreshold;}const scrollState={isScrollable:newIsScrollable,canScrollStart:newCanScrollStart,canScrollEnd:newCanScrollEnd,isRTL:newIsRtl,scroll,scrollDescription:scrollDescription||strings.scrollAnswers};scrollInstances.set(id,scrollState);},[id,scrollableThreshold,scrollDescription,strings.scrollAnswers,scroll]);React.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);scrollInstances.delete(id);}},[children,updateScrollState,id]);const mergeStyle={overflowX:isScrollable&&overflowX==="auto"?"scroll":overflowX,overflowY:isScrollable&&overflowY==="auto"?"scroll":overflowY,scrollbarWidth:"thin",...style};return jsxRuntimeExports.jsx("div",{...additionalProps,id:id,role:role,className:className,style:mergeStyle,ref:containerRef,children:children})}function ScrollControls({target,scrollDescription:overrideDescription}){const{strings}=usePerseusI18n();const[scrollState,setScrollState]=React.useState(null);React.useEffect(()=>{if(!target){return}const checkForScrollState=()=>{const state=scrollInstances.get(target);if(state){setScrollState(state);}};checkForScrollState();const interval=setInterval(checkForScrollState,100);return ()=>{clearInterval(interval);}},[target]);if(!scrollState||!scrollState.isScrollable){return null}const description=overrideDescription||scrollState.scrollDescription;return jsxRuntimeExports.jsxs("div",{className:styles$
|
|
1758
|
+
const SCROLL_DISTANCE=100;const scrollInstances=new Map;function ScrollableArea({overflowX,overflowY,children,className,scrollDescription,style,role="group",id:providedId,...additionalProps}){const{strings}=usePerseusI18n();const containerRef=React.useRef(null);const[isScrollable,setIsScrollable]=React.useState(false);const[isScrolling,setIsScrolling]=React.useState(false);const generatedId=React__namespace.useId();const id=providedId||generatedId;const scrollableThreshold=React__namespace.useMemo(()=>{return window.innerWidth<=767?8:5},[]);const scroll=React__namespace.useCallback(direction=>{if(!containerRef.current||isScrolling){return}setIsScrolling(true);const contentIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const scrollNegative=contentIsRtl&&direction==="end"||!contentIsRtl&&direction==="start";const scrollAmount=scrollNegative?-100:SCROLL_DISTANCE;containerRef.current.scrollBy({left:scrollAmount,behavior:"smooth"});setTimeout(()=>{setIsScrolling(false);},150);},[isScrolling]);const updateScrollState=React__namespace.useCallback(()=>{if(!containerRef.current){return}const{scrollLeft,scrollWidth,clientWidth}=containerRef.current;const newIsRtl=getComputedStyle(containerRef.current).direction==="rtl";const newIsScrollable=scrollWidth>clientWidth+scrollableThreshold;setIsScrollable(newIsScrollable);let newCanScrollStart;let newCanScrollEnd;if(newIsRtl){newCanScrollStart=scrollLeft<-scrollableThreshold;newCanScrollEnd=Math.abs(scrollLeft)<scrollWidth-clientWidth-scrollableThreshold;}else {newCanScrollStart=scrollLeft>scrollableThreshold;newCanScrollEnd=scrollLeft+clientWidth<scrollWidth-scrollableThreshold;}const scrollState={isScrollable:newIsScrollable,canScrollStart:newCanScrollStart,canScrollEnd:newCanScrollEnd,isRTL:newIsRtl,scroll,scrollDescription:scrollDescription||strings.scrollAnswers};scrollInstances.set(id,scrollState);},[id,scrollableThreshold,scrollDescription,strings.scrollAnswers,scroll]);React.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);scrollInstances.delete(id);}},[children,updateScrollState,id]);const mergeStyle={overflowX:isScrollable&&overflowX==="auto"?"scroll":overflowX,overflowY:isScrollable&&overflowY==="auto"?"scroll":overflowY,scrollbarWidth:"thin",...style};return jsxRuntimeExports.jsx("div",{...additionalProps,id:id,role:role,className:className,style:mergeStyle,ref:containerRef,children:children})}function ScrollControls({target,scrollDescription:overrideDescription}){const{strings}=usePerseusI18n();const[scrollState,setScrollState]=React.useState(null);React.useEffect(()=>{if(!target){return}const checkForScrollState=()=>{const state=scrollInstances.get(target);if(state){setScrollState(state);}};checkForScrollState();const interval=setInterval(checkForScrollState,100);return ()=>{clearInterval(interval);}},[target]);if(!scrollState||!scrollState.isScrollable){return null}const description=overrideDescription||scrollState.scrollDescription;return jsxRuntimeExports.jsxs("div",{className:styles$u.scrollButtonsContainer,"aria-live":"polite",role:"group","aria-label":description,children:[jsxRuntimeExports.jsx(IconButton__default.default,{icon:scrollState.isRTL?caretRightIcon__default.default:caretLeftIcon__default.default,actionType:"neutral",kind:"secondary",size:"small",onClick:()=>scrollState.scroll("start"),"aria-label":strings.scrollStart,disabled:!scrollState.canScrollStart}),jsxRuntimeExports.jsx(IconButton__default.default,{icon:scrollState.isRTL?caretLeftIcon__default.default:caretRightIcon__default.default,actionType:"neutral",kind:"secondary",size:"small",onClick:()=>scrollState.scroll("end"),"aria-label":strings.scrollEnd,disabled:!scrollState.canScrollEnd}),jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"small",children:description})]})}const ScrollableView=ScrollableArea;ScrollableView.Controls=ScrollControls;
|
|
1760
1759
|
|
|
1761
|
-
var styles$
|
|
1760
|
+
var styles$t = {"base":"perseus_C4cWo-dY","is-correct":"perseus_vWc7XkhJ","isCorrect":"perseus_vWc7XkhJ","is-wrong":"perseus_yVmsF9sA","isWrong":"perseus_yVmsF9sA","icon":"perseus_brEUCVvd","circle-shape":"perseus_irgRpkgB","circleShape":"perseus_irgRpkgB","square-shape":"perseus_JsUZt48D","squareShape":"perseus_JsUZt48D"};
|
|
1762
1761
|
|
|
1763
|
-
const Indicator=props=>{const{checked,content,showCorrectness}=props;const indicatorId=React.useId();const ariaLabelledby=content.labelledBy?`${indicatorId} ${content.labelledBy}`:undefined;const ariaDisabled=showCorrectness?"true":"false";const iconImage=checked&&showCorrectness==="correct"?checkIcon__default.default:checked&&showCorrectness==="wrong"?minusIcon__default.default:undefined;const icon=iconImage?jsxRuntimeExports.jsx(wonderBlocksIcon.PhosphorIcon,{"aria-hidden":true,className:styles$
|
|
1762
|
+
const Indicator=props=>{const{checked,content,showCorrectness}=props;const indicatorId=React.useId();const ariaLabelledby=content.labelledBy?`${indicatorId} ${content.labelledBy}`:undefined;const ariaDisabled=showCorrectness?"true":"false";const iconImage=checked&&showCorrectness==="correct"?checkIcon__default.default:checked&&showCorrectness==="wrong"?minusIcon__default.default:undefined;const icon=iconImage?jsxRuntimeExports.jsx(wonderBlocksIcon.PhosphorIcon,{"aria-hidden":true,className:styles$t.icon,icon:iconImage}):undefined;const classes=[styles$t.base,styles$t[props.shape+"-shape"]];if(showCorrectness){classes.push(styles$t["is-"+showCorrectness]);}const handleClick=showCorrectness?undefined:event=>{event.stopPropagation();props.updateChecked(!checked);};return jsxRuntimeExports.jsxs("button",{"aria-describedby":content.describedBy,"aria-disabled":ariaDisabled,"aria-pressed":checked,"aria-label":content.screenReader,"aria-labelledby":ariaLabelledby,className:classes.join(" "),id:indicatorId,type:"button",ref:props.buttonRef,onClick:handleClick,children:[icon,jsxRuntimeExports.jsx("span",{children:content.visible})]})};
|
|
1764
1763
|
|
|
1765
|
-
var styles$
|
|
1764
|
+
var styles$s = {"choice":"perseus_hm3uu-sq","is-correct":"perseus_qpU2z5U7","isCorrect":"perseus_qpU2z5U7","is-wrong":"perseus_dUXUrBDI","isWrong":"perseus_dUXUrBDI"};
|
|
1766
1765
|
|
|
1767
|
-
const Choice=props=>{const showCorrectness=props.showCorrectness;const buttonRef=React.useRef(null);const indicatorShape=props.isMultiSelect?"square":"circle";const clickHandler=showCorrectness?undefined:()=>{buttonRef.current?.click();};const classes=[styles$
|
|
1766
|
+
const Choice=props=>{const showCorrectness=props.showCorrectness;const buttonRef=React.useRef(null);const indicatorShape=props.isMultiSelect?"square":"circle";const clickHandler=showCorrectness?undefined:()=>{buttonRef.current?.click();};const classes=[styles$s.choice].concat(showCorrectness?[styles$s["is-"+showCorrectness]]:[]).join(" ");return jsxRuntimeExports.jsxs("li",{className:classes,onClick:clickHandler,role:"listitem",children:[jsxRuntimeExports.jsx(Indicator,{buttonRef:buttonRef,checked:props.checked,content:props.indicatorContent,shape:indicatorShape,showCorrectness:showCorrectness,updateChecked:props.updateChecked}),props.children]})};
|
|
1768
1767
|
|
|
1769
|
-
var styles$
|
|
1768
|
+
var styles$r = {"container":"perseus_yewUvpCl","choiceList":"perseus_ejJezW-c","content":"perseus_zAWs4E3G","instructions":"perseus_WyGpYl3q","rationale":"perseus_6vMrWVz0","isCorrect":"perseus_Zv66BVdg","reviewAnswers":"perseus_hJzSXKwq"};
|
|
1770
1769
|
|
|
1771
1770
|
function getChoiceLetter(pos,strings){const lettersString=strings.letters;const letters=lettersString.split(" ");if(pos<letters.length){return letters[pos]}return " "}function hasChoiceData(state){return state!=null&&typeof state==="object"&&"choiceStates"in state&&"choices"in state&&Array.isArray(state.choiceStates)&&Array.isArray(state.choices)}function getUserInputFromSerializedState$f(serializedState){const selectedChoiceIds=[];if(hasChoiceData(serializedState)){const{choiceStates,choices}=serializedState;for(let i=0;i<choiceStates.length;i++){const choiceState=choiceStates[i];const choice=choices[i];if(choiceState?.selected&&choice?.id){selectedChoiceIds.push(choice.id);}}}return {selectedChoiceIds}}function moveNoneOfTheAboveToEnd(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}function enforceOrdering(choices,strings){const ReversedChoices=[[strings.false,strings.true],[strings.no,strings.yes]];const content=choices.map(c=>c.content);if(ReversedChoices.some(reversed=>___default.default.isEqual(content,reversed))){return [choices[1],choices[0]]}return choices}function choiceTransform(choices,randomize,strings,seed){const choicesWithMetadata=choices.map((choice,i)=>{return {...choice,originalIndex:i,correct:Boolean(choice.correct)}});return moveNoneOfTheAboveToEnd(enforceOrdering(randomize?perseusCore.shuffle(choicesWithMetadata,seed):choicesWithMetadata,strings))}
|
|
1772
1771
|
|
|
1773
1772
|
const getInstructionsText=({multipleSelect,countChoices,numCorrect,strings})=>{if(multipleSelect){if(perseusCore.usesNumCorrect(multipleSelect,!!countChoices,numCorrect)){return strings.chooseNumAnswers({numCorrect:String(numCorrect)})}return strings.chooseAllAnswers}return strings.chooseOneAnswer};
|
|
1774
1773
|
|
|
1775
|
-
const RadioComponent=({choices,countChoices,multipleSelect=false,numCorrect,onChoiceChange,reviewMode})=>{const{strings}=usePerseusI18n();const legendId=React.useId();const containerRef=React.useRef(null);const[backgroundColor,setBackgroundColor]=React.useState("transparent");React.useEffect(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},[]);wonderBlocksTiming.useTimeout(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},100);const instructions=getInstructionsText({multipleSelect,countChoices,numCorrect,strings});const choiceListClasses=reviewMode?`${styles$
|
|
1774
|
+
const RadioComponent=({choices,countChoices,multipleSelect=false,numCorrect,onChoiceChange,reviewMode})=>{const{strings}=usePerseusI18n();const legendId=React.useId();const containerRef=React.useRef(null);const[backgroundColor,setBackgroundColor]=React.useState("transparent");React.useEffect(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},[]);wonderBlocksTiming.useTimeout(()=>{const container=containerRef.current;if(container){setBackgroundColor(getBackgroundColor(container));}},100);const instructions=getInstructionsText({multipleSelect,countChoices,numCorrect,strings});const choiceListClasses=reviewMode?`${styles$r.choiceList} ${styles$r.reviewAnswers}`:styles$r.choiceList;const cssVariableDeclaration=backgroundColor!=="transparent"?{"--perseus-widget-background-color":backgroundColor}:undefined;const scrollId=React.useId()+"-scroll";return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsxs("fieldset",{className:styles$r.container,ref:containerRef,style:cssVariableDeclaration,children:[jsxRuntimeExports.jsx("legend",{id:legendId,"aria-hidden":"true",className:styles$r.instructions,children:instructions}),jsxRuntimeExports.jsx(ScrollableView,{id:scrollId,overflowX:"auto",children:jsxRuntimeExports.jsx("ul",{"data-widget":"radio","aria-labelledby":legendId,className:choiceListClasses,role:"list",children:jsxRuntimeExports.jsx(ChoiceListItems,{choices:choices,i18nStrings:strings,onChoiceChange:onChoiceChange,reviewMode:reviewMode,multipleSelect:multipleSelect})})})]}),jsxRuntimeExports.jsx(ScrollableView.Controls,{target:scrollId})]})};const ChoiceListItems=props=>{const{choices,i18nStrings,multipleSelect,onChoiceChange,reviewMode}=props;const listId=React.useId();const items=choices.map((choice,i)=>{const updateChecked=isChecked=>{onChoiceChange(choice.id,isChecked);};const contentId=`${listId}-choice-${i+1}`;const choiceLetter=getChoiceLetter(i,i18nStrings);const srContent=reviewMode&&choice.correct?i18nStrings.choiceCorrect:i18nStrings.choice;const indicatorContent={visible:choiceLetter,screenReader:srContent({letter:choiceLetter}),labelledBy:contentId};const showCorrectness=reviewMode?choice.correct?"correct":"wrong":undefined;const content=choice.isNoneOfTheAbove?i18nStrings.noneOfTheAbove:choice.content;let rationale;if(reviewMode&&choice.hasRationale){const rationaleId=`${contentId}-rationale`;indicatorContent.describedBy=rationaleId;const rationaleClasses=showCorrectness==="correct"?`${styles$r.rationale} ${styles$r.isCorrect}`:styles$r.rationale;rationale=jsxRuntimeExports.jsx("div",{id:rationaleId,className:rationaleClasses,children:choice.rationale});}return jsxRuntimeExports.jsx(Choice,{checked:choice.checked,indicatorContent:indicatorContent,isMultiSelect:multipleSelect,showCorrectness:showCorrectness,updateChecked:updateChecked,children:jsxRuntimeExports.jsxs("div",{className:styles$r.content,children:[jsxRuntimeExports.jsx("div",{id:contentId,children:content}),rationale]})},choice.id)});return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment,{children:items})};
|
|
1776
1775
|
|
|
1777
1776
|
const getChoiceStates=({choices,showSolutions,choiceStates,reviewMode})=>{if(showSolutions==="all"||reviewMode){return choices.map(choice=>({selected:!!choice.correct}))}if(choiceStates){return choiceStates}return choices.map(()=>({selected:false}))};
|
|
1778
1777
|
|
|
1779
|
-
const RadioWidget=React.forwardRef(function RadioWidget(props,ref){const{multipleSelect=false,countChoices=false,showSolutions="none",apiOptions,handleUserInput,trackInteraction,findWidgets,reviewMode,widgetId}=props;const{strings}=usePerseusI18n();const{analytics}=useDependencies();const randomSeed=(props.problemNum??0)+(props.widgetIndex??0);const choices=React.useMemo(()=>{return [...choiceTransform(props.choices,props.randomize,strings,randomSeed)]},[props.choices,props.randomize,strings,randomSeed]);wonderBlocksCore.useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:multipleSelect?"multiple-select":"single-select",widgetType:"radio",widgetId:widgetId}});});React.useImperativeHandle(ref,()=>({getPromptJSON:()=>{return getPromptJSON$o({...props,choices},props.userInput)},getSerializedState(){const{userInput
|
|
1778
|
+
const RadioWidget=React.forwardRef(function RadioWidget(props,ref){const{multipleSelect=false,countChoices=false,showSolutions="none",apiOptions,handleUserInput,trackInteraction,findWidgets,reviewMode,widgetId}=props;const{strings}=usePerseusI18n();const{analytics}=useDependencies();const randomSeed=(props.problemNum??0)+(props.widgetIndex??0);const choices=React.useMemo(()=>{return [...choiceTransform(props.choices,props.randomize,strings,randomSeed)]},[props.choices,props.randomize,strings,randomSeed]);wonderBlocksCore.useOnMountEffect(()=>{analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:multipleSelect?"multiple-select":"single-select",widgetType:"radio",widgetId:widgetId}});});React.useImperativeHandle(ref,()=>({getPromptJSON:()=>{return getPromptJSON$o({...props,choices},props.userInput)},getSerializedState(){const{userInput,randomize,static:__,...rest}=props;return {...rest,numCorrect:props.numCorrect??0,choices,hasNoneOfTheAbove:props.hasNoneOfTheAbove??false,choiceStates:choices.map(choice=>{const selected=props.userInput?.selectedChoiceIds.includes(choice?.id)??false;return {selected,highlighted:false,readOnly:false,rationaleShown:false,correctnessShown:false,previouslyAnswered:false}})}}}),[choices,props]);const renderContent=(content="")=>{const linterContext={contentType:"radio",highlightLint:false,stack:[]};return jsxRuntimeExports.jsx(MathRenderingContext.Provider,{value:{shouldAddAriaLabels:true},children:jsxRuntimeExports.jsx(Renderer,{apiOptions:apiOptions,content:content,findExternalWidgets:findWidgets,alwaysUpdate:true,linterContext:linterContext,strings:strings},"choiceContentRenderer")})};const handleChoiceChange=(choiceId,newCheckedState)=>{const checkedChoiceIds=[];const choiceStates=choices.map(choice=>{return {selected:props.userInput?.selectedChoiceIds.includes(choice.id)??false,id:choice.id}});const currentSelectedIds=choiceStates.filter(choice=>choice.selected).map(choice=>choice.id);if(newCheckedState&&!multipleSelect){checkedChoiceIds.push(choiceId);}else if(newCheckedState&&multipleSelect){checkedChoiceIds.push(...currentSelectedIds,choiceId);}else {checkedChoiceIds.push(...currentSelectedIds.filter(id=>id!==choiceId));}handleUserInput({selectedChoiceIds:checkedChoiceIds});trackInteraction();announceChoiceChange(checkedChoiceIds.length);};const announceChoiceChange=newCheckedCount=>{let screenReaderMessage="";if(!props.multipleSelect){screenReaderMessage=newCheckedCount===0?strings.notSelected:"";}else {screenReaderMessage=strings.choicesSelected({num:newCheckedCount});}wonderBlocksAnnouncer.announceMessage({message:screenReaderMessage});if(props.multipleSelect){setTimeout(()=>{wonderBlocksAnnouncer.announceMessage({message:""});},300);}};const buildChoiceProps=choiceStates=>{return choices.map((choice,i)=>{const content=choice.isNoneOfTheAbove&&!choice.content?strings.noneOfTheAbove:choice.content;const{selected=false}=choiceStates[i]??{};return {id:choice.id,content:renderContent(content),checked:selected,correct:!!choice.correct,hasRationale:!!choice.rationale,rationale:renderContent(choice.rationale),isNoneOfTheAbove:!!choice.isNoneOfTheAbove}})};const prepareChoicesProps=()=>{const choiceStates=choices.map(choice=>{return {selected:props.userInput?.selectedChoiceIds.includes(choice.id)??false}});const processedChoiceStates=getChoiceStates({choices,showSolutions,choiceStates,reviewMode});return buildChoiceProps(processedChoiceStates)};const choicesProps=prepareChoicesProps();const numCorrect=props.numCorrect;const isReviewMode=reviewMode||showSolutions==="all";const onChoiceChange=apiOptions.readOnly||isReviewMode?()=>{}:handleChoiceChange;return jsxRuntimeExports.jsx(RadioComponent,{reviewMode:isReviewMode,multipleSelect:multipleSelect,countChoices:countChoices,numCorrect:numCorrect,choices:choicesProps,onChoiceChange:onChoiceChange})});let Radio$1 = class Radio extends React__namespace.Component{getSerializedState(){if(!this.radioRef.current){throw new Error("Radio widget is not mounted; getSerializedState is unavailable.")}return this.radioRef.current.getSerializedState()}getPromptJSON(){if(!this.radioRef.current){throw new Error("Radio widget is not mounted; getPromptJSON is unavailable.")}return this.radioRef.current.getPromptJSON()}render(){return jsxRuntimeExports.jsx(RadioWidget,{ref:this.radioRef,...this.props})}constructor(...args){super(...args),this.radioRef=React__namespace.createRef();}};
|
|
1780
1779
|
|
|
1781
1780
|
function getStartUserInput$g(){return {selectedChoiceIds:[]}}var Radio = {name:"radio",displayName:"Radio / Multiple choice",widget:Radio$1,getStartUserInput: getStartUserInput$g,isLintable:true,getUserInputFromSerializedState:serializedState=>{return getUserInputFromSerializedState$f(serializedState)}};
|
|
1782
1781
|
|
|
@@ -1784,11 +1783,11 @@ var basicWidgets = [Radio,InputNumber,NumericInput$1,Expression$1];
|
|
|
1784
1783
|
|
|
1785
1784
|
const{pureXsMax,pureSmMax,pureMdMin,pureMdMax,pureLgMin,pureLgMax}=constants;var mediaQueries = {md:`@media screen and (min-width: ${pureMdMin}) and `+`(max-width: ${pureMdMax})`,xsOrSmaller:`@media screen and (max-width: ${pureXsMax})`,smOrSmaller:`@media screen and (max-width: ${pureSmMax})`,mdOrSmaller:`@media screen and (max-width: ${pureMdMax})`,lgOrSmaller:`@media screen and (max-width: ${pureLgMax})`,lgOrLarger:`@media screen and (min-width: ${pureLgMin})`};
|
|
1786
1785
|
|
|
1787
|
-
const{
|
|
1786
|
+
const{circleSize,radioMarginWidth}=constants;var sharedStyles = aphrodite.StyleSheet.create({blankBackground:{backgroundColor:"#FDFDFD"},perseusSrOnly:{border:0,clip:"rect(0,0,0,0)",height:1,margin:-1,overflow:"hidden",padding:0,position:"absolute",width:1},responsiveLabel:{[mediaQueries.smOrSmaller]:{fontSize:14,lineHeight:1.3},[mediaQueries.md]:{fontSize:17,lineHeight:1.4},[mediaQueries.lgOrLarger]:{fontSize:20,lineHeight:1.4}},responsiveInput:{display:"inline-block",WebkitAppearance:"none",appearance:"none","::-ms-check":{display:"none"},backgroundColor:"#fff",border:"2px solid #fff",boxShadow:`0 0px 0px ${wonderBlocksTokens.border.width.medium} ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,outline:"none",boxSizing:"border-box",flexShrink:0,marginBottom:1,marginLeft:1,marginRight:1,marginTop:1,height:circleSize-2,width:circleSize-2},responsiveRadioInput:{borderRadius:"50%",":checked":{backgroundColor:wonderBlocksTokens.semanticColor.core.foreground.instructive.default,border:"none",borderRadius:"50%",boxShadow:`inset 0px 0px 0px 2px white, `+`0 0px 0px 2px ${wonderBlocksTokens.semanticColor.core.foreground.instructive.default}`,marginTop:radioMarginWidth,marginBottom:radioMarginWidth,marginLeft:radioMarginWidth,marginRight:radioMarginWidth,height:circleSize-2*radioMarginWidth,width:circleSize-2*radioMarginWidth}},responsiveRadioInputStatic:{":checked":{backgroundColor:wonderBlocksTokens.semanticColor.core.foreground.disabled.strong,boxShadow:`inset 0px 0px 0px 2px white, `+`0 0px 0px 2px ${wonderBlocksTokens.semanticColor.core.foreground.disabled.strong}`}},responsiveRadioInputActive:{backgroundColor:"#fff",border:"2px solid #fff",borderRadius:"50%",boxShadow:`0 0px 0px 2px ${wonderBlocksTokens.semanticColor.core.border.neutral.strong}`,marginTop:radioMarginWidth,marginBottom:radioMarginWidth,marginLeft:radioMarginWidth,marginRight:radioMarginWidth,height:circleSize-2*radioMarginWidth,width:circleSize-2*radioMarginWidth,":checked":{backgroundColor:"#fff"}},disableTextSelection:{userSelect:"none"}});
|
|
1788
1787
|
|
|
1789
1788
|
const getPromptJSON$n=widgetData=>{return {type:"categorizer",options:{items:widgetData.items,categories:widgetData.categories},userInput:{itemToCategoryMapping:widgetData.userInput.values}}};
|
|
1790
1789
|
|
|
1791
|
-
|
|
1790
|
+
const Categorizer=React.forwardRef(function Categorizer(props,ref){const{items,categories,randomizeItems,userInput,problemNum,apiOptions,linterContext,handleUserInput,trackInteraction,dependencies}=props;const{strings}=usePerseusI18n();const idPrefix=React.useMemo(()=>___default.default.uniqueId("perseus_radio_"),[]);wonderBlocksCore.useOnMountEffect(()=>{dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"categorizer",widgetId:props.widgetId}});});React.useImperativeHandle(ref,()=>({getPromptJSON:()=>getPromptJSON$n(props),getSerializedState(){const{userInput,...rest}=props;return {...rest,values:userInput.values}}}));function _handleUserInput(itemNum,catNum){const values=[...userInput.values];values[itemNum]=catNum;handleUserInput({values});trackInteraction();}let indexedItems=items.map((item,n)=>[item,n]);if(randomizeItems){indexedItems=perseusCore.shuffle(indexedItems,problemNum);}const table=jsxRuntimeExports.jsxs("table",{className:"categorizer-table "+aphrodite.css(styles$q.mobileTable),children:[jsxRuntimeExports.jsx("thead",{children:jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{className:aphrodite.css(styles$q.emptyHeaderCell)}),categories.map((category,i)=>{return jsxRuntimeExports.jsx("th",{className:aphrodite.css(styles$q.header),children:jsxRuntimeExports.jsx(Renderer,{content:category,linterContext:linterContext,strings:strings})},i)})]})}),jsxRuntimeExports.jsx("tbody",{children:indexedItems.map(indexedItem=>{const item=indexedItem[0];const itemNum=indexedItem[1];const uniqueId=idPrefix+"_"+itemNum;return jsxRuntimeExports.jsxs("tr",{children:[jsxRuntimeExports.jsx("td",{children:jsxRuntimeExports.jsx(Renderer,{content:item,linterContext:linterContext,strings:strings})}),categories.map((catName,catNum)=>{const selected=userInput.values[itemNum]===catNum;return jsxRuntimeExports.jsx("td",{className:"category "+aphrodite.css(styles$q.cell),children:jsxRuntimeExports.jsxs("div",{role:"button","aria-label":catName,onClick:()=>_handleUserInput(itemNum,catNum),children:[apiOptions.isMobile&&jsxRuntimeExports.jsx("input",{type:"radio",name:uniqueId,className:aphrodite.css(sharedStyles.responsiveInput,sharedStyles.responsiveRadioInput,props.static&&sharedStyles.responsiveRadioInputStatic),checked:selected,onChange:()=>_handleUserInput(itemNum,catNum),onClick:e=>e.stopPropagation()}),!apiOptions.isMobile&&jsxRuntimeExports.jsx("span",{className:aphrodite.css(styles$q.radioSpan,selected&&styles$q.checkedRadioSpan,props.static&&selected&&styles$q.staticCheckedRadioSpan),children:selected?jsxRuntimeExports.jsx(InlineIcon,{...iconCircle}):jsxRuntimeExports.jsx(InlineIcon,{...iconCircleThin})})]})},catNum)})]},itemNum)})})]});const extraClassNames=classNames__default.default({"categorizer-container":true,"static-mode":props.static});const inlineStyles=apiOptions.isMobile?[styles$q.fullBleedContainer]:[];return jsxRuntimeExports.jsx("div",{className:extraClassNames+" "+aphrodite.css(...inlineStyles),children:table})});const styles$q=aphrodite.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:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,verticalAlign:"middle"},emptyHeaderCell:{backgroundColor:"inherit",borderBottom:`${wonderBlocksTokens.border.width.medium} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`},radioSpan:{fontSize:wonderBlocksTokens.sizing.size_280,paddingRight:3,cursor:"pointer",":hover":{color:wonderBlocksTokens.semanticColor.core.foreground.instructive.subtle}},checkedRadioSpan:{color:wonderBlocksTokens.semanticColor.core.foreground.instructive.default},staticCheckedRadioSpan:{color:wonderBlocksTokens.semanticColor.core.foreground.disabled.strong}});function getUserInputFromSerializedState$e(serializedState){return {values:serializedState.values}}function getCorrectUserInput$7(options){return {values:options.values}}function getStartUserInput$f(){return {values:[]}}const WrappedCategorizer=withDependencies(Categorizer);var Categorizer$1 = {name:"categorizer",displayName:"Categorizer",widget:WrappedCategorizer,getUserInputFromSerializedState: getUserInputFromSerializedState$e,getCorrectUserInput: getCorrectUserInput$7,getStartUserInput: getStartUserInput$f,isLintable:true};
|
|
1792
1791
|
|
|
1793
1792
|
const isFileProtocol=protocol=>{if(protocol&&protocol.toLowerCase()==="file:"){return true}return false};
|
|
1794
1793
|
|
|
@@ -1798,45 +1797,45 @@ const getUnsupportedPromptJSON=(widgetType,message="")=>{return {type:widgetType
|
|
|
1798
1797
|
|
|
1799
1798
|
const getPromptJSON$m=()=>{return getUnsupportedPromptJSON("cs-program")};
|
|
1800
1799
|
|
|
1801
|
-
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)}const CSProgram=React.forwardRef(function CSProgram(props,ref){const{strings,locale}=usePerseusI18n();const{programID,programType,height,settings,showEditor=false,showButtons=false}=props;React.useEffect(()=>{const handleMessageEvent=e=>{let data={};try{data=JSON.parse(e.data);}catch{return}if(data.testsPassed===undefined){return}const status=data.testsPassed?"correct":"incorrect";props.handleUserInput({status:status,message:data.message});};window.addEventListener("message",handleMessageEvent);return ()=>{window.removeEventListener("message",handleMessageEvent);}},[props]);React.useImperativeHandle(ref,()=>({getPromptJSON:()=>{return getPromptJSON$m()},getSerializedState:()=>{const{userInput
|
|
1800
|
+
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)}const CSProgram=React.forwardRef(function CSProgram(props,ref){const{strings,locale}=usePerseusI18n();const{programID,programType,height,settings,showEditor=false,showButtons=false}=props;React.useEffect(()=>{const handleMessageEvent=e=>{let data={};try{data=JSON.parse(e.data);}catch{return}if(data.testsPassed===undefined){return}const status=data.testsPassed?"correct":"incorrect";props.handleUserInput({status:status,message:data.message});};window.addEventListener("message",handleMessageEvent);return ()=>{window.removeEventListener("message",handleMessageEvent);}},[props]);React.useImperativeHandle(ref,()=>({getPromptJSON:()=>{return getPromptJSON$m()},getSerializedState:()=>{const{userInput,alignment,...rest}=props;return {...rest,programType:rest.programType||null}}}));if(!programID){return jsxRuntimeExports.jsx("div",{})}let styleContainer=false;let url=getUrlFromProgramID$1(programID);let className;if(showEditor){url+="&editor=yes";className="perseus-scratchpad-editor";}else {url+=`&editor=no&width=${articleMaxWidthInPx}`;className="perseus-scratchpad";if(programType!=="webpage"){styleContainer=true;}}if(showButtons){url+="&buttons=yes";}else {url+="&buttons=no";}if(settings){const settingsObject={};settings.forEach(setting=>{if(setting.name&&setting.value){settingsObject[setting.name]=setting.value;}});url=updateQueryString$1(url,"settings",JSON.stringify(settingsObject));}if(locale){url=updateQueryString$1(url,"lang",locale);}const style={height:showButtons?height+67:height,width:"100%"};const sandboxOptions=["allow-popups","allow-same-origin","allow-scripts","allow-top-navigation"].join(" ");return jsxRuntimeExports.jsx("div",{className:aphrodite.css(styleContainer&&styles$p.container),children:jsxRuntimeExports.jsx("iframe",{title:strings.computerScienceProgram,sandbox:sandboxOptions,src:url,style:style,className:className,allowFullScreen:true})})});const styles$p=aphrodite.StyleSheet.create({container:{margin:"auto"}});function getUserInputFromSerializedState$d(serializedState){return {status:serializedState.status,message:serializedState.message}}function getStartUserInput$e(){return {status:"incomplete",message:null}}var CSProgram$1 = {name:"cs-program",displayName:"CS Program",widget:CSProgram,hidden:true,getStartUserInput: getStartUserInput$e,getUserInputFromSerializedState: getUserInputFromSerializedState$d};
|
|
1802
1801
|
|
|
1803
1802
|
const getPromptJSON$l=widgetData=>{return {type:"definition",definition:widgetData.definition,togglePrompt:widgetData.togglePrompt}};
|
|
1804
1803
|
|
|
1805
|
-
var styles$
|
|
1804
|
+
var styles$o = {"definition":"perseus_5CDFHduT"};
|
|
1806
1805
|
|
|
1807
|
-
const styles$
|
|
1806
|
+
const styles$n={tooltipBody:{color:"var(--wb-semanticColor-core-foreground-neutral-strong)",fontSize:"var(--wb-font-body-size-medium)",fontWeight:"var(--wb-font-weight-medium)",lineHeight:"var(--wb-font-body-lineHeight-medium)"}};
|
|
1808
1807
|
|
|
1809
|
-
class Definition extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"definition",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$l(this.props)}render(){return jsxRuntimeExports.jsx(DefinitionConsumer,{children:({activeDefinitionId,setActiveDefinitionId})=>jsxRuntimeExports.jsx(wonderBlocksPopover.Popover,{dismissEnabled:true,content:jsxRuntimeExports.jsx(wonderBlocksPopover.PopoverContentCore,{style:styles$
|
|
1808
|
+
class Definition extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"definition",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$l(this.props)}render(){return jsxRuntimeExports.jsx(DefinitionConsumer,{children:({activeDefinitionId,setActiveDefinitionId})=>jsxRuntimeExports.jsx(wonderBlocksPopover.Popover,{dismissEnabled:true,content:jsxRuntimeExports.jsx(wonderBlocksPopover.PopoverContentCore,{style:styles$n.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__default.default,{onClick:()=>{this.props.trackInteraction();setActiveDefinitionId(this.props.widgetId);},"aria-label":this.context.strings.definitionIdentifier({word:this.props.togglePrompt}),children:()=>jsxRuntimeExports.jsx("span",{className:styles$o.definition,children:this.props.togglePrompt})})})})}constructor(...args){super(...args),this.isWidget=true;}}Definition.contextType=PerseusI18nContext;Definition.defaultProps={togglePrompt:"define me",definition:"definition goes here"};const WrappedDefinition=withDependencies(Definition);var Definition$1 = {name:"definition",displayName:"Definition",widget:WrappedDefinition};
|
|
1810
1809
|
|
|
1811
1810
|
class DeprecatedStandin extends React__namespace.default.Component{render(){return jsxRuntimeExports.jsx("div",{style:{paddingTop:8,paddingBottom:8},children:jsxRuntimeExports.jsx(Banner__default.default,{text:this.context.strings.deprecatedStandin,kind:"info"})})}constructor(...args){super(...args),this.isWidget=true;}}DeprecatedStandin.contextType=PerseusI18nContext;var DeprecatedStandin$1 = {name:"deprecated-standin",displayName:"Deprecated Standin",widget:DeprecatedStandin,hidden:true};
|
|
1812
1811
|
|
|
1813
1812
|
const getPromptJSON$k=widgetData=>{return {type:"dropdown",options:{items:widgetData.choices.map(choice=>choice.content)},userInput:{selectedIndex:widgetData.userInput.value-1}}};
|
|
1814
1813
|
|
|
1815
|
-
const Dropdown=React.forwardRef(function Dropdown(props,ref){const{strings}=usePerseusI18n();const dropdownId=React.useId();const{choices=[],placeholder="",apiOptions=ApiOptions.defaults,userInput={value:0},static:isStatic=false,dependencies,visibleLabel,ariaLabel,widgetId,trackInteraction,handleUserInput}=props;React.useEffect(()=>{dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"dropdown",widgetId:widgetId}});},[]);const handleChange=selected=>{trackInteraction();handleUserInput({value:selected});};const rootRef=React.useRef(null);React.useImperativeHandle(ref,()=>({focus:()=>{if(apiOptions.readOnly||isStatic){return false}if(!rootRef.current){return false}const button=rootRef.current.querySelector("[role='combobox']");if(!(button instanceof HTMLElement)){return false}if(button instanceof HTMLButtonElement&&button.disabled||button.getAttribute("aria-disabled")==="true"){return false}const previouslyFocused=document.activeElement;button.focus();return document.activeElement===button&&previouslyFocused!==button},getPromptJSON:()=>{return getPromptJSON$k(props)},getSerializedState:()=>{const{userInput,choices,...rest}=props;return {...rest,choices:choices.map(choice=>choice.content),selected:userInput.value}}}));const children=[jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"0",disabled:true,label:jsxRuntimeExports.jsx(Renderer,{content:placeholder,strings:strings}),labelAsText:placeholder},"placeholder"),...choices.map((choice,i)=>jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:String(i+1),label:jsxRuntimeExports.jsx(Renderer,{content:choice.content,strings:strings}),labelAsText:choice.content},String(i+1)))];return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{ref:rootRef,onClick:e=>{e.stopPropagation();},onTouchStart:e=>{e.stopPropagation();},children:[visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"label",htmlFor:dropdownId,children:visibleLabel}),jsxRuntimeExports.jsx(wonderBlocksDropdown.SingleSelect,{id:dropdownId,placeholder:"",className:"perseus-dropdown",onChange:value=>handleChange(parseInt(value)),selectedValue:String(userInput.value),disabled:apiOptions.readOnly||isStatic,"aria-label":ariaLabel||visibleLabel||strings.selectAnAnswer,showOpenerLabelAsText:false,children:children})]})});function getUserInputFromSerializedState$c(serializedState){return {value:serializedState.selected}}function getStartUserInput$d(){return {value:0}}function getCorrectUserInput$6(options){return {value:options.choices.findIndex(c=>c.correct)+1}}const WrappedDropdown=withDependencies(Dropdown);var Dropdown$1 = {name:"dropdown",displayName:"Drop down",widget:WrappedDropdown,getStartUserInput: getStartUserInput$d,getCorrectUserInput: getCorrectUserInput$6,getUserInputFromSerializedState: getUserInputFromSerializedState$c};
|
|
1814
|
+
const Dropdown=React.forwardRef(function Dropdown(props,ref){const{strings}=usePerseusI18n();const dropdownId=React.useId();const{choices=[],placeholder="",apiOptions=ApiOptions.defaults,userInput={value:0},static:isStatic=false,dependencies,visibleLabel,ariaLabel,widgetId,trackInteraction,handleUserInput}=props;React.useEffect(()=>{dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"dropdown",widgetId:widgetId}});},[]);const handleChange=selected=>{trackInteraction();handleUserInput({value:selected});};const rootRef=React.useRef(null);React.useImperativeHandle(ref,()=>({focus:()=>{if(apiOptions.readOnly||isStatic){return false}if(!rootRef.current){return false}const button=rootRef.current.querySelector("[role='combobox']");if(!(button instanceof HTMLElement)){return false}if(button instanceof HTMLButtonElement&&button.disabled||button.getAttribute("aria-disabled")==="true"){return false}const previouslyFocused=document.activeElement;button.focus();return document.activeElement===button&&previouslyFocused!==button},getPromptJSON:()=>{return getPromptJSON$k(props)},getSerializedState:()=>{const{userInput,choices,...rest}=props;return {...rest,choices:choices.map(choice=>choice.content),selected:userInput.value}}}));const inline=perseusCore.isFeatureOn({apiOptions:props.apiOptions},"perseus-renderer-upgrade");const children=[jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:"0",disabled:true,label:jsxRuntimeExports.jsx(Renderer,{content:placeholder,strings:strings,apiOptions:{flags:apiOptions.flags},inline:inline}),labelAsText:placeholder},"placeholder"),...choices.map((choice,i)=>jsxRuntimeExports.jsx(wonderBlocksDropdown.OptionItem,{value:String(i+1),label:jsxRuntimeExports.jsx(Renderer,{content:choice.content,strings:strings,apiOptions:{flags:apiOptions.flags},inline:inline}),labelAsText:choice.content},String(i+1)))];return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{ref:rootRef,onClick:e=>{e.stopPropagation();},onTouchStart:e=>{e.stopPropagation();},children:[visibleLabel&&jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{size:"medium",weight:"bold",tag:"label",htmlFor:dropdownId,children:visibleLabel}),jsxRuntimeExports.jsx(wonderBlocksDropdown.SingleSelect,{id:dropdownId,placeholder:"",className:"perseus-dropdown",onChange:value=>handleChange(parseInt(value)),selectedValue:String(userInput.value),disabled:apiOptions.readOnly||isStatic,"aria-label":ariaLabel||visibleLabel||strings.selectAnAnswer,showOpenerLabelAsText:false,children:children})]})});function getUserInputFromSerializedState$c(serializedState){return {value:serializedState.selected}}function getStartUserInput$d(){return {value:0}}function getCorrectUserInput$6(options){return {value:options.choices.findIndex(c=>c.correct)+1}}const WrappedDropdown=withDependencies(Dropdown);var Dropdown$1 = {name:"dropdown",displayName:"Drop down",widget:WrappedDropdown,getStartUserInput: getStartUserInput$d,getCorrectUserInput: getCorrectUserInput$6,getUserInputFromSerializedState: getUserInputFromSerializedState$c};
|
|
1816
1815
|
|
|
1817
1816
|
function sharedInitializeUserInput(widgetOptions,problemNum){const startUserInput={};if(!widgetOptions){return startUserInput}Object.entries(widgetOptions).forEach(([id,widgetInfo])=>{const widgetExports=getWidgetExport(widgetInfo.type);if(widgetInfo.static&&widgetExports?.getCorrectUserInput){startUserInput[id]=widgetExports.getCorrectUserInput(widgetInfo.options);}else if(widgetExports?.getStartUserInput){startUserInput[id]=widgetExports.getStartUserInput(widgetInfo.options,problemNum??0);}});return startUserInput}function deriveUserInputFromSerializedState(serializedState,widgetsMap){const restoredUserInput={};Object.entries(serializedState).forEach(([widgetId,props])=>{const widgetType=getWidgetTypeByWidgetId(widgetId,widgetsMap);const widgetExport=getWidgetExport(widgetType);if(widgetExport?.getUserInputFromSerializedState){const restoreResult=widgetExport.getUserInputFromSerializedState(props,widgetsMap[widgetId].options);restoredUserInput[widgetId]=restoreResult;}});return restoredUserInput}function UserInputManager(props){const[userInput,setUserInput]=React.useState(props.initialUserInput||sharedInitializeUserInput(props.widgets,props.problemNum??0));function handleUserInput(id,nextUserInput,widgetsEmpty){const next={...userInput,[id]:nextUserInput};setUserInput(next);props.handleUserInput?.(next,widgetsEmpty);}function initializeUserInput(widgetOptions,problemNum){setUserInput(props.initialUserInput||sharedInitializeUserInput(widgetOptions,problemNum));}return props.children({userInput,handleUserInput,initializeUserInput})}
|
|
1818
1817
|
|
|
1819
1818
|
const getPromptJSON$j=widgetData=>{return {type:"explanation",showPrompt:widgetData.showPrompt,explanation:widgetData.explanation}};
|
|
1820
1819
|
|
|
1821
|
-
var styles$
|
|
1820
|
+
var styles$m = {"content":"perseus_HDIlPzEz","contentCollapsed":"perseus_NkFQFgcZ","contentExpanded":"perseus_XhV-9haB","contentWrapper":"perseus_WEJESS6h","transitionCollapsed":"perseus_sbBrAODD","transitionExpanded":"perseus_Wp72j6qk"};
|
|
1822
1821
|
|
|
1823
|
-
const styles$
|
|
1822
|
+
const styles$l={buttonStyleOverrides:{height:"auto",lineHeight:"inherit",marginLeft:"-0.2rem",marginRight:"0.2rem",paddingLeft:"0.2rem"},content:{borderLeft:"0px solid var(--wb-semanticColor-core-border-neutral-subtle)",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",marginBottom:"1.4rem",marginLeft:"-2.3rem",marginTop:"1.4rem",minWidth:"100%",paddingBottom:"1rem",paddingLeft:"2.3rem",visibility:"visible"},contentWrapper:{overflow:"hidden"},labelStyle:{fontSize:"var(--wb-font-heading-size-medium)",lineHeight:"inherit",marginRight:"-0.6rem",textAlign:"left",whiteSpace:"normal"},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"}};
|
|
1824
1823
|
|
|
1825
|
-
function mediaQueryIsMatched(mediaQuery){if(typeof window.matchMedia!=="function"){return false}return window.matchMedia(mediaQuery).matches}class Explanation extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"explanation",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$j(this.props)}render(){const promptText=this.state.expanded?this.props.hidePrompt:this.props.showPrompt;const caretIcon=this.state.expanded?caretUp__default.default:caretDown__default.default;const legacyContentStyling=[styles$
|
|
1824
|
+
function mediaQueryIsMatched(mediaQuery){if(typeof window.matchMedia!=="function"){return false}return window.matchMedia(mediaQuery).matches}class Explanation extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"explanation",widgetId:this.props.widgetId}});}getPromptJSON(){return getPromptJSON$j(this.props)}render(){const promptText=this.state.expanded?this.props.hidePrompt:this.props.showPrompt;const caretIcon=this.state.expanded?caretUp__default.default:caretDown__default.default;const legacyContentStyling=[styles$l.content,this.state.expanded?styles$l.contentExpanded:styles$l.contentCollapsed,mediaQueryIsMatched("(prefers-reduced-motion: no-preference)")&&(this.state.expanded?styles$l.transitionExpanded:styles$l.transitionCollapsed)];const contentClasses=[styles$m.content,this.state.expanded?styles$m.contentExpanded:styles$m.contentCollapsed,this.state.expanded?styles$m.transitionExpanded:styles$m.transitionCollapsed];return jsxRuntimeExports.jsx(wonderBlocksCore.Id,{children:contentId=>jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(Button__default.default,{"aria-expanded":this.state.expanded,"aria-controls":contentId,endIcon:caretIcon,kind:"tertiary",labelStyle:styles$l.labelStyle,onClick:this._onClick,size:"small",style:styles$l.buttonStyleOverrides,children:promptText}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{id:contentId,style:legacyContentStyling,className:contentClasses.join(" "),"aria-hidden":!this.state.expanded,testId:"content-container",children:jsxRuntimeExports.jsx(wonderBlocksCore.View,{className:styles$m.contentWrapper,style:styles$l.contentWrapper,children:jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>{return jsxRuntimeExports.jsx(Renderer,{apiOptions:this.props.apiOptions,content:this.props.explanation,widgets:this.props.widgets,linterContext:this.props.linterContext,strings:this.context.strings,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput})}})})})]})})}constructor(...args){super(...args),this.isWidget=true,this.state={expanded:false},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:PerseusLinter.linterContextDefault};const WrappedExplanation=withDependencies(Explanation);var Explanation$1 = {name:"explanation",displayName:"Explanation",widget:WrappedExplanation,isLintable:true};
|
|
1826
1825
|
|
|
1827
|
-
class FreeResponse extends React__namespace.Component{isOverLimit(){return !this.props.allowUnlimitedCharacters&&this.characterCount()>this.props.characterLimit}render(){const isOverLimit=this.isOverLimit();const characterCountText=this.props.allowUnlimitedCharacters?undefined:this.context.strings.characterCount({used:this.characterCount(),num:this.props.characterLimit});if(characterCountText){this.announceCharacterCount(characterCountText,isOverLimit);}return jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$
|
|
1826
|
+
class FreeResponse extends React__namespace.Component{isOverLimit(){return !this.props.allowUnlimitedCharacters&&this.characterCount()>this.props.characterLimit}render(){const isOverLimit=this.isOverLimit();const characterCountText=this.props.allowUnlimitedCharacters?undefined:this.context.strings.characterCount({used:this.characterCount(),num:this.props.characterLimit});if(characterCountText){this.announceCharacterCount(characterCountText,isOverLimit);}return jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$k.container,className:"free-response",children:jsxRuntimeExports.jsx(wonderBlocksLabeledField.LabeledField,{label:jsxRuntimeExports.jsx(wonderBlocksCore.View,{className:"free-response-question",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.question,strings:this.context.strings})}),field:jsxRuntimeExports.jsx(wonderBlocksForm.TextArea,{error:isOverLimit,onChange:this._handleUserInput,placeholder:this.props.placeholder,style:styles$k.textarea,value:this.props.userInput.currentValue}),additionalHelperMessage:jsxRuntimeExports.jsxs("p",{className:aphrodite.css(styles$k.characterCountText,isOverLimit?styles$k.overCharacterLimit:undefined),children:[isOverLimit&&jsxRuntimeExports.jsx(wonderBlocksIcon.PhosphorIcon,{"aria-label":"Error:",icon:warningCircleIcon__default.default,size:"small",style:styles$k.warningCircleIcon}),characterCountText]})})})}constructor(...args){super(...args),this.isWidget=true,this.announceCharacterCount=(message,isOverLimit)=>{const level=isOverLimit?"assertive":"polite";wonderBlocksAnnouncer.announceMessage({message,level,debounceThreshold:750});},this.characterCount=()=>{return this.props.userInput.currentValue.replace(/\n/g,"").length},this._handleUserInput=newValue=>{this.props.handleUserInput({currentValue:newValue});};}}FreeResponse.contextType=PerseusI18nContext;function getStartUserInput$c(){return {currentValue:""}}var FreeResponse$1 = {name:"free-response",accessible:true,displayName:"Free Response (Assessments only)",widget:FreeResponse,hidden:false,getUserInputFromSerializedState:getStartUserInput$c,getStartUserInput: getStartUserInput$c};const styles$k=aphrodite.StyleSheet.create({container:{gap:wonderBlocksTokens.spacing.xSmall_8},characterCountText:{color:wonderBlocksTokens.semanticColor.core.foreground.neutral.default,fontSize:wonderBlocksTokens.font.body.size.small,margin:0},overCharacterLimit:{color:wonderBlocksTokens.semanticColor.core.foreground.critical.default},textarea:{padding:wonderBlocksTokens.spacing.medium_16},warningCircleIcon:{marginInlineEnd:wonderBlocksTokens.spacing.xSmall_8}});
|
|
1828
1827
|
|
|
1829
1828
|
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}};
|
|
1830
1829
|
|
|
1831
|
-
class GradedGroupAnswerBar extends React__namespace.Component{render(){const{apiOptions,answerBarState,onCheckAnswer,onNextQuestion}=this.props;const{keepTrying,tryAgain,check,correctExcited,nextQuestion}=this.context.strings;const answerBarStyle={...styles$
|
|
1830
|
+
class GradedGroupAnswerBar extends React__namespace.Component{render(){const{apiOptions,answerBarState,onCheckAnswer,onNextQuestion}=this.props;const{keepTrying,tryAgain,check,correctExcited,nextQuestion}=this.context.strings;const answerBarStyle={...styles$j.answerBar,backgroundColor:answerBarState==="CORRECT"?wonderBlocksTokens.semanticColor.core.background.base.subtle:wonderBlocksTokens.semanticColor.core.background.base.default,justifyContent:answerBarState==="CORRECT"&&!onNextQuestion?"center":"space-between"};const message=answerBarState==="INCORRECT"?jsxRuntimeExports.jsxs("span",{style:styles$j.text,children:[jsxRuntimeExports.jsx("span",{style:styles$j.tryAgainIcon,children:jsxRuntimeExports.jsx(InlineIcon,{...iconTryAgain})}),jsxRuntimeExports.jsx("span",{style:{marginLeft:8},children:keepTrying})]}):jsxRuntimeExports.jsx("span",{});if(answerBarState!=="CORRECT"){const buttonLabel=answerBarState==="INCORRECT"?tryAgain:check;return jsxRuntimeExports.jsxs("div",{style:answerBarStyle,children:[message,jsxRuntimeExports.jsx(Button__default.default,{disabled:apiOptions.readOnly||answerBarState!=="ACTIVE",onClick:onCheckAnswer,children:buttonLabel})]})}return jsxRuntimeExports.jsxs("div",{style:answerBarStyle,children:[jsxRuntimeExports.jsxs("span",{style:styles$j.text,children:[jsxRuntimeExports.jsx("span",{style:{color:wonderBlocksTokens.semanticColor.core.foreground.success.default},children:jsxRuntimeExports.jsx(InlineIcon,{...iconStar,style:{marginBottom:5}})}),jsxRuntimeExports.jsx("span",{role:"alert","aria-label":correctExcited,style:{marginLeft:8},children:correctExcited})]}),onNextQuestion&&jsxRuntimeExports.jsx(Button__default.default,{onClick:onNextQuestion,children:nextQuestion})]})}}GradedGroupAnswerBar.contextType=PerseusI18nContext;const styles$j={answerBar:{display:"flex",alignItems:"center",height:68,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,marginBottom:negativePhoneMargin,marginTop:phoneMargin,paddingLeft:phoneMargin,paddingRight:10,borderTop:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.default}`},tryAgainIcon:{color:wonderBlocksTokens.semanticColor.core.foreground.neutral.subtle,transform:"scale(-1,1) rotate(-268deg)"},text:{display:"flex",flexDirection:"row",alignItems:"center",fontWeight:wonderBlocksTokens.font.weight.bold,fontSize:wonderBlocksTokens.font.body.size.medium}};
|
|
1832
1831
|
|
|
1833
|
-
const GRADING_STATUSES={ungraded:"ungraded",correct:"correct",incorrect:"incorrect",invalid:"invalid"};const getNextState=(currentState,answerable)=>{switch(currentState){case "ACTIVE":return !answerable?"INACTIVE":currentState;case "INACTIVE":return answerable?"ACTIVE":currentState;case "INCORRECT":return answerable?"ACTIVE":"INACTIVE";default:return currentState}};class GradedGroup extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"graded-group",widgetSubType:"null",widgetId:this.props.widgetId}});}shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}_handleUserInput(_userInput,widgetsEmpty){this.setState({status:GRADING_STATUSES.ungraded,message:""});const answerable=!widgetsEmpty;const answerBarState=this.state.answerBarState;const nextState=getNextState(answerBarState,answerable);this.setState({answerBarState:nextState});}getPromptJSON(){const hint=this.hintRendererRef.current?.getPromptJSON()||{content:this.props.hint?.content||"",widgets:{}};return getPromptJSON$i(this.props.title,this.rendererRef.current?.getPromptJSON(),hint)}render(){const apiOptions=___default.default.extend({},ApiOptions.defaults,this.props.apiOptions,{onFocusChange:(newFocus,oldFocus)=>{if(oldFocus){this.props.onBlur(oldFocus);}if(newFocus){this.props.onFocus(newFocus);}}});let gradeStatus=null;let icon=null;if(this.state.status===GRADING_STATUSES.correct){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconOk,style:{color:wonderBlocksTokens.semanticColor.core.foreground.success.default}});gradeStatus=this.context.strings.correct;}else if(this.state.status===GRADING_STATUSES.incorrect){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconRemove,style:{color:wonderBlocksTokens.semanticColor.core.foreground.critical.default}});gradeStatus=this.context.strings.incorrect;}const mobileClass=this.props.inGradedGroupSet?aphrodite.css(styles$
|
|
1832
|
+
const GRADING_STATUSES={ungraded:"ungraded",correct:"correct",incorrect:"incorrect",invalid:"invalid"};const getNextState=(currentState,answerable)=>{switch(currentState){case "ACTIVE":return !answerable?"INACTIVE":currentState;case "INACTIVE":return answerable?"ACTIVE":currentState;case "INCORRECT":return answerable?"ACTIVE":"INACTIVE";default:return currentState}};class GradedGroup extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"graded-group",widgetSubType:"null",widgetId:this.props.widgetId}});}shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}_handleUserInput(_userInput,widgetsEmpty){this.setState({status:GRADING_STATUSES.ungraded,message:""});const answerable=!widgetsEmpty;const answerBarState=this.state.answerBarState;const nextState=getNextState(answerBarState,answerable);this.setState({answerBarState:nextState});}getPromptJSON(){const hint=this.hintRendererRef.current?.getPromptJSON()||{content:this.props.hint?.content||"",widgets:{}};return getPromptJSON$i(this.props.title,this.rendererRef.current?.getPromptJSON(),hint)}render(){const apiOptions=___default.default.extend({},ApiOptions.defaults,this.props.apiOptions,{onFocusChange:(newFocus,oldFocus)=>{if(oldFocus){this.props.onBlur(oldFocus);}if(newFocus){this.props.onFocus(newFocus);}}});let gradeStatus=null;let icon=null;if(this.state.status===GRADING_STATUSES.correct){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconOk,style:{color:wonderBlocksTokens.semanticColor.core.foreground.success.default}});gradeStatus=this.context.strings.correct;}else if(this.state.status===GRADING_STATUSES.incorrect){icon=jsxRuntimeExports.jsx(InlineIcon,{...iconRemove,style:{color:wonderBlocksTokens.semanticColor.core.foreground.critical.default}});gradeStatus=this.context.strings.incorrect;}const mobileClass=this.props.inGradedGroupSet?aphrodite.css(styles$i.gradedGroupInSet):aphrodite.css(styles$i.gradedGroup);const classes=classNames__default.default({[mobileClass]:apiOptions.isMobile,"perseus-graded-group":true,"answer-correct":apiOptions.isMobile?false:this.state.status===GRADING_STATUSES.correct,"answer-incorrect":apiOptions.isMobile?false:this.state.status===GRADING_STATUSES.incorrect});const{answerBarState}=this.state;const isCorrect=answerBarState==="CORRECT";const readOnly=apiOptions.readOnly||apiOptions.isMobile&&isCorrect;const showSolutions=isCorrect?"all":"none";return jsxRuntimeExports.jsxs("div",{className:classes,children:[!!this.props.title&&jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$i.title),children:this.props.title}),jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.widgets,handleUserInput:(userInput,widgetsEmpty)=>this._handleUserInput(userInput,widgetsEmpty),problemNum:0,children:({userInput,handleUserInput})=>jsxRuntimeExports.jsx(Renderer,{content:this.props.content,widgets:this.props.widgets,images:this.props.images,userInput:userInput,handleUserInput:handleUserInput,problemNum:0,ref:this.rendererRef,keypadElement:this.props.keypadElement,apiOptions:{...apiOptions,readOnly},showSolutions:showSolutions,linterContext:this.props.linterContext,strings:this.context.strings})}),!apiOptions.isMobile&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[icon!=null&&jsxRuntimeExports.jsx("div",{className:"group-icon",children:icon}),gradeStatus&&jsxRuntimeExports.jsx("div",{className:aphrodite.css(a11y.srOnly),role:"alert","aria-label":gradeStatus,children:gradeStatus}),jsxRuntimeExports.jsx("div",{role:"status","aria-live":"polite",children:jsxRuntimeExports.jsx(Renderer,{content:this.state.message,strings:this.context.strings})}),jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",disabled:this.props.apiOptions.readOnly,onClick:this._checkAnswer,children:this.context.strings.check}),isCorrect&&this.props.onNextQuestion&&jsxRuntimeExports.jsx(Button__default.default,{kind:"secondary",disabled:this.props.apiOptions.readOnly,onClick:this.props.onNextQuestion,style:{marginLeft:5},children:this.context.strings.nextQuestion})]}),this.props.hint?.content&&(this.state.showHint?jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("button",{tabIndex:"0",className:aphrodite.css(styles$i.explanationTitle),onClick:()=>this.setState({showHint:false}),onKeyPress:e=>{e.preventDefault();this.setState({showHint:false});},children:this.context.strings.hideExplanation}),jsxRuntimeExports.jsx(UserInputManager,{widgets:this.props.hint.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>{const{content,widgets,images}=this.props.hint;return jsxRuntimeExports.jsx(Renderer,{content:content,widgets:widgets,images:images,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,ref:this.hintRendererRef,apiOptions:apiOptions,linterContext:this.props.linterContext,strings:this.context.strings,showSolutions:showSolutions})}})]}):jsxRuntimeExports.jsx("button",{tabIndex:"0",onClick:()=>this.setState({showHint:true}),onKeyPress:e=>{e.preventDefault();this.setState({showHint:true});},className:aphrodite.css(styles$i.showHintLink),children:this.context.strings.explain})),apiOptions.isMobile&&jsxRuntimeExports.jsx(GradedGroupAnswerBar,{apiOptions:apiOptions,answerBarState:answerBarState,onCheckAnswer:this._checkAnswer,onNextQuestion:this.props.onNextQuestion})]})}constructor(...args){super(...args),this.state={status:GRADING_STATUSES.ungraded,showHint:false,message:"",answerBarState:"INACTIVE"},this.rendererRef=React__namespace.createRef(),this.hintRendererRef=React__namespace.createRef(),this._checkAnswer=()=>{const score=this.rendererRef.current?.score()||{type:"invalid"};const{INVALID_MESSAGE_PREFIX,DEFAULT_INVALID_MESSAGE_1,DEFAULT_INVALID_MESSAGE_2}=this.context.strings;const status=score.type==="points"?score.total===score.earned?GRADING_STATUSES.correct:GRADING_STATUSES.incorrect:GRADING_STATUSES.invalid;const message=score.type==="points"?score.message||"":score.message?`${INVALID_MESSAGE_PREFIX} ${mapErrorToString(score.message,this.context.strings)}`:`${INVALID_MESSAGE_PREFIX} ${DEFAULT_INVALID_MESSAGE_1}${DEFAULT_INVALID_MESSAGE_2}`;this.setState({status:status,message:message,answerBarState:status==="correct"?"CORRECT":"INCORRECT"});this.props.trackInteraction({status:status});},this.getInputPaths=()=>{return this.rendererRef.current?.getInputPaths()||[]},this.focus=()=>{return !!this.rendererRef.current?.focus()},this.focusInputPath=path=>{this.rendererRef.current?.focusPath(path);},this.blurInputPath=path=>{this.rendererRef.current?.blurPath(path);};}}GradedGroup.contextType=PerseusI18nContext;GradedGroup.defaultProps={title:"",content:"",widgets:{},images:{},hint:null,hasHint:false,linterContext:PerseusLinter.linterContextDefault};const styles$i=aphrodite.StyleSheet.create({gradedGroupInSet:{marginLeft:0,paddingLeft:0},gradedGroup:{borderTop:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderBottom:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.subtle,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"},showHintLink:{backgroundColor:"unset",fontSize:wonderBlocksTokens.font.body.size.small,padding:0,border:"none",marginTop:20,color:wonderBlocksTokens.semanticColor.core.foreground.instructive.default,cursor:"pointer",display:"block",clear:"both"},explanationTitle:{backgroundColor:"unset",marginTop:20,color:wonderBlocksTokens.semanticColor.core.foreground.instructive.default,marginBottom:10,cursor:"pointer",fontSize:wonderBlocksTokens.font.body.size.small,padding:0,border:"none",display:"block",clear:"both"},title:{fontSize:wonderBlocksTokens.font.heading.size.small,color:wonderBlocksTokens.semanticColor.core.foreground.neutral.default,textTransform:"uppercase",marginBottom:11,letterSpacing:.8}});const WrappedGradedGroup=withDependencies(GradedGroup);var GradedGroup$1 = {name:"graded-group",displayName:"Graded group (articles only)",widget:WrappedGradedGroup,hidden:false,tracking:"all",isLintable:true};
|
|
1834
1833
|
|
|
1835
1834
|
const getPromptJSON$h=(widgetData,activeGroupJSON)=>{return {type:"graded-group-set",options:{groupCount:widgetData.gradedGroups.length,currentGroup:activeGroupJSON}}};
|
|
1836
1835
|
|
|
1837
|
-
class Indicators extends React__namespace.Component{render(){return jsxRuntimeExports.jsx("ul",{role:"list",className:classNames__default.default(aphrodite.css(styles$
|
|
1836
|
+
class Indicators extends React__namespace.Component{render(){return jsxRuntimeExports.jsx("ul",{role:"list",className:classNames__default.default(aphrodite.css(styles$h.indicatorContainer),"indicatorContainer"),children:this.props.gradedGroups.map(({title},i)=>{const isCurrent=i===this.props.currentGroup;return jsxRuntimeExports.jsx("li",{className:aphrodite.css(styles$h.indicator),children:jsxRuntimeExports.jsx(Clickable__default.default,{role:"button","aria-label":title,"aria-current":isCurrent,style:styles$h.indicatorButton,onClick:()=>this.props.onChangeCurrentGroup(i),onKeyDown:e=>this.handleKeyDown(e,i),children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:[styles$h.indicatorDot,isCurrent&&styles$h.indicatorDotActive,(hovered||focused||pressed)&&styles$h.indicatorDotFocused]})})},i)})})}constructor(...args){super(...args),this.handleKeyDown=(e,i)=>{if(e.key==="Enter"||e.key===" "){this.props.onChangeCurrentGroup(i);}};}}Indicators.contextType=PerseusI18nContext;class GradedGroupSet extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"graded-group-set",widgetSubType:"null",widgetId:this.props.widgetId}});}shouldComponentUpdate(nextProps,nextState){return nextProps!==this.props||nextState!==this.state}getPromptJSON(){const activeGroupPromptJSON=this._childGroup.getPromptJSON();return getPromptJSON$h(this.props,activeGroupPromptJSON)}render(){const{JIPT}=getDependencies();if(JIPT.useJIPT&&this.props.gradedGroups.length>1){return jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$h.container),children:this.props.gradedGroups.map((gradedGroup,i)=>{return jsxRuntimeExports.jsx(GradedGroup,{...this.props,...gradedGroup,inGradedGroupSet:false,linterContext:this.props.linterContext},i)})})}const currentGroup=this.props.gradedGroups[this.state.currentGroup];if(!currentGroup){return jsxRuntimeExports.jsx("span",{children:"No current group..."})}const numGroups=this.props.gradedGroups.length;const handleNextQuestion=this.state.currentGroup<numGroups-1?this.handleNextQuestion:null;return jsxRuntimeExports.jsxs("div",{className:aphrodite.css(styles$h.container),children:[jsxRuntimeExports.jsxs("div",{className:aphrodite.css(styles$h.top),children:[jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$h.title),children:currentGroup.title}),jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$h.spacer)}),jsxRuntimeExports.jsx(Indicators,{currentGroup:this.state.currentGroup,gradedGroups:this.props.gradedGroups,onChangeCurrentGroup:currentGroup=>this.setState({currentGroup})})]}),jsxRuntimeExports.jsx(GradedGroup,{ref:comp=>this._childGroup=comp,...this.props,...currentGroup,inGradedGroupSet:true,title:null,onNextQuestion:handleNextQuestion,linterContext:this.props.linterContext},this.state.currentGroup)]})}constructor(...args){super(...args),this.state={currentGroup:0},this.getInputPaths=()=>{return this._childGroup.getInputPaths()},this.focus=()=>{return this._childGroup.focus()},this.focusInputPath=path=>{this._childGroup.focusInputPath(path);},this.blurInputPath=path=>{this._childGroup.blurInputPath(path);},this.handleNextQuestion=()=>{const{currentGroup}=this.state;const numGroups=this.props.gradedGroups.length;if(currentGroup<numGroups-1){this.setState({currentGroup:currentGroup+1});}};}}GradedGroupSet.defaultProps={gradedGroups:[],linterContext:PerseusLinter.linterContextDefault};const WrappedGradedGroupSet=withDependencies(GradedGroupSet);var GradedGroupSet$1 = {name:"graded-group-set",displayName:"Graded group set (articles only)",widget:WrappedGradedGroupSet,hidden:false,tracking:"all",isLintable:true};const styles$h=aphrodite.StyleSheet.create({top:{display:"flex",flexDirection:"row"},spacer:{flex:1},title:{fontSize:wonderBlocksTokens.font.heading.size.small,color:wonderBlocksTokens.semanticColor.core.foreground.neutral.default,textTransform:"uppercase",marginBottom:11,letterSpacing:.8},indicatorContainer:{display:"flex",flexDirection:"row",listStyleType:"none",margin:"unset",paddingInlineStart:"unset",flexWrap:"wrap"},indicator:{width:24,height:24},indicatorButton:{width:"100%",height:"100%",display:"flex",flexWrap:"wrap",placeContent:"center",cursor:"pointer",":focus":{outline:"none"}},indicatorDot:{boxSizing:"content-box",width:10,height:10,borderRadius:wonderBlocksTokens.border.radius.radius_full,borderWidth:wonderBlocksTokens.border.width.medium,borderColor:wonderBlocksTokens.semanticColor.core.border.instructive.default,borderStyle:"solid"},indicatorDotFocused:{outlineColor:wonderBlocksTokens.semanticColor.focus.outer,outlineStyle:"solid",outlineWidth:wonderBlocksTokens.border.width.medium,outlineOffset:wonderBlocksTokens.border.width.medium,boxShadow:`0 0 0 ${wonderBlocksTokens.border.width.medium} ${wonderBlocksTokens.semanticColor.focus.inner}`},indicatorDotActive:{backgroundColor:wonderBlocksTokens.semanticColor.core.foreground.instructive.default,borderColor:wonderBlocksTokens.semanticColor.core.foreground.instructive.default},container:{borderTop:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderBottom:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,backgroundColor:wonderBlocksTokens.semanticColor.core.background.base.subtle,marginLeft:negativePhoneMargin,marginRight:negativePhoneMargin,paddingBottom:phoneMargin,paddingLeft:phoneMargin,paddingRight:phoneMargin,paddingTop:10,width:"auto"}});
|
|
1838
1837
|
|
|
1839
|
-
class ButtonGroup extends React__namespace.Component{componentWillUnmount(){this.container=null;}focus(){if(this.container){this.container.focus();return true}}toggleSelect(newValue){const value=this.props.value;if(this.props.allowEmpty){this.props.onChange(value!==newValue?newValue:null);}else {this.props.onChange(newValue);}}render(){const value=this.props.value;const buttons=this.props.buttons.map((button,i)=>{return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",disabled:this.props.disabled,className:aphrodite.css(styles$
|
|
1838
|
+
class ButtonGroup extends React__namespace.Component{componentWillUnmount(){this.container=null;}focus(){if(this.container){this.container.focus();return true}}toggleSelect(newValue){const value=this.props.value;if(this.props.allowEmpty){this.props.onChange(value!==newValue?newValue:null);}else {this.props.onChange(newValue);}}render(){const value=this.props.value;const buttons=this.props.buttons.map((button,i)=>{return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",disabled:this.props.disabled,className:aphrodite.css(styles$g.buttonStyle,button.value===value&&styles$g.selectedStyle,button.value===value&&this.props.selectedButtonStyle,this.props.disabled&&styles$g.disabledStyle),onClick:()=>this.toggleSelect(button.value),children:button.content||""+button.value},""+i)});const outerStyle={display:"inline-block"};return jsxRuntimeExports.jsx("div",{style:outerStyle,ref:node=>this.container=node,children:buttons})}}ButtonGroup.defaultProps={value:null,allowEmpty:true};const styles$g=aphrodite.StyleSheet.create({buttonStyle:{backgroundColor:"white",border:"1px solid #ccc",borderLeft:"0",cursor:"pointer",margin:"0",padding:"5px 10px",position:"relative",":first-child":{borderLeft:"1px solid #ccc",borderTopLeftRadius:"3px",borderBottomLeftRadius:"3px"},":last-child":{borderRight:"1px solid #ccc",borderTopRightRadius:"3px",borderBottomRightRadius:"3px"},":hover":{backgroundColor:"#ccc"},":focus":{zIndex:2}},selectedStyle:{backgroundColor:"#ddd"},disabledStyle:{cursor:"not-allowed",backgroundColor:wonderBlocksTokens.semanticColor.core.background.disabled.default,color:wonderBlocksTokens.semanticColor.core.foreground.disabled.strong,":hover":{backgroundColor:wonderBlocksTokens.semanticColor.core.background.disabled.default}}});
|
|
1840
1839
|
|
|
1841
1840
|
const getPromptJSON$g=widgetData=>{const{userInput}=widgetData;const{type,coords}=userInput;const input={type,coords};if(userInput.type==="logarithm"||userInput.type==="exponential"){input["asymptote"]=userInput.asymptote;}return {type:"grapher",options:{availableTypes:widgetData.availableTypes,range:widgetData.graph.range,labels:widgetData.graph.labels,tickStep:widgetData.graph.step,gridStep:widgetData.graph.gridStep,snapStep:widgetData.graph.snapStep,backgroundImageUrl:widgetData.graph.backgroundImage.url},userInput:input}};
|
|
1842
1841
|
|
|
@@ -1860,7 +1859,7 @@ function srFormatNumber(a,locale,maximumFractionDigits){const piBasedNumber=getP
|
|
|
1860
1859
|
|
|
1861
1860
|
const getIntersectionOfRayWithBox=(initialPoint,throughPoint,box)=>{const[[xMin,xMax],[yMin,yMax]]=box;const[aX,aY]=initialPoint;const[bX,bY]=throughPoint;const yDiff=bY-aY;const xDiff=bX-aX;const slope=yDiff/xDiff;const inverseSlope=1/slope;const xExtreme=xDiff<0?xMin:xMax;const yExtreme=yDiff<0?yMin:yMax;const yAtXExtreme=aY+(xExtreme-aX)*slope;const xAtYExtreme=aX+(yExtreme-aY)*inverseSlope;switch(true){case isBetween(yAtXExtreme,yMin,yMax):return [xExtreme,yAtXExtreme];case isBetween(xAtYExtreme,xMin,xMax):return [xAtYExtreme,yExtreme];default:return [xExtreme,yExtreme]}};function isBetween(x,low,high){return x>=low&&x<=high}function getArrayWithoutDuplicates(array){const returnArray=[];for(const coordPair of array){if(!returnArray.some(([x,y])=>x===coordPair[0]&&y===coordPair[1])){returnArray.push(coordPair);}}return returnArray}function getSlopeStringForLine(line,strings){const slope=(line[1][1]-line[0][1])/(line[1][0]-line[0][0]);if(!Number.isFinite(slope)){return strings.srLinearGraphSlopeVertical}if(slope===0){return strings.srLinearGraphSlopeHorizontal}return slope>0?strings.srLinearGraphSlopeIncreasing:strings.srLinearGraphSlopeDecreasing}function getInterceptStringForLine(line,strings,locale){const slope=(line[1][1]-line[0][1])/(line[1][0]-line[0][0]);const xIntercept=(0-line[0][1])/slope+line[0][0];const yIntercept=line[0][1]-slope*line[0][0];const overlapsXAxis=line[0][1]===0&&line[1][1]===0;const overlapsYAxis=line[0][0]===0&&line[1][0]===0;const hasXIntercept=Number.isFinite(xIntercept)&&!overlapsXAxis;const hasYIntercept=Number.isFinite(yIntercept)&&!overlapsYAxis;if(hasXIntercept&&hasYIntercept){return xIntercept===0&&yIntercept===0?strings.srLinearGraphOriginIntercept:strings.srLinearGraphBothIntercepts({xIntercept:srFormatNumber(xIntercept,locale),yIntercept:srFormatNumber(yIntercept,locale)})}return hasXIntercept?strings.srLinearGraphXOnlyIntercept({xIntercept:srFormatNumber(xIntercept,locale)}):strings.srLinearGraphYOnlyIntercept({yIntercept:srFormatNumber(yIntercept,locale)})}function getQuadraticXIntercepts(a,b,c){if(a===0){if(b===0){return []}return [-c/b]}const discriminant=b*b-4*a*c;if(discriminant<0){return []}const x1=(-b+Math.sqrt(discriminant))/(2*a);const x2=(-b-Math.sqrt(discriminant))/(2*a);if(x1===x2){return [x1]}return [x1,x2]}function getQuadraticVertex(coeffs){const[a,b,c]=coeffs;if(a===0){return undefined}return [-b/(2*a),c-b*b/(4*a)]}function getAngleFromPoints(points,i){if(i<0||i>=points.length||!Number.isInteger(i)){return null}if(points.length<3){return null}const point=points.at(i);const pt1=points.at(i-1);const pt2=points[(i+1)%points.length];if(!point||!pt1||!pt2){return null}const a=mafs.vec.dist(point,pt1);const b=mafs.vec.dist(point,pt2);const c=mafs.vec.dist(pt1,pt2);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);return angle}function getSideLengthsFromPoints(points,i,isPolygonOpen){if(i<0||i>=points.length||!Number.isInteger(i)){return []}if(points.length<2){return []}const returnArray=[];const point=points[i];const point1Index=i===0?points.length-1:i-1;const point1=points[point1Index];const side1=i!==point1Index?mafs.vec.dist(point,point1):null;if(side1&&!(isPolygonOpen&&i===0)){returnArray.push({pointIndex:point1Index,sideLength:side1});}const point2Index=(i+1)%points.length;const point2=points[point2Index];const side2=i!==point2Index&&point2Index!==point1Index?mafs.vec.dist(point,point2):null;if(side2&&!(isPolygonOpen&&i===points.length-1)){returnArray.push({pointIndex:point2Index,sideLength:side2});}return returnArray}function getPolygonSideString(sideLength,pointIndex,strings,locale){return Number.isInteger(sideLength)?strings.srPolygonSideLength({pointNum:pointIndex+1,length:`${sideLength}`}):strings.srPolygonSideLengthApprox({pointNum:pointIndex+1,length:srFormatNumber(sideLength,locale,1)})}function calculateScaledRadius(range){const[[xMin,xMax],[yMin,yMax]]=range;const xSpan=xMax-xMin;const ySpan=yMax-yMin;const minSpan=Math.min(xSpan,ySpan);return minSpan*.06}function getAsymptoteGraphKeyboardConstraint(coords,snapStep,pointIndex,isValidPosition){const coordToBeMoved=coords[pointIndex];const movePointWithConstraint=moveFunc=>{let movedCoord=moveFunc(coordToBeMoved);for(let i=0;i<3&&!isValidPosition(movedCoord);i++){movedCoord=moveFunc(movedCoord);}if(!isValidPosition(movedCoord)){return coordToBeMoved}return movedCoord};return {up:movePointWithConstraint(coord=>mafs.vec.add(coord,[0,snapStep[1]])),down:movePointWithConstraint(coord=>mafs.vec.sub(coord,[0,snapStep[1]])),left:movePointWithConstraint(coord=>mafs.vec.sub(coord,[snapStep[0],0])),right:movePointWithConstraint(coord=>mafs.vec.add(coord,[snapStep[0],0]))}}function getAsymptoteHandleCoord(orientation,range,asymptote){if(orientation==="horizontal"){const midX=(range[0][0]+range[0][1])/2;return [midX,asymptote]}const midY=(range[1][0]+range[1][1])/2;return [asymptote,midY]}function skipAsymptoteKeyboardOverPoint(proposed,currentAsymptote,coords,handleCoord,snapStep,orientation){const snapped=snap(snapStep,proposed);const moveAxis=orientation==="horizontal"?1:0;const pinAxis=orientation==="horizontal"?0:1;const step=snapStep[moveAxis];const dir=Math.sign(snapped[moveAxis]-currentAsymptote);if(dir===0){return snapped}const pinValue=handleCoord[pinAxis];const isForbidden=v=>coords.some(c=>c[pinAxis]===pinValue&&c[moveAxis]===v);let value=snapped[moveAxis];for(let i=0;i<3&&isForbidden(value);i++){value+=dir*step;}const result=[0,0];result[moveAxis]=value;result[pinAxis]=snapped[pinAxis];return result}const getQuadraticCoefficients$2=coords=>{const p1=coords[0];const p2=coords[1];const p3=coords[2];const denom=(p1[0]-p2[0])*(p1[0]-p3[0])*(p2[0]-p3[0]);if(denom===0){return}const a=(p3[0]*(p2[1]-p1[1])+p2[0]*(p1[1]-p3[1])+p1[0]*(p3[1]-p2[1]))/denom;const b=(p3[0]*p3[0]*(p1[1]-p2[1])+p2[0]*p2[0]*(p3[1]-p1[1])+p1[0]*p1[0]*(p2[1]-p3[1]))/denom;const c=(p2[0]*p3[0]*(p2[0]-p3[0])*p1[1]+p3[0]*p1[0]*(p3[0]-p1[0])*p2[1]+p1[0]*p2[0]*(p1[0]-p2[0])*p3[1])/denom;return [a,b,c]};function getLengthOfSegment(segment){return kmath.point.distanceToPoint(...segment)}function getAbsoluteValueCoefficients$1(coords){const p1=coords[0];const p2=coords[1];const denom=p2[X]-p1[X];const num=p2[Y]-p1[Y];let m=Math.abs(num/denom);if(p2[Y]<p1[Y]){m=-m;}return {m,h:p1[X],v:p1[Y]}}
|
|
1862
1861
|
|
|
1863
|
-
const{getClockwiseAngle: getClockwiseAngle$2}=kmath.angles;const{getSinusoidCoefficients: getSinusoidCoefficients$1,getTangentCoefficients: getTangentCoefficients$1,getQuadraticCoefficients: getQuadraticCoefficients$1,getExponentialCoefficients: getExponentialCoefficients$3,getLogarithmCoefficients: getLogarithmCoefficients$3}=kmath.coefficients;const{getLineEquation,getLineIntersectionString,magnitude: magnitude$2,vector: vector$2}=kmath.geometry;const UNLIMITED="unlimited";function numSteps(range,step){return Math.floor((range[1]-range[0])/step)}const makeInvalidTypeError=(functionName,graphType)=>{return new perseusCore.PerseusError(`${functionName} called but current graph type is not a '${graphType}'`,perseusCore.Errors.NotAllowed,{metadata:{graphType}})};function getLineCoords$1(graph,props){return graph.coords||pointsFromNormalized$1(props,[[.25,.75],[.75,.75]])}function getPointCoords$1(graph,props){const numPoints=graph.numPoints||1;let coords=graph.coords;if(coords){return coords}switch(numPoints){case 1:coords=[graph.coord||[0,0]];break;case 2:coords=[[-5,0],[5,0]];break;case 3:coords=[[-5,0],[0,0],[5,0]];break;case 4:coords=[[-6,0],[-2,0],[2,0],[6,0]];break;case 5:coords=[[-6,0],[-3,0],[0,0],[3,0],[6,0]];break;case 6:coords=[[-5,0],[-3,0],[-1,0],[1,0],[3,0],[5,0]];break;case UNLIMITED:coords=[];break}const range=[[-10,10],[-10,10]];const newCoords=normalizeCoords$1(coords,range);return pointsFromNormalized$1(props,newCoords)}function getLinearSystemCoords$1(graph,props){return graph.coords||___default.default.map([[[.25,.75],[.75,.75]],[[.25,.25],[.75,.25]]],coords=>{return pointsFromNormalized$1(props,coords)})}function getPolygonCoords$1(graph,props){if(graph.type!=="polygon"){throw makeInvalidTypeError("toggleShowSides","polygon")}let coords=graph.coords;if(coords){return coords}const n=graph.numSides||3;if(n===UNLIMITED){coords=[];}else {const angle=2*Math.PI/n;const offset=(1/n-1/2)*Math.PI;const radius=graph.snapTo==="sides"?Math.sqrt(3)/3*7:4;coords=___default.default.times(n,function(i){return [radius*Math.cos(i*angle+offset),radius*Math.sin(i*angle+offset)]});}const ranges=[[-10,10],[-10,10]];coords=normalizeCoords$1(coords,ranges);const snapToGrid=!___default.default.contains(["angles","sides"],graph.snapTo);coords=pointsFromNormalized$1(props,coords,!snapToGrid);return coords}function getSegmentCoords$1(graph,props){const coords=graph.coords;if(coords){return coords}const n=graph.numSegments||1;const ys={1:[5],2:[5,-5],3:[5,0,-5],4:[6,2,-2,-6],5:[6,3,0,-3,-6],6:[5,3,1,-1,-3,-5]}[n];const range=[[-10,10],[-10,10]];return ys.map(function(y){let segment=[[-5,y],[5,y]];segment=normalizeCoords$1(segment,range);segment=pointsFromNormalized$1(props,segment);return segment})}function getAngleCoords$1(graph,props){let coords=graph.coords;if(coords){return coords}const snap=graph.snapDegrees||1;let angle=snap;while(angle<20){angle+=snap;}angle=angle*Math.PI/180;const offset=(graph.angleOffsetDeg||0)*Math.PI/180;coords=pointsFromNormalized$1(props,[[.85,.5],[.5,.5]]);const radius=magnitude$2(vector$2(...coords));coords[0]=[coords[1][0]+radius*Math.cos(offset),coords[1][1]+radius*Math.sin(offset)];coords[2]=[coords[1][0]+radius*Math.cos(angle+offset),coords[1][1]+radius*Math.sin(angle+offset)];return coords}function normalizeCoords$1(coordsList,ranges){return ___default.default.map(coordsList,function(coords){return ___default.default.map(coords,function(coord,i){const extent=ranges[i][1]-ranges[i][0];return (coord+ranges[i][1])/extent})})}function pointsFromNormalized$1(props,coordsList,noSnap){return ___default.default.map(coordsList,function(coords){return ___default.default.map(coords,function(coord,i){const range=props.range[i];if(noSnap){return range[0]+(range[1]-range[0])*coord}const step=props.step[i];const nSteps=numSteps(range,step);const tick=Math.round(coord*nSteps);return range[0]+step*tick})})}function getNoneEquationString(){return ""}function getLinearEquationString(props){const coords=getLineCoords$1(props.userInput,props);if(perseusCore.approximateEqual(coords[0][0],coords[1][0])){return "x = "+coords[0][0].toFixed(3)}const m=(coords[1][1]-coords[0][1])/(coords[1][0]-coords[0][0]);const b=coords[0][1]-m*coords[0][0];if(perseusCore.approximateEqual(m,0)){return "y = "+b.toFixed(3)}return "y = "+m.toFixed(3)+"x + "+b.toFixed(3)}function getCurrentQuadraticCoefficients(props){const coords=props.userInput.coords||defaultQuadraticCoords(props);return getQuadraticCoefficients$1(coords)}function defaultQuadraticCoords(props){const coords=[[.25,.75],[.5,.25],[.75,.75]];return pointsFromNormalized$1(props,coords)}function getQuadraticEquationString(props){const coeffs=getCurrentQuadraticCoefficients(props);return "y = "+coeffs[0].toFixed(3)+"x^2 + "+coeffs[1].toFixed(3)+"x + "+coeffs[2].toFixed(3)}function getCurrentSinusoidCoefficients(props){const coords=props.userInput.coords||defaultSinusoidCoords(props);return getSinusoidCoefficients$1(coords)}function defaultSinusoidCoords(props){const coords=[[.5,.5],[.65,.6]];return pointsFromNormalized$1(props,coords)}function getSinusoidEquationString(props){const coeffs=getCurrentSinusoidCoefficients(props);return "y = "+coeffs[0].toFixed(3)+"sin("+coeffs[1].toFixed(3)+"x - "+coeffs[2].toFixed(3)+") + "+coeffs[3].toFixed(3)}function defaultExponentialCoords(props){const coords=[[.5,.55],[.75,.75]];return pointsFromNormalized$1(props,coords,true)}function getExponentialEquationString(props){const coords=props.userInput.coords||defaultExponentialCoords(props);const asymptote=props.userInput.asymptote??0;const coeffs=getExponentialCoefficients$3(coords,asymptote);if(coeffs==null){return "y = e^x"}return "y = "+coeffs.a.toFixed(3)+"e^("+coeffs.b.toFixed(3)+"x) + "+coeffs.c.toFixed(3)}function defaultLogarithmCoords(props){const coords=[[.55,.55],[.75,.75]];return pointsFromNormalized$1(props,coords,true)}function getLogarithmEquationString(props){const coords=props.userInput.coords||defaultLogarithmCoords(props);const asymptote=props.userInput.asymptote??0;const coeffs=getLogarithmCoefficients$3(coords,asymptote);if(coeffs==null){return "y = ln(x)"}const cStr=coeffs.c===0?"x":coeffs.c<0?"x - "+Math.abs(coeffs.c).toFixed(3):"x + "+coeffs.c.toFixed(3);return "y = "+coeffs.a.toFixed(3)+"ln("+coeffs.b.toFixed(3)+cStr+")"}function getAbsoluteValueEquationString(props){const userInput=props.userInput;if(userInput.type!=="absolute-value"||!userInput.coords){return ""}const{m,h,v}=getAbsoluteValueCoefficients$1(userInput.coords);if(!Number.isFinite(m)){return ""}return "y = "+m.toFixed(3)+"|x - "+h.toFixed(3)+"| + "+v.toFixed(3)}function getCurrentTangentCoefficients(props){const coords=props.userInput.coords||defaultTangentCoords(props);return getTangentCoefficients$1(coords)}function defaultTangentCoords(props){const coords=[[.5,.5],[.75,.75]];return pointsFromNormalized$1(props,coords)}function getTangentEquationString(props){const coeffs=getCurrentTangentCoefficients(props);return "y = "+coeffs[0].toFixed(3)+"tan("+coeffs[1].toFixed(3)+"x - "+coeffs[2].toFixed(3)+") + "+coeffs[3].toFixed(3)}function getCircleEquationString(props){const graph=props.userInput;const center=graph.center||[0,0];const radius=graph.radius||2;return "center ("+center[0]+", "+center[1]+"), radius "+radius}function getLinearSystemEquationString(props){const coords=getLinearSystemCoords$1(props.userInput,props);return "\n"+getLineEquation(coords[0][0],coords[0][1])+"\n"+getLineEquation(coords[1][0],coords[1][1])+"\n"+getLineIntersectionString(coords[0],coords[1])}function getPointEquationString(props){if(props.userInput.type!=="point"){throw makeInvalidTypeError("getPointEquationString","point")}const coords=getPointCoords$1(props.userInput,props);return coords.map(function(coord){return "("+coord[0]+", "+coord[1]+")"}).join(", ")}function getSegmentEquationString(props){if(props.userInput.type!=="segment"){throw makeInvalidTypeError("getSegmentEquationString","segment")}const segments=getSegmentCoords$1(props.userInput,props);return ___default.default.map(segments,function(segment){return "["+___default.default.map(segment,function(coord){return "("+coord.join(", ")+")"}).join(" ")+"]"}).join(" ")}function getRayEquationString(props){if(props.userInput.type!=="ray"){throw makeInvalidTypeError("createPointForPolygonType","ray")}const coords=getLineCoords$1(props.userInput,props);const a=coords[0];const b=coords[1];let eq=getLinearEquationString(props);if(a[0]>b[0]){eq+=" (for x <= "+a[0].toFixed(3)+")";}else if(a[0]<b[0]){eq+=" (for x >= "+a[0].toFixed(3)+")";}else if(a[1]>b[1]){eq+=" (for y <= "+a[1].toFixed(3)+")";}else {eq+=" (for y >= "+a[1].toFixed(3)+")";}return eq}function getPolygonEquationString(props){if(props.userInput.type!=="polygon"){throw makeInvalidTypeError("getPolygonEquationString","polygon")}const coords=getPolygonCoords$1(props.userInput,props);return ___default.default.map(coords,function(coord){return "("+coord.join(", ")+")"}).join(" ")}function getAngleEquationString(props){if(props.userInput.type!=="angle"){throw makeInvalidTypeError("getAngleEquationString","angle")}const coords=getAngleCoords$1(props.userInput,props);const allowReflexAngles=props.userInput.allowReflexAngles;const angle=getClockwiseAngle$2(coords,allowReflexAngles);return angle.toFixed(0)+"° angle"+" at ("+coords[1].join(", ")+")"}function getVectorEquationString(props){if(props.userInput.type!=="vector"){throw makeInvalidTypeError("getVectorEquationString","vector")}const coords=props.userInput.coords;if(!coords){return ""}const[tail,tip]=coords;const dx=tip[0]-tail[0];const dy=tip[1]-tail[1];return `\u27E8${dx.toFixed(3)}, ${dy.toFixed(3)}\u27E9`}function getEquationString$1(props){const type=props.userInput.type;switch(type){case "none":return getNoneEquationString();case "linear":return getLinearEquationString(props);case "quadratic":return getQuadraticEquationString(props);case "sinusoid":return getSinusoidEquationString(props);case "circle":return getCircleEquationString(props);case "linear-system":return getLinearSystemEquationString(props);case "point":return getPointEquationString(props);case "segment":return getSegmentEquationString(props);case "ray":return getRayEquationString(props);case "polygon":return getPolygonEquationString(props);case "angle":return getAngleEquationString(props);case "absolute-value":return getAbsoluteValueEquationString(props);case "exponential":return getExponentialEquationString(props);case "tangent":return getTangentEquationString(props);case "logarithm":return getLogarithmEquationString(props);case "vector":return getVectorEquationString(props);default:throw new wonderStuffCore.UnreachableCaseError(type)}}
|
|
1862
|
+
const{getClockwiseAngle: getClockwiseAngle$2}=kmath.angles;const{getSinusoidCoefficients: getSinusoidCoefficients$1,getTangentCoefficients: getTangentCoefficients$1,getQuadraticCoefficients: getQuadraticCoefficients$1,getExponentialCoefficients: getExponentialCoefficients$3,getLogarithmCoefficients: getLogarithmCoefficients$3}=kmath.coefficients;const{getLineEquation,getLineIntersectionString,magnitude: magnitude$2,vector: vector$2}=kmath.geometry;const UNLIMITED="unlimited";function numSteps(range,step){return Math.floor((range[1]-range[0])/step)}const makeInvalidTypeError=(functionName,graphType)=>{return new perseusCore.PerseusError(`${functionName} called but current graph type is not a '${graphType}'`,perseusCore.Errors.NotAllowed,{metadata:{graphType}})};function getLineCoords$1(graph,props){return graph.coords||pointsFromNormalized$1(props,[[.25,.75],[.75,.75]])}function getPointCoords$1(graph,props){const numPoints=graph.numPoints||1;let coords=graph.coords;if(coords){return coords}switch(numPoints){case 1:coords=[graph.coord||[0,0]];break;case 2:coords=[[-5,0],[5,0]];break;case 3:coords=[[-5,0],[0,0],[5,0]];break;case 4:coords=[[-6,0],[-2,0],[2,0],[6,0]];break;case 5:coords=[[-6,0],[-3,0],[0,0],[3,0],[6,0]];break;case 6:coords=[[-5,0],[-3,0],[-1,0],[1,0],[3,0],[5,0]];break;case UNLIMITED:coords=[];break}const range=[[-10,10],[-10,10]];const newCoords=normalizeCoords$1(coords,range);return pointsFromNormalized$1(props,newCoords)}function getLinearSystemCoords$1(graph,props){const defaultCoords=[[[.25,.75],[.75,.75]],[[.25,.25],[.75,.25]]];return graph.coords||defaultCoords.map(coords=>{return pointsFromNormalized$1(props,coords)})}function getPolygonCoords$1(graph,props){if(graph.type!=="polygon"){throw makeInvalidTypeError("toggleShowSides","polygon")}let coords=graph.coords;if(coords){return coords}const n=graph.numSides||3;if(n===UNLIMITED){coords=[];}else {const angle=2*Math.PI/n;const offset=(1/n-1/2)*Math.PI;const radius=graph.snapTo==="sides"?Math.sqrt(3)/3*7:4;coords=___default.default.times(n,function(i){return [radius*Math.cos(i*angle+offset),radius*Math.sin(i*angle+offset)]});}const ranges=[[-10,10],[-10,10]];coords=normalizeCoords$1(coords,ranges);const snapToGrid=graph.snapTo!=="angles"&&graph.snapTo!=="sides";coords=pointsFromNormalized$1(props,coords,!snapToGrid);return coords}function getSegmentCoords$1(graph,props){const coords=graph.coords;if(coords){return coords}const n=graph.numSegments||1;const ys={1:[5],2:[5,-5],3:[5,0,-5],4:[6,2,-2,-6],5:[6,3,0,-3,-6],6:[5,3,1,-1,-3,-5]}[n];const range=[[-10,10],[-10,10]];return ys.map(function(y){let segment=[[-5,y],[5,y]];segment=normalizeCoords$1(segment,range);segment=pointsFromNormalized$1(props,segment);return segment})}function getAngleCoords$1(graph,props){let coords=graph.coords;if(coords){return coords}const snap=graph.snapDegrees||1;let angle=snap;while(angle<20){angle+=snap;}angle=angle*Math.PI/180;const offset=(graph.angleOffsetDeg||0)*Math.PI/180;coords=pointsFromNormalized$1(props,[[.85,.5],[.5,.5]]);const radius=magnitude$2(vector$2(...coords));coords[0]=[coords[1][0]+radius*Math.cos(offset),coords[1][1]+radius*Math.sin(offset)];coords[2]=[coords[1][0]+radius*Math.cos(angle+offset),coords[1][1]+radius*Math.sin(angle+offset)];return coords}function normalizeCoords$1(coordsList,ranges){return coordsList.map(function(coords){return coords.map(function(coord,i){const extent=ranges[i][1]-ranges[i][0];return (coord+ranges[i][1])/extent})})}function pointsFromNormalized$1(props,coordsList,noSnap){return coordsList.map(function(coords){return coords.map(function(coord,i){const range=props.range[i];if(noSnap){return range[0]+(range[1]-range[0])*coord}const step=props.step[i];const nSteps=numSteps(range,step);const tick=Math.round(coord*nSteps);return range[0]+step*tick})})}function getNoneEquationString(){return ""}function getLinearEquationString(props){const coords=getLineCoords$1(props.userInput,props);if(perseusCore.approximateEqual(coords[0][0],coords[1][0])){return "x = "+coords[0][0].toFixed(3)}const m=(coords[1][1]-coords[0][1])/(coords[1][0]-coords[0][0]);const b=coords[0][1]-m*coords[0][0];if(perseusCore.approximateEqual(m,0)){return "y = "+b.toFixed(3)}return "y = "+m.toFixed(3)+"x + "+b.toFixed(3)}function getCurrentQuadraticCoefficients(props){const coords=props.userInput.coords||defaultQuadraticCoords(props);return getQuadraticCoefficients$1(coords)}function defaultQuadraticCoords(props){const coords=[[.25,.75],[.5,.25],[.75,.75]];return pointsFromNormalized$1(props,coords)}function getQuadraticEquationString(props){const coeffs=getCurrentQuadraticCoefficients(props);return "y = "+coeffs[0].toFixed(3)+"x^2 + "+coeffs[1].toFixed(3)+"x + "+coeffs[2].toFixed(3)}function getCurrentSinusoidCoefficients(props){const coords=props.userInput.coords||defaultSinusoidCoords(props);return getSinusoidCoefficients$1(coords)}function defaultSinusoidCoords(props){const coords=[[.5,.5],[.65,.6]];return pointsFromNormalized$1(props,coords)}function getSinusoidEquationString(props){const coeffs=getCurrentSinusoidCoefficients(props);return "y = "+coeffs[0].toFixed(3)+"sin("+coeffs[1].toFixed(3)+"x - "+coeffs[2].toFixed(3)+") + "+coeffs[3].toFixed(3)}function defaultExponentialCoords(props){const coords=[[.5,.55],[.75,.75]];return pointsFromNormalized$1(props,coords,true)}function getExponentialEquationString(props){const coords=props.userInput.coords||defaultExponentialCoords(props);const asymptote=props.userInput.asymptote??0;const coeffs=getExponentialCoefficients$3(coords,asymptote);if(coeffs==null){return "y = e^x"}return "y = "+coeffs.a.toFixed(3)+"e^("+coeffs.b.toFixed(3)+"x) + "+coeffs.c.toFixed(3)}function defaultLogarithmCoords(props){const coords=[[.55,.55],[.75,.75]];return pointsFromNormalized$1(props,coords,true)}function getLogarithmEquationString(props){const coords=props.userInput.coords||defaultLogarithmCoords(props);const asymptote=props.userInput.asymptote??0;const coeffs=getLogarithmCoefficients$3(coords,asymptote);if(coeffs==null){return "y = ln(x)"}const cStr=coeffs.c===0?"x":coeffs.c<0?"x - "+Math.abs(coeffs.c).toFixed(3):"x + "+coeffs.c.toFixed(3);return "y = "+coeffs.a.toFixed(3)+"ln("+coeffs.b.toFixed(3)+cStr+")"}function getAbsoluteValueEquationString(props){const userInput=props.userInput;if(userInput.type!=="absolute-value"||!userInput.coords){return ""}const{m,h,v}=getAbsoluteValueCoefficients$1(userInput.coords);if(!Number.isFinite(m)){return ""}return "y = "+m.toFixed(3)+"|x - "+h.toFixed(3)+"| + "+v.toFixed(3)}function getCurrentTangentCoefficients(props){const coords=props.userInput.coords||defaultTangentCoords(props);return getTangentCoefficients$1(coords)}function defaultTangentCoords(props){const coords=[[.5,.5],[.75,.75]];return pointsFromNormalized$1(props,coords)}function getTangentEquationString(props){const coeffs=getCurrentTangentCoefficients(props);return "y = "+coeffs[0].toFixed(3)+"tan("+coeffs[1].toFixed(3)+"x - "+coeffs[2].toFixed(3)+") + "+coeffs[3].toFixed(3)}function getCircleEquationString(props){const graph=props.userInput;const center=graph.center||[0,0];const radius=graph.radius||2;return "center ("+center[0]+", "+center[1]+"), radius "+radius}function getLinearSystemEquationString(props){const coords=getLinearSystemCoords$1(props.userInput,props);return "\n"+getLineEquation(coords[0][0],coords[0][1])+"\n"+getLineEquation(coords[1][0],coords[1][1])+"\n"+getLineIntersectionString(coords[0],coords[1])}function getPointEquationString(props){if(props.userInput.type!=="point"){throw makeInvalidTypeError("getPointEquationString","point")}const coords=getPointCoords$1(props.userInput,props);return coords.map(function(coord){return "("+coord[0]+", "+coord[1]+")"}).join(", ")}function getSegmentEquationString(props){if(props.userInput.type!=="segment"){throw makeInvalidTypeError("getSegmentEquationString","segment")}const segments=getSegmentCoords$1(props.userInput,props);return segments.map(function(segment){return "["+segment.map(function(coord){return "("+coord.join(", ")+")"}).join(" ")+"]"}).join(" ")}function getRayEquationString(props){if(props.userInput.type!=="ray"){throw makeInvalidTypeError("createPointForPolygonType","ray")}const coords=getLineCoords$1(props.userInput,props);const a=coords[0];const b=coords[1];let eq=getLinearEquationString(props);if(a[0]>b[0]){eq+=" (for x <= "+a[0].toFixed(3)+")";}else if(a[0]<b[0]){eq+=" (for x >= "+a[0].toFixed(3)+")";}else if(a[1]>b[1]){eq+=" (for y <= "+a[1].toFixed(3)+")";}else {eq+=" (for y >= "+a[1].toFixed(3)+")";}return eq}function getPolygonEquationString(props){if(props.userInput.type!=="polygon"){throw makeInvalidTypeError("getPolygonEquationString","polygon")}const coords=getPolygonCoords$1(props.userInput,props);return coords.map(function(coord){return "("+coord.join(", ")+")"}).join(" ")}function getAngleEquationString(props){if(props.userInput.type!=="angle"){throw makeInvalidTypeError("getAngleEquationString","angle")}const coords=getAngleCoords$1(props.userInput,props);const allowReflexAngles=props.userInput.allowReflexAngles;const angle=getClockwiseAngle$2(coords,allowReflexAngles);return angle.toFixed(0)+"° angle"+" at ("+coords[1].join(", ")+")"}function getVectorEquationString(props){if(props.userInput.type!=="vector"){throw makeInvalidTypeError("getVectorEquationString","vector")}const coords=props.userInput.coords;if(!coords){return ""}const[tail,tip]=coords;const dx=tip[0]-tail[0];const dy=tip[1]-tail[1];return `\u27E8${dx.toFixed(3)}, ${dy.toFixed(3)}\u27E9`}function getEquationString$1(props){const type=props.userInput.type;switch(type){case "none":return getNoneEquationString();case "linear":return getLinearEquationString(props);case "quadratic":return getQuadraticEquationString(props);case "sinusoid":return getSinusoidEquationString(props);case "circle":return getCircleEquationString(props);case "linear-system":return getLinearSystemEquationString(props);case "point":return getPointEquationString(props);case "segment":return getSegmentEquationString(props);case "ray":return getRayEquationString(props);case "polygon":return getPolygonEquationString(props);case "angle":return getAngleEquationString(props);case "absolute-value":return getAbsoluteValueEquationString(props);case "exponential":return getExponentialEquationString(props);case "tangent":return getTangentEquationString(props);case "logarithm":return getLogarithmEquationString(props);case "vector":return getVectorEquationString(props);default:throw new wonderStuffCore.UnreachableCaseError(type)}}
|
|
1864
1863
|
|
|
1865
1864
|
function getCustomPointLabel(pointLabels,index){const label=pointLabels?.[index];return typeof label==="string"&&label!==""?label:undefined}function resolvePointLabel(pointLabels,index){return getCustomPointLabel(pointLabels,index)??`${index+1}`}function buildPointAriaLabel(pointLabels,index,point,strings,locale){const customLabel=getCustomPointLabel(pointLabels,index);if(customLabel===undefined){return undefined}const x=srFormatNumber(point[0],locale);const y=srFormatNumber(point[1],locale);return strings.srPointAtCoordinates({pointLabel:customLabel,x,y})}function usePointAriaLabel(pointLabels){const{strings,locale}=usePerseusI18n();return (index,point)=>buildPointAriaLabel(pointLabels,index,point,strings,locale)}
|
|
1866
1865
|
|
|
@@ -1918,39 +1917,31 @@ const GraphBorder=({range,width,height,markings})=>{if(markings!=="graph"&&marki
|
|
|
1918
1917
|
|
|
1919
1918
|
const gridLineOptions=(props,axisIndex)=>{const lines=props.markings==="axes"?false:props.gridStep[axisIndex];return {axis:false,lines:lines,labels:false}};const axisLineOptions=props=>{return {axis:props.markings==="graph"||props.markings==="axes",lines:false,labels:false}};const Grid=props=>{return props.markings==="none"?null:jsxRuntimeExports.jsx(mafs.Coordinates.Cartesian,{xAxis:gridLineOptions(props,X),yAxis:gridLineOptions(props,Y)})};const Axes=props=>{return props.markings==="none"?null:jsxRuntimeExports.jsx(mafs.Coordinates.Cartesian,{xAxis:axisLineOptions(props),yAxis:axisLineOptions(props)})};
|
|
1920
1919
|
|
|
1921
|
-
const VisibleIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",className:aphrodite.css(styles$
|
|
1920
|
+
const VisibleIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",className:aphrodite.css(styles$f.icon),children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsx("path",{id:"a",d:"M7.401 10.035c-1.424.748-2.599 1.905-3.544 "+"3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 "+"12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 "+"1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-"+"3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 "+"0 0 0 0 6z"})}),jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[jsxRuntimeExports.jsx("path",{fill:"none",d:"M0 0h24v24H0z"}),jsxRuntimeExports.jsx("mask",{id:"b",fill:"#fff",children:jsxRuntimeExports.jsx("use",{href:"#a"})}),jsxRuntimeExports.jsx("use",{fill:"#fff",fillRule:"nonzero",href:"#a"}),jsxRuntimeExports.jsx("g",{fill:"#fff",mask:"url(#b)",children:jsxRuntimeExports.jsx("path",{d:"M0 0h24v24H0z"})})]})]});const HiddenIcon=()=>jsxRuntimeExports.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",className:aphrodite.css(styles$f.icon),children:[jsxRuntimeExports.jsx("defs",{children:jsxRuntimeExports.jsx("path",{id:"a",d:"M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 "+"7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 "+"1.028c-.945-1.574-2.12-2.73-3.544-3.48.258."+"604.401 1.268.401 1.966 0 1.02-.305 "+"1.967-.828 2.757l2.535 2.536a1 1 0 0 "+"1-1.414 1.414l-12-12a1 1 0 0 1 "+"1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 "+"0-4.001-4.001l4 4.001zM6.072 8.486l2.976 "+"2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 "+"0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 "+"3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 "+"2.363-3.085 3.929-4z"})}),jsxRuntimeExports.jsxs("g",{fill:"none",fillRule:"evenodd",children:[jsxRuntimeExports.jsx("path",{fill:"none",d:"M0 0h24v24H0z"}),jsxRuntimeExports.jsx("mask",{id:"b",fill:"#fff",children:jsxRuntimeExports.jsx("use",{href:"#a"})}),jsxRuntimeExports.jsx("use",{fill:"#fff",fillRule:"nonzero",href:"#a"}),jsxRuntimeExports.jsx("g",{fill:"#fff",mask:"url(#b)",children:jsxRuntimeExports.jsx("path",{d:"M0 0h24v24H0z"})})]})]});const HUD=({message,enabled,onClick,fixedPosition=true})=>{let state;let icon;if(enabled){state=styles$f.enabled;icon=jsxRuntimeExports.jsx(VisibleIcon,{});}else {state=styles$f.disabled;icon=jsxRuntimeExports.jsx(HiddenIcon,{});}return jsxRuntimeExports.jsxs("button",{className:aphrodite.css(styles$f.hud,fixedPosition&&styles$f.hudFixedPosition,state),onClick:e=>{onClick();},children:[icon,message]})};const styles$f=aphrodite.StyleSheet.create({hud:{boxSizing:"border-box",height:36,padding:"9px 16px",borderRadius:18,fontFamily:boldFontFamily,fontSize:"15px",lineHeight:"18px",color:white,userSelect:"none",borderWidth:0},hudFixedPosition:{bottom:20,position:"fixed",right:20,zIndex:1},icon:{width:24,height:24,marginRight:8,marginTop:-3,verticalAlign:"middle"},enabled:{backgroundColor:warningColor,":hover":{backgroundColor:warningColorHover},":active":{backgroundColor:warningColorActive}},disabled:{backgroundColor:gray76,":hover":{backgroundColor:"#a1a5a9"},":active":{backgroundColor:gray68}}});
|
|
1922
1921
|
|
|
1923
1922
|
const BASE_ICON_SIZE=10;class Icon extends React__namespace.Component{render(){const{color,pathClassName,className,title,style,alt}=this.props;let{icon,size}=this.props;let units="";if(typeof icon==="string"){icon={path:icon,width:BASE_ICON_SIZE,height:BASE_ICON_SIZE};}if(typeof size!=="number"){size=1;units="em";}const height=size;const width=height/icon.height*icon.width;const xMin=0;const yMin=0;const focusable=!!this.props.focusable;return jsxRuntimeExports.jsxs("svg",{role:"img",alt:alt,"aria-label":title,"aria-hidden":title?null:true,className:className,style:style,focusable:focusable.toString(),width:width+units,height:height+units,viewBox:`${xMin} ${yMin} ${icon.width} ${icon.height}`,children:[!!title&&jsxRuntimeExports.jsx("title",{children:title}),jsxRuntimeExports.jsx("path",{className:pathClassName,fill:color,d:icon.path})]})}}Icon.defaultProps={color:"currentColor"};
|
|
1924
1923
|
|
|
1925
|
-
const InfoTipBase=props=>{return jsxRuntimeExports.jsx(Tooltip__default.default,{content:jsxRuntimeExports.jsx(wonderBlocksTypography.BodyText,{style:styles$f.body,children:props.children}),placement:"right",children:jsxRuntimeExports.jsx(wonderBlocksIcon.PhosphorIcon,{size:"small",icon:questionIcon__default.default,style:styles$f.spacingLeft})})};const styles$f=aphrodite.StyleSheet.create({spacingLeft:{marginInlineStart:wonderBlocksTokens.spacing.xxxSmall_4},body:{padding:wonderBlocksTokens.spacing.medium_16}});
|
|
1926
|
-
|
|
1927
|
-
class InfoTip extends React__namespace.Component{componentDidMount(){this.setState({didMount:true});}render(){if(this.state.didMount){return jsxRuntimeExports.jsx(InfoTipBase,{...this.props})}return jsxRuntimeExports.jsx("div",{})}constructor(...args){super(...args),this.state={didMount:false};}}
|
|
1928
|
-
|
|
1929
1924
|
class MultiButtonGroup extends React__namespace.Component{focus(){this.buttonContainerRef.current?.focus();return true}render(){const values=this.props.values||[];const buttons=this.props.buttons.map((button,i)=>{const selected=values.indexOf(button.value)>=0;return jsxRuntimeExports.jsx("button",{title:button.title,type:"button",id:""+i,ref:"button"+i,className:aphrodite.css(styles$e.buttonStyle,selected&&styles$e.selectedStyle),onClick:()=>this.toggleSelect(button.value),children:button.content||""+button.value},""+i)});const outerStyle={display:"inline-block"};return jsxRuntimeExports.jsx("div",{style:outerStyle,ref:this.buttonContainerRef,children:buttons})}constructor(...args){super(...args),this.buttonContainerRef=React__namespace.createRef(),this.toggleSelect=newValue=>{const values=(this.props.values||[]).slice(0);const allowEmpty=this.props.allowEmpty;if(values.indexOf(newValue)>=0&&(values.length>1||allowEmpty)){values.splice(values.indexOf(newValue),1);}else {if(values.indexOf(newValue)<0){values.push(newValue);}}this.props.onChange(values);};}}MultiButtonGroup.defaultProps={values:[],allowEmpty:true};const styles$e=aphrodite.StyleSheet.create({buttonStyle:{backgroundColor:"white",border:"1px solid #ccc",borderLeft:"0",cursor:"pointer",margin:"0",padding:"5px 10px",position:"relative",":first-child":{borderLeft:"1px solid #ccc",borderTopLeftRadius:"3px",borderBottomLeftRadius:"3px"},":last-child":{borderRight:"1px solid #ccc",borderTopRightRadius:"3px",borderBottomRightRadius:"3px"},":hover":{backgroundColor:"#ccc"},":focus":{zIndex:2}},selectedStyle:{backgroundColor:"#ddd"}});
|
|
1930
1925
|
|
|
1931
1926
|
function isPiMultiple(value){if(Number.isInteger(value)){return false}return value%Math.PI===0||value%(Math.PI/2)===0||value%(Math.PI/3)===0||value%(Math.PI/4)===0||value%(Math.PI/6)===0}
|
|
1932
1927
|
|
|
1933
|
-
const{firstNumericalParse,captureScratchpadTouchStart}=Util;const toNumericString=kmath.KhanMath.toNumericString;const getNumericFormat=kmath.KhanMath.getNumericFormat;class NumberInput extends React__namespace.Component{componentDidMount(){const value=this.getValue();if(this.props.allowPiTruncation&&value!==null&&value!==0){if(this.state.format!=="pi"&&isPiMultiple(value)){this._setValue(value/Math.PI,"pi");this.setState({format:"pi"});}}}componentDidUpdate(prevProps){if(!kmath.number.equal(this.getValue(),this.props.value)){this._setValue(this.props.value,this.state.format);}}render(){let classes=classNames__default.default({"number-input":true,"invalid-input":!this._checkValidity(this.props.value),mini:this.props.size==="mini",small:this.props.size==="small",normal:this.props.size==="normal"});if(this.props.className!=null){classes=classes+" "+this.props.className;}const{onFormatChange
|
|
1928
|
+
const{firstNumericalParse,captureScratchpadTouchStart}=Util;const toNumericString=kmath.KhanMath.toNumericString;const getNumericFormat=kmath.KhanMath.getNumericFormat;class NumberInput extends React__namespace.Component{componentDidMount(){const value=this.getValue();if(this.props.allowPiTruncation&&value!==null&&value!==0){if(this.state.format!=="pi"&&isPiMultiple(value)){this._setValue(value/Math.PI,"pi");this.setState({format:"pi"});}}}componentDidUpdate(prevProps){if(!kmath.number.equal(this.getValue(),this.props.value)){this._setValue(this.props.value,this.state.format);}}render(){let classes=classNames__default.default({"number-input":true,"invalid-input":!this._checkValidity(this.props.value),mini:this.props.size==="mini",small:this.props.size==="small",normal:this.props.size==="normal"});if(this.props.className!=null){classes=classes+" "+this.props.className;}const{onFormatChange,checkValidity,useArrowKeys,allowPiTruncation,...restProps}=this.props;return jsxRuntimeExports.jsx("input",{...restProps,className:classes,type:"text",ref:this.inputRef,onChange:this._handleChange,onFocus:this._handleFocus,onBlur:this._handleBlur,onKeyPress:this._handleBlur,onKeyDown:this._onKeyDown,onTouchStart:captureScratchpadTouchStart,defaultValue:toNumericString(this.props.value,this.state.format),value:undefined})}constructor(...args){super(...args),this.inputRef=React__namespace.createRef(),this.state={format:this.props.format},this._getInput=()=>{if(!this.inputRef.current){throw new perseusCore.PerseusError("Input ref accessed before set",perseusCore.Errors.Internal)}return this.inputRef.current},this.getValue=()=>{return this.parseInputValue(this._getInput().value)},this.getStringValue=()=>{return this._getInput().toString()},this.parseInputValue=value=>{if(value===""){const placeholder=this.props.placeholder;return ___default.default.isFinite(placeholder)?+placeholder:null}const result=firstNumericalParse(value);return ___default.default.isFinite(result)?result:this.props.value},this.focus=()=>{this._getInput().focus();this._handleFocus();},this.blur=()=>{this._getInput().blur();this._handleBlur();},this.setSelectionRange=(selectionStart,selectionEnd)=>{this._getInput().setSelectionRange(selectionStart,selectionEnd);},this.getSelectionStart=()=>{return this._getInput().selectionStart},this.getSelectionEnd=()=>{return this._getInput().selectionEnd},this._checkValidity=value=>{if(value==null){return true}const val=firstNumericalParse(value);const checkValidity=this.props.checkValidity;return ___default.default.isFinite(val)&&checkValidity(val)},this._handleChange=e=>{const text=e.target.value;const value=this.parseInputValue(text);const format=getNumericFormat(text);this.props.onChange(value);if(format){this.props.onFormatChange(value,format);this.setState({format:format});}},this._handleFocus=()=>{if(this.props.onFocus){this.props.onFocus();}},this._handleBlur=e=>{if(e&&e.type==="keypress"&&e.keyCode!==13){return}this._setValue(this.props.value,this.state.format);if(this.props.onBlur){this.props.onBlur();}},this._onKeyDown=e=>{if(this.props.onKeyDown){this.props.onKeyDown(e);}if(!this.props.useArrowKeys||!["ArrowUp","ArrowDown"].includes(e.key)){return}let val=this.getValue();if(val!==Math.floor(val)){return}if(e.key==="ArrowUp"){val=val+1;}else if(e.key==="ArrowDown"){val=val-1;}if(this._checkValidity(val)){this.props.onChange(val);}},this._setValue=(val,format)=>{this._getInput().value=toNumericString(val,format);};}}NumberInput.propTypes={value:PropTypes__default.default.number,format:PropTypes__default.default.string,placeholder:PropTypes__default.default.oneOfType([PropTypes__default.default.string,PropTypes__default.default.number]),onChange:PropTypes__default.default.func.isRequired,onFormatChange:PropTypes__default.default.func,checkValidity:PropTypes__default.default.func,size:PropTypes__default.default.oneOf(["mini","small","normal"]),label:PropTypes__default.default.oneOf(["put your labels outside your inputs!"]),allowPiTruncation:PropTypes__default.default.bool};NumberInput.defaultProps={value:null,placeholder:null,format:null,onFormatChange:()=>null,checkValidity:()=>true,useArrowKeys:false};
|
|
1934
1929
|
|
|
1935
1930
|
const truth=()=>true;class RangeInput extends React__namespace.Component{render(){const value=this.props.value;const checkValidity=this.props.checkValidity||truth;return jsxRuntimeExports.jsxs("div",{className:"range-input",children:[jsxRuntimeExports.jsx(NumberInput,{...this.props,value:value[0],checkValidity:val=>checkValidity([val,value[1]]),onChange:this.onChange.bind(this,0),placeholder:this.props.placeholder[0],allowPiTruncation:this.props.allowPiTruncation}),jsxRuntimeExports.jsx(NumberInput,{...this.props,value:value[1],checkValidity:val=>checkValidity([value[0],val]),onChange:this.onChange.bind(this,1),placeholder:this.props.placeholder[1],allowPiTruncation:this.props.allowPiTruncation})]})}constructor(...args){super(...args),this.onChange=(i,newVal)=>{const value=this.props.value;if(i===0){this.props.onChange([newVal,value[1]]);}else {this.props.onChange([value[0],newVal]);}};}}RangeInput.propTypes={value:PropTypes__default.default.array.isRequired,onChange:PropTypes__default.default.func.isRequired,placeholder:PropTypes__default.default.array,checkValidity:PropTypes__default.default.func,allowPiTruncation:PropTypes__default.default.bool};RangeInput.defaultProps={placeholder:[null,null]};
|
|
1936
1931
|
|
|
1937
|
-
const textWidthCache={};function getTextWidth(text){if(!textWidthCache[text]){const $test=$__default.default("<span>").text(text).appendTo("body");textWidthCache[text]=$test.width()+5;$test.remove();}return textWidthCache[text]}class TextListEditor extends React__namespace.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({items:nextProps.options.concat("")});}render(){const className=["perseus-text-list-editor","perseus-clearfix","layout-"+this.props.layout].join(" ");const inputs=___default.default.map(this.state.items,function(item,i){return jsxRuntimeExports.jsx("li",{children:jsxRuntimeExports.jsx("input",{ref:"input_"+i,type:"text",value:item,onChange:this.onChange.bind(this,i),onKeyDown:this.onKeyDown.bind(this,i),style:{width:getTextWidth(item)}})},i)},this);return jsxRuntimeExports.jsx("ul",{className:className,children:inputs})}constructor(...args){super(...args),this.state={items:this.props.options.concat("")},this.onChange=(index,event)=>{let items=___default.default.clone(this.state.items);items[index]=event.target.value;if(index===items.length-1){items=items.concat("");}this.setState({items:items});this.props.onChange(___default.default.compact(items));},this.onKeyDown=(index,event)=>{const which=event.nativeEvent.keyCode;if(which===8&&this.state.items[index]===""){event.preventDefault();const items=___default.default.clone(this.state.items);const focusIndex=index===0?0:index-1;if(index===items.length-1&&(index===0||items[focusIndex]!=="")){ReactDOM__namespace.default.findDOMNode(this.refs["input_"+focusIndex]).focus();}else {items.splice(index,1);this.setState({items:items},function(){ReactDOM__namespace.default.findDOMNode(this.refs["input_"+focusIndex]).focus();});}}else if(which===8&&this.state.items[index].length===1&&index===this.state.items.length-2){event.preventDefault();const items=___default.default.clone(this.state.items);items.splice(index,1);this.setState({items:items});this.props.onChange(___default.default.compact(items));}else if(which===13){event.preventDefault();const items=___default.default.clone(this.state.items);const focusIndex=index+1;if(index===items.length-2){ReactDOM__namespace.default.findDOMNode(this.refs["input_"+focusIndex]).focus();}else {items.splice(focusIndex,0,"");this.setState({items:items},function(){ReactDOM__namespace.default.findDOMNode(this.refs["input_"+focusIndex]).focus();});}}};}}TextListEditor.propTypes={options:PropTypes__default.default.array,layout:PropTypes__default.default.oneOf(["horizontal","vertical"]),onChange:PropTypes__default.default.func.isRequired};TextListEditor.defaultProps={options:[],layout:"horizontal"};
|
|
1938
|
-
|
|
1939
1932
|
var components = /*#__PURE__*/Object.freeze({
|
|
1940
1933
|
__proto__: null,
|
|
1941
1934
|
ButtonGroup: ButtonGroup,
|
|
1942
1935
|
Graphie: Graphie,
|
|
1943
1936
|
HUD: HUD,
|
|
1944
1937
|
Icon: Icon,
|
|
1945
|
-
InfoTip: InfoTip,
|
|
1946
1938
|
InlineIcon: InlineIcon,
|
|
1947
1939
|
MathInput: MathInput,
|
|
1948
1940
|
MultiButtonGroup: MultiButtonGroup,
|
|
1949
1941
|
NumberInput: NumberInput,
|
|
1950
1942
|
RangeInput: RangeInput,
|
|
1951
1943
|
SvgImage: SvgImage,
|
|
1952
|
-
TextInput: TextInput
|
|
1953
|
-
TextListEditor: TextListEditor
|
|
1944
|
+
TextInput: TextInput
|
|
1954
1945
|
});
|
|
1955
1946
|
|
|
1956
1947
|
const LegacyGrid=({box,backgroundImage})=>{const{url,width,height}=backgroundImage??{};if(url&&typeof url==="string"){const scale=box[X]/interactiveSizes$1.defaultBoxSize;return jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{position:"absolute",bottom:0,left:0},children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{src:url,allowZoom:false,width:width,height:height,scale:scale,responsive:false,setAssetStatus:setAssetStatus,alt:""})})})}return null};
|
|
@@ -1991,7 +1982,7 @@ const HitboxLayerContext=React__namespace.createContext(null);
|
|
|
1991
1982
|
|
|
1992
1983
|
const HANDLE_HITBOX_SIZE_PX=48;function useHitbox(params){const{shape,hitboxRef,layer="handle",cursor,dragging=false,onClick,onHoverChange,testId}=params;const layerEl=React.useContext(HitboxLayerContext);const graphConfig=useGraphConfig();if(!layerEl){return null}if(shape.kind==="polygon"&&shape.vertices.length<3){return null}return ReactDOM.createPortal(jsxRuntimeExports.jsx("div",{ref:hitboxRef,"aria-hidden":true,"data-testid":testId,style:{position:"absolute",touchAction:"none",pointerEvents:"auto",zIndex:layer==="body"?1:2,cursor:dragging?"grabbing":cursor??"grab",...shapeStyle(shape,graphConfig)},onClick:onClick,onPointerEnter:()=>onHoverChange?.(true),onPointerLeave:()=>onHoverChange?.(false)}),layerEl)}function shapeStyle(shape,graphConfig){switch(shape.kind){case "box":{const[x,y]=pointToPixel(shape.center,graphConfig);return {left:x,top:y,width:shape.sizePx,height:shape.sizePx,transform:"translate(-50%, -50%)"}}case "line":{const[sx,sy]=pointToPixel(shape.start,graphConfig);const[ex,ey]=pointToPixel(shape.end,graphConfig);const dx=ex-sx;const dy=ey-sy;const length=Math.hypot(dx,dy);const angleDeg=Math.atan2(dy,dx)*180/Math.PI;return {left:(sx+ex)/2,top:(sy+ey)/2,width:length,height:shape.thicknessPx,transform:`translate(-50%, -50%) rotate(${angleDeg}deg)`}}case "ellipse":{const[cx,cy]=pointToPixel(shape.center,graphConfig);const[[rxPx,ryPx]]=dimensionsToPixels([shape.radius],graphConfig);return {left:cx,top:cy,width:rxPx*2,height:ryPx*2,transform:"translate(-50%, -50%)",borderRadius:"50%"}}case "polygon":{const pts=shape.vertices.map(v=>pointToPixel(v,graphConfig));const xs=pts.map(p=>p[0]);const ys=pts.map(p=>p[1]);const minX=Math.min(...xs);const minY=Math.min(...ys);const maxX=Math.max(...xs);const maxY=Math.max(...ys);const clip=pts.map(([px,py])=>`${px-minX}px ${py-minY}px`).join(", ");return {left:minX,top:minY,width:maxX-minX,height:maxY-minY,clipPath:`polygon(${clip})`}}}}
|
|
1993
1984
|
|
|
1994
|
-
function Hairlines(props){const{point}=props;const{range}=useGraphConfig();const[[xMin,xMax],[yMin,yMax]]=range;const[[x,y]]=useTransformVectorsToPixels(point);const[[verticalStartX]]=useTransformVectorsToPixels([xMin,0]);const[[verticalEndX]]=useTransformVectorsToPixels([xMax,0]);const[[
|
|
1985
|
+
function Hairlines(props){const{point}=props;const{range}=useGraphConfig();const[[xMin,xMax],[yMin,yMax]]=range;const[[x,y]]=useTransformVectorsToPixels(point);const[[verticalStartX]]=useTransformVectorsToPixels([xMin,0]);const[[verticalEndX]]=useTransformVectorsToPixels([xMax,0]);const[[,horizontalStartY]]=useTransformVectorsToPixels([0,yMin]);const[[,horizontalEndY]]=useTransformVectorsToPixels([0,yMax]);return jsxRuntimeExports.jsxs("g",{"aria-hidden":true,children:[jsxRuntimeExports.jsx("line",{x1:verticalStartX,y1:y,x2:verticalEndX,y2:y,stroke:wonderBlocksTokens.semanticColor.core.border.instructive.default}),jsxRuntimeExports.jsx("line",{x1:x,y1:horizontalStartY,x2:x,y2:horizontalEndY,stroke:wonderBlocksTokens.semanticColor.core.border.instructive.default})]})}
|
|
1995
1986
|
|
|
1996
1987
|
const MovablePointView=React.forwardRef(function MovablePointViewWithRef(props,hitboxRef){const{markings,showTooltips,interactiveColor,snapStep}=useGraphConfig();const{point,dragging,focused,hovered,cursor,showFocusRing,onClick=()=>{}}=props;const pointClasses=classNames$1("movable-point",dragging&&"movable-point--dragging",showFocusRing&&"movable-point--focus",hovered&&"movable-point--hover");const[[x,y]]=useTransformVectorsToPixels(point);const showHairlines=(dragging||focused)&&markings!=="none";const xSigFigs=countSignificantDecimals(snapStep[X]);const ySigFigs=countSignificantDecimals(snapStep[Y]);const xTickLabel=point[X].toFixed(xSigFigs);const yTickLabel=point[Y].toFixed(ySigFigs);const pointTooltipContent=`(${xTickLabel}, ${yTickLabel})`;const svgForPoint=jsxRuntimeExports.jsxs("g",{"aria-hidden":true,ref:hitboxRef,className:pointClasses,style:{"--movable-point-color":interactiveColor,cursor},"data-testid":"movable-point",onClick:onClick,children:[jsxRuntimeExports.jsx("circle",{className:"movable-point-halo",cx:x,cy:y}),jsxRuntimeExports.jsx("circle",{className:"movable-point-ring",cx:x,cy:y}),jsxRuntimeExports.jsx("circle",{className:"movable-point-focus-outline",cx:x,cy:y}),jsxRuntimeExports.jsx("circle",{className:"movable-point-center",cx:x,cy:y,style:{fill:interactiveColor},"data-testid":"movable-point__center"})]});return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[showHairlines&&jsxRuntimeExports.jsx(Hairlines,{point:point}),showTooltips?jsxRuntimeExports.jsx(Tooltip__default.default,{autoUpdate:true,opened:true,variant:"strong",content:pointTooltipContent,children:svgForPoint}):svgForPoint]})});function classNames$1(...names){return names.filter(Boolean).join(" ")}
|
|
1997
1988
|
|
|
@@ -2045,7 +2036,7 @@ function renderPointGraph(state,dispatch,i18n){return {graph:jsxRuntimeExports.j
|
|
|
2045
2036
|
|
|
2046
2037
|
const{magnitude: magnitude$1,vector: vector$1}=kmath.geometry;function initializeGraphState(params){const{graph,step,snapStep,range}=params;const shared={hasBeenInteractedWith:false,range,snapStep,pointLabels:"pointLabels"in graph?graph.pointLabels:undefined,showPointLabels:"showPointLabels"in graph?Boolean(graph.showPointLabels):undefined};switch(graph.type){case "segment":return {...shared,type:"segment",coords:getSegmentCoords(graph,range,step)};case "linear":return {...shared,type:graph.type,coords:getLineCoords(graph,range,step)};case "ray":return {...shared,type:graph.type,coords:getLineCoords(graph,range,step)};case "linear-system":return {...shared,type:graph.type,coords:getLinearSystemCoords(graph,range,step)};case "polygon":return {...shared,type:"polygon",numSides:graph.numSides||0,showAngles:Boolean(graph.showAngles),showSides:Boolean(graph.showSides),coords:getPolygonCoords(graph,range,step),snapTo:graph.snapTo??"grid",focusedPointIndex:null,showRemovePointButton:false,interactionMode:"mouse",showKeyboardInteractionInvitation:false,closedPolygon:false};case "point":return {...shared,type:graph.type,coords:getPointCoords(graph,range,step),numPoints:graph.numPoints||0,focusedPointIndex:null,showRemovePointButton:false,interactionMode:"mouse",showKeyboardInteractionInvitation:false};case "circle":return {...shared,type:graph.type,...getCircleCoords(graph)};case "quadratic":return {...shared,type:graph.type,coords:getQuadraticCoords(graph,range,step)};case "sinusoid":return {...shared,type:graph.type,coords:getSinusoidCoords(graph,range,step)};case "exponential":return {...shared,type:graph.type,...getExponentialCoords(graph,range,step)};case "angle":return {...shared,type:graph.type,showAngles:Boolean(graph.showAngles),coords:getAngleCoords({graph,range,step}),angleOffsetDeg:graph.angleOffsetDeg??0,allowReflexAngles:Boolean(graph.allowReflexAngles),snapDegrees:Number(graph.snapDegrees)};case "none":return {...shared,type:"none"};case "absolute-value":return {...shared,type:graph.type,coords:getAbsoluteValueCoords(graph,range,step)};case "tangent":return {...shared,type:graph.type,coords:getTangentCoords(graph,range,step)};case "logarithm":return {...shared,type:graph.type,...getLogarithmCoords(graph,range,step)};case "vector":return {...shared,type:graph.type,coords:getVectorCoords(graph,range,step)};default:throw new wonderStuffCore.UnreachableCaseError(graph)}}function getPointCoords(graph,range,step){const numPoints=graph.numPoints||1;let coords=graph.coords?.slice();if(coords){return coords}const startCoords=graph.startCoords?.slice();if(startCoords){return startCoords}switch(numPoints){case 1:coords=[graph.coord||[0,0]];break;case 2:coords=[[-5,0],[5,0]];break;case 3:coords=[[-5,0],[0,0],[5,0]];break;case 4:coords=[[-6,0],[-2,0],[2,0],[6,0]];break;case 5:coords=[[-6,0],[-3,0],[0,0],[3,0],[6,0]];break;case 6:coords=[[-5,0],[-3,0],[-1,0],[1,0],[3,0],[5,0]];break;default:coords=[];break}const newCoords=normalizeCoords(coords,[[-10,10],[-10,10]]);return normalizePoints(range,step,newCoords)}function getSegmentCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}const ys=n=>{switch(n){case 2:return [5,-5];case 3:return [5,0,-5];case 4:return [6,2,-2,-6];case 5:return [6,3,0,-3,-6];case 6:return [5,3,1,-1,-3,-5];default:return [5]}};const defaultRange=[[-10,10],[-10,10]];return ys(graph.numSegments).map(y=>{let endpoints=[[-5,y],[5,y]];endpoints=normalizeCoords(endpoints,defaultRange);endpoints=normalizePoints(range,step,endpoints);return endpoints})}const defaultLinearCoords=[[[.25,.75],[.75,.75]],[[.25,.25],[.75,.25]]];function getLineCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}return normalizePoints(range,step,defaultLinearCoords[0])}function getVectorCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}return normalizePoints(range,step,[[.6,.6],[.85,.85]])}function getLinearSystemCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}return defaultLinearCoords.map(points=>normalizePoints(range,step,points))}function getPolygonCoords(graph,range,step){let coords=graph.coords?.slice();if(coords){return coords}const startCoords=graph.startCoords?.slice();if(startCoords){return startCoords}const n=graph.numSides||3;if(n==="unlimited"){coords=[];}else {const angle=2*Math.PI/n;const offset=(1/n-1/2)*Math.PI;const radius=graph.snapTo==="sides"?Math.sqrt(3)/3*7:4;coords=[...Array(n).keys()].map(i=>[radius*Math.cos(i*angle+offset),radius*Math.sin(i*angle+offset)]);}coords=normalizeCoords(coords,[[-10,10],[-10,10]]);const snapToGrid=!["angles","sides"].includes(graph.snapTo||"");coords=normalizePoints(range,step,coords,!snapToGrid);return coords}function getSinusoidCoords(graph,range,step){if(graph.coords){return [graph.coords[0],graph.coords[1]]}if(graph.startCoords){return [graph.startCoords[0],graph.startCoords[1]]}let coords=[[.5,.5],[.65,.6]];coords=normalizePoints(range,step,coords,true);return coords}function getAbsoluteValueCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}const defaultCoords=[[.5,.5],[.75,.75]];return normalizePoints(range,step,defaultCoords,true)}function getTangentCoords(graph,range,step){if(graph.coords){return [graph.coords[0],graph.coords[1]]}if(graph.startCoords){return [graph.startCoords[0],graph.startCoords[1]]}let coords=[[.5,.5],[.75,.75]];coords=normalizePoints(range,step,coords,true);return coords}function getQuadraticCoords(graph,range,step){if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}const defaultCoords=[[.25,.75],[.5,.25],[.75,.75]];return normalizePoints(range,step,defaultCoords,true)}function getCircleCoords(graph){if(graph.center!=null&&graph.radius!=null){return {center:graph.center,radiusPoint:mafs.vec.add(graph.center,[graph.radius,0])}}if(graph.startCoords?.center&&graph.startCoords.radius){return {center:graph.startCoords.center,radiusPoint:mafs.vec.add(graph.startCoords.center,[graph.startCoords.radius,0])}}return {center:[0,0],radiusPoint:[2,0]}}function getExponentialCoords(graph,range,step){if(graph.coords&&graph.asymptote!=null){return {coords:[graph.coords[0],graph.coords[1]],asymptote:graph.asymptote}}let defaultCoords=[[.5,.6],[.75,.75]];defaultCoords=normalizePoints(range,step,defaultCoords,true);const coords=graph.startCoords?graph.startCoords.coords:defaultCoords;const asymptote=graph.startCoords?graph.startCoords.asymptote:0;return {coords,asymptote}}function getLogarithmCoords(graph,range,step){if(graph.coords&&graph.asymptote!=null){return {coords:[graph.coords[0],graph.coords[1]],asymptote:graph.asymptote}}let defaultCoords=[[.6,.55],[.75,.75]];defaultCoords=normalizePoints(range,step,defaultCoords,true);const coords=graph.startCoords?graph.startCoords.coords:defaultCoords;const asymptote=graph.startCoords?graph.startCoords.asymptote:0;return {coords,asymptote}}const getAngleCoords=params=>{const{graph,range,step}=params;if(graph.coords){return graph.coords}if(graph.startCoords){return graph.startCoords}const{snapDegrees,angleOffsetDeg}=graph;const snap=snapDegrees||1;let angle=snap;while(angle<20){angle+=snap;}angle=angle*Math.PI/180;const offset=(angleOffsetDeg||0)*Math.PI/180;let defaultCoords=[[.85,.5],[.5,.5]];defaultCoords=normalizePoints(range,step,defaultCoords,true);const radius=magnitude$1(vector$1(...defaultCoords));const coords=[...defaultCoords,[0,0]];coords[0]=[coords[1][0]+radius*Math.cos(offset),coords[1][1]+radius*Math.sin(offset)];coords[2]=[coords[1][0]+radius*Math.cos(angle+offset),coords[1][1]+radius*Math.sin(angle+offset)];return coords};
|
|
2047
2038
|
|
|
2048
|
-
const{getAngleFromVertex,getClockwiseAngle,polar}=kmath.angles;const{angleMeasures,ccw,lawOfCosines,magnitude,polygonSidesIntersect,reverseVector,sign,vector}=kmath.geometry;const{getAbsoluteValueCoefficients,getLogarithmCoefficients,getExponentialCoefficients,getQuadraticCoefficients}=kmath.coefficients;const minDistanceBetweenAngleVertexAndSidePoint=2;function interactiveGraphReducer(state,action){switch(action.type){case REINITIALIZE:return initializeGraphState(action.params);case MOVE_POINT_IN_FIGURE:return doMovePointInFigure(state,action);case MOVE_LINE:return doMoveLine(state,action);case MOVE_ALL:return doMoveAll(state,action);case MOVE_POINT:return doMovePoint(state,action);case MOVE_CENTER:return doMoveCenter(state,action);case MOVE_RADIUS_POINT:return doMoveRadiusPoint(state,action);case CHANGE_SNAP_STEP:return doChangeSnapStep(state,action);case CHANGE_RANGE:return doChangeRange(state,action);case ADD_POINT:return doAddPoint(state,action);case REMOVE_POINT:return doRemovePoint(state,action);case FOCUS_POINT:return doFocusPoint(state,action);case BLUR_POINT:return doBlurPoint(state);case DELETE_INTENT:return doDeleteIntent(state);case CLICK_POINT:return doClickPoint(state,action);case CLOSE_POLYGON:return doClosePolygon(state);case OPEN_POLYGON:return doOpenPolygon(state);case CHANGE_INTERACTION_MODE:return doChangeInteractionMode(state,action);case CHANGE_KEYBOARD_INVITATION_VISIBILITY:return doChangeKeyboardInvitationVisibility(state,action);default:throw new wonderStuffCore.UnreachableCaseError(action)}}function doDeleteIntent(state,action){if(isUnlimitedGraphState(state)){if(state.focusedPointIndex!==null){return doRemovePoint(state,actions.pointGraph.removePoint(state.focusedPointIndex))}}return state}function doFocusPoint(state,action){switch(state.type){case "polygon":case "point":return {...state,focusedPointIndex:action.index};default:return state}}function doBlurPoint(state,action){switch(state.type){case "polygon":case "point":const nextState={...state,showRemovePointButton:false};if(state.interactionMode==="mouse"){nextState.focusedPointIndex=null;}return nextState;default:return state}}function doClickPoint(state,action){if(isUnlimitedGraphState(state)){return {...state,focusedPointIndex:action.index,showRemovePointButton:true}}return state}function doClosePolygon(state){if(isUnlimitedGraphState(state)&&state.type==="polygon"){const noDupedPoints=getArrayWithoutDuplicates(state.coords);return {...state,coords:noDupedPoints,closedPolygon:true}}return state}function doOpenPolygon(state){if(isUnlimitedGraphState(state)&&state.type==="polygon"){return {...state,closedPolygon:false}}return state}function doChangeInteractionMode(state,action){if(isUnlimitedGraphState(state)){const nextKeyboardInvitation=action.mode==="keyboard"?false:state.showKeyboardInteractionInvitation;return {...state,interactionMode:action.mode,showKeyboardInteractionInvitation:nextKeyboardInvitation}}return state}function doChangeKeyboardInvitationVisibility(state,action){if(isUnlimitedGraphState(state)){return {...state,showKeyboardInteractionInvitation:action.shouldShow,hasBeenInteractedWith:true}}return state}function doMovePointInFigure(state,action){switch(state.type){case "segment":case "linear-system":{const newValue=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=updateAtIndex({array:state.coords,index:action.figureIndex,update:tuple=>setAtIndex({array:tuple,index:action.pointIndex,newValue})});const coordsToCheck=newCoords[action.figureIndex];if(coordsOverlap(coordsToCheck)){return state}const sharedAnnouncement={pointIndex:action.pointIndex,pointLabel:getCustomPointLabel(state.pointLabels,action.figureIndex*2+action.pointIndex),x:newValue[X],y:newValue[Y]};const stateAnnouncement=state.type==="segment"?{type:"move-segment-point",segmentIndex:action.figureIndex,totalSegments:state.coords.length,...sharedAnnouncement}:{type:"move-linear-system-point",lineIndex:action.figureIndex,...sharedAnnouncement};return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement}}case "ray":case "linear":case "vector":{const newValue=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=setAtIndex({array:state.coords,index:action.pointIndex,newValue});if(coordsOverlap(newCoords)){return state}let stateAnnouncement;if(state.type==="ray"){stateAnnouncement={type:"move-ray-point",pointIndex:action.pointIndex,pointLabel:getCustomPointLabel(state.pointLabels,action.pointIndex),x:newValue[X],y:newValue[Y]};}else if(state.type==="vector"){stateAnnouncement={type:"move-vector-point",pointIndex:action.pointIndex,x:newValue[X],y:newValue[Y]};}else {stateAnnouncement={type:"move-point",pointLabel:resolvePointLabel(state.pointLabels,action.pointIndex),x:newValue[X],y:newValue[Y]};}return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement}}case "circle":throw new Error(`Don't use movePointInFigure for circle graphs. Use moveCenter or moveRadiusPoint.`);case "angle":case "none":case "point":case "polygon":case "quadratic":case "sinusoid":case "absolute-value":case "tangent":case "exponential":case "logarithm":throw new Error(`Don't use movePointInFigure for ${state.type} graphs. Use movePoint instead!`);default:throw new wonderStuffCore.UnreachableCaseError(state)}}function doMoveLine(state,action){const{snapStep,range}=state;const{newStart}=action;switch(state.type){case "segment":case "linear-system":{if(action.itemIndex===undefined){throw new Error("Please provide index of line to move")}const currentLine=state.coords[action.itemIndex];const constrainedLine=constrainShapePreservingMove(currentLine,newStart,{snapStep,range});const newCoords=setAtIndex({array:state.coords,index:action.itemIndex,newValue:constrainedLine});const stateAnnouncement=state.type==="segment"?{type:"move-segment-line",coords:constrainedLine}:{type:"move-linear-system-line",lineIndex:action.itemIndex,coords:constrainedLine};return {...state,type:state.type,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement}}case "ray":case "linear":case "vector":{const constrainedLine=constrainShapePreservingMove(state.coords,newStart,{snapStep,range});let type;if(state.type==="ray"){type="move-ray-line";}else if(state.type==="vector"){type="move-vector-line";}else {type="move-linear-line";}const stateAnnouncement={type,coords:constrainedLine};return {...state,type:state.type,hasBeenInteractedWith:true,coords:constrainedLine,stateAnnouncement}}default:return state}}function doMoveAll(state,action){const{snapStep,range}=state;const{newStart}=action;switch(state.type){case "polygon":{const useGridSnap=state.snapTo!=="sides"&&state.snapTo!=="angles";const desiredDelta=mafs.vec.sub(newStart,state.coords[0]);const change=getChange(state.coords,desiredDelta,{snapStep:useGridSnap?snapStep:[0,0],range});const newCoords=state.coords.map(point=>useGridSnap?snap(snapStep,mafs.vec.add(point,change)):mafs.vec.add(point,change));return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement:{type:"move-polygon",coords:newCoords,pointLabels:state.pointLabels}}}default:return state}}function doMovePoint(state,action){switch(state.type){case "angle":const newState=(()=>{if(action.index===1){const updatedCoords=boundAndSnapAngleVertex(state,action);return {...state,hasBeenInteractedWith:true,coords:updatedCoords}}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundAndSnapAngleEndPoints(action.destination,state,action.index)})}})();if(angleSidePointsTooCloseToVertex(newState)){return state}return {...newState,stateAnnouncement:{type:"move-angle-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:newState.coords[action.index][X],y:newState.coords[action.index][Y],angleMeasure:getClockwiseAngle(newState.coords,newState.allowReflexAngles??false)}};case "polygon":let newValue;if(state.snapTo==="sides"){newValue=boundAndSnapToSides(action.destination,state,action.index);}else if(state.snapTo==="angles"){newValue=boundAndSnapToPolygonAngle(action.destination,state,action.index);}else {newValue=boundToEdgeAndSnapToGrid(action.destination,state);}const newCoords=setAtIndex({array:state.coords,index:action.index,newValue:newValue});const polygonSidesCanIntersect=state.numSides==="unlimited"&&!state.closedPolygon;if(!polygonSidesCanIntersect&&polygonSidesIntersect(newCoords)){return state}return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement:{type:"move-point",pointLabel:resolvePointLabel(state.pointLabels,action.index),x:newValue[X],y:newValue[Y]}};case "point":{const newCoord=boundToEdgeAndSnapToGrid(action.destination,state);return {...state,hasBeenInteractedWith:true,focusedPointIndex:action.index,coords:setAtIndex({array:state.coords,index:action.index,newValue:newCoord}),stateAnnouncement:{type:"move-point",pointLabel:resolvePointLabel(state.pointLabels,action.index),x:newCoord[X],y:newCoord[Y]}}}case "sinusoid":{const destination=action.destination;const boundDestination=boundToEdgeAndSnapToGrid(destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-sinusoid-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:newCoords[action.index][X],y:newCoords[action.index][Y],otherY:newCoords[1-action.index][Y]}}}case "exponential":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}const expHandle=getAsymptoteHandleCoord("horizontal",state.range,state.asymptote);if(boundDestination[X]===expHandle[X]&&boundDestination[Y]===expHandle[Y]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-exponential-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],hasCurve:getExponentialCoefficients(newCoords,state.asymptote)!==undefined}}}case "logarithm":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}if(newCoords[0][Y]===newCoords[1][Y]){return state}const logHandle=getAsymptoteHandleCoord("vertical",state.range,state.asymptote);if(boundDestination[X]===logHandle[X]&&boundDestination[Y]===logHandle[Y]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-logarithm-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],hasCurve:getLogarithmCoefficients(newCoords,state.asymptote)!==undefined}}}case "absolute-value":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-absolute-value-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],slope:getAbsoluteValueCoefficients(newCoords)[0]}}}case "tangent":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]||newCoords[0][Y]===newCoords[1][Y]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-tangent-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y]}}}case "quadratic":{const newCoords=[...state.coords];const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);newCoords[action.index]=boundDestination;const QuadraticCoefficients=getQuadraticCoefficients(newCoords);if(QuadraticCoefficients===undefined){return state}const vertex=getQuadraticVertex(QuadraticCoefficients);return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-quadratic-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],vertex}}}default:throw new Error("The movePoint action is only for point, quadratic, and polygon graphs")}}function doMoveCenter(state,action){switch(state.type){case "circle":{const constrainedCenter=boundToEdgeAndSnapToGrid(action.destination,state);const newRadiusPoint=[...mafs.vec.add(state.radiusPoint,mafs.vec.sub(constrainedCenter,state.center))];const[xMin,xMax]=state.range[X];const[radX]=newRadiusPoint;if(radX<xMin||radX>xMax){const xJumpDist=(radX-constrainedCenter[X])*2;const possibleNewX=radX-xJumpDist;if(possibleNewX>=xMin&&possibleNewX<=xMax){newRadiusPoint[X]=possibleNewX;}else {return state}}return {...state,hasBeenInteractedWith:true,center:constrainedCenter,radiusPoint:newRadiusPoint,stateAnnouncement:{type:"move-center",x:constrainedCenter[X],y:constrainedCenter[Y]}}}case "exponential":{const newY=boundAndSnapToGrid(action.destination,state)[Y];if(newY===state.asymptote){return state}const expFutureHandle=getAsymptoteHandleCoord("horizontal",state.range,newY);if(state.coords.some(c=>c[X]===expFutureHandle[X]&&c[Y]===expFutureHandle[Y])){return state}return {...state,hasBeenInteractedWith:true,asymptote:newY,stateAnnouncement:{type:"move-exponential-asymptote",asymptoteY:newY}}}case "logarithm":{const newX=boundAndSnapToGrid(action.destination,state)[X];if(newX===state.asymptote){return state}const logFutureHandle=getAsymptoteHandleCoord("vertical",state.range,newX);if(state.coords.some(c=>c[X]===logFutureHandle[X]&&c[Y]===logFutureHandle[Y])){return state}return {...state,hasBeenInteractedWith:true,asymptote:newX,stateAnnouncement:{type:"move-logarithm-asymptote",asymptoteX:newX}}}default:throw new Error("The doMoveCenter action is only for circle, exponential, or logarithm graphs")}}function doMoveRadiusPoint(state,action){switch(state.type){case "circle":{const nextRadiusPoint=boundToEdgeAndSnapToGrid([action.destination[X],state.center[1]],state);if(kmath.vector.equal(nextRadiusPoint,state.center)){return state}return {...state,hasBeenInteractedWith:true,radiusPoint:nextRadiusPoint,stateAnnouncement:{type:"move-radius-point",x:nextRadiusPoint[X],y:nextRadiusPoint[Y],centerX:state.center[X],radius:mafs.vec.dist(state.center,nextRadiusPoint),pointLabel:getCustomPointLabel(state.pointLabels,0)}}}default:throw new Error("The doMoveRadiusPoint action is only for circle graphs")}}function doChangeSnapStep(state,action){if(___default.default.isEqual(state.snapStep,action.snapStep)){return state}return {...state,snapStep:action.snapStep}}function doChangeRange(state,action){if(___default.default.isEqual(state.range,action.range)){return state}return {...state,range:action.range}}function doAddPoint(state,action){if(!isUnlimitedGraphState(state)){return state}const{snapStep}=state;const snappedPoint=snap(snapStep,action.location);for(const point of state.coords){if(point[X]===snappedPoint[X]&&point[Y]===snappedPoint[Y]){return state}}const newCoords=[...state.coords,snappedPoint];return {...state,hasBeenInteractedWith:true,coords:newCoords,showRemovePointButton:true,focusedPointIndex:newCoords.length-1}}function doRemovePoint(state,action){if(!isUnlimitedGraphState(state)){return state}const nextFocusedPointIndex=state.coords.length>1?state.coords.length-2:null;return {...state,coords:state.coords.filter((_,i)=>i!==action.index),focusedPointIndex:nextFocusedPointIndex,showRemovePointButton:nextFocusedPointIndex!==null?true:false}}const getDeltaVertex=(maxMoves,minMoves,delta)=>{const[deltaX,deltaY]=delta;const maxXMove=Math.min(...maxMoves.map(move=>move[X]));const maxYMove=Math.min(...maxMoves.map(move=>move[Y]));const minXMove=Math.max(...minMoves.map(move=>move[X]));const minYMove=Math.max(...minMoves.map(move=>move[Y]));const dx=clamp(deltaX,minXMove,maxXMove);const dy=clamp(deltaY,minYMove,maxYMove);return [dx,dy]};const getChange=(coords,delta,constraintOpts)=>{const maxMoves=coords.map(point=>maxMove({...constraintOpts,point}));const minMoves=coords.map(point=>minMove({...constraintOpts,point}));const[dx,dy]=getDeltaVertex(maxMoves,minMoves,delta);return [dx,dy]};const constrainShapePreservingMove=(currentLine,newStart,constraintOpts)=>{const desiredDelta=mafs.vec.sub(newStart,currentLine[0]);const change=getChange(currentLine,desiredDelta,constraintOpts);const{snapStep}=constraintOpts;return [snap(snapStep,mafs.vec.add(currentLine[0],change)),snap(snapStep,mafs.vec.add(currentLine[1],change))]};function leq(a,b){return a<b||perseusCore.approximateEqual(a,b)}function boundAndSnapToGrid(point,{snapStep,range}){return snap(snapStep,bound$1({snapStep,range,point}))}function boundAndSnapAngleVertex({range,coords,snapStep},{destination}){const coordsCopy=[...coords];const startingVertex=coordsCopy[1];const insetAmount=mafs.vec.add(snapStep,[minDistanceBetweenAngleVertexAndSidePoint,minDistanceBetweenAngleVertexAndSidePoint]);const newVertex=clampToBox(inset(insetAmount,range),snap(snapStep,destination));const delta=mafs.vec.add(newVertex,reverseVector(startingVertex));const newPoints={};for(const i of [0,2]){const oldPoint=coordsCopy[i];let newPoint=mafs.vec.add(oldPoint,delta);let angle=getAngleFromVertex(newVertex,newPoint);angle*=Math.PI/180;newPoint=constrainToBoundsOnAngle(newPoint,angle,range,snapStep);newPoints[i]=newPoint;}newPoints[1]=newVertex;Object.entries(newPoints).forEach(([i,newPoint])=>{coordsCopy[i]=newPoint;});return coordsCopy}function tooClose(point1,point2,range){const safeDistance=2;const distance=mafs.vec.dist(point1,point2);return distance<safeDistance}function constrainToBoundsOnAngle(point,angle,range,snapStep){const lower=[range[0][0]+snapStep[0],range[1][0]+snapStep[0]];const upper=[range[0][1]-snapStep[1],range[1][1]-snapStep[1]];let result=point;if(result[0]<lower[0]){result=[lower[0],result[1]+(lower[0]-result[0])*Math.tan(angle)];}else if(result[0]>upper[0]){result=[upper[0],result[1]-(result[0]-upper[0])*Math.tan(angle)];}if(result[1]<lower[1]){result=[result[0]+(lower[1]-result[1])/Math.tan(angle),lower[1]];}else if(result[1]>upper[1]){result=[result[0]-(result[1]-upper[1])/Math.tan(angle),upper[1]];}return result}function boundAndSnapAngleEndPoints(destinationPoint,{range,coords,snapDegrees,angleOffsetDeg,snapStep},index){const snap=snapDegrees||1;const offsetDegrees=angleOffsetDeg||0;const coordsCopy=[...coords];const angleRange=[[range[0][0]+snapStep[0],range[0][1]-snapStep[0]],[range[1][0]+snapStep[1],range[1][1]-snapStep[1]]];const boundPoint=bound$1({snapStep:[0,0],range:angleRange,point:destinationPoint});coordsCopy[index]=boundPoint;const vertex=coords[1];let angle=getAngleFromVertex(coordsCopy[index],vertex);angle=Math.round((angle-offsetDegrees)/snap)*snap+offsetDegrees;const minDistance=minDistanceBetweenAngleVertexAndSidePoint+.01;const distance=Math.max(mafs.vec.dist(coordsCopy[index],vertex),minDistance);const snappedValue=mafs.vec.add(vertex,polar(distance,angle));return snappedValue}function angleSidePointsTooCloseToVertex(state){return tooClose(state.coords[0],state.coords[1],state.range)||tooClose(state.coords[2],state.coords[1],state.range)}function boundAndSnapToPolygonAngle(destinationPoint,{range,coords},index){const startingPoint=coords[index];return calculateAngleSnap(destinationPoint,range,coords,index,startingPoint)}function calculateAngleSnap(destinationPoint,range,coords,index,startingPoint){const coordsCopy=[...coords];coordsCopy[index]=bound$1({snapStep:[0,0],range,point:destinationPoint});const angles=angleMeasures(coordsCopy).map(angle=>angle*180/Math.PI);const rel=j=>{return (index+j+coordsCopy.length)%coordsCopy.length};___default.default.each([-1,1],function(j){angles[rel(j)]=Math.round(angles[rel(j)]);});const getAngle=function(a,vertex,b){const angle=getClockwiseAngle([coordsCopy[rel(a)],coordsCopy[rel(vertex)],coordsCopy[rel(b)]]);return angle};const innerAngles=[angles[rel(-1)]-getAngle(-2,-1,1),angles[rel(1)]-getAngle(-1,1,2)];innerAngles[2]=180-(innerAngles[0]+innerAngles[1]);if(innerAngles.some(function(angle){return leq(angle,1)})){return startingPoint}const knownSide=magnitude(vector(coordsCopy[rel(-1)],coordsCopy[rel(1)]));const onLeft=sign(ccw(coordsCopy[rel(-1)],coordsCopy[rel(1)],coordsCopy[index]))===1;const side=Math.sin(innerAngles[1]*Math.PI/180)/Math.sin(innerAngles[2]*Math.PI/180)*knownSide;const outerAngle=getAngleFromVertex(coordsCopy[rel(1)],coordsCopy[rel(-1)]);const offset=polar(side,outerAngle+(onLeft?1:-1)*innerAngles[0]);return kmath.vector.add(coordsCopy[rel(-1)],offset)}function boundAndSnapToSides(destinationPoint,{range,coords},index){const startingPoint=coords[index];return calculateSideSnap(destinationPoint,range,coords,index,startingPoint)}function calculateSideSnap(destinationPoint,range,coords,index,startingPoint){const boundedDestinationPoint=bound$1({snapStep:[0,0],range,point:destinationPoint});const rel=j=>{return (index+j+coords.length)%coords.length};const sides=___default.default.map([[coords[rel(-1)],boundedDestinationPoint],[boundedDestinationPoint,coords[rel(1)]],[coords[rel(-1)],coords[rel(1)]]],function(coords){return magnitude(vector(...coords))});___default.default.each([0,1],function(j){sides[j]=Math.round(sides[j]);});if(leq(sides[1]+sides[2],sides[0])||leq(sides[0]+sides[2],sides[1])||leq(sides[0]+sides[1],sides[2])){return startingPoint}const innerAngle=lawOfCosines(sides[0],sides[2],sides[1]);const outerAngle=getAngleFromVertex(coords[rel(1)],coords[rel(-1)]);const onLeft=sign(ccw(coords[rel(-1)],coords[rel(1)],boundedDestinationPoint))===1;const offset=polar(sides[0],outerAngle+(onLeft?1:-1)*innerAngle);return kmath.vector.add(coords[rel(-1)],offset)}function maxMove({snapStep,range,point}){const topRight=boundToEdgeAndSnapToGrid([Infinity,Infinity],{snapStep,range});return mafs.vec.sub(topRight,point)}function minMove({snapStep,range,point}){const bottomLeft=boundToEdgeAndSnapToGrid([-Infinity,-Infinity],{snapStep,range});return mafs.vec.sub(bottomLeft,point)}const coordsOverlap=coords=>coords.some((coord,i)=>coords.some((c,j)=>i!==j&&kmath.vector.equal(coord,c)));function updateAtIndex(args){const{array,index,update}=args;const newValue=update(array[index]);return setAtIndex({array,index,newValue})}function setAtIndex(args){const{array,index,newValue}=args;const copy=[...array];copy[index]=newValue;return copy}
|
|
2039
|
+
const{getAngleFromVertex,getClockwiseAngle,polar}=kmath.angles;const{angleMeasures,ccw,lawOfCosines,magnitude,polygonSidesIntersect,reverseVector,sign,vector}=kmath.geometry;const{getAbsoluteValueCoefficients,getLogarithmCoefficients,getExponentialCoefficients,getQuadraticCoefficients}=kmath.coefficients;const minDistanceBetweenAngleVertexAndSidePoint=2;function interactiveGraphReducer(state,action){switch(action.type){case REINITIALIZE:return initializeGraphState(action.params);case MOVE_POINT_IN_FIGURE:return doMovePointInFigure(state,action);case MOVE_LINE:return doMoveLine(state,action);case MOVE_ALL:return doMoveAll(state,action);case MOVE_POINT:return doMovePoint(state,action);case MOVE_CENTER:return doMoveCenter(state,action);case MOVE_RADIUS_POINT:return doMoveRadiusPoint(state,action);case CHANGE_SNAP_STEP:return doChangeSnapStep(state,action);case CHANGE_RANGE:return doChangeRange(state,action);case ADD_POINT:return doAddPoint(state,action);case REMOVE_POINT:return doRemovePoint(state,action);case FOCUS_POINT:return doFocusPoint(state,action);case BLUR_POINT:return doBlurPoint(state);case DELETE_INTENT:return doDeleteIntent(state);case CLICK_POINT:return doClickPoint(state,action);case CLOSE_POLYGON:return doClosePolygon(state);case OPEN_POLYGON:return doOpenPolygon(state);case CHANGE_INTERACTION_MODE:return doChangeInteractionMode(state,action);case CHANGE_KEYBOARD_INVITATION_VISIBILITY:return doChangeKeyboardInvitationVisibility(state,action);default:throw new wonderStuffCore.UnreachableCaseError(action)}}function doDeleteIntent(state,action){if(isUnlimitedGraphState(state)){if(state.focusedPointIndex!==null){return doRemovePoint(state,actions.pointGraph.removePoint(state.focusedPointIndex))}}return state}function doFocusPoint(state,action){switch(state.type){case "polygon":case "point":return {...state,focusedPointIndex:action.index};default:return state}}function doBlurPoint(state,action){switch(state.type){case "polygon":case "point":const nextState={...state,showRemovePointButton:false};if(state.interactionMode==="mouse"){nextState.focusedPointIndex=null;}return nextState;default:return state}}function doClickPoint(state,action){if(isUnlimitedGraphState(state)){return {...state,focusedPointIndex:action.index,showRemovePointButton:true}}return state}function doClosePolygon(state){if(isUnlimitedGraphState(state)&&state.type==="polygon"){const noDupedPoints=getArrayWithoutDuplicates(state.coords);return {...state,coords:noDupedPoints,closedPolygon:true}}return state}function doOpenPolygon(state){if(isUnlimitedGraphState(state)&&state.type==="polygon"){return {...state,closedPolygon:false}}return state}function doChangeInteractionMode(state,action){if(isUnlimitedGraphState(state)){const nextKeyboardInvitation=action.mode==="keyboard"?false:state.showKeyboardInteractionInvitation;return {...state,interactionMode:action.mode,showKeyboardInteractionInvitation:nextKeyboardInvitation}}return state}function doChangeKeyboardInvitationVisibility(state,action){if(isUnlimitedGraphState(state)){return {...state,showKeyboardInteractionInvitation:action.shouldShow,hasBeenInteractedWith:true}}return state}function doMovePointInFigure(state,action){switch(state.type){case "segment":case "linear-system":{const newValue=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=updateAtIndex({array:state.coords,index:action.figureIndex,update:tuple=>setAtIndex({array:tuple,index:action.pointIndex,newValue})});const coordsToCheck=newCoords[action.figureIndex];if(coordsOverlap(coordsToCheck)){return state}const sharedAnnouncement={pointIndex:action.pointIndex,pointLabel:getCustomPointLabel(state.pointLabels,action.figureIndex*2+action.pointIndex),x:newValue[X],y:newValue[Y]};const stateAnnouncement=state.type==="segment"?{type:"move-segment-point",segmentIndex:action.figureIndex,totalSegments:state.coords.length,...sharedAnnouncement}:{type:"move-linear-system-point",lineIndex:action.figureIndex,...sharedAnnouncement};return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement}}case "ray":case "linear":case "vector":{const newValue=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=setAtIndex({array:state.coords,index:action.pointIndex,newValue});if(coordsOverlap(newCoords)){return state}let stateAnnouncement;if(state.type==="ray"){stateAnnouncement={type:"move-ray-point",pointIndex:action.pointIndex,pointLabel:getCustomPointLabel(state.pointLabels,action.pointIndex),x:newValue[X],y:newValue[Y]};}else if(state.type==="vector"){stateAnnouncement={type:"move-vector-point",pointIndex:action.pointIndex,x:newValue[X],y:newValue[Y]};}else {stateAnnouncement={type:"move-point",pointLabel:resolvePointLabel(state.pointLabels,action.pointIndex),x:newValue[X],y:newValue[Y]};}return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement}}case "circle":throw new Error(`Don't use movePointInFigure for circle graphs. Use moveCenter or moveRadiusPoint.`);case "angle":case "none":case "point":case "polygon":case "quadratic":case "sinusoid":case "absolute-value":case "tangent":case "exponential":case "logarithm":throw new Error(`Don't use movePointInFigure for ${state.type} graphs. Use movePoint instead!`);default:throw new wonderStuffCore.UnreachableCaseError(state)}}function doMoveLine(state,action){const{snapStep,range}=state;const{newStart}=action;switch(state.type){case "segment":case "linear-system":{if(action.itemIndex===undefined){throw new Error("Please provide index of line to move")}const currentLine=state.coords[action.itemIndex];const constrainedLine=constrainShapePreservingMove(currentLine,newStart,{snapStep,range});const newCoords=setAtIndex({array:state.coords,index:action.itemIndex,newValue:constrainedLine});const stateAnnouncement=state.type==="segment"?{type:"move-segment-line",coords:constrainedLine}:{type:"move-linear-system-line",lineIndex:action.itemIndex,coords:constrainedLine};return {...state,type:state.type,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement}}case "ray":case "linear":case "vector":{const constrainedLine=constrainShapePreservingMove(state.coords,newStart,{snapStep,range});let type;if(state.type==="ray"){type="move-ray-line";}else if(state.type==="vector"){type="move-vector-line";}else {type="move-linear-line";}const stateAnnouncement={type,coords:constrainedLine};return {...state,type:state.type,hasBeenInteractedWith:true,coords:constrainedLine,stateAnnouncement}}default:return state}}function doMoveAll(state,action){const{snapStep,range}=state;const{newStart}=action;switch(state.type){case "polygon":{const useGridSnap=state.snapTo!=="sides"&&state.snapTo!=="angles";const desiredDelta=mafs.vec.sub(newStart,state.coords[0]);const change=getChange(state.coords,desiredDelta,{snapStep:useGridSnap?snapStep:[0,0],range});const newCoords=state.coords.map(point=>useGridSnap?snap(snapStep,mafs.vec.add(point,change)):mafs.vec.add(point,change));return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement:{type:"move-polygon",coords:newCoords,pointLabels:state.pointLabels}}}default:return state}}function doMovePoint(state,action){switch(state.type){case "angle":const newState=(()=>{if(action.index===1){const updatedCoords=boundAndSnapAngleVertex(state,action);return {...state,hasBeenInteractedWith:true,coords:updatedCoords}}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundAndSnapAngleEndPoints(action.destination,state,action.index)})}})();if(angleSidePointsTooCloseToVertex(newState)){return state}return {...newState,stateAnnouncement:{type:"move-angle-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:newState.coords[action.index][X],y:newState.coords[action.index][Y],angleMeasure:getClockwiseAngle(newState.coords,newState.allowReflexAngles??false)}};case "polygon":let newValue;if(state.snapTo==="sides"){newValue=boundAndSnapToSides(action.destination,state,action.index);}else if(state.snapTo==="angles"){newValue=boundAndSnapToPolygonAngle(action.destination,state,action.index);}else {newValue=boundToEdgeAndSnapToGrid(action.destination,state);}const newCoords=setAtIndex({array:state.coords,index:action.index,newValue:newValue});const polygonSidesCanIntersect=state.numSides==="unlimited"&&!state.closedPolygon;if(!polygonSidesCanIntersect&&polygonSidesIntersect(newCoords)){return state}return {...state,hasBeenInteractedWith:true,coords:newCoords,stateAnnouncement:{type:"move-point",pointLabel:resolvePointLabel(state.pointLabels,action.index),x:newValue[X],y:newValue[Y]}};case "point":{const newCoord=boundToEdgeAndSnapToGrid(action.destination,state);return {...state,hasBeenInteractedWith:true,focusedPointIndex:action.index,coords:setAtIndex({array:state.coords,index:action.index,newValue:newCoord}),stateAnnouncement:{type:"move-point",pointLabel:resolvePointLabel(state.pointLabels,action.index),x:newCoord[X],y:newCoord[Y]}}}case "sinusoid":{const destination=action.destination;const boundDestination=boundToEdgeAndSnapToGrid(destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-sinusoid-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:newCoords[action.index][X],y:newCoords[action.index][Y],otherY:newCoords[1-action.index][Y]}}}case "exponential":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}const expHandle=getAsymptoteHandleCoord("horizontal",state.range,state.asymptote);if(boundDestination[X]===expHandle[X]&&boundDestination[Y]===expHandle[Y]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-exponential-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],hasCurve:getExponentialCoefficients(newCoords,state.asymptote)!==undefined}}}case "logarithm":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}if(newCoords[0][Y]===newCoords[1][Y]){return state}const logHandle=getAsymptoteHandleCoord("vertical",state.range,state.asymptote);if(boundDestination[X]===logHandle[X]&&boundDestination[Y]===logHandle[Y]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-logarithm-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],hasCurve:getLogarithmCoefficients(newCoords,state.asymptote)!==undefined}}}case "absolute-value":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-absolute-value-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],slope:getAbsoluteValueCoefficients(newCoords)[0]}}}case "tangent":{const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);const newCoords=[...state.coords];newCoords[action.index]=boundDestination;if(newCoords[0][X]===newCoords[1][X]||newCoords[0][Y]===newCoords[1][Y]){return state}return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-tangent-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y]}}}case "quadratic":{const newCoords=[...state.coords];const boundDestination=boundToEdgeAndSnapToGrid(action.destination,state);newCoords[action.index]=boundDestination;const QuadraticCoefficients=getQuadraticCoefficients(newCoords);if(QuadraticCoefficients===undefined){return state}const vertex=getQuadraticVertex(QuadraticCoefficients);return {...state,hasBeenInteractedWith:true,coords:setAtIndex({array:state.coords,index:action.index,newValue:boundDestination}),stateAnnouncement:{type:"move-quadratic-point",pointIndex:action.index,pointLabel:getCustomPointLabel(state.pointLabels,action.index),x:boundDestination[X],y:boundDestination[Y],vertex}}}default:throw new Error("The movePoint action is only for point, quadratic, and polygon graphs")}}function doMoveCenter(state,action){switch(state.type){case "circle":{const constrainedCenter=boundToEdgeAndSnapToGrid(action.destination,state);const newRadiusPoint=[...mafs.vec.add(state.radiusPoint,mafs.vec.sub(constrainedCenter,state.center))];const[xMin,xMax]=state.range[X];const[radX]=newRadiusPoint;if(radX<xMin||radX>xMax){const xJumpDist=(radX-constrainedCenter[X])*2;const possibleNewX=radX-xJumpDist;if(possibleNewX>=xMin&&possibleNewX<=xMax){newRadiusPoint[X]=possibleNewX;}else {return state}}return {...state,hasBeenInteractedWith:true,center:constrainedCenter,radiusPoint:newRadiusPoint,stateAnnouncement:{type:"move-center",x:constrainedCenter[X],y:constrainedCenter[Y]}}}case "exponential":{const newY=boundAndSnapToGrid(action.destination,state)[Y];if(newY===state.asymptote){return state}const expFutureHandle=getAsymptoteHandleCoord("horizontal",state.range,newY);if(state.coords.some(c=>c[X]===expFutureHandle[X]&&c[Y]===expFutureHandle[Y])){return state}return {...state,hasBeenInteractedWith:true,asymptote:newY,stateAnnouncement:{type:"move-exponential-asymptote",asymptoteY:newY}}}case "logarithm":{const newX=boundAndSnapToGrid(action.destination,state)[X];if(newX===state.asymptote){return state}const logFutureHandle=getAsymptoteHandleCoord("vertical",state.range,newX);if(state.coords.some(c=>c[X]===logFutureHandle[X]&&c[Y]===logFutureHandle[Y])){return state}return {...state,hasBeenInteractedWith:true,asymptote:newX,stateAnnouncement:{type:"move-logarithm-asymptote",asymptoteX:newX}}}default:throw new Error("The doMoveCenter action is only for circle, exponential, or logarithm graphs")}}function doMoveRadiusPoint(state,action){switch(state.type){case "circle":{const nextRadiusPoint=boundToEdgeAndSnapToGrid([action.destination[X],state.center[1]],state);if(kmath.vector.equal(nextRadiusPoint,state.center)){return state}return {...state,hasBeenInteractedWith:true,radiusPoint:nextRadiusPoint,stateAnnouncement:{type:"move-radius-point",x:nextRadiusPoint[X],y:nextRadiusPoint[Y],centerX:state.center[X],radius:mafs.vec.dist(state.center,nextRadiusPoint),pointLabel:getCustomPointLabel(state.pointLabels,0)}}}default:throw new Error("The doMoveRadiusPoint action is only for circle graphs")}}function doChangeSnapStep(state,action){if(___default.default.isEqual(state.snapStep,action.snapStep)){return state}return {...state,snapStep:action.snapStep}}function doChangeRange(state,action){if(___default.default.isEqual(state.range,action.range)){return state}return {...state,range:action.range}}function doAddPoint(state,action){if(!isUnlimitedGraphState(state)){return state}const{snapStep}=state;const snappedPoint=snap(snapStep,action.location);for(const point of state.coords){if(point[X]===snappedPoint[X]&&point[Y]===snappedPoint[Y]){return state}}const newCoords=[...state.coords,snappedPoint];return {...state,hasBeenInteractedWith:true,coords:newCoords,showRemovePointButton:true,focusedPointIndex:newCoords.length-1}}function doRemovePoint(state,action){if(!isUnlimitedGraphState(state)){return state}const nextFocusedPointIndex=state.coords.length>1?state.coords.length-2:null;return {...state,coords:state.coords.filter((_,i)=>i!==action.index),focusedPointIndex:nextFocusedPointIndex,showRemovePointButton:nextFocusedPointIndex!==null?true:false}}const getDeltaVertex=(maxMoves,minMoves,delta)=>{const[deltaX,deltaY]=delta;const maxXMove=Math.min(...maxMoves.map(move=>move[X]));const maxYMove=Math.min(...maxMoves.map(move=>move[Y]));const minXMove=Math.max(...minMoves.map(move=>move[X]));const minYMove=Math.max(...minMoves.map(move=>move[Y]));const dx=clamp(deltaX,minXMove,maxXMove);const dy=clamp(deltaY,minYMove,maxYMove);return [dx,dy]};const getChange=(coords,delta,constraintOpts)=>{const maxMoves=coords.map(point=>maxMove({...constraintOpts,point}));const minMoves=coords.map(point=>minMove({...constraintOpts,point}));const[dx,dy]=getDeltaVertex(maxMoves,minMoves,delta);return [dx,dy]};const constrainShapePreservingMove=(currentLine,newStart,constraintOpts)=>{const desiredDelta=mafs.vec.sub(newStart,currentLine[0]);const change=getChange(currentLine,desiredDelta,constraintOpts);const{snapStep}=constraintOpts;return [snap(snapStep,mafs.vec.add(currentLine[0],change)),snap(snapStep,mafs.vec.add(currentLine[1],change))]};function leq(a,b){return a<b||perseusCore.approximateEqual(a,b)}function boundAndSnapToGrid(point,{snapStep,range}){return snap(snapStep,bound$1({snapStep,range,point}))}function boundAndSnapAngleVertex({range,coords,snapStep},{destination}){const coordsCopy=[...coords];const startingVertex=coordsCopy[1];const insetAmount=mafs.vec.add(snapStep,[minDistanceBetweenAngleVertexAndSidePoint,minDistanceBetweenAngleVertexAndSidePoint]);const newVertex=clampToBox(inset(insetAmount,range),snap(snapStep,destination));const delta=mafs.vec.add(newVertex,reverseVector(startingVertex));const newPoints={};for(const i of [0,2]){const oldPoint=coordsCopy[i];let newPoint=mafs.vec.add(oldPoint,delta);let angle=getAngleFromVertex(newVertex,newPoint);angle*=Math.PI/180;newPoint=constrainToBoundsOnAngle(newPoint,angle,range,snapStep);newPoints[i]=newPoint;}newPoints[1]=newVertex;Object.entries(newPoints).forEach(([i,newPoint])=>{coordsCopy[i]=newPoint;});return coordsCopy}function tooClose(point1,point2,range){const safeDistance=2;const distance=mafs.vec.dist(point1,point2);return distance<safeDistance}function constrainToBoundsOnAngle(point,angle,range,snapStep){const lower=[range[0][0]+snapStep[0],range[1][0]+snapStep[0]];const upper=[range[0][1]-snapStep[1],range[1][1]-snapStep[1]];let result=point;if(result[0]<lower[0]){result=[lower[0],result[1]+(lower[0]-result[0])*Math.tan(angle)];}else if(result[0]>upper[0]){result=[upper[0],result[1]-(result[0]-upper[0])*Math.tan(angle)];}if(result[1]<lower[1]){result=[result[0]+(lower[1]-result[1])/Math.tan(angle),lower[1]];}else if(result[1]>upper[1]){result=[result[0]-(result[1]-upper[1])/Math.tan(angle),upper[1]];}return result}function boundAndSnapAngleEndPoints(destinationPoint,{range,coords,snapDegrees,angleOffsetDeg,snapStep},index){const snap=snapDegrees||1;const offsetDegrees=angleOffsetDeg||0;const coordsCopy=[...coords];const angleRange=[[range[0][0]+snapStep[0],range[0][1]-snapStep[0]],[range[1][0]+snapStep[1],range[1][1]-snapStep[1]]];const boundPoint=bound$1({snapStep:[0,0],range:angleRange,point:destinationPoint});coordsCopy[index]=boundPoint;const vertex=coords[1];let angle=getAngleFromVertex(coordsCopy[index],vertex);angle=Math.round((angle-offsetDegrees)/snap)*snap+offsetDegrees;const minDistance=minDistanceBetweenAngleVertexAndSidePoint+.01;const distance=Math.max(mafs.vec.dist(coordsCopy[index],vertex),minDistance);const snappedValue=mafs.vec.add(vertex,polar(distance,angle));return snappedValue}function angleSidePointsTooCloseToVertex(state){return tooClose(state.coords[0],state.coords[1],state.range)||tooClose(state.coords[2],state.coords[1],state.range)}function boundAndSnapToPolygonAngle(destinationPoint,{range,coords},index){const startingPoint=coords[index];return calculateAngleSnap(destinationPoint,range,coords,index,startingPoint)}function calculateAngleSnap(destinationPoint,range,coords,index,startingPoint){const coordsCopy=[...coords];coordsCopy[index]=bound$1({snapStep:[0,0],range,point:destinationPoint});const angles=angleMeasures(coordsCopy).map(angle=>angle*180/Math.PI);const rel=j=>{return (index+j+coordsCopy.length)%coordsCopy.length};___default.default.each([-1,1],function(j){angles[rel(j)]=Math.round(angles[rel(j)]);});const getAngle=function(a,vertex,b){const angle=getClockwiseAngle([coordsCopy[rel(a)],coordsCopy[rel(vertex)],coordsCopy[rel(b)]]);return angle};const innerAngles=[angles[rel(-1)]-getAngle(-2,-1,1),angles[rel(1)]-getAngle(-1,1,2)];innerAngles[2]=180-(innerAngles[0]+innerAngles[1]);if(innerAngles.some(function(angle){return leq(angle,1)})){return startingPoint}const knownSide=magnitude(vector(coordsCopy[rel(-1)],coordsCopy[rel(1)]));const onLeft=sign(ccw(coordsCopy[rel(-1)],coordsCopy[rel(1)],coordsCopy[index]))===1;const side=Math.sin(innerAngles[1]*Math.PI/180)/Math.sin(innerAngles[2]*Math.PI/180)*knownSide;const outerAngle=getAngleFromVertex(coordsCopy[rel(1)],coordsCopy[rel(-1)]);const offset=polar(side,outerAngle+(onLeft?1:-1)*innerAngles[0]);return kmath.vector.add(coordsCopy[rel(-1)],offset)}function boundAndSnapToSides(destinationPoint,{range,coords},index){const startingPoint=coords[index];return calculateSideSnap(destinationPoint,range,coords,index,startingPoint)}function calculateSideSnap(destinationPoint,range,coords,index,startingPoint){const boundedDestinationPoint=bound$1({snapStep:[0,0],range,point:destinationPoint});const rel=j=>{return (index+j+coords.length)%coords.length};const sides=[[coords[rel(-1)],boundedDestinationPoint],[boundedDestinationPoint,coords[rel(1)]],[coords[rel(-1)],coords[rel(1)]]].map(function(coords){return magnitude(vector(...coords))});___default.default.each([0,1],function(j){sides[j]=Math.round(sides[j]);});if(leq(sides[1]+sides[2],sides[0])||leq(sides[0]+sides[2],sides[1])||leq(sides[0]+sides[1],sides[2])){return startingPoint}const innerAngle=lawOfCosines(sides[0],sides[2],sides[1]);const outerAngle=getAngleFromVertex(coords[rel(1)],coords[rel(-1)]);const onLeft=sign(ccw(coords[rel(-1)],coords[rel(1)],boundedDestinationPoint))===1;const offset=polar(sides[0],outerAngle+(onLeft?1:-1)*innerAngle);return kmath.vector.add(coords[rel(-1)],offset)}function maxMove({snapStep,range,point}){const topRight=boundToEdgeAndSnapToGrid([Infinity,Infinity],{snapStep,range});return mafs.vec.sub(topRight,point)}function minMove({snapStep,range,point}){const bottomLeft=boundToEdgeAndSnapToGrid([-Infinity,-Infinity],{snapStep,range});return mafs.vec.sub(bottomLeft,point)}const coordsOverlap=coords=>coords.some((coord,i)=>coords.some((c,j)=>i!==j&&kmath.vector.equal(coord,c)));function updateAtIndex(args){const{array,index,update}=args;const newValue=update(array[index]);return setAtIndex({array,index,newValue})}function setAtIndex(args){const{array,index,newValue}=args;const copy=[...array];copy[index]=newValue;return copy}
|
|
2049
2040
|
|
|
2050
2041
|
const{clockwise}=kmath.geometry;const{convertRadiansToDegrees}=kmath.angles;function renderPolygonGraph(state,dispatch,i18n,markings){return {graph:jsxRuntimeExports.jsx(PolygonGraph,{graphState:state,dispatch:dispatch}),interactiveElementsDescription:describePolygonGraph(state,i18n,markings).srPolygonInteractiveElements}}const PolygonGraph=props=>{const{dispatch}=props;const{numSides,coords,snapStep,snapTo="grid"}=props.graphState;const graphConfig=useGraphConfig();const polygonRef=React__namespace.useRef(null);const polygonHitboxRef=React__namespace.useRef(null);const pointsRef=React__namespace.useRef([]);const lastMoveTimeRef=React__namespace.useRef(0);const{range:[x,y]}=graphConfig;const[[left,top]]=useTransformVectorsToPixels([x[0],y[1]]);const dragReferencePoint=coords[0];const constrain=getKeyboardMovementConstraintForPolygon(snapStep,snapTo);const moveAll=newStart=>{dispatch(actions.polygon.moveAll(newStart));};useDraggable({gestureTarget:polygonRef,point:dragReferencePoint,onMove:moveAll,constrainKeyboardMovement:constrain});const{dragging}=useDraggable({gestureTarget:polygonHitboxRef,point:dragReferencePoint,onMove:moveAll,constrainKeyboardMovement:constrain});const[hovered,setHovered]=React__namespace.useState(false);const[focusVisible,setFocusVisible]=React__namespace.useState(false);const polygonHitbox=useHitbox({shape:{kind:"polygon",vertices:coords},hitboxRef:polygonHitboxRef,layer:"body",dragging,onHoverChange:setHovered,testId:"movable-polygon__hitbox"});React__namespace.useEffect(()=>{const focusedIndex=props.graphState.focusedPointIndex;if(focusedIndex!=null){pointsRef.current[focusedIndex]?.focus();}},[props.graphState.focusedPointIndex,props.graphState.coords.length,pointsRef]);React__namespace.useEffect(()=>{if(numSides==="unlimited"&&props.graphState.coords.length>2){dispatch(actions.polygon.closePolygon());}},[]);const statefulProps={...props,graphConfig,polygonRef,pointsRef,lastMoveTimeRef,left,top,dragging,points:coords,hovered,setHovered,focusVisible,setFocusVisible};return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[polygonHitbox,numSides==="unlimited"?jsxRuntimeExports.jsx(UnlimitedPolygonGraph,{...statefulProps}):jsxRuntimeExports.jsx(LimitedPolygonGraph,{...statefulProps})]})};const LimitedPolygonGraph=statefulProps=>{const{dispatch,hovered,setHovered,focusVisible,setFocusVisible,graphConfig,polygonRef,lastMoveTimeRef,dragging,points}=statefulProps;const{showAngles,showSides,range,snapTo="grid",snapStep,pointLabels}=statefulProps.graphState;const{disableKeyboardInteraction,interactiveColor}=graphConfig;const{strings,locale}=usePerseusI18n();const buildLabel=usePointAriaLabel(pointLabels);const id=React__namespace.useId();const lines=getLines(points);const polygonPointsNumId=id+"-points-num";const polygonPointsId=id+"-points";const{srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints,srPolygonElementsNum}=describePolygonGraph(statefulProps.graphState,{strings,locale},statefulProps.graphConfig.markings);return jsxRuntimeExports.jsxs("g",{"aria-label":srPolygonGraph,"aria-describedby":`${polygonPointsNumId} ${polygonPointsId}`,children:[jsxRuntimeExports.jsx(mafs.Polygon,{points:[...points],color:interactiveColor,svgPolygonProps:{strokeWidth:focusVisible?"var(--movable-line-stroke-weight-active)":"var(--movable-line-stroke-weight)",style:{fill:"transparent"},"aria-hidden":true}}),points.map((point,i)=>{const pt1=points.at(i-1);const pt2=points[(i+1)%points.length];if(!pt1||!pt2){return null}return jsxRuntimeExports.jsx(PolygonAngle,{centerPoint:point,endPoints:[pt1,pt2],areEndPointsClockwise:clockwise(points),showAngles:!!showAngles,snapTo:snapTo},"angle-"+i)}),showSides&&lines.map(([start,end],i)=>{const[x,y]=mafs.vec.midpoint(start,end);const length=mafs.vec.dist(start,end);const isApprox=!Number.isInteger(length);return jsxRuntimeExports.jsx(TextLabel,{x:x,y:y,children:isApprox?`≈ ${length.toFixed(snapTo==="sides"?0:1)}`:length},"side-"+i)}),jsxRuntimeExports.jsx(mafs.Polygon,{points:[...points],color:"transparent",svgPolygonProps:{ref:polygonRef,tabIndex:disableKeyboardInteraction?-1:0,strokeWidth:TARGET_SIZE,style:{cursor:dragging?"grabbing":"grab",fill:hovered?"var(--mafs-blue)":"transparent"},onMouseEnter:()=>setHovered(true),onMouseLeave:()=>setHovered(false),onKeyDownCapture:()=>{setFocusVisible(hasFocusVisible(polygonRef.current));},onFocus:()=>{setFocusVisible(hasFocusVisible(polygonRef.current));},onBlur:()=>setFocusVisible(hasFocusVisible(polygonRef.current)),className:"movable-polygon",role:"button","aria-label":srPolygonGraphPoints?`${srPolygonElementsNum} ${srPolygonGraphPoints}`:srPolygonElementsNum,"aria-disabled":disableKeyboardInteraction}}),points.map((point,i)=>{const angleId=`${id}-angle-${i}`;const side1Id=`${id}-point-${i}-side-1`;const side2Id=`${id}-point-${i}-side-2`;const angle=getAngleFromPoints(points,i);const angleDegree=angle?convertRadiansToDegrees(angle):null;const sidesArray=getSideLengthsFromPoints(points,i);const{pointIndex:point1Index,sideLength:side1Length}=sidesArray[0];const{pointIndex:point2Index,sideLength:side2Length}=sidesArray[1];return jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx(MovablePoint$3,{ariaDescribedBy:`${angleId} ${side1Id} ${side2Id}`,ariaLabel:buildLabel(i,point),constrain:getKeyboardMovementConstraintForPoint(points,i,range,snapStep,snapTo),point:point,sequenceNumber:i+1,onMove:destination=>{const now=Date.now();const targetFPS=40;const moveThresholdTime=1e3/targetFPS;if(now-lastMoveTimeRef.current>moveThresholdTime){dispatch(actions.polygon.movePoint(i,destination));lastMoveTimeRef.current=now;}}}),angleDegree&&jsxRuntimeExports.jsx(SRDescInSVG,{id:angleId,children:Number.isInteger(angleDegree)?strings.srPolygonPointAngle({angle:angleDegree}):strings.srPolygonPointAngleApprox({angle:srFormatNumber(angleDegree,locale,1)})}),jsxRuntimeExports.jsx(SRDescInSVG,{id:side1Id,children:getPolygonSideString(side1Length,point1Index,strings,locale)}),jsxRuntimeExports.jsx(SRDescInSVG,{id:side2Id,children:getPolygonSideString(side2Length,point2Index,strings,locale)})]},"point-"+i)}),jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsNumId,children:srPolygonGraphPointsNum}),srPolygonGraphPoints&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsId,children:srPolygonGraphPoints})]})};const UnlimitedPolygonGraph=statefulProps=>{const{dispatch,graphConfig,left,top,pointsRef,points}=statefulProps;const{coords,closedPolygon,pointLabels}=statefulProps.graphState;const{strings,locale}=usePerseusI18n();const buildLabel=usePointAriaLabel(pointLabels);const{interactiveColor}=useGraphConfig();const[isCurrentlyDragging,setIsCurrentlyDragging]=React.useState(false);const dragEndCallbackTimer=wonderBlocksTiming.useTimeout(()=>setIsCurrentlyDragging(false),400);const id=React__namespace.useId();const polygonPointsNumId=id+"-points-num";const polygonPointsId=id+"-points";if(closedPolygon){const closedPolygonProps={...statefulProps,numSides:coords.length};return jsxRuntimeExports.jsx(LimitedPolygonGraph,{...closedPolygonProps})}const{graphDimensionsInPixels}=graphConfig;const widthPx=graphDimensionsInPixels[0];const heightPx=graphDimensionsInPixels[1];const emptyGraph=coords.length===0;const{srPolygonGraph,srPolygonGraphPointsNum,srPolygonGraphPoints}=describePolygonGraph(statefulProps.graphState,{strings,locale},statefulProps.graphConfig.markings);return jsxRuntimeExports.jsxs("g",{"aria-label":emptyGraph?strings.srUnlimitedPolygonEmpty:srPolygonGraph,"aria-describedby":`${polygonPointsNumId} ${polygonPointsId}`,children:[jsxRuntimeExports.jsx(mafs.Polyline,{points:[...points],color:interactiveColor,svgPolylineProps:{strokeWidth:"var(--movable-line-stroke-weight)",style:{fill:"transparent"},"aria-hidden":true}}),jsxRuntimeExports.jsx("rect",{"aria-hidden":true,style:{fill:"none",pointerEvents:"all",cursor:"crosshair"},width:widthPx,height:heightPx,x:left,y:top,onClick:event=>{if(isCurrentlyDragging){return}const elementRect=event.currentTarget.getBoundingClientRect();const zoomFactor=getCSSZoomFactor(event.currentTarget);const x=(event.clientX-elementRect.x)/zoomFactor;const y=(event.clientY-elementRect.y)/zoomFactor;const graphCoordinates=pixelsToVectors([[x,y]],graphConfig);dispatch(actions.polygon.addPoint(graphCoordinates[0]));}}),coords.map((point,i)=>{const angleId=`${id}-angle-${i}`;let sideIds="";const hasAngle=i>0&&i<coords.length-1;const angle=hasAngle?getAngleFromPoints(points,i):null;const angleDegree=angle?convertRadiansToDegrees(angle):null;const sidesArray=getSideLengthsFromPoints(points,i,true);for(let sideIndex=0;sideIndex<sidesArray.length;sideIndex++){sideIds+=`${id}-point-${i}-side-${sideIndex} `;}return jsxRuntimeExports.jsxs("g",{children:[jsxRuntimeExports.jsx(MovablePoint$3,{ariaDescribedBy:`${angleId} ${sideIds}`,ariaLabel:buildLabel(i,point),point:point,sequenceNumber:i+1,onDragStart:()=>{dragEndCallbackTimer.clear();setIsCurrentlyDragging(true);},onMove:destination=>{dispatch(actions.polygon.movePoint(i,destination));},onDragEnd:()=>{dragEndCallbackTimer.set();},ref:ref=>{pointsRef.current[i]=ref;},onFocus:()=>{dispatch(actions.polygon.focusPoint(i));},onClick:()=>{if(i===0&&getArrayWithoutDuplicates(coords).length>=3){dispatch(actions.polygon.closePolygon());}dispatch(actions.polygon.clickPoint(i));}}),angleDegree&&jsxRuntimeExports.jsx(SRDescInSVG,{id:angleId,children:Number.isInteger(angleDegree)?strings.srPolygonPointAngle({angle:angleDegree}):strings.srPolygonPointAngleApprox({angle:srFormatNumber(angleDegree,locale,1)})}),sidesArray.map(({pointIndex,sideLength},j)=>jsxRuntimeExports.jsx(SRDescInSVG,{id:`${id}-point-${i}-side-${j}`,children:getPolygonSideString(sideLength,pointIndex,strings,locale)},`${id}-point-${i}-side-${j}`))]},"point-"+i)}),coords.length>0&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsNumId,children:srPolygonGraphPointsNum}),srPolygonGraphPoints&&jsxRuntimeExports.jsx(SRDescInSVG,{id:polygonPointsId,children:srPolygonGraphPoints})]})};function getLines(points){return points.map((point,i)=>{const next=points[(i+1)%points.length];return [point,next]})}const hasFocusVisible=element=>{const matches=selector=>element?.matches(selector)??false;try{return matches(":focus-visible")}catch{return matches(":focus")}};function getKeyboardMovementConstraintForPoint(points,index,range,snapStep,snapTo){switch(snapTo){case "grid":return p=>snap(snapStep,p);case "sides":return getSideSnapConstraint(points,index,range);case "angles":return getAngleSnapConstraint(points,index,range);default:throw new wonderStuffCore.UnreachableCaseError(snapTo)}}function getKeyboardMovementConstraintForPolygon(snapStep,snapTo){switch(snapTo){case "grid":return p=>snap(snapStep,p);case "sides":case "angles":return p=>p;default:throw new wonderStuffCore.UnreachableCaseError(snapTo)}}function getSideSnapConstraint(points,index,range){const newPoints=[...points];const pointToBeMoved=newPoints[index];const movePointWithConstraint=moveFunc=>{let destinationAttempt=moveFunc(pointToBeMoved);let newPoint=pointToBeMoved;while(newPoint[0]===pointToBeMoved[0]&&newPoint[1]===pointToBeMoved[1]&&isInBound({range,point:destinationAttempt})){newPoint=calculateSideSnap(destinationAttempt,range,newPoints,index,pointToBeMoved);destinationAttempt=moveFunc(destinationAttempt);}return newPoint};return {up:movePointWithConstraint(coord=>mafs.vec.add(coord,[0,1])),down:movePointWithConstraint(coord=>mafs.vec.sub(coord,[0,1])),left:movePointWithConstraint(coord=>mafs.vec.sub(coord,[1,0])),right:movePointWithConstraint(coord=>mafs.vec.add(coord,[1,0]))}}function getAngleSnapConstraint(points,index,range){const newPoints=[...points];const pointToBeMoved=newPoints[index];const movePointWithConstraint=moveFunc=>{let destinationAttempt=bound$1({snapStep:[0,0],range,point:moveFunc(pointToBeMoved)});let newPoint=pointToBeMoved;while(newPoint[0]===pointToBeMoved[0]&&newPoint[1]===pointToBeMoved[1]&&isInBound({range,point:destinationAttempt})){newPoint=calculateAngleSnap(destinationAttempt,range,newPoints,index,pointToBeMoved);destinationAttempt=moveFunc(destinationAttempt);}return newPoint};return {up:movePointWithConstraint(coord=>mafs.vec.add(coord,[0,.1])),down:movePointWithConstraint(coord=>mafs.vec.sub(coord,[0,.1])),left:movePointWithConstraint(coord=>mafs.vec.sub(coord,[.1,0])),right:movePointWithConstraint(coord=>mafs.vec.add(coord,[.1,0]))}}
|
|
2051
2042
|
|
|
@@ -2075,11 +2066,11 @@ function useReinitializeOnGraphChange(props,dispatch){const{graph}=props;const n
|
|
|
2075
2066
|
|
|
2076
2067
|
const StatefulMafsGraph=React__namespace.forwardRef(function StatefulMafsGraphWithRef(props,ref){const{onChange,graph}=props;const{strings,locale}=usePerseusI18n();const[state,dispatch]=React__namespace.useReducer(interactiveGraphReducer,props,initializeGraphState);React.useImperativeHandle(ref,()=>({getUserInput:()=>getGradableGraph(state,graph)}));const prevState=React.useRef(state);React.useEffect(()=>{if(prevState.current!==state){onChange(mafsStateToInteractiveGraph(state,graph));}prevState.current=state;},[onChange,state,graph]);React.useEffect(()=>{if(!state.stateAnnouncement){return}wonderBlocksAnnouncer.announceMessage({message:getAnnouncementText(state.stateAnnouncement,strings,locale)});},[state.stateAnnouncement,strings,locale]);const[xSnap,ySnap]=props.snapStep;React.useEffect(()=>{dispatch(changeSnapStep([xSnap,ySnap]));},[dispatch,xSnap,ySnap]);const[[xMinRange,xMaxRange],[yMinRange,yMaxRange]]=props.range;React.useEffect(()=>{dispatch(changeRange([[xMinRange,xMaxRange],[yMinRange,yMaxRange]]));},[dispatch,xMinRange,xMaxRange,yMinRange,yMaxRange]);useReinitializeOnGraphChange(props,dispatch);if(props.static&&props.correct&&props.graded!==false){return jsxRuntimeExports.jsx(MafsGraph,{...props,state:initializeGraphState({...props,graph:props.correct}),dispatch:dispatch})}return jsxRuntimeExports.jsx(MafsGraph,{...props,state:state,dispatch:dispatch})});
|
|
2077
2068
|
|
|
2078
|
-
const defaultBackgroundImage={url:null};class InteractiveGraph extends React__namespace.Component{static getEquationString(props){return getEquationString$1(props)}getUserInput(){if(this.mafsRef.current?.getUserInput){return this.mafsRef.current.getUserInput()}throw new perseusCore.PerseusError("Cannot getUserInput from a graph that has never rendered",perseusCore.Errors.NotAllowed)}getPromptJSON(){return getPromptJSON$f(this.props,this.getUserInput())}getSerializedState(){const{userInput
|
|
2069
|
+
const defaultBackgroundImage={url:null};class InteractiveGraph extends React__namespace.Component{static getEquationString(props){return getEquationString$1(props)}getUserInput(){if(this.mafsRef.current?.getUserInput){return this.mafsRef.current.getUserInput()}throw new perseusCore.PerseusError("Cannot getUserInput from a graph that has never rendered",perseusCore.Errors.NotAllowed)}getPromptJSON(){return getPromptJSON$f(this.props,this.getUserInput())}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,graph:this.props.userInput}}render(){const box=getInteractiveBoxFromSizeClass(this.props.containerSizeClass);const gridStep=this.props.gridStep||Util.getGridStep(this.props.range,this.props.step,box[0]);const snapStep=this.props.snapStep||Util.snapStepFromGridStep(gridStep);const mafsProps={...this.props,graph:this.props.userInput,onChange:()=>this.props.handleUserInput(this.mafsRef.current?.getUserInput())};const showUngradedText=this.props.graded===false&&this.props.graph.type!=="none";const ungradedDescriptionId=`interactive-graph-ungraded-description-${this.props.widgetId?.replace(/\s+/g,"-")}`;return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[showUngradedText&&jsxRuntimeExports.jsx("p",{id:ungradedDescriptionId,children:this.context.strings.ungradedInteractiveGraph}),jsxRuntimeExports.jsx(StatefulMafsGraph,{...mafsProps,ref:this.mafsRef,gridStep:gridStep,snapStep:snapStep,box:box,showTooltips:!!this.props.showTooltips,readOnly:this.props.apiOptions?.readOnly,widgetId:this.props.widgetId,graded:this.props.graded,ungradedDescriptionId:showUngradedText?ungradedDescriptionId:undefined})]})}constructor(...args){super(...args),this.mafsRef=React__namespace.createRef();}}InteractiveGraph.contextType=PerseusI18nContext;InteractiveGraph.defaultProps={labels:["$x$","$y$"],labelLocation:"onAxis",range:[[-10,10],[-10,10]],showAxisArrows:{xMin:true,xMax:true,yMin:true,yMax:true},showAxisTicks:{x:true,y:true},step:[1,1],backgroundImage:defaultBackgroundImage,markings:"graph",showTooltips:false,showProtractor:false,userInput:{type:"none"}};function getUserInputFromSerializedState$b(serializedState){return serializedState.graph}function getStartUserInput$b(options){return options.graph}function getCorrectUserInput$5(options){return options.correct}var InteractiveGraph$1 = {name:"interactive-graph",displayName:"Interactive graph",widget:InteractiveGraph,getStartUserInput: getStartUserInput$b,getCorrectUserInput: getCorrectUserInput$5,getUserInputFromSerializedState: getUserInputFromSerializedState$b,supportsUngraded:true};
|
|
2079
2070
|
|
|
2080
2071
|
const movableTypeToComponent={PLOT:Graphie.Plot,PARABOLA:Graphie.Parabola,SINUSOID:Graphie.Sinusoid};const DEFAULT_BACKGROUND_IMAGE={url:null};const getEquationString=plot=>{if(plot.type&&plot.coords){const handler=perseusCore.GrapherUtil.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 kmath.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=perseusCore.GrapherUtil.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=___default.default.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(perseusCore.GrapherUtil.functionForType(type).url),alt:capitalized})}};
|
|
2081
2072
|
|
|
2082
|
-
const MovablePoint$2=Graphie.MovablePoint;const MovableLine$1=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__namespace.Component{render(){const pointForCoord=(coord,i)=>{return jsxRuntimeExports.jsx(MovablePoint$2,{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||!kmath.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=perseusCore.deepClone(this._coords());const oldCoord=perseusCore.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 kmath.point.reflectOverLine(coord,asymptote)});}else {coords=perseusCore.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,allowZoom:false,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,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.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 React.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$1,{onMove:(newCoord,oldCoord)=>{const delta=kmath.vector.subtract(newCoord,oldCoord);const newAsymptote=this._asymptote().map(coord=>kmath.vector.add(coord,delta));this.props.onChange({asymptote:newAsymptote});},constraints:[Interactive2.MovableLine.constraints.bound(),Interactive2.MovableLine.constraints.snap(),(newCoord,oldCoord)=>{const delta=kmath.vector.subtract(newCoord,oldCoord);const proposedAsymptote=this._asymptote().map(coord=>kmath.vector.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$2,{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__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"grapher",widgetSubType:"null",widgetId:this.props.widgetId}});}_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}getPromptJSON(){return getPromptJSON$g(this.props)}getSerializedState(){const{userInput:_,correct:__,...rest}=this.props;return {...rest,plot:this.props.userInput}}getAvailableTypes(){if(this.props.static){invariant__default.default(this.props.correct,"static widgets must have a correct answer");return [this.props.correct.type]}return this.props.availableTypes}renderLegacyGrapher(){const availableTypes=this.getAvailableTypes();const type=this.props.userInput.type;const coords=this.props.userInput.coords;const asymptote="asymptote"in this.props.userInput?this.props.userInput.asymptote:undefined;const typeSelector=jsxRuntimeExports.jsx("div",{style:typeSelectorStyle,children:jsxRuntimeExports.jsx(ButtonGroup,{value:type,allowEmpty:true,buttons: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&&perseusCore.GrapherUtil.functionForType(type),coords:coords,asymptote:asymptote,static:this.props.static,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}),availableTypes.length>1&&typeSelector]})}render(){const interactiveGraphOptions=perseusCore.convertGrapherOptionsToInteractiveGraph(this.props);if(interactiveGraphOptions==null){return this.renderLegacyGrapher()}const interactiveGraphUserInput=perseusCore.convertGrapherUserInputToInteractiveGraph(this.props.userInput);return jsxRuntimeExports.jsx(InteractiveGraph$1.widget,{...this.props,...interactiveGraphOptions,userInput:interactiveGraphUserInput,handleUserInput:interactiveGraphUserInput=>this.props.handleUserInput(perseusCore.convertInteractiveGraphUserInputToGrapher(interactiveGraphUserInput))})}constructor(...args){super(...args),this.handlePlotChanges=newPlot=>{const plot={...this.props.userInput,...newPlot};this.props.handleUserInput(plot);this.props.trackInteraction();},this.handleActiveTypeChange=newType=>{const graph=this.props.graph;const plot={...this.props.userInput,...defaultPlotProps(newType,graph)};this.props.handleUserInput(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();}};}}function getUserInputFromSerializedState$a(serializedState){return serializedState.plot}function getStartUserInput$a(options){if(options.availableTypes.length===1){const graph=options.graph;const type=chooseType(options.availableTypes);if(type){return defaultPlotProps(type,graph)}}return DEFAULT_GRAPHER_PROPS.plot}function getCorrectUserInput$4(options){invariant__default.default(options.correct,"getCorrectUserInput should only be called for static widgets");return options.correct}const WrappedGrapher=withDependencies(Grapher);var Grapher$1 = {name:"grapher",displayName:"Grapher",hidden:true,widget:WrappedGrapher,getUserInputFromSerializedState: getUserInputFromSerializedState$a,getStartUserInput: getStartUserInput$a,getCorrectUserInput: getCorrectUserInput$4};
|
|
2073
|
+
const MovablePoint$2=Graphie.MovablePoint;const MovableLine$1=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__namespace.Component{render(){const pointForCoord=(coord,i)=>{return jsxRuntimeExports.jsx(MovablePoint$2,{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||!kmath.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=perseusCore.deepClone(this._coords());const oldCoord=perseusCore.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 kmath.point.reflectOverLine(coord,asymptote)});}else {coords=perseusCore.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,allowZoom:false,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,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.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 React.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$1,{onMove:(newCoord,oldCoord)=>{const delta=kmath.vector.subtract(newCoord,oldCoord);const newAsymptote=this._asymptote().map(coord=>kmath.vector.add(coord,delta));this.props.onChange({asymptote:newAsymptote});},constraints:[Interactive2.MovableLine.constraints.bound(),Interactive2.MovableLine.constraints.snap(),(newCoord,oldCoord)=>{const delta=kmath.vector.subtract(newCoord,oldCoord);const proposedAsymptote=this._asymptote().map(coord=>kmath.vector.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$2,{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__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"grapher",widgetSubType:"null",widgetId:this.props.widgetId}});}_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}getPromptJSON(){return getPromptJSON$g(this.props)}getSerializedState(){const{userInput,correct,...rest}=this.props;return {...rest,plot:this.props.userInput}}getAvailableTypes(){if(this.props.static){invariant__default.default(this.props.correct,"static widgets must have a correct answer");return [this.props.correct.type]}return this.props.availableTypes}renderLegacyGrapher(){const availableTypes=this.getAvailableTypes();const type=this.props.userInput.type;const coords=this.props.userInput.coords;const asymptote="asymptote"in this.props.userInput?this.props.userInput.asymptote:undefined;const typeSelector=jsxRuntimeExports.jsx("div",{style:typeSelectorStyle,children:jsxRuntimeExports.jsx(ButtonGroup,{value:type,allowEmpty:true,buttons: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&&perseusCore.GrapherUtil.functionForType(type),coords:coords,asymptote:asymptote,static:this.props.static,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}),availableTypes.length>1&&typeSelector]})}render(){const interactiveGraphOptions=perseusCore.convertGrapherOptionsToInteractiveGraph(this.props);if(interactiveGraphOptions==null){return this.renderLegacyGrapher()}const interactiveGraphUserInput=perseusCore.convertGrapherUserInputToInteractiveGraph(this.props.userInput);return jsxRuntimeExports.jsx(InteractiveGraph$1.widget,{...this.props,...interactiveGraphOptions,userInput:interactiveGraphUserInput,handleUserInput:interactiveGraphUserInput=>this.props.handleUserInput(perseusCore.convertInteractiveGraphUserInputToGrapher(interactiveGraphUserInput))})}constructor(...args){super(...args),this.handlePlotChanges=newPlot=>{const plot={...this.props.userInput,...newPlot};this.props.handleUserInput(plot);this.props.trackInteraction();},this.handleActiveTypeChange=newType=>{const graph=this.props.graph;const plot={...this.props.userInput,...defaultPlotProps(newType,graph)};this.props.handleUserInput(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();}};}}function getUserInputFromSerializedState$a(serializedState){return serializedState.plot}function getStartUserInput$a(options){if(options.availableTypes.length===1){const graph=options.graph;const type=chooseType(options.availableTypes);if(type){return defaultPlotProps(type,graph)}}return DEFAULT_GRAPHER_PROPS.plot}function getCorrectUserInput$4(options){invariant__default.default(options.correct,"getCorrectUserInput should only be called for static widgets");return options.correct}const WrappedGrapher=withDependencies(Grapher);var Grapher$1 = {name:"grapher",displayName:"Grapher",hidden:true,widget:WrappedGrapher,getUserInputFromSerializedState: getUserInputFromSerializedState$a,getStartUserInput: getStartUserInput$a,getCorrectUserInput: getCorrectUserInput$4};
|
|
2083
2074
|
|
|
2084
2075
|
const getPromptJSON$e=rendererJSON=>{if(!rendererJSON){return {type:"group",content:"",widgets:{}}}return {...rendererJSON,type:"group"}};
|
|
2085
2076
|
|
|
@@ -2087,7 +2078,7 @@ class Group extends React__namespace.Component{componentDidMount(){this.forceUpd
|
|
|
2087
2078
|
|
|
2088
2079
|
const getPromptJSON$d=()=>{return getUnsupportedPromptJSON("iframe")};
|
|
2089
2080
|
|
|
2090
|
-
const{updateQueryString}=Util;class Iframe extends React__namespace.Component{componentDidMount(){$__default.default(window).on("message",this.handleMessageEvent);}componentWillUnmount(){$__default.default(window).off("message",this.handleMessageEvent);}getPromptJSON(){return getPromptJSON$d()}getSerializedState(){const{userInput
|
|
2081
|
+
const{updateQueryString}=Util;class Iframe extends React__namespace.Component{componentDidMount(){$__default.default(window).on("message",this.handleMessageEvent);}componentWillUnmount(){$__default.default(window).off("message",this.handleMessageEvent);}getPromptJSON(){return getPromptJSON$d()}getSerializedState(){const{userInput,alignment,...rest}=this.props;return rest}render(){const style={width:String(this.props.width),height:String(this.props.height)};const{InitialRequestUrl}=getDependencies();Object.entries(style).forEach(([key,value])=>{if(!value.endsWith("%")&&!value.endsWith("px")){style[key]=value+"px";}});let url=this.props.url;if(url&&url.length&&url.indexOf("http")!==0){url="https://www.khanacademy.org/computer-programming/program/"+url+"/embedded?buttons=no&embed=yes&editor=no&author=no";url=updateQueryString(url,"width",`${this.props.width}`);url=updateQueryString(url,"height",`${this.props.height}`);url=updateQueryString(url,"origin",InitialRequestUrl.origin);}if(this.context?.locale&&url?.includes("khanacademy.org")){url=updateQueryString(url,"lang",this.context.locale);}if(this.props.settings){const settings={};this.props.settings.forEach(setting=>{if(setting.name&&setting.value){settings[setting.name]=setting.value;}});url=updateQueryString(url,"settings",JSON.stringify(settings));}let sandboxProperties="allow-same-origin allow-scripts";sandboxProperties+=" allow-top-navigation";return jsxRuntimeExports.jsx("iframe",{title:this.context.strings.embeddedContent,sandbox:sandboxProperties,style:style,src:url,allowFullScreen:this.props.allowFullScreen})}constructor(...args){super(...args),this.handleMessageEvent=e=>{let data={};try{data=JSON.parse(e.originalEvent.data);}catch{return}if(data.testsPassed===undefined){return}const status=data.testsPassed?"correct":"incorrect";this.props.handleUserInput({status:status,message:data.message});};}}Iframe.contextType=PerseusI18nContext;Iframe.defaultProps={allowFullScreen:false,allowTopNavigation:false,userInput:{status:"incomplete",message:null}};function getUserInputFromSerializedState$8(serializedState){return {status:serializedState.status,message:serializedState.message}}function getStartUserInput$8(){return {status:"incomplete",message:null}}var Iframe$1 = {name:"iframe",displayName:"Iframe (deprecated)",widget:Iframe,hidden:true,getStartUserInput: getStartUserInput$8,getUserInputFromSerializedState: getUserInputFromSerializedState$8};
|
|
2091
2082
|
|
|
2092
2083
|
const getPromptJSON$c=widgetData=>{return {type:"image",options:{altText:widgetData.alt,title:widgetData.title,caption:widgetData.caption,imageUrl:widgetData.backgroundImage.url}}};
|
|
2093
2084
|
|
|
@@ -2109,7 +2100,7 @@ const ImageWidget=React.forwardRef(function ImageWidget(props,ref){const{apiOpti
|
|
|
2109
2100
|
|
|
2110
2101
|
const getPromptJSON$b=()=>{return getUnsupportedPromptJSON("interaction")};
|
|
2111
2102
|
|
|
2112
|
-
const Label=Graphie.Label;const Line$1=Graphie.Line;const MovablePoint$1=Graphie.MovablePoint;const MovableLine=Graphie.MovableLine;const Plot=Graphie.Plot;const PlotParametric=Graphie.PlotParametric;const Point=Graphie.Point;const Rect=Graphie.Rect;const{unescapeMathMode}=Util;const KAShashFunc=(expr,options)=>{options=options||{};let result=expr+"||"+options.decimal_separator+"||";const functions=options.functions;const functionsLength=functions?functions.length:0;for(let i=0;i<functionsLength;i++){result+=functions[i]+"|";}return result};const _parseCache=Object.create(null);const KASparse=(expr,options)=>{const hash=KAShashFunc(expr,options);let cached=_parseCache[hash];if(cached){return cached}cached=KAS__namespace.parse(expr,options);_parseCache[hash]=cached;return cached};const _compileCache=Object.create(null);const KAScompile=(expr,options)=>{const hash=KAShashFunc(expr,options);let cached=_compileCache[hash];if(cached){return cached}const parsed=KAS__namespace.parse(expr,options).expr;cached=parsed?parsed.compile():function(){return 0};_compileCache[hash]=cached;return cached};class Interaction extends React__namespace.Component{UNSAFE_componentWillReceiveProps(nextProps){if(!___default.default.isEqual(this.props.elements,nextProps.elements)){this.setState({variables:_getInitialVariables(nextProps.elements),functions:_getInitialFunctions(nextProps.elements)});}}getPromptJSON(){return getPromptJSON$b()}render(){const range=this.props.graph.range;let labels=this.props.graph.labels;if(this.props.graph.markings==="graph"){labels=this.props.graph.labels.map(label=>label.startsWith("$")&&label.endsWith("$")?label.slice(1,-1):label);}return jsxRuntimeExports.jsxs(Graphie,{box:this.props.graph.box,range:this.props.graph.range,options:this.props.graph,setup:this._setupGraphie,children:[this.props.graph.markings==="graph"&&jsxRuntimeExports.jsx(Label,{coord:[0,range[1][1]],text:labels[1],direction:"above"}),this.props.graph.markings==="graph"&&jsxRuntimeExports.jsx(Label,{coord:[range[0][1],0],text:labels[0],direction:"right"}),___default.default.map(this.props.elements,function(element,n){if(element.type==="point"){return jsxRuntimeExports.jsx(Point,{coord:[this._eval(element.options.coordX),this._eval(element.options.coordY)],color:element.options.color},element.key)}if(element.type==="line"){const start=[this._eval(element.options.startX),this._eval(element.options.startY)];const end=[this._eval(element.options.endX),this._eval(element.options.endY)];return jsxRuntimeExports.jsx(Line$1,{start:start,end:end,style:{stroke:element.options.color,strokeWidth:element.options.strokeWidth,strokeDasharray:element.options.strokeDasharray,arrows:element.options.arrows}},element.key)}if(element.type==="movable-point"){const constraints=[coord=>{const coordX=Math.max(this._eval(element.options.constraintXMin),Math.min(this._eval(element.options.constraintXMax),coord[0]));const coordY=Math.max(this._eval(element.options.constraintYMin),Math.min(this._eval(element.options.constraintYMax),coord[1]));return [coordX,coordY]}];if(element.options.constraint==="snap"){constraints.push(MovablePoint$1.constraints.snap(element.options.snap));}else if(element.options.constraint==="x"){constraints.push(coord=>{return [this._eval(element.options.constraintFn,{y:coord[1]}),coord[1]]});}else if(element.options.constraint==="y"){constraints.push(coord=>{return [coord[0],this._eval(element.options.constraintFn,{x:coord[0]})]});}return jsxRuntimeExports.jsx(MovablePoint$1,{coord:[this.state.variables["x_"+element.options.varSubscript],this.state.variables["y_"+element.options.varSubscript]],constraints:constraints,foo_x:element.options.constraint,foo_y:element.options.constraintFn,foo_z:element.options.snap,onMove:___default.default.partial(this._updatePointLocation,element.options.varSubscript)},element.key)}if(element.type==="movable-line"){const constraints=[coord=>{const coordX=Math.max(this._eval(element.options.constraintXMin),Math.min(this._eval(element.options.constraintXMax),coord[0]));const coordY=Math.max(this._eval(element.options.constraintYMin),Math.min(this._eval(element.options.constraintYMax),coord[1]));return [coordX,coordY]}];if(element.options.constraint==="snap"){constraints.push(MovablePoint$1.constraints.snap(element.options.snap));}else if(element.options.constraint==="x"){constraints.push(coord=>{return [this._eval(element.options.constraintFn,{y:coord[1]}),coord[1]]});}else if(element.options.constraint==="y"){constraints.push(coord=>{return [coord[0],this._eval(element.options.constraintFn,{x:coord[0]})]});}const start=[this.state.variables["x_"+element.options.startSubscript],this.state.variables["y_"+element.options.startSubscript]];const end=[this.state.variables["x_"+element.options.endSubscript],this.state.variables["y_"+element.options.endSubscript]];return jsxRuntimeExports.jsxs(MovableLine,{constraints:constraints,onMove:___default.default.bind(this._updateLineLocation,this,element.options),foo_x:element.options.constraint,foo_y:element.options.constraintFn,foo_z:element.options.snap,children:[jsxRuntimeExports.jsx(MovablePoint$1,{coord:start,static:true,normalStyle:{stroke:"none",fill:"none"}}),jsxRuntimeExports.jsx(MovablePoint$1,{coord:end,static:true,normalStyle:{stroke:"none",fill:"none"}})]},element.key)}if(element.type==="function"){const fn=x=>{return this._eval(element.options.value,{x:x})};const vars=___default.default.without(this._extractVars(KASparse(element.options.value).expr),"x");const varValues=___default.default.object(vars,___default.default.map(vars,v=>this.state.variables[v]));const range=[this._eval(element.options.rangeMin,this.state.variables),this._eval(element.options.rangeMax,this.state.variables)];return jsxRuntimeExports.jsx(Plot,{fn:fn,foo_fn:element.options.value,foo_varvalues:varValues,range:range,style:{stroke:element.options.color,strokeWidth:element.options.strokeWidth,strokeDasharray:element.options.strokeDasharray,plotPoints:100}},element.key)}if(element.type==="parametric"){const fn=t=>{return [this._eval(element.options.x,{t:t}),this._eval(element.options.y,{t:t})]};const vars=___default.default.without(this._extractVars(KASparse(element.options.x).expr).concat(this._extractVars(KASparse(element.options.y).expr)),"t");const varValues=___default.default.object(vars,___default.default.map(vars,v=>this.state.variables[v]));const range=[this._eval(element.options.rangeMin,this.state.variables),this._eval(element.options.rangeMax,this.state.variables)];return jsxRuntimeExports.jsx(PlotParametric,{fn:fn,foo_fnx:element.options.x,foo_fny:element.options.y,foo_varvalues:varValues,range:range,style:{stroke:element.options.color,strokeWidth:element.options.strokeWidth,strokeDasharray:element.options.strokeDasharray,plotPoints:100}},element.key)}if(element.type==="label"){const coord=[this._eval(element.options.coordX),this._eval(element.options.coordY)];return jsxRuntimeExports.jsx(Label,{coord:coord,text:unescapeMathMode(element.options.label),style:{color:element.options.color}},n+1)}if(element.type==="rectangle"){return jsxRuntimeExports.jsx(Rect,{x:this._eval(element.options.coordX),y:this._eval(element.options.coordY),width:___default.default.max([this._eval(element.options.width),0]),height:___default.default.max([this._eval(element.options.height),0]),style:{stroke:"none",fill:element.options.color}},n+1)}},this)]})}constructor(...args){super(...args),this.isWidget=true,this.state={variables:_getInitialVariables(this.props.elements),functions:_getInitialFunctions(this.props.elements)},this._setupGraphie=(graphie,options)=>{graphie.graphInit(___default.default.extend({},options,{grid:___default.default.contains(["graph","grid"],this.props.graph.markings),axes:___default.default.contains(["graph"],this.props.graph.markings),ticks:___default.default.contains(["graph"],this.props.graph.markings),labels:___default.default.contains(["graph"],this.props.graph.markings),labelFormat:function(s){return "\\small{"+s+"}"},axisArrows:"<->",unityLabels:false}));},this._updatePointLocation=(subscript,coord)=>{const variables=___default.default.clone(this.state.variables);variables["x_"+subscript]=coord[0];variables["y_"+subscript]=coord[1];this.setState({variables:variables});this.props.trackInteraction();},this._updateLineLocation=(options,startCoord)=>{const xDiff=this._eval("("+options.endX+")-("+options.startX+")");const yDiff=this._eval("("+options.endY+")-("+options.startY+")");const endCoord=kmath.vector.add(startCoord,[xDiff,yDiff]);const variables=___default.default.clone(this.state.variables);variables["x_"+options.startSubscript]=startCoord[0];variables["y_"+options.startSubscript]=startCoord[1];variables["x_"+options.endSubscript]=endCoord[0];variables["y_"+options.endSubscript]=endCoord[1];this.setState({variables:variables});this.props.trackInteraction();},this._eval=(expression,variables)=>{const func=KAScompile(expression,{functions:this.state.functions});const compiledVars=___default.default.extend({},this.state.variables,variables);___default.default.each(___default.default.keys(compiledVars),name=>{if(___default.default.isString(compiledVars[name])){const func=KAScompile(compiledVars[name],{functions:this.state.functions});compiledVars[name]=function(x){return func(___default.default.extend({},compiledVars,{x:x}))};}});return func(compiledVars)||0},this._extractVars=expr=>{if(expr==null){return []}let vars=[];___default.default.each(expr.args(),function(arg){if(arg&&arg.constructor.name==="Expr"){vars=vars.concat(this._extractVars(arg));}},this);if(expr.name()==="Var"){vars.push(expr.prettyPrint());}return vars};}}Interaction.defaultProps={graph:{box:[400,400],labels:["x","y"],range:[[-10,10],[-10,10]],tickStep:[1,1],gridStep:[1,1],markings:"graph"},elements:[]};const _getInitialVariables=elements=>{const variables={};___default.default.each(___default.default.where(elements,{type:"movable-point"}),element=>{const subscript=element.options.varSubscript;const startXExpr=KASparse(element.options.startX||"0").expr;const startYExpr=KASparse(element.options.startY||"0").expr;let startX=0;let startY=0;if(startXExpr){startX=startXExpr.eval({})||0;}if(startYExpr){startY=startYExpr.eval({})||0;}variables["x_"+subscript]=startX;variables["y_"+subscript]=startY;});___default.default.each(___default.default.where(elements,{type:"movable-line"}),element=>{const startSubscript=element.options.startSubscript;const endSubscript=element.options.endSubscript;const startXExpr=KASparse(element.options.startX||"0").expr;const startYExpr=KASparse(element.options.startY||"0").expr;const endXExpr=KASparse(element.options.endX||"0").expr;const endYExpr=KASparse(element.options.endY||"0").expr;let startX=0;let startY=0;let endX=0;let endY=0;if(startXExpr){startX=startXExpr.eval({})||0;}if(startYExpr){startY=startYExpr.eval({})||0;}if(endXExpr){endX=endXExpr.eval({})||0;}if(endYExpr){endY=endYExpr.eval({})||0;}variables["x_"+startSubscript]=startX;variables["y_"+startSubscript]=startY;variables["x_"+endSubscript]=endX;variables["y_"+endSubscript]=endY;});___default.default.each(___default.default.where(elements,{type:"function"}),element=>{variables[element.options.funcName]=element.options.value;});return variables};const _getInitialFunctions=elements=>{return ___default.default.map(___default.default.where(elements,{type:"function"}),element=>element.options.funcName)};var Interactive = {name:"interaction",displayName:"Interaction",widget:Interaction,hidden:true};
|
|
2103
|
+
const Label=Graphie.Label;const Line$1=Graphie.Line;const MovablePoint$1=Graphie.MovablePoint;const MovableLine=Graphie.MovableLine;const Plot=Graphie.Plot;const PlotParametric=Graphie.PlotParametric;const Point=Graphie.Point;const Rect=Graphie.Rect;const{unescapeMathMode}=Util;function KAShashFunc(expr,options){let result=expr+"||";const functions=options?.functions;const functionsLength=functions?functions.length:0;for(let i=0;i<functionsLength;i++){result+=functions[i]+"|";}return result}const _parseCache=Object.create(null);function KASparse(expr){const hash=KAShashFunc(expr);let cached=_parseCache[hash];if(cached){return cached}cached=KAS__namespace.parse(expr);_parseCache[hash]=cached;return cached}const _compileCache=Object.create(null);function KAScompile(expr,options){const hash=KAShashFunc(expr,options);let cached=_compileCache[hash];if(cached){return cached}const parsed=KAS__namespace.parse(expr,options).expr;cached=parsed?parsed.compile():function(){return 0};_compileCache[hash]=cached;return cached}class Interaction extends React__namespace.Component{UNSAFE_componentWillReceiveProps(nextProps){if(!___default.default.isEqual(this.props.elements,nextProps.elements)){this.setState({variables:_getInitialVariables(nextProps.elements),functions:_getInitialFunctions(nextProps.elements)});}}getPromptJSON(){return getPromptJSON$b()}render(){const range=this.props.graph.range;let labels=this.props.graph.labels;if(this.props.graph.markings==="graph"){labels=this.props.graph.labels.map(label=>label.startsWith("$")&&label.endsWith("$")?label.slice(1,-1):label);}return jsxRuntimeExports.jsxs(Graphie,{box:this.props.graph.box,range:this.props.graph.range,options:this.props.graph,setup:this._setupGraphie,children:[this.props.graph.markings==="graph"&&jsxRuntimeExports.jsx(Label,{coord:[0,range[1][1]],text:labels[1],direction:"above"}),this.props.graph.markings==="graph"&&jsxRuntimeExports.jsx(Label,{coord:[range[0][1],0],text:labels[0],direction:"right"}),this.props.elements.map((element,n)=>{if(element.type==="point"){return jsxRuntimeExports.jsx(Point,{coord:[this._eval(element.options.coordX),this._eval(element.options.coordY)],color:element.options.color},element.key)}if(element.type==="line"){const start=[this._eval(element.options.startX),this._eval(element.options.startY)];const end=[this._eval(element.options.endX),this._eval(element.options.endY)];return jsxRuntimeExports.jsx(Line$1,{start:start,end:end,style:{stroke:element.options.color,strokeWidth:element.options.strokeWidth,strokeDasharray:element.options.strokeDasharray,arrows:element.options.arrows}},element.key)}if(element.type==="movable-point"){const constraints=[coord=>{const coordX=Math.max(this._eval(element.options.constraintXMin),Math.min(this._eval(element.options.constraintXMax),coord[0]));const coordY=Math.max(this._eval(element.options.constraintYMin),Math.min(this._eval(element.options.constraintYMax),coord[1]));return [coordX,coordY]}];if(element.options.constraint==="snap"){constraints.push(MovablePoint$1.constraints.snap(element.options.snap));}else if(element.options.constraint==="x"){constraints.push(coord=>{return [this._eval(element.options.constraintFn,{y:coord[1]}),coord[1]]});}else if(element.options.constraint==="y"){constraints.push(coord=>{return [coord[0],this._eval(element.options.constraintFn,{x:coord[0]})]});}return jsxRuntimeExports.jsx(MovablePoint$1,{coord:[this.state.variables["x_"+element.options.varSubscript],this.state.variables["y_"+element.options.varSubscript]],constraints:constraints,foo_x:element.options.constraint,foo_y:element.options.constraintFn,foo_z:element.options.snap,onMove:___default.default.partial(this._updatePointLocation,element.options.varSubscript)},element.key)}if(element.type==="movable-line"){const constraints=[coord=>{const coordX=Math.max(this._eval(element.options.constraintXMin),Math.min(this._eval(element.options.constraintXMax),coord[0]));const coordY=Math.max(this._eval(element.options.constraintYMin),Math.min(this._eval(element.options.constraintYMax),coord[1]));return [coordX,coordY]}];if(element.options.constraint==="snap"){constraints.push(MovablePoint$1.constraints.snap(element.options.snap));}else if(element.options.constraint==="x"){constraints.push(coord=>{return [this._eval(element.options.constraintFn,{y:coord[1]}),coord[1]]});}else if(element.options.constraint==="y"){constraints.push(coord=>{return [coord[0],this._eval(element.options.constraintFn,{x:coord[0]})]});}const start=[this.state.variables["x_"+element.options.startSubscript],this.state.variables["y_"+element.options.startSubscript]];const end=[this.state.variables["x_"+element.options.endSubscript],this.state.variables["y_"+element.options.endSubscript]];return jsxRuntimeExports.jsxs(MovableLine,{constraints:constraints,onMove:this._updateLineLocation.bind(this,element.options),foo_x:element.options.constraint,foo_y:element.options.constraintFn,foo_z:element.options.snap,children:[jsxRuntimeExports.jsx(MovablePoint$1,{coord:start,static:true,normalStyle:{stroke:"none",fill:"none"}}),jsxRuntimeExports.jsx(MovablePoint$1,{coord:end,static:true,normalStyle:{stroke:"none",fill:"none"}})]},element.key)}if(element.type==="function"){const fn=x=>{return this._eval(element.options.value,{x:x})};const vars=this._extractVars(KASparse(element.options.value).expr).filter(v=>v!=="x");const varValues=Object.fromEntries(vars.map(v=>[v,this.state.variables[v]]));const range=[this._eval(element.options.rangeMin,this.state.variables),this._eval(element.options.rangeMax,this.state.variables)];return jsxRuntimeExports.jsx(Plot,{fn:fn,foo_fn:element.options.value,foo_varvalues:varValues,range:range,style:{stroke:element.options.color,strokeWidth:element.options.strokeWidth,strokeDasharray:element.options.strokeDasharray,plotPoints:100}},element.key)}if(element.type==="parametric"){const fn=t=>{return [this._eval(element.options.x,{t:t}),this._eval(element.options.y,{t:t})]};const vars=this._extractVars(KASparse(element.options.x).expr).concat(this._extractVars(KASparse(element.options.y).expr)).filter(v=>v!=="t");const varValues=Object.fromEntries(vars.map(v=>[v,this.state.variables[v]]));const range=[this._eval(element.options.rangeMin,this.state.variables),this._eval(element.options.rangeMax,this.state.variables)];return jsxRuntimeExports.jsx(PlotParametric,{fn:fn,foo_fnx:element.options.x,foo_fny:element.options.y,foo_varvalues:varValues,range:range,style:{stroke:element.options.color,strokeWidth:element.options.strokeWidth,strokeDasharray:element.options.strokeDasharray,plotPoints:100}},element.key)}if(element.type==="label"){const coord=[this._eval(element.options.coordX),this._eval(element.options.coordY)];return jsxRuntimeExports.jsx(Label,{coord:coord,text:unescapeMathMode(element.options.label),style:{color:element.options.color}},n+1)}if(element.type==="rectangle"){return jsxRuntimeExports.jsx(Rect,{x:this._eval(element.options.coordX),y:this._eval(element.options.coordY),width:Math.max(this._eval(element.options.width),0),height:Math.max(this._eval(element.options.height),0),style:{stroke:"none",fill:element.options.color}},n+1)}})]})}constructor(...args){super(...args),this.isWidget=true,this.state={variables:_getInitialVariables(this.props.elements),functions:_getInitialFunctions(this.props.elements)},this._setupGraphie=(graphie,options)=>{graphie.graphInit({...options,grid:["graph","grid"].includes(this.props.graph.markings),axes:["graph"].includes(this.props.graph.markings),ticks:["graph"].includes(this.props.graph.markings),labels:["graph"].includes(this.props.graph.markings),labelFormat:function(s){return "\\small{"+s+"}"},axisArrows:"<->",unityLabels:false});},this._updatePointLocation=(subscript,coord)=>{const variables={...this.state.variables};variables["x_"+subscript]=coord[0];variables["y_"+subscript]=coord[1];this.setState({variables:variables});this.props.trackInteraction();},this._updateLineLocation=(options,startCoord)=>{const xDiff=this._eval("("+options.endX+")-("+options.startX+")");const yDiff=this._eval("("+options.endY+")-("+options.startY+")");const endCoord=kmath.vector.add(startCoord,[xDiff,yDiff]);const variables={...this.state.variables};variables["x_"+options.startSubscript]=startCoord[0];variables["y_"+options.startSubscript]=startCoord[1];variables["x_"+options.endSubscript]=endCoord[0];variables["y_"+options.endSubscript]=endCoord[1];this.setState({variables:variables});this.props.trackInteraction();},this._eval=(expression,variables)=>{const func=KAScompile(expression,{functions:this.state.functions});const compiledVars={...this.state.variables,...variables};Object.keys(compiledVars).forEach(name=>{if(typeof compiledVars[name]==="string"){const func=KAScompile(compiledVars[name],{functions:this.state.functions});compiledVars[name]=function(x){return func({...compiledVars,x})};}});return func(compiledVars)||0},this._extractVars=expr=>{if(expr==null){return []}let vars=[];expr.args().forEach(arg=>{if(arg&&arg.constructor.name==="Expr"){vars=vars.concat(this._extractVars(arg));}});if(expr.name()==="Var"){vars.push(expr.prettyPrint());}return vars};}}Interaction.defaultProps={graph:{box:[400,400],labels:["x","y"],range:[[-10,10],[-10,10]],tickStep:[1,1],gridStep:[1,1],markings:"graph"},elements:[]};const _getInitialVariables=elements=>{const variables={};elements.filter(element=>element.type==="movable-point").forEach(element=>{const subscript=element.options.varSubscript;const startXExpr=KASparse(element.options.startX||"0").expr;const startYExpr=KASparse(element.options.startY||"0").expr;let startX=0;let startY=0;if(startXExpr){startX=startXExpr.eval({})||0;}if(startYExpr){startY=startYExpr.eval({})||0;}variables["x_"+subscript]=startX;variables["y_"+subscript]=startY;});elements.filter(element=>element.type==="movable-line").forEach(element=>{const startSubscript=element.options.startSubscript;const endSubscript=element.options.endSubscript;const startXExpr=KASparse(element.options.startX||"0").expr;const startYExpr=KASparse(element.options.startY||"0").expr;const endXExpr=KASparse(element.options.endX||"0").expr;const endYExpr=KASparse(element.options.endY||"0").expr;let startX=0;let startY=0;let endX=0;let endY=0;if(startXExpr){startX=startXExpr.eval({})||0;}if(startYExpr){startY=startYExpr.eval({})||0;}if(endXExpr){endX=endXExpr.eval({})||0;}if(endYExpr){endY=endYExpr.eval({})||0;}variables["x_"+startSubscript]=startX;variables["y_"+startSubscript]=startY;variables["x_"+endSubscript]=endX;variables["y_"+endSubscript]=endY;});elements.filter(element=>element.type==="function").forEach(element=>{variables[element.options.funcName]=element.options.value;});return variables};const _getInitialFunctions=elements=>{return elements.filter(element=>element.type==="function").map(element=>element.options.funcName)};var Interactive = {name:"interaction",displayName:"Interaction",widget:Interaction,hidden:true};
|
|
2113
2104
|
|
|
2114
2105
|
const bodyXsmallBold={fontFamily:"inherit",fontSize:15,fontWeight:"bold",lineHeight:"22px"};
|
|
2115
2106
|
|
|
@@ -2125,23 +2116,23 @@ function shouldReduceMotion(){if(typeof window.matchMedia!=="function"){return t
|
|
|
2125
2116
|
|
|
2126
2117
|
function isAnswerful(marker){return marker.answers!=null}function getComputedSelectedState(marker,userInputMarker,reviewMode,showSolutions){const shouldShowFeedback=showSolutions==="all"||reviewMode;if(!shouldShowFeedback){return userInputMarker}if(isAnswerful(marker)){return {...userInputMarker,selected:marker.answers}}else {return {...userInputMarker,selected:undefined}}}class LabelImage extends React__namespace.Component{static pointInTriangle(p,a,b,c){const sign=(p1,p2,p3)=>(p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y);const b1=sign(p,a,b)<0;const b2=sign(p,b,c)<0;const b3=sign(p,c,a)<0;return b1===b2&&b2===b3}static imageSideForMarkerPosition(x,y,preferredDirection){if(preferredDirection&&preferredDirection!=="NONE"){if(preferredDirection==="LEFT"&&x>20){return "right"}else if(preferredDirection==="RIGHT"&&x<80){return "left"}else if(preferredDirection==="UP"&&y>20){return "bottom"}else if(preferredDirection==="DOWN"&&y<80){return "top"}}if(x<20){return "left"}if(x>80){return "right"}const tl={x:20,y:0};const tr={x:80,y:0};const br={x:80,y:100};const bl={x:20,y:100};const cp={x:50,y:50};const sides=["top","right","bottom","left"];const triangles={top:[tl,tr,cp],right:[cp,tr,br],bottom:[bl,cp,br],left:[tl,cp,bl]};const p={x,y};for(const side of sides){const corners=triangles[side];if(LabelImage.pointInTriangle(p,...corners)){return side}}return "center"}static navigateToMarkerIndex(navigateDirection,markers,thisIndex){const thisMarker=markers[thisIndex];const sortedMarkers=markers.map((otherMarker,index)=>{const x=otherMarker.x-thisMarker.x;const y=otherMarker.y-thisMarker.y;const dist=Math.sqrt(x**2+y**2);return {index,dist,dir:{x:dist!==0?x/dist:0,y:dist!==0?y/dist:0}}}).filter(marker=>{if(marker.index===thisIndex){return false}return markers[marker.index].showCorrectness!=="correct"}).sort((a,b)=>{const distA=Math.round(a.dist*(navigateDirection.x*a.dir.x+navigateDirection.y*a.dir.y));const distB=Math.round(b.dist*(navigateDirection.x*b.dir.x+navigateDirection.y*b.dir.y));let dirA;let dirB;if(navigateDirection.x>0){dirA=a.dir.x>0&&distA!==0;dirB=b.dir.x>0&&distB!==0;}else if(navigateDirection.x<0){dirA=a.dir.x<0&&distA!==0;dirB=b.dir.x<0&&distB!==0;}else if(navigateDirection.y>0){dirA=a.dir.y>0&&distA!==0;dirB=b.dir.y>0&&distB!==0;}else if(navigateDirection.y<0){dirA=a.dir.y<0&&distA!==0;dirB=b.dir.y<0&&distB!==0;}if(dirA!==dirB){if(dirA){return -1}return 1}return distA-distB});return sortedMarkers.length>0?sortedMarkers[0].index:thisIndex}componentDidMount(){this.props.analytics?.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"label-image",widgetId:this.props.widgetId}});this._mounted=true;}componentWillUnmount(){this._mounted=false;}getPromptJSON(){return getPromptJSON$a(this.props)}handleMarkerChange(index,marker){const{userInput,handleUserInput}=this.props;const updatedUserInput=[...userInput.markers.slice(0,index),{label:marker.label,selected:marker.selected},...userInput.markers.slice(index+1)];handleUserInput({markers:updatedUserInput});}activateMarker(index,opened){this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:marker-interacted-with",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:marker-interacted-with:ti",payload:null});const{activeMarkerIndex}=this.state;if(activeMarkerIndex!==index&&opened){this.setState({activeMarkerIndex:index,markersInteracted:true});}else {this.setState({activeMarkerIndex:-1});}}handleMarkerKeyDown(index,e){const{markers}=this.props;if(markers.length<2){return}const directions={ArrowUp:{x:0,y:-1},ArrowRight:{x:1,y:0},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0}};if(!(e.key in directions)){return}const navigateDirection=directions[e.key];e.preventDefault();const marker=this._markers[LabelImage.navigateToMarkerIndex(navigateDirection,markers,index)];if(marker){ReactDOM__namespace.findDOMNode(marker).focus();}}handleAnswerChoicesChangeForMarker(index,selection){const{choices,markers}=this.props;const selected=choices.filter((_,index)=>selection[index]);this.handleMarkerChange(index,{...markers[index],selected:selected.length>0?selected:undefined});}renderMarkers(){const{markers,preferredPopoverDirection,userInput}=this.props;const{markersInteracted,activeMarkerIndex}=this.state;const isNarrowPage=this._mounted&&window.matchMedia(mediaQueries.xsOrSmaller.replace("@media ","")).matches;const isWideImage=this.props.imageWidth/2>this.props.imageHeight;return markers.map((marker,index)=>{const userInputMarker=userInput.markers[index];let side;let markerPosition;if(isNarrowPage||isWideImage){side=marker.y>50?"top":"bottom";markerPosition=marker.y>50?"bottom":"top";}else {markerPosition=LabelImage.imageSideForMarkerPosition(marker.x,marker.y,preferredPopoverDirection);if(markerPosition==="center"){markerPosition="bottom";}side=({left:"right",top:"bottom",right:"left",bottom:"top"})[markerPosition];}const computedSelectedState=getComputedSelectedState(marker,userInputMarker,this.props.reviewMode,this.props.showSolutions);let score;if(isAnswerful(marker)){score=perseusScore.scoreLabelImageMarker(computedSelectedState.selected,marker.answers);}else {score={hasAnswers:false,isCorrect:false};}const shouldShowFeedback=this.props.showSolutions==="all"||this.props.reviewMode;const showCorrectness=shouldShowFeedback&&score.isCorrect?"correct":marker.showCorrectness;const disabled=shouldShowFeedback;const isActiveAnswerChoice=activeMarkerIndex===index;const showAnswerChoice=computedSelectedState.selected&&!this.state.hideAnswers&&!isActiveAnswerChoice;const adjustPillDistance={[`margin${markerPosition.charAt(0).toUpperCase()+markerPosition.slice(1)}`]:10};return jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{position:"absolute",left:`${marker.x}%`,top:`${marker.y}%`,zIndex:"unset"},children:jsxRuntimeExports.jsx(AnswerChoices,{choices:this.props.choices.map(choice=>({content:choice,checked:computedSelectedState.selected?computedSelectedState.selected.includes(choice):false})),multipleSelect:this.props.multipleAnswers,onChange:selection=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:choiced-interacted-with",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:choiced-interacted-with:ti",payload:null});this.handleAnswerChoicesChangeForMarker(index,selection);},onToggle:opened=>this.activateMarker(index,opened),disabled:disabled,opener:({opened})=>jsxRuntimeExports.jsx(Clickable__default.default,{role:"button","aria-expanded":opened,children:({hovered,focused,pressed})=>jsxRuntimeExports.jsx(Marker,{label:marker.label,showCorrectness:showCorrectness,showSelected:opened,showPulsate:!markersInteracted,ref:node=>this._markers[index]=node,showAnswer:showAnswerChoice,answerSide:side,answerStyles:adjustPillDistance,focused:focused||pressed,hovered:hovered,selected:computedSelectedState.selected})},`marker-${marker.x}.${marker.y}`)},`answers-${marker.x}.${marker.y}`)},index)})}renderInstructions(){const{apiOptions:{isMobile},choices,multipleAnswers,hideChoicesFromInstructions:hideChoices}=this.props;const{strings}=this.context;const promptString=isMobile?multipleAnswers?strings.tapMultiple:strings.tapSingle:multipleAnswers?strings.clickMultiple:strings.clickSingle;const choicesString=strings.choices;return jsxRuntimeExports.jsxs("div",{className:classNames__default.default("perseus-label-image-widget-instructions",aphrodite.css(styles$9.instructions)),children:[jsxRuntimeExports.jsxs("div",{className:aphrodite.css(styles$9.instructionsCaption),children:[promptString," ",!hideChoices&&choicesString]}),!hideChoices&&jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$9.instructionsChoices),children:choices.map((choice,index)=>jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$9.instructionsChoice),children:jsxRuntimeExports.jsx(Renderer,{content:choice,strings:strings})},index))})]})}getSerializedState(){const{userInput,markers,...rest}=this.props;return {...rest,markers:markers.map((marker,index)=>({...marker,selected:userInput.markers[index].selected}))}}render(){const{imageAlt,imageUrl,imageWidth,imageHeight}=this.props;const{activeMarkerIndex}=this.state;return jsxRuntimeExports.jsxs("div",{children:[this.renderInstructions(),jsxRuntimeExports.jsxs("div",{className:aphrodite.css(styles$9.markersCanvas),style:{maxWidth:imageWidth,maxHeight:imageHeight},children:[jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$9.imageContainer,activeMarkerIndex!==-1&&styles$9.imageInteractionDisabled),children:jsxRuntimeExports.jsx(context$1.Consumer,{children:({setAssetStatus})=>jsxRuntimeExports.jsx(SvgImage,{alt:imageAlt,src:imageUrl,width:imageWidth,height:imageHeight,setAssetStatus:setAssetStatus,allowZoom:true})})}),this.renderMarkers()]}),jsxRuntimeExports.jsx(HideAnswersToggle,{areAnswersHidden:this.state.hideAnswers,onChange:hideAnswers=>{this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:toggle-answers-hidden",payload:null});this.props.analytics?.onAnalyticsEvent({type:"perseus:label-image:toggle-answers-hidden:ti",payload:null});this.setState({hideAnswers});}})]})}constructor(props){super(props),this._mounted=false;this._markers=[];this.state={activeMarkerIndex:-1,markersInteracted:false,hideAnswers:false};}}LabelImage.contextType=PerseusI18nContext;const LabelImageWithDependencies=React__namespace.forwardRef((props,ref)=>{const deps=useDependencies();return jsxRuntimeExports.jsx(LabelImage,{ref:ref,analytics:deps.analytics,...props})});function getStartUserInput$7(options){return {markers:options.markers.map(m=>({label:m.label}))}}function getUserInputFromSerializedState$7(serializedState){return {markers:serializedState.markers.map(m=>({label:m.label,selected:m.selected}))}}function getCorrectUserInput$3(options){return {markers:options.markers.map(marker=>({label:marker.label,selected:marker.answers}))}}var LabelImage$1 = {name:"label-image",displayName:"Label Image",widget:LabelImageWithDependencies,isLintable:true,getStartUserInput: getStartUserInput$7,getCorrectUserInput: getCorrectUserInput$3,getUserInputFromSerializedState: getUserInputFromSerializedState$7};const styles$9=aphrodite.StyleSheet.create({instructions:{paddingBottom:16},instructionsCaption:{...bodyXsmallBold,paddingBottom:16},instructionsChoices:{display:"flex",flexWrap:"wrap",margin:"-8px 0"},instructionsChoice:{display:"flex",alignItems:"center",margin:"8px 0",":not(:last-child)":{"::after":{content:"''",display:"inline-block",position:"relative",width:2,height:2,marginLeft:5,marginRight:5,background:wonderBlocksTokens.semanticColor.core.border.neutral.default,borderRadius:2}}},markersCanvas:{position:"relative"},imageContainer:{display:"flex"},imageInteractionDisabled:{pointerEvents:"none"}});
|
|
2127
2118
|
|
|
2128
|
-
const addOffsetParentScroll=($el,position)=>{const $offsetParent=$el.offsetParent();return {top:position.top+$offsetParent.scrollTop(),left:position.left+$offsetParent.scrollLeft()}};class Placeholder extends React__namespace.Component{render(){const{layout}=this.props;const className=aphrodite.css(styles$8.card,styles$8.placeholder,layout==="horizontal"&&styles$8.horizontalCard);const style={width:this.props.width,height:this.props.height};if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style})}}class Draggable extends React__namespace.Component{componentDidMount(){this._mounted=true;this.isMouseMoveUpBound=false;document.addEventListener("touchmove",this.onMouseMove,Util.supportsPassiveEvents()?{passive:false}:false);}componentDidUpdate(prevProps){if(this.props.state===prevProps.state){return}if(this.props.state==="animating"&&this.props.endPosition){const current=this.getCurrentPosition();const duration=15*Math.sqrt(Math.sqrt(Math.pow(this.props.endPosition.left-current.left,2)+Math.pow(this.props.endPosition.top-current.top,2)));$__default.default(ReactDOM__namespace.default.findDOMNode(this)).animate(this.props.endPosition,{duration:Math.max(duration,1),complete:this.props.onAnimationEnd});}else if(this.props.state==="static"){$__default.default(ReactDOM__namespace.default.findDOMNode(this)).finish();}}componentWillUnmount(){this._mounted=false;if(this.isMouseMoveUpBound){this.unbindMouseMoveUp();}if(this.animationFrameRequest){cancelAnimationFrame(this.animationFrameRequest);}document.removeEventListener("touchmove",this.onMouseMove);}render(){const{includePadding,layout,state:type}=this.props;let className=aphrodite.css(styles$8.card,styles$8.draggable,layout==="horizontal"&&styles$8.horizontalCard,layout==="vertical"&&styles$8.verticalCard,type==="dragging"&&styles$8.dragging,type==="disabled"&&styles$8.disabled,!includePadding&&styles$8.unpaddedCard)+" "+"perseus-sortable-draggable";if(!includePadding){className+=" perseus-sortable-draggable-unpadded";}const style={position:"static"};if(this.props.state==="dragging"||this.props.state==="animating"){___default.default.extend(style,{position:"absolute"},this.getCurrentPosition());}if(this.props.width){style.width=this.props.width+1;}if(this.props.height){style.height=this.props.height;}if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style,onMouseDown:this.onMouseDown,onTouchStart:this.onMouseDown,onTouchMove:this.onMouseMove,onTouchEnd:this.onMouseUp,onTouchCancel:this.onMouseUp,children:jsxRuntimeExports.jsx(Renderer,{content:this.props.content,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"draggable"),onRender:this.props.onRender,strings:this.context.strings})})}constructor(...args){super(...args),this.animationFrameRequest=null,this.state={startPosition:{left:0,top:0},startMouse:{left:0,top:0},mouse:{left:0,top:0},dragging:false},this.getCurrentPosition=()=>{return {left:this.state.startPosition.left+this.state.mouse.left-this.state.startMouse.left,top:this.state.startPosition.top+this.state.mouse.top-this.state.startMouse.top}},this.bindMouseMoveUp=()=>{this.isMouseMoveUpBound=true;$__default.default(document).on("mousemove",this.onMouseMove);$__default.default(document).on("mouseup",this.onMouseUp);},this.unbindMouseMoveUp=()=>{this.isMouseMoveUpBound=false;$__default.default(document).off("mousemove",this.onMouseMove);$__default.default(document).off("mouseup",this.onMouseUp);},this.onMouseDown=event=>{if(this.props.state!=="static"){return}if(!(event.button===0||event.touches!=null&&event.touches.length===1)){return}event.preventDefault();const loc=Util.extractPointerLocation(event);this.animationFrameRequest=requestAnimationFrame(()=>{const $el=$__default.default(ReactDOM__namespace.default.findDOMNode(this));const position=$el.position();const startPosition=addOffsetParentScroll($el,position);if(loc&&this._mounted){this.setState({startPosition,startMouse:loc,mouse:loc,dragging:true},function(){this.bindMouseMoveUp();this.props.onMouseDown();});}});},this.onMouseMove=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.animationFrameRequest=requestAnimationFrame(()=>{this.setState({mouse:loc},this.props.onMouseMove);});}},this.onMouseUp=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.setState({dragging:false});this.unbindMouseMoveUp();this.props.onMouseUp();}};}}Draggable.contextType=PerseusI18nContext;Draggable.defaultProps={includePadding:true,type:"static",linterContext:PerseusLinter__namespace.linterContextDefault};class Sortable extends React__namespace.Component{static itemsFromProps(props){const state=props.disabled?"disabled":"static";return props.options.map((option,i)=>{return {option:option,key:i,state,width:0,height:0}})}static clearItemMeasurements(items){return items.map(item=>{return {...item,width:0,height:0}})}UNSAFE_componentWillReceiveProps(nextProps){const prevProps=this.props;if(!___default.default.isEqual(nextProps.options,prevProps.options)){this.setState({items:Sortable.itemsFromProps(nextProps)});}else if(nextProps.layout!==prevProps.layout||nextProps.padding!==prevProps.padding||nextProps.disabled!==prevProps.disabled||!___default.default.isEqual(nextProps.constraints,prevProps.constraints)){this.setState({items:Sortable.clearItemMeasurements(this.state.items)});}}componentDidUpdate(){if(this.state.items.length&&!this.state.items[0].width&&!this.state.items[0].height){setTimeout(()=>{this.measureItems();},0);}}measureItems(){let items=[...this.state.items];const $items=___default.default.map(items,function(item){return $__default.default(ReactDOM__namespace.default.findDOMNode(this.refs[item.key]))},this);const widths=___default.default.invoke($items,"outerWidth");const heights=___default.default.invoke($items,"outerHeight");const{constraints,layout}=this.props;let syncWidth=null;if(constraints?.width){syncWidth=___default.default.max(widths.concat(constraints.width));}else if(layout==="vertical"){syncWidth=___default.default.max(widths);}let syncHeight=null;if(constraints?.height){syncHeight=___default.default.max(heights.concat(constraints.height));}else if(layout==="horizontal"){syncHeight=___default.default.max(heights);}items=___default.default.map(items,function(item,i){item.width=syncWidth||widths[i];item.height=syncHeight||heights[i];return item});this.setState({items},()=>{this.props.onMeasure?.({widths:widths,heights:heights});});}onMouseDown(key){const items=___default.default.map(this.state.items,function(item){if(item.key===key){item.state="dragging";}return item});this.setState({items:items});}moveOptionToIndex(option,index){const{items}=this.state;if(index<0||index>items.length){throw new Error(`index ${index} out of bounds`)}const nextItems=___default.default.clone(items);const item=items.filter(item=>{return item.option===option})[0];if(item==null){throw new Error(`option ${option} not found`)}const currentIndex=items.findIndex(i=>{return i.key===item.key});nextItems.splice(currentIndex,1);nextItems.splice(index,0,item);this.setState({items:nextItems},()=>{this.props.onChange?.({});});}onMouseMove(key){const $draggable=$__default.default(ReactDOM__namespace.default.findDOMNode(this.refs[key]));const $sortable=$__default.default(ReactDOM__namespace.default.findDOMNode(this));const items=___default.default.clone(this.state.items);const item=___default.default.findWhere(this.state.items,{key:key});const margin=this.props.margin||0;const currentIndex=___default.default.indexOf(items,item);let newIndex=0;items.splice(currentIndex,1);if(this.props.layout==="horizontal"){const midWidth=$draggable.offset().left-$sortable.offset().left;let sumWidth=0;let cardWidth;___default.default.each(items,function(item){cardWidth=item.width;if(midWidth>sumWidth+cardWidth/2){newIndex+=1;}sumWidth+=cardWidth+margin;});}else {const midHeight=$draggable.offset().top-$sortable.offset().top;let sumHeight=0;let cardHeight;___default.default.each(items,function(item){cardHeight=item.height;if(midHeight>sumHeight+cardHeight/2){newIndex+=1;}sumHeight+=cardHeight+margin;});}if(newIndex!==currentIndex){items.splice(newIndex,0,item);this.setState({items:items});}}onMouseUp(key){const nextAnimationFrame=requestAnimationFrame(()=>{const items=___default.default.map(this.state.items,function(item){if(item.key===key){item.state="animating";const $placeholder=$__default.default(ReactDOM__namespace.default.findDOMNode(this.refs["placeholder_"+key]));const position=$placeholder.position();const endPosition=addOffsetParentScroll($placeholder,position);item.endPosition=endPosition;}return item},this);this.setState({items:items},()=>{this.props.onChange?.({});});});this.animationFrameRequest=nextAnimationFrame;}onAnimationEnd(key){const items=___default.default.map(this.state.items,function(item){if(item.key===key){item.state="static";}return item});this.setState({items:items});}getOptions(){return ___default.default.pluck(this.state.items,"option")}render(){if(this.props.waitForTexRendererToLoad&&!this.state.texRendererLoaded){const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksProgressSpinner.CircularSpinner,{}),jsxRuntimeExports.jsx("div",{style:{display:"none"},children:jsxRuntimeExports.jsx(TeX,{onRender:()=>this.setState({texRendererLoaded:true}),children:"1"})})]})}const cards=[];const{layout}=this.props;const className=aphrodite.css(styles$8.sortable)+" perseus-sortable";const syncWidth=this.props.constraints?.width||layout==="vertical";const syncHeight=this.props.constraints?.height||layout==="horizontal";___default.default.each(this.state.items,function(item,i,items){const isLast=i===items.length-1;const isStatic=item.state==="static"||item.state==="disabled";let margin;if(this.props.layout==="horizontal"){margin="0 "+this.props.margin+"px 0 0";}else if(this.props.layout==="vertical"){margin="0 0 "+this.props.margin+"px 0";}cards.push(jsxRuntimeExports.jsx(Draggable,{content:item.option,state:item.state,ref:item.key,width:syncWidth?item.width:undefined,height:syncHeight?item.height:undefined,layout:layout,includePadding:this.props.padding,margin:isLast&&isStatic?0:margin,endPosition:item.endPosition,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"sortable"),onRender:this.remeasureItems,onMouseDown:this.onMouseDown.bind(this,item.key),onMouseMove:this.onMouseMove.bind(this,item.key),onMouseUp:this.onMouseUp.bind(this,item.key),onTouchMove:this.onMouseMove.bind(this,item.key),onTouchEnd:this.onMouseUp.bind(this,item.key),onTouchCancel:this.onMouseUp.bind(this,item.key),onAnimationEnd:this.onAnimationEnd.bind(this,item.key)},item.key));if(item.state==="dragging"||item.state==="animating"){cards.push(jsxRuntimeExports.jsx(Placeholder,{ref:"placeholder_"+item.key,width:item.width,height:item.height,layout:layout,margin:isLast?0:margin},"placeholder_"+item.key));}},this);return jsxRuntimeExports.jsx("ul",{className:className,children:cards})}constructor(props){super(props),this.remeasureItems=___default.default.debounce(()=>{this.setState({items:Sortable.clearItemMeasurements(this.state.items)});},20);this.state={items:Sortable.itemsFromProps(this.props),texRendererLoaded:false};}}Sortable.defaultProps={layout:"horizontal",padding:true,disabled:false,constraints:{},onMeasure:function(){},margin:5,onChange:function(){},linterContext:PerseusLinter__namespace.linterContextDefault,waitForTexRendererToLoad:true};const styles$8=aphrodite.StyleSheet.create({sortable:{boxSizing:"border-box",float:"left",padding:0,margin:0},card:{boxSizing:"border-box",background:wonderBlocksTokens.semanticColor.core.background.base.default,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderRadius:4,cursor:"pointer",minWidth:25,minHeight:44,padding:10,listStyleType:"none",userSelect:"none",touchAction:"none"},placeholder:{background:wonderBlocksTokens.semanticColor.core.background.neutral.subtle,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`},draggable:{textAlign:"center"},horizontalCard:{float:"left",cursor:"ew-resize"},verticalCard:{maxWidth:"100%",cursor:"ns-resize"},unpaddedCard:{padding:0},dragging:{background:wonderBlocksTokens.semanticColor.core.background.instructive.subtle,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.instructive.default}`,opacity:.8},disabled:{backgroundColor:"inherit",border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.disabled.subtle}`,cursor:"default"}});
|
|
2119
|
+
const addOffsetParentScroll=($el,position)=>{const $offsetParent=$el.offsetParent();return {top:position.top+$offsetParent.scrollTop(),left:position.left+$offsetParent.scrollLeft()}};class Placeholder extends React__namespace.Component{render(){const{layout}=this.props;const className=aphrodite.css(styles$8.card,styles$8.placeholder,layout==="horizontal"&&styles$8.horizontalCard);const style={width:this.props.width,height:this.props.height};if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style})}}class Draggable extends React__namespace.Component{componentDidMount(){this._mounted=true;this.isMouseMoveUpBound=false;document.addEventListener("touchmove",this.onMouseMove,Util.supportsPassiveEvents()?{passive:false}:false);}componentDidUpdate(prevProps){if(this.props.state===prevProps.state){return}if(this.props.state==="animating"&&this.props.endPosition){const current=this.getCurrentPosition();const duration=15*Math.sqrt(Math.sqrt(Math.pow(this.props.endPosition.left-current.left,2)+Math.pow(this.props.endPosition.top-current.top,2)));$__default.default(ReactDOM__namespace.default.findDOMNode(this)).animate(this.props.endPosition,{duration:Math.max(duration,1),complete:this.props.onAnimationEnd});}else if(this.props.state==="static"){$__default.default(ReactDOM__namespace.default.findDOMNode(this)).finish();}}componentWillUnmount(){this._mounted=false;if(this.isMouseMoveUpBound){this.unbindMouseMoveUp();}if(this.animationFrameRequest){cancelAnimationFrame(this.animationFrameRequest);}document.removeEventListener("touchmove",this.onMouseMove);}render(){const{includePadding,layout,state:type}=this.props;let className=aphrodite.css(styles$8.card,styles$8.draggable,layout==="horizontal"&&styles$8.horizontalCard,layout==="vertical"&&styles$8.verticalCard,type==="dragging"&&styles$8.dragging,type==="disabled"&&styles$8.disabled,!includePadding&&styles$8.unpaddedCard)+" "+"perseus-sortable-draggable";if(!includePadding){className+=" perseus-sortable-draggable-unpadded";}const style={position:"static"};if(this.props.state==="dragging"||this.props.state==="animating"){Object.assign(style,{position:"absolute"},this.getCurrentPosition());}if(this.props.width){style.width=this.props.width+1;}if(this.props.height){style.height=this.props.height;}if(this.props.margin!=null){style.margin=this.props.margin;}return jsxRuntimeExports.jsx("li",{className:className,style:style,onMouseDown:this.onMouseDown,onTouchStart:this.onMouseDown,onTouchMove:this.onMouseMove,onTouchEnd:this.onMouseUp,onTouchCancel:this.onMouseUp,children:jsxRuntimeExports.jsx(Renderer,{content:this.props.content,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"draggable"),onRender:this.props.onRender,strings:this.context.strings})})}constructor(...args){super(...args),this.animationFrameRequest=null,this.state={startPosition:{left:0,top:0},startMouse:{left:0,top:0},mouse:{left:0,top:0},dragging:false},this.getCurrentPosition=()=>{return {left:this.state.startPosition.left+this.state.mouse.left-this.state.startMouse.left,top:this.state.startPosition.top+this.state.mouse.top-this.state.startMouse.top}},this.bindMouseMoveUp=()=>{this.isMouseMoveUpBound=true;$__default.default(document).on("mousemove",this.onMouseMove);$__default.default(document).on("mouseup",this.onMouseUp);},this.unbindMouseMoveUp=()=>{this.isMouseMoveUpBound=false;$__default.default(document).off("mousemove",this.onMouseMove);$__default.default(document).off("mouseup",this.onMouseUp);},this.onMouseDown=event=>{if(this.props.state!=="static"){return}if(!(event.button===0||event.touches!=null&&event.touches.length===1)){return}event.preventDefault();const loc=Util.extractPointerLocation(event);this.animationFrameRequest=requestAnimationFrame(()=>{const $el=$__default.default(ReactDOM__namespace.default.findDOMNode(this));const position=$el.position();const startPosition=addOffsetParentScroll($el,position);if(loc&&this._mounted){this.setState({startPosition,startMouse:loc,mouse:loc,dragging:true},function(){this.bindMouseMoveUp();this.props.onMouseDown();});}});},this.onMouseMove=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.animationFrameRequest=requestAnimationFrame(()=>{this.setState({mouse:loc},this.props.onMouseMove);});}},this.onMouseUp=event=>{const notDragging=this.props.state!=="dragging"||!this.state.dragging;if(notDragging){return}event.preventDefault();const loc=Util.extractPointerLocation(event);if(loc){this.setState({dragging:false});this.unbindMouseMoveUp();this.props.onMouseUp();}};}}Draggable.contextType=PerseusI18nContext;Draggable.defaultProps={includePadding:true,type:"static",linterContext:PerseusLinter__namespace.linterContextDefault};class Sortable extends React__namespace.Component{static itemsFromProps(props){const state=props.disabled?"disabled":"static";return props.options.map((option,i)=>{return {option:option,key:i,state,width:0,height:0}})}static clearItemMeasurements(items){return items.map(item=>{return {...item,width:0,height:0}})}UNSAFE_componentWillReceiveProps(nextProps){const prevProps=this.props;if(!___default.default.isEqual(nextProps.options,prevProps.options)){this.setState({items:Sortable.itemsFromProps(nextProps)});}else if(nextProps.layout!==prevProps.layout||nextProps.padding!==prevProps.padding||nextProps.disabled!==prevProps.disabled||!___default.default.isEqual(nextProps.constraints,prevProps.constraints)){this.setState({items:Sortable.clearItemMeasurements(this.state.items)});}}componentDidUpdate(){if(this.state.items.length&&!this.state.items[0].width&&!this.state.items[0].height){setTimeout(()=>{this.measureItems();},0);}}measureItems(){let items=[...this.state.items];const $items=items.map(item=>{return $__default.default(ReactDOM__namespace.default.findDOMNode(this.refs[item.key]))});const widths=___default.default.invoke($items,"outerWidth");const heights=___default.default.invoke($items,"outerHeight");const{constraints,layout}=this.props;let syncWidth=null;if(constraints?.width){syncWidth=Math.max(...widths,constraints.width);}else if(layout==="vertical"){syncWidth=Math.max(...widths);}let syncHeight=null;if(constraints?.height){syncHeight=Math.max(...heights,constraints.height);}else if(layout==="horizontal"){syncHeight=Math.max(...heights);}items=items.map(function(item,i){item.width=syncWidth||widths[i];item.height=syncHeight||heights[i];return item});this.setState({items},()=>{this.props.onMeasure?.({widths:widths,heights:heights});});}onMouseDown(key){const items=this.state.items.map(function(item){if(item.key===key){item.state="dragging";}return item});this.setState({items:items});}moveOptionToIndex(option,index){const{items}=this.state;if(index<0||index>items.length){throw new Error(`index ${index} out of bounds`)}const nextItems=[...items];const item=items.filter(item=>{return item.option===option})[0];if(item==null){throw new Error(`option ${option} not found`)}const currentIndex=items.findIndex(i=>{return i.key===item.key});nextItems.splice(currentIndex,1);nextItems.splice(index,0,item);this.setState({items:nextItems},()=>{this.props.onChange?.({});});}onMouseMove(key){const $draggable=$__default.default(ReactDOM__namespace.default.findDOMNode(this.refs[key]));const $sortable=$__default.default(ReactDOM__namespace.default.findDOMNode(this));const items=[...this.state.items];const item=this.state.items.find(item=>item.key===key);const margin=this.props.margin||0;const currentIndex=items.indexOf(item);let newIndex=0;items.splice(currentIndex,1);if(this.props.layout==="horizontal"){const midWidth=$draggable.offset().left-$sortable.offset().left;let sumWidth=0;let cardWidth;items.forEach(function(item){cardWidth=item.width;if(midWidth>sumWidth+cardWidth/2){newIndex+=1;}sumWidth+=cardWidth+margin;});}else {const midHeight=$draggable.offset().top-$sortable.offset().top;let sumHeight=0;let cardHeight;items.forEach(function(item){cardHeight=item.height;if(midHeight>sumHeight+cardHeight/2){newIndex+=1;}sumHeight+=cardHeight+margin;});}if(newIndex!==currentIndex){items.splice(newIndex,0,item);this.setState({items:items});}}onMouseUp(key){const nextAnimationFrame=requestAnimationFrame(()=>{const items=this.state.items.map(item=>{if(item.key===key){item.state="animating";const $placeholder=$__default.default(ReactDOM__namespace.default.findDOMNode(this.refs["placeholder_"+key]));const position=$placeholder.position();const endPosition=addOffsetParentScroll($placeholder,position);item.endPosition=endPosition;}return item},this);this.setState({items:items},()=>{this.props.onChange?.({});});});this.animationFrameRequest=nextAnimationFrame;}onAnimationEnd(key){const items=this.state.items.map(function(item){if(item.key===key){item.state="static";}return item});this.setState({items:items});}getOptions(){return this.state.items.map(item=>item.option)}render(){if(this.props.waitForTexRendererToLoad&&!this.state.texRendererLoaded){const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksProgressSpinner.CircularSpinner,{}),jsxRuntimeExports.jsx("div",{style:{display:"none"},children:jsxRuntimeExports.jsx(TeX,{onRender:()=>this.setState({texRendererLoaded:true}),children:"1"})})]})}const cards=[];const{layout}=this.props;const className=aphrodite.css(styles$8.sortable)+" perseus-sortable";const syncWidth=this.props.constraints?.width||layout==="vertical";const syncHeight=this.props.constraints?.height||layout==="horizontal";this.state.items.forEach((item,i,items)=>{const isLast=i===items.length-1;const isStatic=item.state==="static"||item.state==="disabled";let margin;if(this.props.layout==="horizontal"){margin="0 "+this.props.margin+"px 0 0";}else if(this.props.layout==="vertical"){margin="0 0 "+this.props.margin+"px 0";}cards.push(jsxRuntimeExports.jsx(Draggable,{content:item.option,state:item.state,ref:item.key,width:syncWidth?item.width:undefined,height:syncHeight?item.height:undefined,layout:layout,includePadding:this.props.padding,margin:isLast&&isStatic?0:margin,endPosition:item.endPosition,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"sortable"),onRender:this.remeasureItems,onMouseDown:()=>this.onMouseDown(item.key),onMouseMove:()=>this.onMouseMove(item.key),onMouseUp:()=>this.onMouseUp(item.key),onTouchMove:()=>this.onMouseMove(item.key),onTouchEnd:()=>this.onMouseUp(item.key),onTouchCancel:()=>this.onMouseUp(item.key),onAnimationEnd:()=>this.onAnimationEnd(item.key)},item.key));if(item.state==="dragging"||item.state==="animating"){cards.push(jsxRuntimeExports.jsx(Placeholder,{ref:"placeholder_"+item.key,width:item.width,height:item.height,layout:layout,margin:isLast?0:margin},"placeholder_"+item.key));}},this);return jsxRuntimeExports.jsx("ul",{className:className,children:cards})}constructor(props){super(props),this.remeasureItems=___default.default.debounce(()=>{this.setState({items:Sortable.clearItemMeasurements(this.state.items)});},20);this.state={items:Sortable.itemsFromProps(this.props),texRendererLoaded:false};}}Sortable.defaultProps={layout:"horizontal",padding:true,disabled:false,constraints:{},onMeasure:function(){},margin:5,onChange:function(){},linterContext:PerseusLinter__namespace.linterContextDefault,waitForTexRendererToLoad:true};const styles$8=aphrodite.StyleSheet.create({sortable:{boxSizing:"border-box",float:"left",padding:0,margin:0},card:{boxSizing:"border-box",background:wonderBlocksTokens.semanticColor.core.background.base.default,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderRadius:4,cursor:"pointer",minWidth:25,minHeight:44,padding:10,listStyleType:"none",userSelect:"none",touchAction:"none"},placeholder:{background:wonderBlocksTokens.semanticColor.core.background.neutral.subtle,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`},draggable:{textAlign:"center"},horizontalCard:{float:"left",cursor:"ew-resize"},verticalCard:{maxWidth:"100%",cursor:"ns-resize"},unpaddedCard:{padding:0},dragging:{background:wonderBlocksTokens.semanticColor.core.background.instructive.subtle,border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.instructive.default}`,opacity:.8},disabled:{backgroundColor:"inherit",border:`${wonderBlocksTokens.border.width.thin} solid ${wonderBlocksTokens.semanticColor.core.border.disabled.subtle}`,cursor:"default"}});
|
|
2129
2120
|
|
|
2130
2121
|
const getPromptJSON$9=widgetData=>{const{userInput}=widgetData;return {type:"matcher",options:{labels:widgetData.labels,left:widgetData.left,right:widgetData.right,orderMatters:widgetData.orderMatters},userInput:{left:userInput.left,right:userInput.right}}};
|
|
2131
2122
|
|
|
2132
|
-
const HACKY_CSS_CLASSNAME="perseus-widget-matcher";
|
|
2123
|
+
const HACKY_CSS_CLASSNAME="perseus-widget-matcher";const Matcher=React.forwardRef(function Matcher(props,ref){const{strings}=usePerseusI18n();const leftSortable=React.useRef(null);const rightSortable=React.useRef(null);const[leftHeight,setLeftHeight]=React.useState(0);const[rightHeight,setRightHeight]=React.useState(0);const[texRendererLoaded,setTexRendererLoaded]=React.useState(false);wonderBlocksCore.useOnMountEffect(()=>{props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"matcher",widgetId:props.widgetId}});});React.useImperativeHandle(ref,()=>({getPromptJSON:()=>getPromptJSON$9(props),moveLeftOptionToIndex:(option,index)=>{leftSortable.current?.moveOptionToIndex(option,index);},moveRightOptionToIndex:(option,index)=>{rightSortable.current?.moveOptionToIndex(option,index);}}));function getUserInputFromSortable(){if(!texRendererLoaded){return {left:[],right:[]}}return {left:leftSortable.current?.getOptions()??[],right:rightSortable.current?.getOptions()??[]}}function changeAndTrack(){props.handleUserInput(getUserInputFromSortable());props.trackInteraction();}if(!texRendererLoaded){const{TeX}=getDependencies();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(wonderBlocksProgressSpinner.CircularSpinner,{}),jsxRuntimeExports.jsx("div",{style:{display:"none"},children:jsxRuntimeExports.jsx(TeX,{onRender:()=>setTexRendererLoaded(true),children:"1"})})]})}const showLabels=props.labels.some(wonderStuffCore.isTruthy);const constraints={height:Math.max(leftHeight,rightHeight)};const cellMarginPx=props.apiOptions.isMobile?8:5;return jsxRuntimeExports.jsx("table",{className:aphrodite.css(styles$7.widget)+" "+HACKY_CSS_CLASSNAME,children:jsxRuntimeExports.jsxs("tbody",{children:[showLabels&&jsxRuntimeExports.jsxs("tr",{className:aphrodite.css(styles$7.row),children:[jsxRuntimeExports.jsx("th",{className:aphrodite.css(styles$7.column,styles$7.columnLabel),children:jsxRuntimeExports.jsx(Renderer,{content:props.labels[0]||"...",linterContext:props.linterContext,strings:strings})}),jsxRuntimeExports.jsx("th",{className:aphrodite.css(styles$7.column,styles$7.columnRight,styles$7.columnLabel),children:jsxRuntimeExports.jsx(Renderer,{content:props.labels[1]||"...",linterContext:props.linterContext,strings:strings})})]}),jsxRuntimeExports.jsxs("tr",{className:aphrodite.css(styles$7.row),children:[jsxRuntimeExports.jsx("td",{className:aphrodite.css(styles$7.column),children:jsxRuntimeExports.jsx(Sortable,{options:props.userInput.left,layout:"vertical",padding:props.padding,disabled:!props.orderMatters,constraints:constraints,onMeasure:dimensions=>setLeftHeight(Math.max(...dimensions.heights)),onChange:changeAndTrack,margin:cellMarginPx,linterContext:props.linterContext,ref:leftSortable})}),jsxRuntimeExports.jsx("td",{className:aphrodite.css(styles$7.column,styles$7.columnRight),children:jsxRuntimeExports.jsx(Sortable,{options:props.userInput.right,layout:"vertical",padding:props.padding,constraints:constraints,onMeasure:dimensions=>setRightHeight(Math.max(...dimensions.heights)),onChange:changeAndTrack,margin:cellMarginPx,linterContext:props.linterContext,ref:rightSortable})})]})]})})});function getStartUserInput$6(options,problemNum){const shuffled=perseusCore.shuffleMatcher(options,problemNum);return shuffled}function getUserInputFromSerializedState$6(serializedState){return {left:serializedState.left,right:serializedState.right}}const WrappedMatcher=withDependencies(Matcher);var Matcher$1 = {name:"matcher",displayName:"Matcher (two column)",hidden:true,widget:WrappedMatcher,isLintable:true,getStartUserInput: getStartUserInput$6,getUserInputFromSerializedState: getUserInputFromSerializedState$6};const padding=5;const border=`var(--wb-border-width-thin) solid var(--wb-semanticColor-core-border-neutral-strong)`;const styles$7=aphrodite.StyleSheet.create({widget:{paddingTop:padding,maxWidth:"100%",minWidth:"auto"},row:{border:0},column:{padding:0,border:0},columnRight:{borderLeft:border},columnLabel:{fontWeight:"inherit",borderBottom:border,padding:`0 ${padding}px ${padding}px ${padding}px`,textAlign:"center"}});
|
|
2133
2124
|
|
|
2134
2125
|
const getPromptJSON$8=widgetData=>{return {type:"matrix",options:{height:widgetData.matrixBoardSize[0],width:widgetData.matrixBoardSize[1]},userInput:{answerRows:widgetData.userInput.answers}}};
|
|
2135
2126
|
|
|
2136
|
-
const{assert: assert$
|
|
2127
|
+
const{assert: assert$1}=InteractiveUtil;const NORMAL_DIMENSIONS={INPUT_MARGIN:3,INPUT_HEIGHT:30,INPUT_WIDTH:40};const KEYPAD_INPUT_DIMENSIONS={INPUT_MARGIN:4,INPUT_HEIGHT:36,INPUT_WIDTH:64};function getInputPath$1(row,column){return [""+row,""+column]}const getDefaultPath$1=function(){return getInputPath$1(0,0)};const getRowFromPath$1=function(path){assert$1(Array.isArray(path)&&path.length===2);return +path[0]};const getColumnFromPath$1=function(path){assert$1(Array.isArray(path)&&path.length===2);return +path[1]};const getRefForPath$1=function(path){const row=getRowFromPath$1(path);const column=getColumnFromPath$1(path);return "answer"+row+","+column};class Matrix extends React__namespace.Component{componentDidMount(){this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"matrix",widgetSubType:"null",widgetId:this.props.widgetId}});this.cursorPosition=[0,0];}getDOMNodeForPath(path){const inputID=getRefForPath$1(path);return ReactDOM__namespace.default.findDOMNode(this.refs[inputID])}getPromptJSON(){return getPromptJSON$8(this.props)}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,answers:userInput.answers,cursorPosition:this.state.cursorPosition}}render(){let dimensions;if(this.props.apiOptions.customKeypad){dimensions=KEYPAD_INPUT_DIMENSIONS;}else {dimensions=NORMAL_DIMENSIONS;}const{INPUT_MARGIN,INPUT_HEIGHT,INPUT_WIDTH}=dimensions;const matrixSize=perseusCore.getMatrixSize(this.props.userInput.answers);const maxRows=this.props.matrixBoardSize[0];const maxCols=this.props.matrixBoardSize[1];const cursorRow=this.state.cursorPosition[0];const cursorCol=this.state.cursorPosition[1];const highlightedRow=Math.max(cursorRow,matrixSize[0]-1);const highlightedCol=Math.max(cursorCol,matrixSize[1]-1);const bracketHeight=(highlightedRow+1)*(INPUT_HEIGHT+2*INPUT_MARGIN);const bracketOffset=(highlightedCol+1)*(INPUT_WIDTH+2*INPUT_MARGIN);const className=classNames__default.default({"perseus-matrix":true,"static-mode":this.props.static});return jsxRuntimeExports.jsxs("div",{className:className,children:[this.props.prefix&&jsxRuntimeExports.jsx("div",{className:"matrix-prefix",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.prefix,linterContext:this.props.linterContext,strings:this.context.strings})}),jsxRuntimeExports.jsxs("div",{className:"matrix-input",children:[jsxRuntimeExports.jsx("div",{className:"matrix-bracket bracket-left",style:{height:bracketHeight}}),jsxRuntimeExports.jsx("div",{className:"matrix-bracket bracket-right",style:{height:bracketHeight,left:bracketOffset}}),___default.default(maxRows).times(row=>{const rowVals=this.props.userInput.answers[row];return jsxRuntimeExports.jsx("div",{className:"matrix-row",children:___default.default(maxCols).times(col=>{const outside=row>highlightedRow||col>highlightedCol;const inputProps={className:outside?"outside":"inside",ref:getRefForPath$1(getInputPath$1(row,col)),value:rowVals?rowVals[col]:null,style:{height:INPUT_HEIGHT,width:INPUT_WIDTH,margin:INPUT_MARGIN},disabled:this.props.apiOptions.readOnly||this.props.apiOptions.editingDisabled,onFocus:()=>{this.cursorPosition=[row,col];this.setState({cursorPosition:[row,col]});this._handleFocus(row,col);},onBlur:()=>{if(row===this.cursorPosition[0]&&col===this.cursorPosition[1]){this.setState({cursorPosition:[0,0]});}this._handleBlur(row,col);},onKeyDown:e=>{this.handleKeyDown(row,col,e);},onChange:(value,cb)=>{this.onValueChange(row,col,value,cb);}};let MatrixInput;if(this.props.apiOptions.customKeypad){const style={margin:INPUT_MARGIN,minWidth:INPUT_WIDTH,minHeight:INPUT_HEIGHT,boxSizing:"border-box",borderWidth:outside?wonderBlocksTokens.border.width.thin:wonderBlocksTokens.border.width.medium};MatrixInput=jsxRuntimeExports.jsx(SimpleKeypadInput,{...inputProps,style:style,scrollable:true,keypadElement:this.props.keypadElement});}else {const updatedProps={...inputProps,style:aphrodite.StyleSheet.create({input:{...inputProps.style,display:"inline-block",padding:0,borderWidth:outside?wonderBlocksTokens.border.width.thin:wonderBlocksTokens.border.width.medium}}).input};MatrixInput=jsxRuntimeExports.jsx(TextInput,{...updatedProps});}return jsxRuntimeExports.jsx("span",{className:"matrix-input-field",children:MatrixInput},col)})},row)})]}),this.props.suffix&&jsxRuntimeExports.jsx("div",{className:"matrix-suffix",children:jsxRuntimeExports.jsx(Renderer,{content:this.props.suffix,linterContext:this.props.linterContext,strings:this.context.strings})})]})}constructor(...args){super(...args),this.state={cursorPosition:[0,0]},this.getInputPaths=()=>{const inputPaths=[];const maxRows=this.props.matrixBoardSize[0];const maxCols=this.props.matrixBoardSize[1];for(let row=0;row<maxRows;row++){for(let col=0;col<maxCols;col++){const inputPath=getInputPath$1(row,col);inputPaths.push(inputPath);}}return inputPaths},this._handleFocus=(row,col)=>{this.props.onFocus(getInputPath$1(row,col));},this._handleBlur=(row,col)=>{this.props.onBlur(getInputPath$1(row,col));},this.focus=()=>{this.focusInputPath(getDefaultPath$1());return true},this.focusInputPath=path=>{const inputID=getRefForPath$1(path);this.refs[inputID].focus();},this.blurInputPath=path=>{if(path.length===0){path=getDefaultPath$1();}const inputID=getRefForPath$1(path);this.refs[inputID].blur();},this.handleKeyDown=(row,col,e)=>{const maxRow=this.props.matrixBoardSize[0];const maxCol=this.props.matrixBoardSize[1];const curInput=this.refs[getRefForPath$1(getInputPath$1(row,col))];const curValueString=curInput.getStringValue();const cursorStartPosition=curInput.getSelectionStart();const cursorEndPosition=curInput.getSelectionEnd();let nextPath=null;if(e.key==="ArrowUp"&&row>0){nextPath=getInputPath$1(row-1,col);}else if(e.key==="ArrowDown"&&row+1<maxRow){nextPath=getInputPath$1(row+1,col);}else if(e.key==="ArrowLeft"&&col>0){if(cursorStartPosition===0&&cursorEndPosition===0){nextPath=getInputPath$1(row,col-1);}}else if(e.key==="ArrowRight"&&col+1<maxCol){if(cursorStartPosition===curValueString.length){nextPath=getInputPath$1(row,col+1);}}if(nextPath){e.preventDefault();const input=this.refs[getRefForPath$1(nextPath)];const inputValString=input.getStringValue();const valueLength=inputValString.length*2;input.focus();if(e.key==="ArrowRight"){input.setSelectionRange(0,0);}else {input.setSelectionRange(valueLength,valueLength);}}},this.onValueChange=(row,column,value,cb)=>{const answers=this.props.userInput.answers.map(answer=>[...answer]);if(!answers[row]){answers[row]=[];}answers[row][column]=value;this.props.handleUserInput({answers},cb);this.props.trackInteraction();};}}Matrix.contextType=PerseusI18nContext;Matrix.defaultProps={matrixBoardSize:[3,3],prefix:"",suffix:"",apiOptions:ApiOptions.defaults,linterContext:PerseusLinter.linterContextDefault,userInput:{answers:[[]]}};function getStartUserInput$5(){return {answers:[[]]}}function getCorrectUserInput$2(options){return {answers:options.answers.map(row=>row.map(num=>String(num)))}}function getUserInputFromSerializedState$5(serializedState){return {answers:serializedState.answers}}const WrappedMatrix=withDependencies(Matrix);var Matrix$1 = {name:"matrix",displayName:"Matrix",hidden:true,widget:WrappedMatrix,isLintable:true,getStartUserInput: getStartUserInput$5,getCorrectUserInput: getCorrectUserInput$2,getUserInputFromSerializedState: getUserInputFromSerializedState$5};
|
|
2137
2128
|
|
|
2138
2129
|
const getPromptJSON$7=()=>{return getUnsupportedPromptJSON("measurer")};
|
|
2139
2130
|
|
|
2140
|
-
class Measurer extends React__namespace.Component{componentDidMount(){this.setupGraphie();}componentDidUpdate(prevProps){const shouldSetupGraphie=___default.default.any(["box","showProtractor","showRuler","rulerLabel","rulerTicks","rulerPixels","rulerLength"],prop=>{return prevProps[prop]!==this.props[prop]},this);if(shouldSetupGraphie){this.setupGraphie();}}setupGraphie(){const graphieDiv=ReactDOM__namespace.default.findDOMNode(this.refs.graphieDiv);$__default.default(graphieDiv).empty();const graphie=this.graphie=GraphUtils.createGraphie(graphieDiv);const scale=[40,40];const range=[[0,this.props.box[0]/scale[0]],[0,this.props.box[1]/scale[1]]];graphie.init({range:range,scale:scale});graphie.addMouseLayer({allowScratchpad:true});if(this.protractor){this.protractor.remove();}if(this.props.showProtractor){this.protractor=graphie.protractor([
|
|
2131
|
+
class Measurer extends React__namespace.Component{componentDidMount(){this.setupGraphie();}componentDidUpdate(prevProps){const shouldSetupGraphie=___default.default.any(["box","showProtractor","showRuler","rulerLabel","rulerTicks","rulerPixels","rulerLength"],prop=>{return prevProps[prop]!==this.props[prop]},this);if(shouldSetupGraphie){this.setupGraphie();}}setupGraphie(){const graphieDiv=ReactDOM__namespace.default.findDOMNode(this.refs.graphieDiv);$__default.default(graphieDiv).empty();const graphie=this.graphie=GraphUtils.createGraphie(graphieDiv);const scale=[40,40];const range=[[0,this.props.box[0]/scale[0]],[0,this.props.box[1]/scale[1]]];graphie.init({range:range,scale:scale});graphie.addMouseLayer({allowScratchpad:true});if(this.protractor){this.protractor.remove();}if(this.props.showProtractor){this.protractor=graphie.protractor([7.5,.5]);}if(this.ruler){this.ruler.remove();}if(this.props.showRuler){this.ruler=graphie.ruler({center:[(range[0][0]+range[0][1])/2,(range[1][0]+range[1][1])/2],label:this.props.rulerLabel,pixelsPerUnit:this.props.rulerPixels,ticksPerUnit:this.props.rulerTicks,units:this.props.rulerLength});}}getPromptJSON(){return getPromptJSON$7()}render(){const{image}=this.props;return jsxRuntimeExports.jsxs("div",{className:"perseus-widget perseus-widget-measurer "+"graphie-container blank-background",style:{width:this.props.box[0],height:this.props.box[1]},children:[image.url&&jsxRuntimeExports.jsx("div",{style:{position:"relative",top:image.top??0,left:image.left??0},children:jsxRuntimeExports.jsx(SvgImage,{src:image.url,allowZoom:false})}),jsxRuntimeExports.jsx("div",{className:"graphie",ref:"graphieDiv"})]})}constructor(...args){super(...args),this.isWidget=true;}}var Measurer$1 = {name:"measurer",displayName:"Measurer",hidden:true,widget:Measurer};
|
|
2141
2132
|
|
|
2142
2133
|
const getPromptJSON$6=widgetData=>{const{userInput}=widgetData;return {type:"number-line",options:{range:widgetData.range,snapDivisions:widgetData.snapDivisions},userInput:{numLinePosition:userInput.numLinePosition,numDivisions:userInput.numDivisions,rel:userInput.rel}}};
|
|
2143
2134
|
|
|
2144
|
-
const MovablePoint=Graphie.MovablePoint;const Line=Graphie.Line;const{assert: assert$1}=InteractiveUtil;const bound=(x,gt,lt)=>Math.min(Math.max(x,gt),lt);const EN_DASH="–";const horizontalPadding=30;const reverseRel={eq:"eq",ge:"le",gt:"lt",le:"ge",lt:"gt"};const toggleStrictRel={eq:"eq",ge:"gt",gt:"ge",le:"lt",lt:"le"};function formatImproper(n,d){if(d===1){return ""+n}return `\\dfrac{${n}}{${d}}`}function formatMixed(n,d){if(n<0){return "-"+formatMixed(-n,d)}const w=Math.floor(n/d);if(w===0){return formatImproper(n,d)}if(n-w*d===0){return ""+w}return w+formatImproper(n-w*d,d)}function formatNonReduced(n,d,base){const factor=Math.floor(base/d);return formatImproper(n*factor,base)}const _label=(graphie,labelStyle,pos,value,base)=>{value=value||pos;if(labelStyle==="decimal"){return graphie.label([pos,-0.53],Math.round(value*100)/100,"center")}if(labelStyle==="improper"){const frac=kmath.KhanMath.toFraction(value);return graphie.label([pos,-0.17],formatImproper(frac[0],frac[1]),"below")}if(labelStyle==="mixed"){const frac=kmath.KhanMath.toFraction(value);return graphie.label([pos,-0.17],formatMixed(frac[0],frac[1]),"below")}if(labelStyle==="non-reduced"){const frac=kmath.KhanMath.toFraction(value);return graphie.label([pos,-0.17],formatNonReduced(frac[0],frac[1],base),"below")}};const TickMarks=Graphie.createSimpleClass((graphie,props)=>{if(!Number.isFinite(props.tickStep)||props.tickStep<=0){return []}const results=[];const{range,labelRange,labelStyle,labelTicks,tickStep,numDivisions}=props;const leftLabel=labelRange[0]==null?range[0]:labelRange[0];const rightLabel=labelRange[1]==null?range[1]:labelRange[1];let base;if(labelStyle==="non-reduced"){const fractions=[leftLabel,rightLabel];for(let i=0;i<=numDivisions;i++){const x=range[0]+i*tickStep;fractions.push(x);}const getDenom=x=>kmath.number.toFraction(x)[1];const denoms=fractions.map(getDenom);base=denoms.reduce((x,y)=>kmath.KhanMath.getLCM(x,y));}else {base=undefined;}const highlightedLineStyle={stroke:KhanColors.BLUE,strokeWidth:3.5};const highlightedTextStyle={color:KhanColors.BLUE};const initialTicks=[...Array(Math.round(numDivisions)).keys()].map(index=>range[0]+index*tickStep);const byNumericAscending=(a,b)=>a-b;const allTicks=[...new Set([...initialTicks,leftLabel,rightLabel,...range])].sort(byNumericAscending);allTicks.forEach(tick=>{const tickIsHighlighted=tick===leftLabel||tick===rightLabel;const lineStyle=tickIsHighlighted?highlightedLineStyle:null;const textStyle=tickIsHighlighted?highlightedTextStyle:null;graphie.style(lineStyle,()=>{results.push(graphie.line([tick,-0.2],[tick,.2]));});if(labelTicks||tickIsHighlighted){graphie.style(textStyle,()=>{results.push(_label(graphie,labelStyle,tick,tick,base));});}});return results});function isValid(props){const range=props.range;let initialX=props.userInput?.numLinePosition;const divisionRange=props.divisionRange;initialX=initialX==null?range[0]:initialX;return range[0]<range[1]&&kmath.number.sign(initialX-range[0])>=0&&kmath.number.sign(initialX-range[1])<=0&&divisionRange[0]<divisionRange[1]&&0<props.userInput?.numDivisions&&0<props.snapDivisions}const NumberLine=React.forwardRef(function NumberLine(props,ref){const{strings}=usePerseusI18n();const propsRef=wonderBlocksCore.useLatestRef(props);const[numDivisionsEmpty,setNumDivisionsEmpty]=React.useState(false);const graphieRef=React.useRef(null);const tickCtrlRef=React.useRef(null);wonderBlocksCore.useOnMountEffect(()=>{props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"number-line",widgetId:props.widgetId}});});React.useImperativeHandle(ref,()=>({focus:()=>{if(props.isTickCtrl){tickCtrlRef.current?.focus();return true}return false},focusInputPath:path=>{if(path?.length===1){tickCtrlRef.current?.focus();}},blurInputPath:path=>{if(path?.length===1){tickCtrlRef.current?.blur();}},getInputPaths:()=>{if(props.isTickCtrl){return [["tick-ctrl"]]}return []},getDOMNodeForPath:inputPath=>{if(inputPath?.length===1){return ReactDOM__namespace.default.findDOMNode(tickCtrlRef.current)}return null},getSerializedState:()=>({alignment:props.alignment,static:props.static,range:props.range,labelRange:props.labelRange,labelStyle:props.labelStyle,labelTicks:props.labelTicks,divisionRange:props.divisionRange,snapDivisions:props.snapDivisions,isInequality:props.isInequality,showTooltips:props.showTooltips,isTickCtrl:props.isTickCtrl,numDivisions:props.userInput.numDivisions,numLinePosition:props.userInput.numLinePosition,rel:"ge"}),getPromptJSON(){return getPromptJSON$6(props)},movePosition}));const setupGraphie=React.useCallback((graphie,options)=>{const latestProps=propsRef.current;if(!isValid(latestProps)){return}const widthInPixels=latestProps.apiOptions.isMobile?288-horizontalPadding*2:400;const range=options.range;const scale=(range[1]-range[0])/widthInPixels;const buffer=horizontalPadding*scale;const left=range[0]-buffer;const right=range[1]+buffer;const hasFractionalLabels=latestProps.labelStyle==="improper"||latestProps.labelStyle==="mixed"||latestProps.labelStyle==="non-reduced";const bottom=hasFractionalLabels?-1.5:-1;const top=1;graphie.init({range:[[left,right],[bottom,top]],scale:[1/scale,40],isMobile:latestProps.apiOptions.isMobile});const center=(range[0]+range[1])/2;graphie.line([center,0],[right,0],{arrows:"->"});graphie.line([center,0],[left,0],{arrows:"->"});},[propsRef]);function snapNumLinePosition(calculatedProps,numLinePosition){const left=calculatedProps.range[0];const right=calculatedProps.range[1];const snapX=calculatedProps.tickStep/calculatedProps.snapDivisions;let x=bound(numLinePosition,left,right);x=left+kmath.number.roundTo(x-left,snapX);assert$1(Number.isFinite(x));return x}function onNumDivisionsChange(numDivisions,cb){const width=props.range[1]-props.range[0];numDivisions=Math.round(numDivisions);numDivisions=numDivisions<0?numDivisions*-1:numDivisions;if(numDivisions){const nextProps={...props,tickStep:width/numDivisions};const newNumLinePosition=snapNumLinePosition(nextProps,props.userInput.numLinePosition);setNumDivisionsEmpty(false);props.handleUserInput({...props.userInput,numDivisions:numDivisions,numLinePosition:newNumLinePosition},cb);}else {setNumDivisionsEmpty(true);cb?.();}}function handleTickCtrlFocus(){props.onFocus(["tick-ctrl"]);}function handleTickCtrlBlur(){props.onBlur(["tick-ctrl"]);}function movePosition(targetPosition){props.handleUserInput({...props.userInput,numLinePosition:targetPosition});props.trackInteraction();}function handleReverse(){const newRel=reverseRel[props.userInput.rel];props.handleUserInput({...props.userInput,rel:newRel});}function handleToggleStrict(){const newRel=toggleStrictRel[props.userInput.rel];props.handleUserInput({...props.userInput,rel:newRel});}function renderNumberLinePoint(calculatedProps){const isOpen=["lt","gt"].includes(calculatedProps.userInput.rel);let fill;if(isOpen){fill=KhanColors._BACKGROUND;}else if(calculatedProps.static){fill=KhanColors.BLUE;}else {fill=KhanColors.GREEN;}const normalStyle={fill:fill,stroke:calculatedProps.static?KhanColors.BLUE:KhanColors.GREEN,"stroke-width":isOpen?3:1};const highlightStyle={fill:isOpen?KhanColors._BACKGROUND:KhanColors.GREEN,"stroke-width":isOpen?3:1};const mobileDotStyle=calculatedProps.isInequality?{stroke:KhanColors.GREEN,"fill-opacity":isOpen?0:1}:{};return jsxRuntimeExports.jsx(MovablePoint,{ref:"numberLinePoint",pointSize:6,coord:[calculatedProps.userInput.numLinePosition,0],constraints:[(coord,prevCoord)=>{return [coord[0],prevCoord[1]]},(coord,prevCoord)=>{const x=snapNumLinePosition(calculatedProps,coord[0]);return [x,coord[1]]}],normalStyle:normalStyle,highlightStyle:highlightStyle,onMove:coord=>{movePosition(coord[0]);},isMobile:calculatedProps.apiOptions.isMobile,mobileStyleOverride:mobileDotStyle,showTooltips:calculatedProps.showTooltips??false,xOnlyTooltip:true})}function getInequalityEndpoint(){const isGreater=["ge","gt"].includes(props.userInput.rel);const widthInPixels=400;const range=props.range;const scale=(range[1]-range[0])/widthInPixels;const buffer=horizontalPadding*scale;const left=range[0]-buffer;const right=range[1]+buffer;const end=isGreater?[right,0]:[left,0];return end}function renderInequality(){if(props.isInequality){const end=getInequalityEndpoint();const style={arrows:"->",stroke:props.apiOptions.isMobile?KhanColors.GREEN:KhanColors.BLUE,strokeWidth:3.5};return jsxRuntimeExports.jsx(Line,{start:[props.userInput.numLinePosition,0],end:end,style:style})}return null}function renderGraphie(){const range=props.range;const width=range[1]-range[0];const options={range:props.range,isTickCtrl:props.isTickCtrl};const calculatedProps={...props,tickStep:width/props.userInput.numDivisions};return jsxRuntimeExports.jsxs(Graphie,{ref:graphieRef,box:[props.apiOptions.isMobile?288:460,80],options:options,onMouseDown:coord=>{const point=graphieRef.current?.movables.numberLinePoint;point?.grab(coord);},setup:setupGraphie,isMobile:props.apiOptions.isMobile,children:[jsxRuntimeExports.jsx(TickMarks,{range:calculatedProps.range,labelTicks:calculatedProps.labelTicks,labelStyle:calculatedProps.labelStyle,labelRange:calculatedProps.labelRange,tickStep:calculatedProps.tickStep,numDivisions:calculatedProps.userInput.numDivisions,isMobile:calculatedProps.apiOptions.isMobile}),renderInequality(),renderNumberLinePoint(calculatedProps)]},props.labelStyle)}const divisionRange=props.divisionRange;const divRangeString=divisionRange[0]+EN_DASH+divisionRange[1];const invalidNumDivisions=props.userInput?.numDivisions<divisionRange[0]||props.userInput?.numDivisions>divisionRange[1];const inequalityControls=jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("input",{type:"button",className:"simple-button",value:strings.switchDirection,onClick:handleReverse}),jsxRuntimeExports.jsx("input",{type:"button",className:"simple-button",value:["le","ge"].includes(props.userInput?.rel)?strings.circleOpen:strings.circleFilled,onClick:handleToggleStrict})]});let tickCtrl;if(props.isTickCtrl){const Input=props.apiOptions.customKeypad?SimpleKeypadInput:NumberInput;tickCtrl=jsxRuntimeExports.jsxs("label",{children:[strings.numDivisions," ",jsxRuntimeExports.jsx(Input,{ref:tickCtrlRef,value:numDivisionsEmpty?null:props.userInput?.numDivisions||divisionRange[0],checkValidity:val=>val>=divisionRange[0]&&val<=divisionRange[1],onChange:onNumDivisionsChange,onFocus:handleTickCtrlFocus,onBlur:handleTickCtrlBlur,useArrowKeys:true,keypadElement:props.keypadElement})]});}return jsxRuntimeExports.jsxs("div",{className:"perseus-widget "+"perseus-widget-interactive-number-line",children:[tickCtrl,!isValid(props)?jsxRuntimeExports.jsx("div",{className:"perseus-error",children:"Invalid number line configuration."}):props.isTickCtrl&&invalidNumDivisions?jsxRuntimeExports.jsx("div",{className:"perseus-error",children:strings.divisions({divRangeString:divRangeString})}):renderGraphie(),!props.static&&props.isInequality&&inequalityControls]})});function getUserInputFromSerializedState$4(serializedState){return {numDivisions:serializedState.numDivisions,numLinePosition:serializedState.numLinePosition,rel:"eq"}}function getStartNumDivisions(options){const width=options.range[1]-options.range[0];let numDivisions;if(options.numDivisions!=null){numDivisions=options.numDivisions;}else if(options.tickStep!=null){numDivisions=width/options.tickStep;}else {numDivisions=undefined;}return numDivisions}function getCorrectUserInput$1(options){const numLinePosition=options.correctX!=null?options.correctX:options.range[0];return {numDivisions:getStartNumDivisions(options),numLinePosition,rel:options.isInequality&&options.correctRel||"eq"}}function getStartUserInput$4(options){const numLinePosition=options.initialX!=null?options.initialX:options.range[0];return {numDivisions:getStartNumDivisions(options),numLinePosition,rel:options.isInequality?"ge":"eq"}}const WrappedNumberLine=withDependencies(NumberLine);var NumberLine$1 = {name:"number-line",displayName:"Number line",widget:WrappedNumberLine,getCorrectUserInput: getCorrectUserInput$1,getStartUserInput: getStartUserInput$4,getUserInputFromSerializedState: getUserInputFromSerializedState$4};
|
|
2135
|
+
const MovablePoint=Graphie.MovablePoint;const Line=Graphie.Line;const{assert}=InteractiveUtil;const bound=(x,gt,lt)=>Math.min(Math.max(x,gt),lt);const EN_DASH="–";const horizontalPadding=30;const reverseRel={eq:"eq",ge:"le",gt:"lt",le:"ge",lt:"gt"};const toggleStrictRel={eq:"eq",ge:"gt",gt:"ge",le:"lt",lt:"le"};function formatImproper(n,d){if(d===1){return ""+n}return `\\dfrac{${n}}{${d}}`}function formatMixed(n,d){if(n<0){return "-"+formatMixed(-n,d)}const w=Math.floor(n/d);if(w===0){return formatImproper(n,d)}if(n-w*d===0){return ""+w}return w+formatImproper(n-w*d,d)}function formatNonReduced(n,d,base){const factor=Math.floor(base/d);return formatImproper(n*factor,base)}const _label=(graphie,labelStyle,pos,value,base)=>{value=value||pos;if(labelStyle==="decimal"){return graphie.label([pos,-0.53],Math.round(value*100)/100,"center")}if(labelStyle==="improper"){const frac=kmath.KhanMath.toFraction(value);return graphie.label([pos,-0.17],formatImproper(frac[0],frac[1]),"below")}if(labelStyle==="mixed"){const frac=kmath.KhanMath.toFraction(value);return graphie.label([pos,-0.17],formatMixed(frac[0],frac[1]),"below")}if(labelStyle==="non-reduced"){const frac=kmath.KhanMath.toFraction(value);return graphie.label([pos,-0.17],formatNonReduced(frac[0],frac[1],base),"below")}};const TickMarks=Graphie.createSimpleClass((graphie,props)=>{if(!Number.isFinite(props.tickStep)||props.tickStep<=0){return []}const results=[];const{range,labelRange,labelStyle,labelTicks,tickStep,numDivisions}=props;const leftLabel=labelRange[0]==null?range[0]:labelRange[0];const rightLabel=labelRange[1]==null?range[1]:labelRange[1];let base;if(labelStyle==="non-reduced"){const fractions=[leftLabel,rightLabel];for(let i=0;i<=numDivisions;i++){const x=range[0]+i*tickStep;fractions.push(x);}const getDenom=x=>kmath.number.toFraction(x)[1];const denoms=fractions.map(getDenom);base=denoms.reduce((x,y)=>kmath.KhanMath.getLCM(x,y));}else {base=undefined;}const highlightedLineStyle={stroke:KhanColors.BLUE,strokeWidth:3.5};const highlightedTextStyle={color:KhanColors.BLUE};const initialTicks=[...Array(Math.round(numDivisions)).keys()].map(index=>range[0]+index*tickStep);const byNumericAscending=(a,b)=>a-b;const allTicks=[...new Set([...initialTicks,leftLabel,rightLabel,...range])].sort(byNumericAscending);allTicks.forEach(tick=>{const tickIsHighlighted=tick===leftLabel||tick===rightLabel;const lineStyle=tickIsHighlighted?highlightedLineStyle:null;const textStyle=tickIsHighlighted?highlightedTextStyle:null;graphie.style(lineStyle,()=>{results.push(graphie.line([tick,-0.2],[tick,.2]));});if(labelTicks||tickIsHighlighted){graphie.style(textStyle,()=>{results.push(_label(graphie,labelStyle,tick,tick,base));});}});return results});function isValid(props){const range=props.range;let initialX=props.userInput?.numLinePosition;const divisionRange=props.divisionRange;initialX=initialX==null?range[0]:initialX;return range[0]<range[1]&&kmath.number.sign(initialX-range[0])>=0&&kmath.number.sign(initialX-range[1])<=0&&divisionRange[0]<divisionRange[1]&&0<props.userInput?.numDivisions&&0<props.snapDivisions}const NumberLine=React.forwardRef(function NumberLine(props,ref){const{strings}=usePerseusI18n();const propsRef=wonderBlocksCore.useLatestRef(props);const[numDivisionsEmpty,setNumDivisionsEmpty]=React.useState(false);const graphieRef=React.useRef(null);const tickCtrlRef=React.useRef(null);wonderBlocksCore.useOnMountEffect(()=>{props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"number-line",widgetId:props.widgetId}});});React.useImperativeHandle(ref,()=>({focus:()=>{if(props.isTickCtrl){tickCtrlRef.current?.focus();return true}return false},focusInputPath:path=>{if(path?.length===1){tickCtrlRef.current?.focus();}},blurInputPath:path=>{if(path?.length===1){tickCtrlRef.current?.blur();}},getInputPaths:()=>{if(props.isTickCtrl){return [["tick-ctrl"]]}return []},getDOMNodeForPath:inputPath=>{if(inputPath?.length===1){return ReactDOM__namespace.default.findDOMNode(tickCtrlRef.current)}return null},getSerializedState:()=>({alignment:props.alignment,static:props.static,range:props.range,labelRange:props.labelRange,labelStyle:props.labelStyle,labelTicks:props.labelTicks,divisionRange:props.divisionRange,snapDivisions:props.snapDivisions,isInequality:props.isInequality,showTooltips:props.showTooltips,isTickCtrl:props.isTickCtrl,numDivisions:props.userInput.numDivisions,numLinePosition:props.userInput.numLinePosition,rel:"ge"}),getPromptJSON(){return getPromptJSON$6(props)},movePosition}));const setupGraphie=React.useCallback((graphie,options)=>{const latestProps=propsRef.current;if(!isValid(latestProps)){return}const widthInPixels=latestProps.apiOptions.isMobile?288-horizontalPadding*2:400;const range=options.range;const scale=(range[1]-range[0])/widthInPixels;const buffer=horizontalPadding*scale;const left=range[0]-buffer;const right=range[1]+buffer;const hasFractionalLabels=latestProps.labelStyle==="improper"||latestProps.labelStyle==="mixed"||latestProps.labelStyle==="non-reduced";const bottom=hasFractionalLabels?-1.5:-1;const top=1;graphie.init({range:[[left,right],[bottom,top]],scale:[1/scale,40],isMobile:latestProps.apiOptions.isMobile});const center=(range[0]+range[1])/2;graphie.line([center,0],[right,0],{arrows:"->"});graphie.line([center,0],[left,0],{arrows:"->"});},[propsRef]);function snapNumLinePosition(calculatedProps,numLinePosition){const left=calculatedProps.range[0];const right=calculatedProps.range[1];const snapX=calculatedProps.tickStep/calculatedProps.snapDivisions;let x=bound(numLinePosition,left,right);x=left+kmath.number.roundTo(x-left,snapX);assert(Number.isFinite(x));return x}function onNumDivisionsChange(numDivisions,cb){const width=props.range[1]-props.range[0];numDivisions=Math.round(numDivisions);numDivisions=numDivisions<0?numDivisions*-1:numDivisions;if(numDivisions){const nextProps={...props,tickStep:width/numDivisions};const newNumLinePosition=snapNumLinePosition(nextProps,props.userInput.numLinePosition);setNumDivisionsEmpty(false);props.handleUserInput({...props.userInput,numDivisions:numDivisions,numLinePosition:newNumLinePosition},cb);}else {setNumDivisionsEmpty(true);cb?.();}}function handleTickCtrlFocus(){props.onFocus(["tick-ctrl"]);}function handleTickCtrlBlur(){props.onBlur(["tick-ctrl"]);}function movePosition(targetPosition){props.handleUserInput({...props.userInput,numLinePosition:targetPosition});props.trackInteraction();}function handleReverse(){const newRel=reverseRel[props.userInput.rel];props.handleUserInput({...props.userInput,rel:newRel});}function handleToggleStrict(){const newRel=toggleStrictRel[props.userInput.rel];props.handleUserInput({...props.userInput,rel:newRel});}function renderNumberLinePoint(calculatedProps){const isOpen=["lt","gt"].includes(calculatedProps.userInput.rel);let fill;if(isOpen){fill=KhanColors._BACKGROUND;}else if(calculatedProps.static){fill=KhanColors.BLUE;}else {fill=KhanColors.GREEN;}const normalStyle={fill:fill,stroke:calculatedProps.static?KhanColors.BLUE:KhanColors.GREEN,"stroke-width":isOpen?3:1};const highlightStyle={fill:isOpen?KhanColors._BACKGROUND:KhanColors.GREEN,"stroke-width":isOpen?3:1};const mobileDotStyle=calculatedProps.isInequality?{stroke:KhanColors.GREEN,"fill-opacity":isOpen?0:1}:{};return jsxRuntimeExports.jsx(MovablePoint,{ref:"numberLinePoint",pointSize:6,coord:[calculatedProps.userInput.numLinePosition,0],constraints:[(coord,prevCoord)=>{return [coord[0],prevCoord[1]]},(coord,prevCoord)=>{const x=snapNumLinePosition(calculatedProps,coord[0]);return [x,coord[1]]}],normalStyle:normalStyle,highlightStyle:highlightStyle,onMove:coord=>{movePosition(coord[0]);},isMobile:calculatedProps.apiOptions.isMobile,mobileStyleOverride:mobileDotStyle,showTooltips:calculatedProps.showTooltips??false,xOnlyTooltip:true})}function getInequalityEndpoint(){const isGreater=["ge","gt"].includes(props.userInput.rel);const widthInPixels=400;const range=props.range;const scale=(range[1]-range[0])/widthInPixels;const buffer=horizontalPadding*scale;const left=range[0]-buffer;const right=range[1]+buffer;const end=isGreater?[right,0]:[left,0];return end}function renderInequality(){if(props.isInequality){const end=getInequalityEndpoint();const style={arrows:"->",stroke:props.apiOptions.isMobile?KhanColors.GREEN:KhanColors.BLUE,strokeWidth:3.5};return jsxRuntimeExports.jsx(Line,{start:[props.userInput.numLinePosition,0],end:end,style:style})}return null}function renderGraphie(){const range=props.range;const width=range[1]-range[0];const options={range:props.range,isTickCtrl:props.isTickCtrl};const calculatedProps={...props,tickStep:width/props.userInput.numDivisions};return jsxRuntimeExports.jsxs(Graphie,{ref:graphieRef,box:[props.apiOptions.isMobile?288:460,80],options:options,onMouseDown:coord=>{const point=graphieRef.current?.movables.numberLinePoint;point?.grab(coord);},setup:setupGraphie,isMobile:props.apiOptions.isMobile,children:[jsxRuntimeExports.jsx(TickMarks,{range:calculatedProps.range,labelTicks:calculatedProps.labelTicks,labelStyle:calculatedProps.labelStyle,labelRange:calculatedProps.labelRange,tickStep:calculatedProps.tickStep,numDivisions:calculatedProps.userInput.numDivisions,isMobile:calculatedProps.apiOptions.isMobile}),renderInequality(),renderNumberLinePoint(calculatedProps)]},props.labelStyle)}const divisionRange=props.divisionRange;const divRangeString=divisionRange[0]+EN_DASH+divisionRange[1];const invalidNumDivisions=props.userInput?.numDivisions<divisionRange[0]||props.userInput?.numDivisions>divisionRange[1];const inequalityControls=jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("input",{type:"button",className:"simple-button",value:strings.switchDirection,onClick:handleReverse}),jsxRuntimeExports.jsx("input",{type:"button",className:"simple-button",value:["le","ge"].includes(props.userInput?.rel)?strings.circleOpen:strings.circleFilled,onClick:handleToggleStrict})]});let tickCtrl;if(props.isTickCtrl){const Input=props.apiOptions.customKeypad?SimpleKeypadInput:NumberInput;tickCtrl=jsxRuntimeExports.jsxs("label",{children:[strings.numDivisions," ",jsxRuntimeExports.jsx(Input,{ref:tickCtrlRef,value:numDivisionsEmpty?null:props.userInput?.numDivisions||divisionRange[0],checkValidity:val=>val>=divisionRange[0]&&val<=divisionRange[1],onChange:onNumDivisionsChange,onFocus:handleTickCtrlFocus,onBlur:handleTickCtrlBlur,useArrowKeys:true,keypadElement:props.keypadElement})]});}return jsxRuntimeExports.jsxs("div",{className:"perseus-widget "+"perseus-widget-interactive-number-line",children:[tickCtrl,!isValid(props)?jsxRuntimeExports.jsx("div",{className:"perseus-error",children:"Invalid number line configuration."}):props.isTickCtrl&&invalidNumDivisions?jsxRuntimeExports.jsx("div",{className:"perseus-error",children:strings.divisions({divRangeString:divRangeString})}):renderGraphie(),!props.static&&props.isInequality&&inequalityControls]})});function getUserInputFromSerializedState$4(serializedState){return {numDivisions:serializedState.numDivisions,numLinePosition:serializedState.numLinePosition,rel:"eq"}}function getStartNumDivisions(options){const width=options.range[1]-options.range[0];let numDivisions;if(options.numDivisions!=null){numDivisions=options.numDivisions;}else if(options.tickStep!=null){numDivisions=width/options.tickStep;}else {numDivisions=undefined;}return numDivisions}function getCorrectUserInput$1(options){const numLinePosition=options.correctX!=null?options.correctX:options.range[0];return {numDivisions:getStartNumDivisions(options),numLinePosition,rel:options.isInequality&&options.correctRel||"eq"}}function getStartUserInput$4(options){const numLinePosition=options.initialX!=null?options.initialX:options.range[0];return {numDivisions:getStartNumDivisions(options),numLinePosition,rel:options.isInequality?"ge":"eq"}}const WrappedNumberLine=withDependencies(NumberLine);var NumberLine$1 = {name:"number-line",displayName:"Number line",widget:WrappedNumberLine,getCorrectUserInput: getCorrectUserInput$1,getStartUserInput: getStartUserInput$4,getUserInputFromSerializedState: getUserInputFromSerializedState$4};
|
|
2145
2136
|
|
|
2146
2137
|
const getPromptJSON$5=widgetData=>{return {type:"orderer",options:{options:widgetData.options.map(option=>option.content)},userInput:{values:widgetData.userInput.current}}};
|
|
2147
2138
|
|
|
@@ -2149,11 +2140,11 @@ class PlaceholderCard extends React__namespace.Component{render(){return jsxRunt
|
|
|
2149
2140
|
|
|
2150
2141
|
const getPromptJSON$4=()=>{return getUnsupportedPromptJSON("phet-simulation")};
|
|
2151
2142
|
|
|
2152
|
-
const MOBILE_APP_BOTTOM_BAR_HEIGHT=66;class PhetSimulation extends React__namespace.Component{async componentDidMount(){await this.updateSimState(this.props.url);}async componentDidUpdate(prevProps){if(prevProps.url!==this.props.url){await this.updateSimState(this.props.url);}}getLocale(){switch(this.context.locale){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 this.context.locale}}getPromptJSON(){return getPromptJSON$4()}async updateSimState(urlString){const url=perseusCore.makeSafeUrl(urlString,this.getLocale(),"https://phet.colorado.edu");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.getLocale().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$6.appFullScreenWidgetContainer}:styles$6.widgetContainer;const iframeContainerStyle=isMobileAppFullscreen?styles$6.appFullScreenIframeContainer:styles$6.iframeContainer;const sandboxProperties="allow-same-origin allow-scripts";return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:containerStyle,children:[banner!==null&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{marginBottom:phoneMargin},children:jsxRuntimeExports.jsx(Banner__default.default,{kind:banner.kind,text:banner.message})}),isMobileAppFullscreen&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$6.closeButtonContainer,children:jsxRuntimeExports.jsx(IconButton__default.default,{icon:xIcon__default.default,onClick:this.toggleFullScreen,kind:"
|
|
2143
|
+
const isFullscreenApiSupported=()=>{if(typeof document==="undefined"){return false}const doc=document;return Boolean(doc.fullscreenEnabled||doc.webkitFullscreenEnabled)};const MOBILE_APP_BOTTOM_BAR_HEIGHT=66;class PhetSimulation extends React__namespace.Component{async componentDidMount(){await this.updateSimState(this.props.url);}async componentDidUpdate(prevProps){if(prevProps.url!==this.props.url){await this.updateSimState(this.props.url);}}getLocale(){switch(this.context.locale){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 this.context.locale}}getPromptJSON(){return getPromptJSON$4()}async updateSimState(urlString){const url=perseusCore.makeSafeUrl(urlString,this.getLocale(),"https://phet.colorado.edu");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.getLocale().split("_")[0];for(const l of locales){if(baseLocale===l.split("_")[0]){return false}}return true}renderCornerButton(url,isMobileApp){if(isMobileApp||isFullscreenApiSupported()){return jsxRuntimeExports.jsx(IconButton__default.default,{icon:cornersOutIcon__default.default,onClick:isMobileApp?this.toggleFullScreen:this.requestIframeFullscreen,kind:"secondary",actionType:"neutral","aria-label":this.context.strings.fullscreen,style:styles$6.cornerButton})}return jsxRuntimeExports.jsx(IconButton__default.default,{icon:arrowSquareOutIcon__default.default,href:url.toString(),target:"_blank",kind:"secondary",actionType:"neutral","aria-label":this.context.strings.openInNewTab,style:styles$6.cornerButton})}render(){const{isFullScreen,banner,url}=this.state;const{isMobileApp}=this.props.apiOptions;const isMobileAppFullscreen=isFullScreen&&isMobileApp;const containerStyle=isMobileAppFullscreen?{...styles$6.appFullScreenWidgetContainer}:styles$6.widgetContainer;const iframeContainerStyle=isMobileAppFullscreen?styles$6.appFullScreenIframeContainer:styles$6.iframeContainer;const sandboxProperties="allow-same-origin allow-scripts";return jsxRuntimeExports.jsxs(wonderBlocksCore.View,{style:containerStyle,children:[banner!==null&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:{marginBottom:phoneMargin},children:jsxRuntimeExports.jsx(Banner__default.default,{kind:banner.kind,text:banner.message})}),isMobileAppFullscreen&&jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:styles$6.closeButtonContainer,children:jsxRuntimeExports.jsx(IconButton__default.default,{icon:xIcon__default.default,onClick:this.toggleFullScreen,kind:"secondary",actionType:"neutral","aria-label":this.context.strings.exitFullscreen})}),jsxRuntimeExports.jsx(wonderBlocksCore.View,{style:iframeContainerStyle,children:jsxRuntimeExports.jsx("iframe",{ref:this.iframeRef,title:this.props.description,sandbox:sandboxProperties,className:aphrodite.css(styles$6.iframeResponsive),src:url?.toString(),allow:"fullscreen"})}),url!==null&&!isMobileAppFullscreen&&this.renderCornerButton(url,isMobileApp)]})}constructor(...args){super(...args),this.iframeRef=React__namespace.createRef(),this.isWidget=true,this.state={url:null,banner:null,isFullScreen:false},this.displayLoadFailure=()=>{this.setState({url:null,banner:{message:this.context.strings.simulationLoadFail,kind:"critical"}});},this.toggleFullScreen=()=>{this.setState(prevState=>({isFullScreen:!prevState.isFullScreen}));},this.requestIframeFullscreen=()=>{const iframe=this.iframeRef.current;if(!iframe){return}if(typeof iframe.requestFullscreen==="function"){iframe.requestFullscreen().catch(()=>{});}else {iframe.webkitRequestFullscreen?.();}};}}PhetSimulation.contextType=PerseusI18nContext;const styles$6=aphrodite.StyleSheet.create({widgetContainer:{borderRadius:wonderBlocksTokens.border.radius.radius_080,borderWidth:wonderBlocksTokens.border.width.thin,borderColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,padding:wonderBlocksTokens.sizing.size_160,paddingBottom:0},cornerButton:{marginTop:5,marginBottom:5,alignSelf:"flex-end"},iframeContainer:{position:"relative",overflow:"hidden",width:"100%",paddingTop:"56.25%"},iframeResponsive:{borderWidth:wonderBlocksTokens.border.width.none,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:wonderBlocksTokens.semanticColor.core.background.base.default,display:"flex",flexDirection:"column"},appFullScreenIframeContainer:{position:"relative",overflow:"hidden",width:"100%",flex:1},closeButtonContainer:{position:"absolute",top:wonderBlocksTokens.sizing.size_080,right:wonderBlocksTokens.sizing.size_080,zIndex:1001}});var PhetSimulation$1 = {name:"phet-simulation",displayName:"PhET Simulation",widget:PhetSimulation,isLintable:true};
|
|
2153
2144
|
|
|
2154
2145
|
const getPromptJSON$3=()=>{return getUnsupportedPromptJSON("plotter")};
|
|
2155
2146
|
|
|
2156
|
-
class Plotter extends React__namespace.Component{componentDidMount(){this._isMounted=true;this.setupGraphie(this.props.userInput);this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"plotter",widgetSubType:"null",widgetId:this.props.widgetId}});}UNSAFE_componentWillReceiveProps(nextProps){const props=["type","labels","categories","scaleY","maxY","snapsPerLine","picUrl","labelInterval","static"];this.shouldSetupGraphie=___default.default.any(props,prop=>!___default.default.isEqual(this.props[prop],nextProps[prop]),this);if(!___default.default.isEqual(this.props.starting,nextProps.starting)&&!___default.default.isEqual(this.props.userInput,nextProps.starting)){this.shouldSetupGraphie=true;this.props.handleUserInput(nextProps.starting);}}componentDidUpdate(prevProps,prevState){this.shouldSetupGraphie=this.shouldSetupGraphie||!___default.default.isEqual(this.state.categoryHeights,prevState.categoryHeights);if(this.shouldSetupGraphie){this.setupGraphie(prevProps.userInput);}}componentWillUnmount(){this._isMounted=false;}setupGraphie(prevValues){const self=this;self.shouldSetupGraphie=false;$__default.default(this.graphieDiv.current).empty();const graphie=GraphUtils.createGraphie(this.graphieDiv.current);self.graphie=graphie;self.graphie.pics=[];self.graphie.dotTicks=[];const isBar=self.props.type==="bar";const isLine=self.props.type==="line";const isPic=self.props.type==="pic";const isHistogram=self.props.type==="histogram";const isDotplot=self.props.type==="dotplot";const isTiledPlot=isPic||isDotplot;const config={};const c=config;const isMobile=this.props.apiOptions.isMobile;c.graph={lines:[],bars:[],points:[],dividers:[]};c.scaleY=self.props.scaleY;c.dimX=self.props.categories.length;const plotDimensions=isMobile?[288,336]:self.props.plotDimensions;if(isLine){c.dimX+=isMobile?-0.2:1;}else if(isHistogram){c.barPad=0;c.barWidth=1;}else if(isBar){c.barPad=isMobile?.08:.15;c.barWidth=1-2*c.barPad;c.dimX+=(isMobile?-2:2)*c.barPad;}else if(isTiledPlot){c.picBoxHeight=self.props.picBoxHeight;c.picBoxWidthPx=plotDimensions[0]/self.props.categories.length;const picPadAllWidth=plotDimensions[0]-c.dimX*c.picBoxWidthPx;c.picPad=picPadAllWidth/(2*c.dimX+2);const picFullWidth=c.picBoxWidthPx+2*c.picPad;c.picPad=c.picPad/picFullWidth;c.picBoxWidth=c.picBoxWidthPx/picFullWidth;c.dimX+=2*c.picPad;}if(isDotplot){c.picBoxHeight=this.DOT_PLOT_POINT_SIZE()*2+this.DOT_PLOT_POINT_PADDING();}c.dimY=Math.ceil(self.props.maxY/c.scaleY)*c.scaleY;let padX=25;if((isBar||isLine)&&isMobile){padX=self.props.labels[1].length!==0?17:11;}if(isDotplot){padX/=2;}if(isMobile&&isTiledPlot&&self.props.labels[1].length===0){padX=0;}let padTop=25;let padBottom=25*3;if(isMobile&&(isBar||isTiledPlot)){const maxCategoryHeight=Math.max(0,...Object.values(self.state.categoryHeights));if(maxCategoryHeight){let offsetY=25;if(isTiledPlot){offsetY+=10;}padBottom=offsetY+maxCategoryHeight;}}if(isMobile){c.scale=[(plotDimensions[0]-padX*4)/c.dimX,(plotDimensions[1]-(padTop+padBottom))/c.dimY];}else {c.scale=___default.default.map([c.dimX,c.dimY],function(dim,i){return plotDimensions[i]/dim});}if(isTiledPlot){c.scale[1]=c.picBoxHeight/c.scaleY;}padX/=c.scale[0];padTop/=c.scale[1];padBottom/=c.scale[1];graphie.init({range:[[-3*padX,c.dimX+padX],[-padBottom,c.dimY+padTop]],scale:c.scale,isMobile:this.props.apiOptions.isMobile});graphie.addMouseLayer({allowScratchpad:true});if(!isTiledPlot){const initialY=isMobile?c.scaleY:0;for(let y=initialY;y<=c.dimY;y+=c.scaleY){graphie.label([0,y],kmath.KhanMath.roundToApprox(y,2),"left",true);graphie.style({stroke:isMobile?"#e9ebec":"#000",strokeWidth:1,opacity:isMobile?1:.3},function(){graphie.line([0,y],[c.dimX,y]);});}}if((isBar||isLine)&&isMobile&&!this.props.static){self.graphie.dragPrompt=graphie.label([c.dimX/2,c.dimY/2],this.context.strings.dragHandles,"center",false).css("font-weight","bold").css("color",KhanColors.KA_GREEN).css("display","none");}self.setupCategories(config);if(isTiledPlot&&isMobile){self.graphie.dotPrompt=graphie.label([c.dimX/2,c.dimY/2],this.context.strings.tapAddPoints,"center",false).css("font-weight","bold").css("color",KhanColors.KA_GREEN).css("display","none");}if(isTiledPlot){self.drawPicHeights(self.props.userInput,prevValues);}graphie.style({stroke:"#000",strokeWidth:2,opacity:1},function(){if(isTiledPlot){if(isDotplot){graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([isMobile?0:.5,0],[c.dimX-(isMobile?0:.5),0]));}else {graphie.line([0,0],[c.dimX,0]);if(self.props.labels[1].length!==0||!isMobile){graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([0,0],[0,c.dimY]));}}}else {graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([isMobile?-padX*3:0,0],[c.dimX+(isMobile?padX:0),0]));if(!((isBar||isLine)&&isMobile)){graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([0,0],[0,c.dimY]));}}});const xAxisLabel=graphie.label([c.dimX/2,isMobile?-padBottom:-35/c.scale[1]],self.props.labels[0],isMobile?"above":"below",false).css("font-weight","bold");if(isMobile){xAxisLabel.css("color",KhanColors.GRAY_F);}const yAxisLabel=graphie.label([(isMobile?-35:-60)/c.scale[0],c.dimY/2],self.props.labels[1],"center",false).css("font-weight","bold").addClass("rotate");if(isMobile){yAxisLabel.css("color",KhanColors.GRAY_F);}if(this.props.apiOptions.isMobile){this.horizHairline=new WrappedLine(this.graphie,[0,0],[0,0],{normalStyle:{strokeWidth:1}});this.horizHairline.attr({stroke:KhanColors.INTERACTIVE});this.horizHairline.hide();this.hairlineRange=[[0,c.dimX],[0,c.dimY]];}}_testInsertUserInput(userInput){this.props.handleUserInput(userInput);}drawPicHeights(values,prevValues){const self=this;const graphie=self.graphie;const pics=graphie.pics;const isMobile=this.props.apiOptions.isMobile;if(isMobile){const shouldDisplay=values.every(v=>v===0);graphie.dotPrompt[0].style.display=shouldDisplay?"inline":"none";}___default.default.each(pics,function(ps,i){___default.default.each(ps,function(pic,j){const y=(j+1)*self.props.scaleY;const show=y<=values[i];if(self.props.type==="dotplot"){const wasShown=y<=prevValues[i];const wasJustShown=show&&!wasShown;if(wasJustShown){pic.animate({"stroke-width":8},75,()=>pic.animate({"stroke-width":2},75));}}$__default.default(pic[0]).css({display:show?"inline":"none"});graphie.dotTicks[i][j][0].style.display=show||!isMobile?"none":"inline";});});}getPromptJSON(){return getPromptJSON$3()}getSerializedState(){const{userInput:_,...rest}=this.props;return {...rest,values:this.props.userInput}}render(){const paddingForBottomLabel=75;const style={marginBottom:this.props.labels[0]?paddingForBottomLabel:0};return jsxRuntimeExports.jsx("div",{className:"perseus-widget-plotter graphie",ref:this.graphieDiv,style:style})}constructor(...args){super(...args),this._isMounted=false,this.graphieDiv=React__namespace.createRef(),this.state={categoryHeights:{}},this.DOT_PLOT_POINT_SIZE=()=>{return this.props.apiOptions.isMobile?6:4},this.DOT_PLOT_POINT_PADDING=()=>{return 8},this.DOT_TICK_POINT_SIZE=()=>{return 2},this.showHairlines=point=>{if(this.props.apiOptions.isMobile){this.horizHairline.moveTo([this.hairlineRange[0][0],point[1]],[this.hairlineRange[0][1],point[1]]);this.horizHairline.show();}},this.hideHairlines=()=>{if(this.props.apiOptions.isMobile){this.horizHairline.hide();}},this.labelCategory=(x,category)=>{const isMobile=this.props.apiOptions.isMobile;const graphie=this.graphie;category=category+"";let isTeX=false;const mathyCategory=category.match(/^\$(.*)\$$/);if(mathyCategory){category=mathyCategory[1];isTeX=true;}const translateX=5;const rotationDeg=45;const rotationRad=rotationDeg*(Math.PI/180);const labelRotation=`translateX(-50%) translateX(${translateX}px) `+`translateY(-50%) rotate(-${rotationDeg}deg)`;const shouldRotate=isMobile&&!mathyCategory;return new Promise(resolve=>{graphie.style({color:isMobile?KhanColors.GRAY_G:"inherit",transform:shouldRotate?labelRotation:"none",transformOrigin:"100%"},()=>{const $span=graphie.label([x,isMobile?-0.5:0],category,"below",isTeX);const height=14+(shouldRotate?Math.round($span.height()*Math.cos(rotationRad)+($span.width()+translateX)*Math.sin(rotationRad)):$span.height());resolve({category,height});});})},this.setupCategories=config=>{const self=this;const c=config;const graphie=self.graphie;const isMobile=this.props.apiOptions.isMobile;const categoryHeightPromises=[];if(self.props.type==="histogram"){___default.default.times(self.props.categories.length-1,function(i){self.setupBar({index:i,startHeight:self.props.userInput[i],config:config,isHistogram:true});});___default.default.each(self.props.categories,function(category,i){const x=.5+i*c.barWidth;categoryHeightPromises.push(self.labelCategory(x,category));const tickHeight=6/c.scale[1];graphie.style({stroke:"#000",strokeWidth:isMobile?1:2,opacity:1},function(){graphie.line([x,-tickHeight],[x,0]);});});}else {___default.default.each(self.props.categories,function(category,i){const startHeight=self.props.userInput[i];let x;if(self.props.type==="bar"){x=self.setupBar({index:i,startHeight:startHeight,config:config,isHistogram:false});}else if(self.props.type==="line"){x=self.setupLine(i,startHeight,config);}else if(self.props.type==="pic"){x=self.setupPic(i,config);}else if(self.props.type==="dotplot"){x=self.setupDotplot(i,config);}let tickStart=0;let tickEnd=-6/c.scale[1];if(self.props.type==="dotplot"&&!isMobile){tickStart=-tickEnd;}if(self.props.type==="dotplot"){if(i%self.props.labelInterval===0||i===self.props.categories.length-1){categoryHeightPromises.push(self.labelCategory(x,category));tickStart*=1.5;tickEnd*=1.5;}}else {categoryHeightPromises.push(self.labelCategory(x,category));}graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2,opacity:1},function(){graphie.line([x,tickStart],[x,tickEnd]);});});}Promise.all(categoryHeightPromises).then(measurements=>{if(self._isMounted){const categoryHeights={};measurements.forEach(({category,height})=>categoryHeights[category]=height);self.setState({categoryHeights});}});},this._clampValue=(v,min,max)=>{return Math.max(Math.min(v,max),min)},this._maybeShowDragPrompt=()=>{if(this.graphie.dragPrompt!=null){this.graphie.dragPrompt[0].style.display="inline";}},this._maybeHideDragPrompt=()=>{if(this.graphie.dragPrompt!=null){this.graphie.dragPrompt[0].style.display="none";}},this.setupBar=args=>{const isMobile=this.props.apiOptions.isMobile;const i=args.index;const startHeight=args.startHeight;const config=args.config;const isHistogram=args.isHistogram;const self=this;const graphie=self.graphie;const barHalfWidth=config.barWidth/2;let x;if(isHistogram){x=.5+i*config.barWidth+barHalfWidth;}else {x=(isMobile?barHalfWidth:.5+config.barPad)+i;}const scaleBar=function(i,height){const center=graphie.scalePoint(0);config.graph.bars[i].scale(1,Math.max(isMobile?.2:.01,height/config.scaleY),center[0],center[1]);if(isHistogram){const leftDivider=config.graph.dividers[i-1];const rightDivider=config.graph.dividers[i];if(leftDivider){const divHeight=Math.min(self.props.userInput[i-1],height);leftDivider.scale(1,Math.max(.01,divHeight/config.scaleY),center[0],center[1]);}if(rightDivider){const divHeight=Math.min(self.props.userInput[i+1],height);rightDivider.scale(1,Math.max(.01,divHeight/config.scaleY),center[0],center[1]);}}};graphie.style({stroke:"none",fill:isMobile?KhanColors.BLUE_C:KhanColors.LIGHT_BLUE,opacity:1},function(){config.graph.bars[i]=graphie.path([[x-barHalfWidth,0],[x-barHalfWidth,config.scaleY],[x+barHalfWidth,config.scaleY],[x+barHalfWidth,0],[x-barHalfWidth,0]]);});if(isHistogram){if(i>0){graphie.style({stroke:"#000",strokeWidth:1,opacity:.3},function(){config.graph.dividers.push(graphie.path([[x-barHalfWidth,0],[x-barHalfWidth,config.scaleY]]));});}}if(isMobile){const snap=config.scaleY/self.props.snapsPerLine;config.graph.lines[i]=Interactive2.addMaybeMobileMovablePoint(this,{coord:[x,startHeight],constraints:[(coord,prev,options)=>{return [x,this._clampValue(Math.round(coord[1]/snap)*snap,0,config.dimY)]}],onMoveStart:function(){config.graph.bars[i].attr({fill:KhanColors.INTERACTIVE});},onMove:function(){const y=config.graph.lines[i].coord()[1];const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);self._maybeHideDragPrompt();scaleBar(i,y);},onMoveEnd:function(){config.graph.bars[i].attr({fill:KhanColors.BLUE_C});}});config.graph.lines[i].state.visibleShape.wrapper.style.zIndex="1";self._maybeShowDragPrompt();}else {config.graph.lines[i]=graphie.addMovableLineSegment({coordA:[x-barHalfWidth,startHeight],coordZ:[x+barHalfWidth,startHeight],snapY:config.scaleY/self.props.snapsPerLine,constraints:{constrainX:true},normalStyle:{stroke:KhanColors.INTERACTIVE,"stroke-width":this.props.static?0:4}});config.graph.lines[i].onMove=function(dx,dy){let y=this.coordA[1];if(y<0||y>config.dimY){y=Math.min(Math.max(y,0),config.dimY);this.coordA[1]=this.coordZ[1]=y;this.transform();}const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);scaleBar(i,y);};}scaleBar(i,startHeight);return x},this.setupLine=(i,startHeight,config)=>{const isMobile=this.props.apiOptions.isMobile;const self=this;const c=config;const graphie=self.graphie;const x=i+(isMobile?.4:1);if(isMobile){const snap=config.scaleY/self.props.snapsPerLine;c.graph.points[i]=Interactive2.addMaybeMobileMovablePoint(this,{coord:[x,startHeight],constraints:[(coord,prev,options)=>{return [x,this._clampValue(Math.round(coord[1]/snap)*snap,0,config.dimY)]}],onMove:function(){const y=c.graph.points[i].coord()[1];const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);self._maybeHideDragPrompt();}});self._maybeShowDragPrompt();if(i>0){c.graph.lines[i]=Interactive2.addMovableLine(graphie,{points:[c.graph.points[i-1],c.graph.points[i]],constraints:Interactive2.MovablePoint.constraints.fixed(),normalStyle:{stroke:KhanColors.BLUE_C,"stroke-width":2},highlightStyle:{stroke:KhanColors.BLUE_C,"stroke-width":2}});}}else {c.graph.points[i]=graphie.addMovablePoint({coord:[x,startHeight],constraints:{constrainX:true},normalStyle:{fill:KhanColors.INTERACTIVE,stroke:KhanColors.INTERACTIVE},snapY:c.scaleY/self.props.snapsPerLine});c.graph.points[i].onMove=function(x,y){y=Math.min(Math.max(y,0),c.dimY);const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);return [x,y]};if(i>0){c.graph.lines[i]=graphie.addMovableLineSegment({pointA:c.graph.points[i-1],pointZ:c.graph.points[i],constraints:{fixed:true},normalStyle:{stroke:"#9ab8ed","stroke-width":2}});}}return x},this.setupDotplot=(i,config)=>{const graphie=this.graphie;const isMobile=this.props.apiOptions.isMobile;return this.setupTiledPlot(i,isMobile?.5:1,config,(x,y)=>{return graphie.ellipse([x,y],[this.DOT_PLOT_POINT_SIZE()/graphie.scale[0],this.DOT_PLOT_POINT_SIZE()/graphie.scale[1]],{fill:KhanColors.INTERACTIVE,stroke:KhanColors.INTERACTIVE})})},this.setupPic=(i,config)=>{const graphie=this.graphie;return this.setupTiledPlot(i,0,config,(x,y)=>{const scaledCenter=graphie.scalePoint([x,y]);const size=this.props.picSize;return graphie.raphael.image(this.props.picUrl,scaledCenter[0]-size/2,scaledCenter[1]-size/2,size,size)})},this.setupTiledPlot=(i,bottomMargin,config,createImage)=>{const self=this;const c=config;const graphie=self.graphie;const pics=graphie.pics;const dotTicks=graphie.dotTicks;const x=i+.5+c.picPad;graphie.mouselayer.canvas.style.touchAction="none";pics[i]=[];dotTicks[i]=[];const n=Math.round(c.dimY/c.scaleY)+1;___default.default(n).times(function(j){j-=1;const midY=(j+.5)*c.scaleY;const leftX=x-c.picBoxWidth/2;const topY=midY+.5*c.scaleY;const coord=graphie.scalePoint([leftX,topY+bottomMargin]);const mouseRect=graphie.mouselayer.rect(coord[0],coord[1],c.picBoxWidthPx,c.picBoxHeight);$__default.default(mouseRect[0]).css({fill:"#000",opacity:0,cursor:"pointer"}).on("vmousedown",function(e){e.preventDefault();self.whichPicClicked=i;self.setPicHeight(i,topY);$__default.default(document).on("vmouseup.plotTile",function(e){$__default.default(document).unbind(".plotTile");});$__default.default(document).on("vmousemove.plotTile",function(e){e.preventDefault();const yCoord=graphie.getMouseCoord(e)[1];const adjustedCoord=Math.floor(yCoord-bottomMargin);const newJ=Math.max(-1,Math.floor(adjustedCoord/c.scaleY));const newMidY=(newJ+.5)*c.scaleY;const newTopY=Math.min(newMidY+.5*c.scaleY,c.dimY);self.setPicHeight(self.whichPicClicked,newTopY);});});if(j<0){return}pics[i][j]=createImage(x,midY+bottomMargin);dotTicks[i][j]=graphie.ellipse([x,midY+bottomMargin],[self.DOT_TICK_POINT_SIZE()/graphie.scale[0],self.DOT_TICK_POINT_SIZE()/graphie.scale[1]],{fill:"#dee1e3",stroke:"#dee1e3"});});return x},this.setPicHeight=(i,y)=>{const values=[...this.props.userInput];values[i]=y;this.drawPicHeights(values,this.props.userInput);this.changeAndTrack(values);},this.changeAndTrack=userInput=>{this.props.handleUserInput(userInput);this.props.trackInteraction();};}}Plotter.contextType=PerseusI18nContext;function getStartUserInput$2(options){return options.starting}function getCorrectUserInput(options){return options.correct}function getUserInputFromSerializedState$2(serializedState){return serializedState.values}const WrappedPlotter=withDependencies(Plotter);var Plotter$1 = {name:"plotter",displayName:"Plotter",hidden:true,widget:WrappedPlotter,getCorrectUserInput,getStartUserInput: getStartUserInput$2,getUserInputFromSerializedState: getUserInputFromSerializedState$2};
|
|
2147
|
+
class Plotter extends React__namespace.Component{componentDidMount(){this._isMounted=true;this.setupGraphie(this.props.userInput);this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetType:"plotter",widgetSubType:"null",widgetId:this.props.widgetId}});}UNSAFE_componentWillReceiveProps(nextProps){const props=["type","labels","categories","scaleY","maxY","snapsPerLine","picUrl","labelInterval","static"];this.shouldSetupGraphie=___default.default.any(props,prop=>!___default.default.isEqual(this.props[prop],nextProps[prop]),this);if(!___default.default.isEqual(this.props.starting,nextProps.starting)&&!___default.default.isEqual(this.props.userInput,nextProps.starting)){this.shouldSetupGraphie=true;this.props.handleUserInput(nextProps.starting);}}componentDidUpdate(prevProps,prevState){this.shouldSetupGraphie=this.shouldSetupGraphie||!___default.default.isEqual(this.state.categoryHeights,prevState.categoryHeights);if(this.shouldSetupGraphie){this.setupGraphie(prevProps.userInput);}}componentWillUnmount(){this._isMounted=false;}setupGraphie(prevValues){const self=this;self.shouldSetupGraphie=false;$__default.default(this.graphieDiv.current).empty();const graphie=GraphUtils.createGraphie(this.graphieDiv.current);self.graphie=graphie;self.graphie.pics=[];self.graphie.dotTicks=[];const isBar=self.props.type==="bar";const isLine=self.props.type==="line";const isPic=self.props.type==="pic";const isHistogram=self.props.type==="histogram";const isDotplot=self.props.type==="dotplot";const isTiledPlot=isPic||isDotplot;const config={};const c=config;const isMobile=this.props.apiOptions.isMobile;c.graph={lines:[],bars:[],points:[],dividers:[]};c.scaleY=self.props.scaleY;c.dimX=self.props.categories.length;const plotDimensions=isMobile?[288,336]:self.props.plotDimensions;if(isLine){c.dimX+=isMobile?-0.2:1;}else if(isHistogram){c.barPad=0;c.barWidth=1;}else if(isBar){c.barPad=isMobile?.08:.15;c.barWidth=1-2*c.barPad;c.dimX+=(isMobile?-2:2)*c.barPad;}else if(isTiledPlot){c.picBoxHeight=self.props.picBoxHeight;c.picBoxWidthPx=plotDimensions[0]/self.props.categories.length;const picPadAllWidth=plotDimensions[0]-c.dimX*c.picBoxWidthPx;c.picPad=picPadAllWidth/(2*c.dimX+2);const picFullWidth=c.picBoxWidthPx+2*c.picPad;c.picPad=c.picPad/picFullWidth;c.picBoxWidth=c.picBoxWidthPx/picFullWidth;c.dimX+=2*c.picPad;}if(isDotplot){c.picBoxHeight=this.DOT_PLOT_POINT_SIZE()*2+this.DOT_PLOT_POINT_PADDING();}c.dimY=Math.ceil(self.props.maxY/c.scaleY)*c.scaleY;let padX=25;if((isBar||isLine)&&isMobile){padX=self.props.labels[1].length!==0?17:11;}if(isDotplot){padX/=2;}if(isMobile&&isTiledPlot&&self.props.labels[1].length===0){padX=0;}let padTop=25;let padBottom=25*3;if(isMobile&&(isBar||isTiledPlot)){const maxCategoryHeight=Math.max(0,...Object.values(self.state.categoryHeights));if(maxCategoryHeight){let offsetY=25;if(isTiledPlot){offsetY+=10;}padBottom=offsetY+maxCategoryHeight;}}if(isMobile){c.scale=[(plotDimensions[0]-padX*4)/c.dimX,(plotDimensions[1]-(padTop+padBottom))/c.dimY];}else {c.scale=[c.dimX,c.dimY].map(function(dim,i){return plotDimensions[i]/dim});}if(isTiledPlot){c.scale[1]=c.picBoxHeight/c.scaleY;}padX/=c.scale[0];padTop/=c.scale[1];padBottom/=c.scale[1];graphie.init({range:[[-3*padX,c.dimX+padX],[-padBottom,c.dimY+padTop]],scale:c.scale,isMobile:this.props.apiOptions.isMobile});graphie.addMouseLayer({allowScratchpad:true});if(!isTiledPlot){const initialY=isMobile?c.scaleY:0;for(let y=initialY;y<=c.dimY;y+=c.scaleY){graphie.label([0,y],kmath.KhanMath.roundToApprox(y,2),"left",true);graphie.style({stroke:isMobile?"#e9ebec":"#000",strokeWidth:1,opacity:isMobile?1:.3},function(){graphie.line([0,y],[c.dimX,y]);});}}if((isBar||isLine)&&isMobile&&!this.props.static){self.graphie.dragPrompt=graphie.label([c.dimX/2,c.dimY/2],this.context.strings.dragHandles,"center",false).css("font-weight","bold").css("color",KhanColors.KA_GREEN).css("display","none");}self.setupCategories(config);if(isTiledPlot&&isMobile){self.graphie.dotPrompt=graphie.label([c.dimX/2,c.dimY/2],this.context.strings.tapAddPoints,"center",false).css("font-weight","bold").css("color",KhanColors.KA_GREEN).css("display","none");}if(isTiledPlot){self.drawPicHeights(self.props.userInput,prevValues);}graphie.style({stroke:"#000",strokeWidth:2,opacity:1},function(){if(isTiledPlot){if(isDotplot){graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([isMobile?0:.5,0],[c.dimX-(isMobile?0:.5),0]));}else {graphie.line([0,0],[c.dimX,0]);if(self.props.labels[1].length!==0||!isMobile){graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([0,0],[0,c.dimY]));}}}else {graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([isMobile?-padX*3:0,0],[c.dimX+(isMobile?padX:0),0]));if(!((isBar||isLine)&&isMobile)){graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2},()=>graphie.line([0,0],[0,c.dimY]));}}});const xAxisLabel=graphie.label([c.dimX/2,isMobile?-padBottom:-35/c.scale[1]],self.props.labels[0],isMobile?"above":"below",false).css("font-weight","bold");if(isMobile){xAxisLabel.css("color",KhanColors.GRAY_F);}const yAxisLabel=graphie.label([(isMobile?-35:-60)/c.scale[0],c.dimY/2],self.props.labels[1],"center",false).css("font-weight","bold").addClass("rotate");if(isMobile){yAxisLabel.css("color",KhanColors.GRAY_F);}if(this.props.apiOptions.isMobile){this.horizHairline=new WrappedLine(this.graphie,[0,0],[0,0],{normalStyle:{strokeWidth:1}});this.horizHairline.attr({stroke:KhanColors.INTERACTIVE});this.horizHairline.hide();this.hairlineRange=[[0,c.dimX],[0,c.dimY]];}}_testInsertUserInput(userInput){this.props.handleUserInput(userInput);}drawPicHeights(values,prevValues){const self=this;const graphie=self.graphie;const pics=graphie.pics;const isMobile=this.props.apiOptions.isMobile;if(isMobile){const shouldDisplay=values.every(v=>v===0);graphie.dotPrompt[0].style.display=shouldDisplay?"inline":"none";}___default.default.each(pics,function(ps,i){___default.default.each(ps,function(pic,j){const y=(j+1)*self.props.scaleY;const show=y<=values[i];if(self.props.type==="dotplot"){const wasShown=y<=prevValues[i];const wasJustShown=show&&!wasShown;if(wasJustShown){pic.animate({"stroke-width":8},75,()=>pic.animate({"stroke-width":2},75));}}$__default.default(pic[0]).css({display:show?"inline":"none"});graphie.dotTicks[i][j][0].style.display=show||!isMobile?"none":"inline";});});}getPromptJSON(){return getPromptJSON$3()}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,values:this.props.userInput}}render(){const paddingForBottomLabel=75;const style={marginBottom:this.props.labels[0]?paddingForBottomLabel:0};return jsxRuntimeExports.jsx("div",{className:"perseus-widget-plotter graphie",ref:this.graphieDiv,style:style})}constructor(...args){super(...args),this._isMounted=false,this.graphieDiv=React__namespace.createRef(),this.state={categoryHeights:{}},this.DOT_PLOT_POINT_SIZE=()=>{return this.props.apiOptions.isMobile?6:4},this.DOT_PLOT_POINT_PADDING=()=>{return 8},this.DOT_TICK_POINT_SIZE=()=>{return 2},this.showHairlines=point=>{if(this.props.apiOptions.isMobile){this.horizHairline.moveTo([this.hairlineRange[0][0],point[1]],[this.hairlineRange[0][1],point[1]]);this.horizHairline.show();}},this.hideHairlines=()=>{if(this.props.apiOptions.isMobile){this.horizHairline.hide();}},this.labelCategory=(x,category)=>{const isMobile=this.props.apiOptions.isMobile;const graphie=this.graphie;category=category+"";let isTeX=false;const mathyCategory=category.match(/^\$(.*)\$$/);if(mathyCategory){category=mathyCategory[1];isTeX=true;}const translateX=5;const rotationDeg=45;const rotationRad=rotationDeg*(Math.PI/180);const labelRotation=`translateX(-50%) translateX(${translateX}px) `+`translateY(-50%) rotate(-${rotationDeg}deg)`;const shouldRotate=isMobile&&!mathyCategory;return new Promise(resolve=>{graphie.style({color:isMobile?KhanColors.GRAY_G:"inherit",transform:shouldRotate?labelRotation:"none",transformOrigin:"100%"},()=>{const $span=graphie.label([x,isMobile?-0.5:0],category,"below",isTeX);const height=14+(shouldRotate?Math.round($span.height()*Math.cos(rotationRad)+($span.width()+translateX)*Math.sin(rotationRad)):$span.height());resolve({category,height});});})},this.setupCategories=config=>{const self=this;const c=config;const graphie=self.graphie;const isMobile=this.props.apiOptions.isMobile;const categoryHeightPromises=[];if(self.props.type==="histogram"){___default.default.times(self.props.categories.length-1,function(i){self.setupBar({index:i,startHeight:self.props.userInput[i],config:config,isHistogram:true});});___default.default.each(self.props.categories,function(category,i){const x=.5+i*c.barWidth;categoryHeightPromises.push(self.labelCategory(x,category));const tickHeight=6/c.scale[1];graphie.style({stroke:"#000",strokeWidth:isMobile?1:2,opacity:1},function(){graphie.line([x,-tickHeight],[x,0]);});});}else {___default.default.each(self.props.categories,function(category,i){const startHeight=self.props.userInput[i];let x;if(self.props.type==="bar"){x=self.setupBar({index:i,startHeight:startHeight,config:config,isHistogram:false});}else if(self.props.type==="line"){x=self.setupLine(i,startHeight,config);}else if(self.props.type==="pic"){x=self.setupPic(i,config);}else if(self.props.type==="dotplot"){x=self.setupDotplot(i,config);}let tickStart=0;let tickEnd=-6/c.scale[1];if(self.props.type==="dotplot"&&!isMobile){tickStart=-tickEnd;}if(self.props.type==="dotplot"){if(i%self.props.labelInterval===0||i===self.props.categories.length-1){categoryHeightPromises.push(self.labelCategory(x,category));tickStart*=1.5;tickEnd*=1.5;}}else {categoryHeightPromises.push(self.labelCategory(x,category));}graphie.style({stroke:isMobile?KhanColors.GRAY_G:"#000",strokeWidth:isMobile?1:2,opacity:1},function(){graphie.line([x,tickStart],[x,tickEnd]);});});}Promise.all(categoryHeightPromises).then(measurements=>{if(self._isMounted){const categoryHeights={};measurements.forEach(({category,height})=>categoryHeights[category]=height);self.setState({categoryHeights});}});},this._clampValue=(v,min,max)=>{return Math.max(Math.min(v,max),min)},this._maybeShowDragPrompt=()=>{if(this.graphie.dragPrompt!=null){this.graphie.dragPrompt[0].style.display="inline";}},this._maybeHideDragPrompt=()=>{if(this.graphie.dragPrompt!=null){this.graphie.dragPrompt[0].style.display="none";}},this.setupBar=args=>{const isMobile=this.props.apiOptions.isMobile;const i=args.index;const startHeight=args.startHeight;const config=args.config;const isHistogram=args.isHistogram;const self=this;const graphie=self.graphie;const barHalfWidth=config.barWidth/2;let x;if(isHistogram){x=.5+i*config.barWidth+barHalfWidth;}else {x=(isMobile?barHalfWidth:.5+config.barPad)+i;}const scaleBar=function(i,height){const center=graphie.scalePoint(0);config.graph.bars[i].scale(1,Math.max(isMobile?.2:.01,height/config.scaleY),center[0],center[1]);if(isHistogram){const leftDivider=config.graph.dividers[i-1];const rightDivider=config.graph.dividers[i];if(leftDivider){const divHeight=Math.min(self.props.userInput[i-1],height);leftDivider.scale(1,Math.max(.01,divHeight/config.scaleY),center[0],center[1]);}if(rightDivider){const divHeight=Math.min(self.props.userInput[i+1],height);rightDivider.scale(1,Math.max(.01,divHeight/config.scaleY),center[0],center[1]);}}};graphie.style({stroke:"none",fill:isMobile?KhanColors.BLUE_C:KhanColors.LIGHT_BLUE,opacity:1},function(){config.graph.bars[i]=graphie.path([[x-barHalfWidth,0],[x-barHalfWidth,config.scaleY],[x+barHalfWidth,config.scaleY],[x+barHalfWidth,0],[x-barHalfWidth,0]]);});if(isHistogram){if(i>0){graphie.style({stroke:"#000",strokeWidth:1,opacity:.3},function(){config.graph.dividers.push(graphie.path([[x-barHalfWidth,0],[x-barHalfWidth,config.scaleY]]));});}}if(isMobile){const snap=config.scaleY/self.props.snapsPerLine;config.graph.lines[i]=Interactive2.addMaybeMobileMovablePoint(this,{coord:[x,startHeight],constraints:[(coord,prev,options)=>{return [x,this._clampValue(Math.round(coord[1]/snap)*snap,0,config.dimY)]}],onMoveStart:function(){config.graph.bars[i].attr({fill:KhanColors.INTERACTIVE});},onMove:function(){const y=config.graph.lines[i].coord()[1];const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);self._maybeHideDragPrompt();scaleBar(i,y);},onMoveEnd:function(){config.graph.bars[i].attr({fill:KhanColors.BLUE_C});}});config.graph.lines[i].state.visibleShape.wrapper.style.zIndex="1";self._maybeShowDragPrompt();}else {config.graph.lines[i]=graphie.addMovableLineSegment({coordA:[x-barHalfWidth,startHeight],coordZ:[x+barHalfWidth,startHeight],snapY:config.scaleY/self.props.snapsPerLine,constraints:{constrainX:true},normalStyle:{stroke:KhanColors.INTERACTIVE,"stroke-width":this.props.static?0:4}});config.graph.lines[i].onMove=function(dx,dy){let y=this.coordA[1];if(y<0||y>config.dimY){y=Math.min(Math.max(y,0),config.dimY);this.coordA[1]=this.coordZ[1]=y;this.transform();}const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);scaleBar(i,y);};}scaleBar(i,startHeight);return x},this.setupLine=(i,startHeight,config)=>{const isMobile=this.props.apiOptions.isMobile;const self=this;const c=config;const graphie=self.graphie;const x=i+(isMobile?.4:1);if(isMobile){const snap=config.scaleY/self.props.snapsPerLine;c.graph.points[i]=Interactive2.addMaybeMobileMovablePoint(this,{coord:[x,startHeight],constraints:[(coord,prev,options)=>{return [x,this._clampValue(Math.round(coord[1]/snap)*snap,0,config.dimY)]}],onMove:function(){const y=c.graph.points[i].coord()[1];const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);self._maybeHideDragPrompt();}});self._maybeShowDragPrompt();if(i>0){c.graph.lines[i]=Interactive2.addMovableLine(graphie,{points:[c.graph.points[i-1],c.graph.points[i]],constraints:Interactive2.MovablePoint.constraints.fixed(),normalStyle:{stroke:KhanColors.BLUE_C,"stroke-width":2},highlightStyle:{stroke:KhanColors.BLUE_C,"stroke-width":2}});}}else {c.graph.points[i]=graphie.addMovablePoint({coord:[x,startHeight],constraints:{constrainX:true},normalStyle:{fill:KhanColors.INTERACTIVE,stroke:KhanColors.INTERACTIVE},snapY:c.scaleY/self.props.snapsPerLine});c.graph.points[i].onMove=function(x,y){y=Math.min(Math.max(y,0),c.dimY);const values=[...self.props.userInput];values[i]=y;self.changeAndTrack(values);return [x,y]};if(i>0){c.graph.lines[i]=graphie.addMovableLineSegment({pointA:c.graph.points[i-1],pointZ:c.graph.points[i],constraints:{fixed:true},normalStyle:{stroke:"#9ab8ed","stroke-width":2}});}}return x},this.setupDotplot=(i,config)=>{const graphie=this.graphie;const isMobile=this.props.apiOptions.isMobile;return this.setupTiledPlot(i,isMobile?.5:1,config,(x,y)=>{return graphie.ellipse([x,y],[this.DOT_PLOT_POINT_SIZE()/graphie.scale[0],this.DOT_PLOT_POINT_SIZE()/graphie.scale[1]],{fill:KhanColors.INTERACTIVE,stroke:KhanColors.INTERACTIVE})})},this.setupPic=(i,config)=>{const graphie=this.graphie;return this.setupTiledPlot(i,0,config,(x,y)=>{const scaledCenter=graphie.scalePoint([x,y]);const size=this.props.picSize;return graphie.raphael.image(this.props.picUrl,scaledCenter[0]-size/2,scaledCenter[1]-size/2,size,size)})},this.setupTiledPlot=(i,bottomMargin,config,createImage)=>{const self=this;const c=config;const graphie=self.graphie;const pics=graphie.pics;const dotTicks=graphie.dotTicks;const x=i+.5+c.picPad;graphie.mouselayer.canvas.style.touchAction="none";pics[i]=[];dotTicks[i]=[];const n=Math.round(c.dimY/c.scaleY)+1;___default.default(n).times(function(j){j-=1;const midY=(j+.5)*c.scaleY;const leftX=x-c.picBoxWidth/2;const topY=midY+.5*c.scaleY;const coord=graphie.scalePoint([leftX,topY+bottomMargin]);const mouseRect=graphie.mouselayer.rect(coord[0],coord[1],c.picBoxWidthPx,c.picBoxHeight);$__default.default(mouseRect[0]).css({fill:"#000",opacity:0,cursor:"pointer"}).on("vmousedown",function(e){e.preventDefault();self.whichPicClicked=i;self.setPicHeight(i,topY);$__default.default(document).on("vmouseup.plotTile",function(e){$__default.default(document).unbind(".plotTile");});$__default.default(document).on("vmousemove.plotTile",function(e){e.preventDefault();const yCoord=graphie.getMouseCoord(e)[1];const adjustedCoord=Math.floor(yCoord-bottomMargin);const newJ=Math.max(-1,Math.floor(adjustedCoord/c.scaleY));const newMidY=(newJ+.5)*c.scaleY;const newTopY=Math.min(newMidY+.5*c.scaleY,c.dimY);self.setPicHeight(self.whichPicClicked,newTopY);});});if(j<0){return}pics[i][j]=createImage(x,midY+bottomMargin);dotTicks[i][j]=graphie.ellipse([x,midY+bottomMargin],[self.DOT_TICK_POINT_SIZE()/graphie.scale[0],self.DOT_TICK_POINT_SIZE()/graphie.scale[1]],{fill:"#dee1e3",stroke:"#dee1e3"});});return x},this.setPicHeight=(i,y)=>{const values=[...this.props.userInput];values[i]=y;this.drawPicHeights(values,this.props.userInput);this.changeAndTrack(values);},this.changeAndTrack=userInput=>{this.props.handleUserInput(userInput);this.props.trackInteraction();};}}Plotter.contextType=PerseusI18nContext;function getStartUserInput$2(options){return options.starting}function getCorrectUserInput(options){return options.correct}function getUserInputFromSerializedState$2(serializedState){return serializedState.values}const WrappedPlotter=withDependencies(Plotter);var Plotter$1 = {name:"plotter",displayName:"Plotter",hidden:true,widget:WrappedPlotter,getCorrectUserInput,getStartUserInput: getStartUserInput$2,getUserInputFromSerializedState: getUserInputFromSerializedState$2};
|
|
2157
2148
|
|
|
2158
2149
|
const getPromptJSON$2=()=>{return getUnsupportedPromptJSON("python-program")};
|
|
2159
2150
|
|
|
@@ -2163,7 +2154,7 @@ const getPromptJSON$1=userInput=>{return {type:"sorter",userInput:{values:userIn
|
|
|
2163
2154
|
|
|
2164
2155
|
class Sorter extends React__namespace.Component{componentDidMount(){this._isMounted=true;this.props.dependencies.analytics.onAnalyticsEvent({type:"perseus:widget:rendered:ti",payload:{widgetSubType:"null",widgetType:"sorter",widgetId:this.props.widgetId}});}componentWillUnmount(){this._isMounted=false;}_getOptionsFromSortable(){const options=this.refs.sortable.getOptions();return options}getPromptJSON(){return getPromptJSON$1(this.props.userInput)}getSerializedState(){const{userInput,...rest}=this.props;return {...rest,changed:userInput.changed,options:userInput.options}}render(){const{apiOptions,userInput}=this.props;const marginPx=apiOptions.isMobile?8:5;return jsxRuntimeExports.jsx("div",{className:"perseus-widget-sorter perseus-clearfix",children:jsxRuntimeExports.jsx(Sortable,{options:userInput.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.handleChange=e=>{if(!this._isMounted){return}this.props.handleUserInput({options:this._getOptionsFromSortable(),changed:true});this.props.trackInteraction();},this.moveOptionToIndex=(option,index)=>{this.refs.sortable.moveOptionToIndex(option,index);};}}Sorter.defaultProps={correct:[],layout:"horizontal",padding:true,problemNum:0,linterContext:PerseusLinter.linterContextDefault};function getStartUserInput$1(options,problemNum){const shuffled=perseusCore.shuffleSorter(options,problemNum);return {options:shuffled,changed:false}}function getUserInputFromSerializedState$1(serializedState){return {changed:serializedState.changed,options:serializedState.options}}const WrappedSorter=withDependencies(Sorter);var Sorter$1 = {name:"sorter",displayName:"Sorter",widget:WrappedSorter,isLintable:true,getStartUserInput: getStartUserInput$1,getUserInputFromSerializedState: getUserInputFromSerializedState$1};
|
|
2165
2156
|
|
|
2166
|
-
|
|
2157
|
+
function getInputPath(row,column){return [""+row,""+column]}function getDefaultPath(){return getInputPath(0,0)}function getRowFromPath(path){invariant__default.default(Array.isArray(path)&&path.length===2,"path should be a (row, colum) pair");return +path[0]}function getColumnFromPath(path){invariant__default.default(Array.isArray(path)&&path.length===2,"path should be a (row, colum) pair");return +path[1]}function getRefForPath(path){const row=getRowFromPath(path);const column=getColumnFromPath(path);return "answer"+row+","+column}const Table=React.forwardRef(function Table(props,ref){const{strings}=usePerseusI18n();const cellRefs=React.useRef({});React.useImperativeHandle(ref,()=>({focus(){getCellForPath(getDefaultPath())?.focus();return true},focusInputPath(path){getCellForPath(path)?.focus();},blurInputPath(path){getCellForPath(path)?.blur();},getDOMNodeForPath(path){const cell=getCellForPath(path);if(cell instanceof HTMLInputElement){return cell}return ReactDOM__namespace.default.findDOMNode(cell??null)},getInputPaths:()=>props.userInput.flatMap((rowArr,r)=>rowArr.map((_,c)=>getInputPath(r,c))),getSerializedState(){const{userInput,editableHeaders,...rest}=props;return {...rest,answers:userInput}}}));function getCellForPath(path){return cellRefs.current[getRefForPath(path)]}function handleValueChange(row,column,eventOrValue){const answers=perseusCore.deepClone(props.userInput);answers[row][column]=eventOrValue.target?eventOrValue.target.value:eventOrValue;props.handleUserInput(answers);props.trackInteraction();}function handleHeaderChange(index,e){const headers=props.headers.slice();headers[index]=e.content;props.onChange({headers:headers});}let InputComponent;let inputStyle;const extraInputProps={};if(props.apiOptions.customKeypad){InputComponent=SimpleKeypadInput;inputStyle={width:80};extraInputProps.keypadElement=props.keypadElement;}else {InputComponent="input";inputStyle={};}const headerRow=jsxRuntimeExports.jsx("tr",{children:props.headers.map((header,i)=>{if(props.editableHeaders){return jsxRuntimeExports.jsx("th",{children:jsxRuntimeExports.jsx(props.Editor,{apiOptions:props.apiOptions,content:header,widgetEnabled:false,onChange:e=>handleHeaderChange(i,e)})},i)}return jsxRuntimeExports.jsx("th",{children:jsxRuntimeExports.jsx(Renderer,{content:header,linterContext:props.linterContext,strings:strings})},i)})});const tableRows=props.userInput.map((rowCells,r)=>jsxRuntimeExports.jsx("tr",{children:rowCells.map((answer,c)=>jsxRuntimeExports.jsx("td",{children:jsxRuntimeExports.jsx(InputComponent,{ref:cell=>{const refId=getRefForPath(getInputPath(r,c));cellRefs.current[refId]=cell??undefined;},type:"text",value:answer,disabled:props.apiOptions.readOnly,onFocus:()=>props.onFocus(getInputPath(r,c)),onBlur:()=>props.onBlur(getInputPath(r,c)),onChange:e=>handleValueChange(r,c,e),style:inputStyle,...extraInputProps})},c))},r));return jsxRuntimeExports.jsxs("table",{className:"perseus-widget-table-of-values non-markdown",children:[jsxRuntimeExports.jsx("thead",{children:headerRow}),jsxRuntimeExports.jsx("tbody",{children:tableRows})]})});function getStartUserInput(options){const rows=options.rows;const columns=options.columns;return Util.stringArrayOfSize2D({rows,columns})}function getUserInputFromSerializedState(serializedState){return serializedState.answers}var Table$1 = {name:"table",displayName:"Table (deprecated - use markdown table instead)",widget:Table,hidden:true,isLintable:true,getStartUserInput,getUserInputFromSerializedState};
|
|
2167
2158
|
|
|
2168
2159
|
const getPromptJSON=()=>{return getUnsupportedPromptJSON("video")};
|
|
2169
2160
|
|
|
@@ -2177,15 +2168,15 @@ var extraWidgets = [CSProgram$1,Categorizer$1,Definition$1,DeprecatedStandin$1,D
|
|
|
2177
2168
|
|
|
2178
2169
|
const init=function(){registerWidgets(basicWidgets);registerWidgets(extraWidgets);replaceDeprecatedWidgets();};
|
|
2179
2170
|
|
|
2180
|
-
const libName="@khanacademy/perseus";const libVersion="
|
|
2171
|
+
const libName="@khanacademy/perseus";const libVersion="83.0.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
2181
2172
|
|
|
2182
2173
|
const apiVersion={major:12,minor:0};
|
|
2183
2174
|
|
|
2184
2175
|
class ArticleRenderer extends React__namespace.Component{componentDidMount(){this._currentFocus=null;}shouldComponentUpdate(nextProps){return nextProps!==this.props}render(){const apiOptions={...ApiOptions.defaults,...this.props.apiOptions,isArticle:true};const classes=classNames__default.default({"framework-perseus":true,"perseus-article":true,[ClassNames.MOBILE]:apiOptions.isMobile});const sections=this._sections().map((section,sectionIndex)=>{return jsxRuntimeExports.jsx("div",{className:"clearfix",children:jsxRuntimeExports.jsx(UserInputManager,{widgets:section.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>React.createElement(Renderer,{...section,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,ref:elem=>{if(elem){this.sectionRenderers[sectionIndex]=elem;}},key:sectionIndex,keypadElement:this.props.keypadElement,apiOptions:{...apiOptions,onFocusChange:(newFocusPath,oldFocusPath)=>{this._handleFocusChange(newFocusPath&&[sectionIndex].concat(newFocusPath),oldFocusPath&&[sectionIndex].concat(oldFocusPath));}},linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"article"),legacyPerseusLint:this.props.legacyPerseusLint,strings:this.context.strings})})},sectionIndex)});return jsxRuntimeExports.jsx("div",{className:classes,children:jsxRuntimeExports.jsx(DependenciesContext.Provider,{value:this.props.dependencies,children:sections})})}constructor(props){super(props),this.sectionRenderers=[],this._handleFocusChange=(newFocusPath,oldFocusPath)=>{if(newFocusPath){this._setCurrentFocus(newFocusPath);}else {this._onRendererBlur(oldFocusPath);}},this._setCurrentFocus=newFocusPath=>{const{keypadElement,apiOptions}=this.props;const{isMobile}=apiOptions;const prevFocusPath=this._currentFocus;this._currentFocus=newFocusPath;let didFocusInput=false;let focusedInput;if(this._currentFocus){const[sectionIndex,...focusPath]=this._currentFocus;const inputPaths=this.sectionRenderers[sectionIndex].getInputPaths();didFocusInput=inputPaths.some(inputPath=>{return Util.inputPathsEqual(inputPath,focusPath)});focusedInput=this.sectionRenderers[sectionIndex].getDOMNodeForPath(focusPath);}const{onFocusChange}=this.props.apiOptions;if(onFocusChange){setTimeout(()=>{const keypadDomNode=keypadElement?.getDOMNode();const keypadHeight=keypadDomNode&&didFocusInput?keypadDomNode.getBoundingClientRect().height:0;onFocusChange(this._currentFocus,prevFocusPath,keypadHeight,didFocusInput?focusedInput:null);},0);}if(keypadElement&&isMobile){if(didFocusInput){keypadElement.activate();}else {keypadElement.dismiss();}}},this._onRendererBlur=blurPath=>{const blurringFocusPath=this._currentFocus;if(!Util.inputPathsEqual(blurPath,blurringFocusPath)){return}setTimeout(()=>{if(Util.inputPathsEqual(this._currentFocus,blurringFocusPath)){this._setCurrentFocus(null);}});},this.blur=()=>{if(this._currentFocus){const[sectionIndex,...inputPath]=this._currentFocus;this.sectionRenderers[sectionIndex].blurPath(inputPath);}},this._sections=()=>{const sections=Array.isArray(this.props.json)?this.props.json:[this.props.json];if(getDependencies().JIPT.useJIPT){const paragraphs=[];for(const section of sections){JiptParagraphs.parseToArray(section.content).forEach(paragraph=>{paragraphs.push({...section,content:paragraph});});}return paragraphs}return sections};}}ArticleRenderer.contextType=PerseusI18nContext;ArticleRenderer.defaultProps={apiOptions:ApiOptions.defaults,linterContext:PerseusLinter__namespace.linterContextDefault};
|
|
2185
2176
|
|
|
2186
|
-
class HintRenderer extends React__namespace.Component{render(){if(this.props.hint.placeholder){return jsxRuntimeExports.jsx("span",{})}const{apiOptions,className,hint,lastHint,lastRendered,pos,totalHints}=this.props;const{isMobile}=apiOptions;const classNames=classNames__default.default("hint",!isMobile&&"perseus-hint-renderer",isMobile&&aphrodite.css(styles$2.newHint),isMobile&&lastRendered&&aphrodite.css(styles$2.lastRenderedNewHint),lastHint&&"last-hint",lastRendered&&"last-rendered",className);const rendererApiOptions={...apiOptions,customKeypad:false};return jsxRuntimeExports.jsx(DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:classNames,tabIndex:"-1",children:[!apiOptions.isMobile&&jsxRuntimeExports.jsx("span",{className:"perseus-sr-only",children:this.context.strings.hintPos({pos:pos+1})}),!apiOptions.isMobile&&totalHints!=null&&pos!=null&&jsxRuntimeExports.jsx("span",{className:"perseus-hint-label",style:{display:"block",color:apiOptions.hintProgressColor},children:`${pos+1} / ${totalHints}`}),jsxRuntimeExports.jsx(UserInputManager,{widgets:hint.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(Renderer,{ref:this.rendererRef,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,widgets:hint.widgets,content:hint.content||"",images:hint.images,apiOptions:rendererApiOptions,findExternalWidgets:this.props.findExternalWidgets,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"hint"),strings:this.context.strings})})]})})}constructor(...args){super(...args),this.rendererRef=React__namespace.createRef(),this.getSerializedState=()=>{return this.rendererRef.current?.getSerializedState()};}}HintRenderer.contextType=PerseusI18nContext;HintRenderer.defaultProps={linterContext:PerseusLinter__namespace.linterContextDefault};const styles$2=aphrodite.StyleSheet.create({newHint:{marginBottom:
|
|
2177
|
+
class HintRenderer extends React__namespace.Component{render(){if(this.props.hint.placeholder){return jsxRuntimeExports.jsx("span",{})}const{apiOptions,className,hint,lastHint,lastRendered,pos,totalHints}=this.props;const{isMobile}=apiOptions;const classNames=classNames__default.default("hint",!isMobile&&"perseus-hint-renderer",isMobile&&aphrodite.css(styles$2.newHint),isMobile&&lastRendered&&aphrodite.css(styles$2.lastRenderedNewHint),lastHint&&"last-hint",lastRendered&&"last-rendered",className);const rendererApiOptions={...apiOptions,customKeypad:false};return jsxRuntimeExports.jsx(DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:classNames,tabIndex:"-1",children:[!apiOptions.isMobile&&jsxRuntimeExports.jsx("span",{className:"perseus-sr-only",children:this.context.strings.hintPos({pos:pos+1})}),!apiOptions.isMobile&&totalHints!=null&&pos!=null&&jsxRuntimeExports.jsx("span",{className:"perseus-hint-label",style:{display:"block",color:apiOptions.hintProgressColor},children:`${pos+1} / ${totalHints}`}),jsxRuntimeExports.jsx(UserInputManager,{widgets:hint.widgets,problemNum:0,children:({userInput,handleUserInput,initializeUserInput})=>jsxRuntimeExports.jsx(Renderer,{ref:this.rendererRef,userInput:userInput,handleUserInput:handleUserInput,initializeUserInput:initializeUserInput,widgets:hint.widgets,content:hint.content||"",images:hint.images,apiOptions:rendererApiOptions,findExternalWidgets:this.props.findExternalWidgets,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"hint"),strings:this.context.strings})})]})})}constructor(...args){super(...args),this.rendererRef=React__namespace.createRef(),this.getSerializedState=()=>{return this.rendererRef.current?.getSerializedState()};}}HintRenderer.contextType=PerseusI18nContext;HintRenderer.defaultProps={linterContext:PerseusLinter__namespace.linterContextDefault};const styles$2=aphrodite.StyleSheet.create({newHint:{marginBottom:wonderBlocksTokens.sizing.size_240,borderInlineStartColor:wonderBlocksTokens.semanticColor.core.background.base.subtle,borderInlineStartStyle:"solid",borderInlineStartWidth:hintBorderWidth,[mediaQueries.lgOrSmaller]:{paddingInlineStart:hintPaddingInlineStart},[mediaQueries.smOrSmaller]:{paddingInlineStart:0},":focus":{outline:"none"}},lastRenderedNewHint:{marginBottom:0,borderInlineStartColor:wonderBlocksTokens.semanticColor.core.border.instructive.default}});
|
|
2187
2178
|
|
|
2188
|
-
class HintsRenderer extends React__namespace.Component{componentDidMount(){this._cacheHintImages();}UNSAFE_componentWillReceiveProps(nextProps){if(nextProps.hintsVisible-this.props.hintsVisible>1){this.setState({isFinalHelpPage:true});}}componentDidUpdate(prevProps,prevState){if(!___default.default.isEqual(prevProps.hints,this.props.hints)||prevProps.hintsVisible!==this.props.hintsVisible){this._cacheHintImages();}const prevHintsVisible=prevProps.hintsVisible||0;const nextHintsVisible=this.props.hintsVisible||0;if(prevHintsVisible<nextHintsVisible&&nextHintsVisible<=this.props.hints.length&&nextHintsVisible>=0){const pos=nextHintsVisible-1;const hint=this.props.hints[pos];if(hint?.placeholder){return}try{const ref=this.refs["hintRenderer"+pos];if(ref==null){return}const domNode=ReactDOM__namespace.default.findDOMNode(ref);if(domNode&&typeof domNode.focus==="function"){domNode.focus();}}catch(e){}}}render(){const apiOptions=this.getApiOptions();const hintsVisible=this._hintsVisible();const hints=[];const isFinalHelpPage=this.state.isFinalHelpPage;this.props.hints.slice(0,hintsVisible).forEach((hint,i)=>{const lastHint=i===this.props.hints.length-1&&!/\*\*/.test(hint.content);const lastRendered=i===hintsVisible-1;const renderer=jsxRuntimeExports.jsx(HintRenderer,{dependencies:this.props.dependencies,lastHint:lastHint,lastRendered:lastRendered,hint:hint,pos:i,totalHints:this.props.hints.length,ref:"hintRenderer"+i,apiOptions:apiOptions,findExternalWidgets:this.props.findExternalWidgets,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"hints["+i+"]")},"hintRenderer"+i);if(isFinalHelpPage){hints.push(renderer);}else {if(hint.replace&&hints.length>0){hints[hints.length-1]=renderer;}else {hints.push(renderer);}}});const{getAnotherHint}=apiOptions;const showGetAnotherHint=getAnotherHint&&hintsVisible>0&&hintsVisible<this.props.hints.length;const hintRatioCopy=`(${hintsVisible}/${this.props.hints.length})`;const classNames=classNames__default.default(this.props.className,apiOptions.isMobile&&hintsVisible>0&&aphrodite.css(styles$1.mobileHintStylesHintsRenderer));return jsxRuntimeExports.jsxs("div",{className:classNames,children:[apiOptions.isMobile&&hintsVisible>0&&jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$1.mobileHintStylesHintTitle,sharedStyles.responsiveLabel),children:this.context.strings.hints}),hints,showGetAnotherHint&&jsxRuntimeExports.
|
|
2179
|
+
class HintsRenderer extends React__namespace.Component{componentDidMount(){this._cacheHintImages();}UNSAFE_componentWillReceiveProps(nextProps){if(nextProps.hintsVisible-this.props.hintsVisible>1){this.setState({isFinalHelpPage:true});}}componentDidUpdate(prevProps,prevState){if(!___default.default.isEqual(prevProps.hints,this.props.hints)||prevProps.hintsVisible!==this.props.hintsVisible){this._cacheHintImages();}const prevHintsVisible=prevProps.hintsVisible||0;const nextHintsVisible=this.props.hintsVisible||0;if(prevHintsVisible<nextHintsVisible&&nextHintsVisible<=this.props.hints.length&&nextHintsVisible>=0){const pos=nextHintsVisible-1;const hint=this.props.hints[pos];if(hint?.placeholder){return}try{const ref=this.refs["hintRenderer"+pos];if(ref==null){return}const domNode=ReactDOM__namespace.default.findDOMNode(ref);if(domNode&&typeof domNode.focus==="function"){domNode.focus();}}catch(e){}}}render(){const apiOptions=this.getApiOptions();const hintsVisible=this._hintsVisible();const hints=[];const isFinalHelpPage=this.state.isFinalHelpPage;this.props.hints.slice(0,hintsVisible).forEach((hint,i)=>{const lastHint=i===this.props.hints.length-1&&!/\*\*/.test(hint.content);const lastRendered=i===hintsVisible-1;const renderer=jsxRuntimeExports.jsx(HintRenderer,{dependencies:this.props.dependencies,lastHint:lastHint,lastRendered:lastRendered,hint:hint,pos:i,totalHints:this.props.hints.length,ref:"hintRenderer"+i,apiOptions:apiOptions,findExternalWidgets:this.props.findExternalWidgets,linterContext:PerseusLinter__namespace.pushContextStack(this.props.linterContext,"hints["+i+"]")},"hintRenderer"+i);if(isFinalHelpPage){hints.push(renderer);}else {if(hint.replace&&hints.length>0){hints[hints.length-1]=renderer;}else {hints.push(renderer);}}});const{getAnotherHint}=apiOptions;const showGetAnotherHint=getAnotherHint&&hintsVisible>0&&hintsVisible<this.props.hints.length;const hintRatioCopy=`(${hintsVisible}/${this.props.hints.length})`;const classNames=classNames__default.default(this.props.className,apiOptions.isMobile&&hintsVisible>0&&aphrodite.css(styles$1.mobileHintStylesHintsRenderer));return jsxRuntimeExports.jsxs("div",{className:classNames,children:[apiOptions.isMobile&&hintsVisible>0&&jsxRuntimeExports.jsx("div",{className:aphrodite.css(styles$1.mobileHintStylesHintTitle,sharedStyles.responsiveLabel),children:this.context.strings.hints}),hints,showGetAnotherHint&&jsxRuntimeExports.jsx(Button__default.default,{rel:"button",kind:"tertiary",startIcon:plus__default.default,onClick:evt=>{evt.preventDefault();evt.stopPropagation();if(getAnotherHint){getAnotherHint();}},children:this.context.strings.getAnotherHint+" "+hintRatioCopy})]})}constructor(...args){super(...args),this.state={isFinalHelpPage:false},this._hintsVisible=()=>{if(this.props.hintsVisible==null||this.props.hintsVisible===-1){return this.props.hints.length}return this.props.hintsVisible},this._cacheImagesInHint=hint=>{___default.default.each(hint.images,(data,src)=>{const image=new Image;image.src=Util.getRealImageUrl(src);});},this._cacheHintImages=()=>{if(this._hintsVisible()>0){___default.default.each(this.props.hints,this._cacheImagesInHint);}else if(this.props.hints.length>0){this._cacheImagesInHint(this.props.hints[0]);}},this.getApiOptions=()=>{return {...ApiOptions.defaults,...this.props.apiOptions,readOnly:false}},this.getSerializedState=()=>{return ___default.default.times(this._hintsVisible(),i=>{return this.refs["hintRenderer"+i].getSerializedState()})};}}HintsRenderer.contextType=PerseusI18nContext;HintsRenderer.defaultProps={linterContext:PerseusLinter__namespace.linterContextDefault};const styles$1=aphrodite.StyleSheet.create({mobileHintStylesHintsRenderer:{marginTop:wonderBlocksTokens.sizing.size_640,border:`solid ${wonderBlocksTokens.semanticColor.core.border.neutral.subtle}`,borderWidth:"1px 0 0 0",position:"relative",":before":{content:'""',display:"table",clear:"both"},":after":{content:'""',display:"table",clear:"both"}},mobileHintStylesHintTitle:{fontWeight:"bold",color:wonderBlocksTokens.semanticColor.core.foreground.neutral.strong,paddingTop:wonderBlocksTokens.sizing.size_160,paddingBottom:wonderBlocksTokens.sizing.size_240,[mediaQueries.lgOrSmaller]:{paddingLeft:0},[mediaQueries.smOrSmaller]:{paddingLeft:`calc(${hintPaddingInlineStart} + ${hintBorderWidth})`}}});
|
|
2189
2180
|
|
|
2190
2181
|
const defaultContext={onRendered:isRendered=>{}};const context=React__namespace.createContext(defaultContext);
|
|
2191
2182
|
|