@khanacademy/perseus 17.6.0 → 17.6.2
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/CHANGELOG.md +17 -0
- package/dist/es/index.js +402 -606
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +411 -603
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +2 -1
- package/dist/strings.js +1 -0
- package/dist/widgets/deprecated-standin/index.d.ts +32 -0
- package/dist/widgets/label-image/answer-choices.d.ts +8 -40
- package/dist/widgets/label-image/answer-pill.d.ts +3 -1
- package/dist/widgets/label-image/marker.d.ts +10 -5
- package/dist/widgets/label-image.d.ts +1 -8
- package/dist/widgets.d.ts +9 -0
- package/package.json +34 -33
- package/src/__tests__/widgets.test.ts +20 -0
- package/src/extra-widgets.ts +2 -0
- package/src/init.ts +5 -0
- package/src/perseus-types.ts +4 -1
- package/src/util/register-all-widgets-for-testing.ts +4 -0
- package/src/widgets/__stories__/orderer.stories.tsx +5 -1
- package/src/widgets/__testdata__/orderer.testdata.ts +66 -0
- package/src/widgets/deprecated-standin/__stories__/deprecated-standin.stories.tsx +34 -0
- package/src/widgets/deprecated-standin/__tests__/__snapshots__/deprecated-standin.test.ts.snap +71 -0
- package/src/widgets/deprecated-standin/__tests__/deprecated-standin.test.ts +93 -0
- package/src/widgets/deprecated-standin/index.tsx +57 -0
- package/src/widgets/label-image/__stories__/answer-choices.stories.tsx +29 -34
- package/src/widgets/label-image/__tests__/answer-pill.test.tsx +2 -10
- package/src/widgets/label-image/answer-choices.tsx +60 -278
- package/src/widgets/label-image/answer-pill.tsx +22 -13
- package/src/widgets/label-image/marker.tsx +103 -146
- package/src/widgets/label-image.test.ts +0 -2
- package/src/widgets/label-image.tsx +94 -195
- package/src/widgets.ts +24 -0
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/es/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as i18n from '@khanacademy/wonder-blocks-i18n';
|
|
|
7
7
|
import Tooltip$1 from '@khanacademy/wonder-blocks-tooltip';
|
|
8
8
|
import classNames from 'classnames';
|
|
9
9
|
import * as React from 'react';
|
|
10
|
-
import { useState, useEffect, useRef } from 'react';
|
|
10
|
+
import React__default, { useState, useEffect, useRef } from 'react';
|
|
11
11
|
import _, { debounce } from 'underscore';
|
|
12
12
|
import Clickable from '@khanacademy/wonder-blocks-clickable';
|
|
13
13
|
import Color, { fade } from '@khanacademy/wonder-blocks-color';
|
|
@@ -25,12 +25,13 @@ import { pureMarkdownRules } from '@khanacademy/pure-markdown';
|
|
|
25
25
|
import { TextField } from '@khanacademy/wonder-blocks-form';
|
|
26
26
|
import Button from '@khanacademy/wonder-blocks-button';
|
|
27
27
|
import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
28
|
-
import
|
|
28
|
+
import Banner from '@khanacademy/wonder-blocks-banner';
|
|
29
|
+
import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-blocks-dropdown';
|
|
29
30
|
import debounce$1 from 'lodash.debounce';
|
|
30
|
-
import Pill from '@khanacademy/wonder-blocks-pill';
|
|
31
|
-
import { Popper } from 'react-popper';
|
|
32
31
|
import Switch from '@khanacademy/wonder-blocks-switch';
|
|
33
32
|
import { LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
33
|
+
import Pill from '@khanacademy/wonder-blocks-pill';
|
|
34
|
+
import { Popper } from 'react-popper';
|
|
34
35
|
import createReactClass from 'create-react-class';
|
|
35
36
|
import Link from '@khanacademy/wonder-blocks-link';
|
|
36
37
|
import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-core';
|
|
@@ -242,7 +243,7 @@ class MathInput extends React.Component {
|
|
|
242
243
|
className = className + " " + this.props.className;
|
|
243
244
|
}
|
|
244
245
|
return /*#__PURE__*/React.createElement(View, {
|
|
245
|
-
style: [styles$
|
|
246
|
+
style: [styles$B.outerWrapper, this.state.focused && styles$B.wrapperFocused, this.props.hasError && styles$B.wrapperError]
|
|
246
247
|
}, /*#__PURE__*/React.createElement("div", {
|
|
247
248
|
style: {
|
|
248
249
|
display: "flex",
|
|
@@ -271,7 +272,7 @@ class MathInput extends React.Component {
|
|
|
271
272
|
var _this$props$keypadBut, _this$props;
|
|
272
273
|
return /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
273
274
|
closeButtonVisible: true,
|
|
274
|
-
style: styles$
|
|
275
|
+
style: styles$B.popoverContent
|
|
275
276
|
}, /*#__PURE__*/React.createElement(DesktopKeypad, _extends({
|
|
276
277
|
onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
|
|
277
278
|
extraKeys: this.props.extraKeys,
|
|
@@ -315,9 +316,9 @@ const MathInputIcon = ({
|
|
|
315
316
|
color = Color.offBlack;
|
|
316
317
|
break;
|
|
317
318
|
}
|
|
318
|
-
const dynamicClass = active || focused ? styles$
|
|
319
|
+
const dynamicClass = active || focused ? styles$B.iconActive : styles$B.iconInactive;
|
|
319
320
|
return /*#__PURE__*/React.createElement(View, {
|
|
320
|
-
style: [styles$
|
|
321
|
+
style: [styles$B.iconContainer, dynamicClass]
|
|
321
322
|
}, /*#__PURE__*/React.createElement("svg", {
|
|
322
323
|
xmlns: "http://www.w3.org/2000/svg",
|
|
323
324
|
width: "16",
|
|
@@ -362,7 +363,7 @@ const inputFocused = {
|
|
|
362
363
|
borderColor: Color.blue,
|
|
363
364
|
margin: -1
|
|
364
365
|
};
|
|
365
|
-
const styles$
|
|
366
|
+
const styles$B = StyleSheet.create({
|
|
366
367
|
iconContainer: {
|
|
367
368
|
display: "flex",
|
|
368
369
|
justifyContent: "center",
|
|
@@ -17566,33 +17567,33 @@ class Lint extends React.Component {
|
|
|
17566
17567
|
let warningText;
|
|
17567
17568
|
let warningTextStyle;
|
|
17568
17569
|
if (this.props.severity === Severity.Error) {
|
|
17569
|
-
severityStyle = styles$
|
|
17570
|
+
severityStyle = styles$A.indicatorError;
|
|
17570
17571
|
warningText = "Error";
|
|
17571
|
-
warningTextStyle = styles$
|
|
17572
|
+
warningTextStyle = styles$A.publishBlockingError;
|
|
17572
17573
|
} else if (this.props.severity === Severity.Warning) {
|
|
17573
|
-
severityStyle = styles$
|
|
17574
|
+
severityStyle = styles$A.indicatorWarning;
|
|
17574
17575
|
warningText = "Warning";
|
|
17575
|
-
warningTextStyle = styles$
|
|
17576
|
+
warningTextStyle = styles$A.warning;
|
|
17576
17577
|
} else {
|
|
17577
|
-
severityStyle = styles$
|
|
17578
|
+
severityStyle = styles$A.indicatorGuideline;
|
|
17578
17579
|
warningText = "Recommendation";
|
|
17579
|
-
warningTextStyle = styles$
|
|
17580
|
+
warningTextStyle = styles$A.warning;
|
|
17580
17581
|
}
|
|
17581
17582
|
return /*#__PURE__*/React.createElement("a", {
|
|
17582
17583
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
17583
17584
|
target: "lint-help-window",
|
|
17584
17585
|
className: css(style)
|
|
17585
17586
|
}, /*#__PURE__*/React.createElement("span", {
|
|
17586
|
-
className: css(styles$
|
|
17587
|
+
className: css(styles$A.indicator, severityStyle)
|
|
17587
17588
|
}, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
|
|
17588
|
-
className: css(styles$
|
|
17589
|
+
className: css(styles$A.tooltip, tooltipAbove && styles$A.tooltipAbove)
|
|
17589
17590
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
|
|
17590
17591
|
key: i,
|
|
17591
|
-
className: css(styles$
|
|
17592
|
+
className: css(styles$A.tooltipParagraph)
|
|
17592
17593
|
}, /*#__PURE__*/React.createElement("span", {
|
|
17593
17594
|
className: css(warningTextStyle)
|
|
17594
17595
|
}, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
|
|
17595
|
-
className: css(styles$
|
|
17596
|
+
className: css(styles$A.tail, tooltipAbove && styles$A.tailAbove)
|
|
17596
17597
|
})));
|
|
17597
17598
|
};
|
|
17598
17599
|
}
|
|
@@ -17630,20 +17631,20 @@ class Lint extends React.Component {
|
|
|
17630
17631
|
}
|
|
17631
17632
|
if (blockHighlight) {
|
|
17632
17633
|
return /*#__PURE__*/React.createElement("span", {
|
|
17633
|
-
className: css(styles$
|
|
17634
|
-
}, this.renderLink(styles$
|
|
17634
|
+
className: css(styles$A.lintContainer, styles$A.lintContainerBlock)
|
|
17635
|
+
}, this.renderLink(styles$A.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
17635
17636
|
}
|
|
17636
17637
|
if (inline) {
|
|
17637
17638
|
return /*#__PURE__*/React.createElement("span", {
|
|
17638
|
-
className: css(styles$
|
|
17639
|
-
}, this.renderLink(styles$
|
|
17639
|
+
className: css(styles$A.lintContainer)
|
|
17640
|
+
}, this.renderLink(styles$A.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
17640
17641
|
}
|
|
17641
17642
|
return /*#__PURE__*/React.createElement("div", {
|
|
17642
|
-
className: css(styles$
|
|
17643
|
-
}, this.renderLink(styles$
|
|
17643
|
+
className: css(styles$A.lintContainer)
|
|
17644
|
+
}, this.renderLink(styles$A.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
|
|
17644
17645
|
}
|
|
17645
17646
|
}
|
|
17646
|
-
const styles$
|
|
17647
|
+
const styles$A = StyleSheet.create({
|
|
17647
17648
|
// This is the class of the outermost element.
|
|
17648
17649
|
// We use relative positioning so that the lint indicator can be
|
|
17649
17650
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -18397,6 +18398,27 @@ const registerWidgets = widgets => {
|
|
|
18397
18398
|
});
|
|
18398
18399
|
validateAlignments();
|
|
18399
18400
|
};
|
|
18401
|
+
|
|
18402
|
+
/**
|
|
18403
|
+
*
|
|
18404
|
+
* @param name - the widget that you are trying to replace
|
|
18405
|
+
* @param replacementName - the name of the widget that takes its place
|
|
18406
|
+
*
|
|
18407
|
+
* e.g. replaceWidget("transformer", "always-correct") will make it so the
|
|
18408
|
+
* transformer widget is replaced by the always correct widget
|
|
18409
|
+
*/
|
|
18410
|
+
const replaceWidget = (name, replacementName) => {
|
|
18411
|
+
const substituteWidget = widgets[replacementName];
|
|
18412
|
+
if (!substituteWidget && Log) {
|
|
18413
|
+
const errorMsg = `Failed to replace ${name} with ${replacementName}`;
|
|
18414
|
+
Log.error(errorMsg, Errors.Internal);
|
|
18415
|
+
return;
|
|
18416
|
+
}
|
|
18417
|
+
registerWidget(name, substituteWidget);
|
|
18418
|
+
if (Log) {
|
|
18419
|
+
Log.log(`INFO: Replacing widget ${name} with ${replacementName}`);
|
|
18420
|
+
}
|
|
18421
|
+
};
|
|
18400
18422
|
const registerEditors = editorsToRegister => {
|
|
18401
18423
|
editorsToRegister.forEach(editor => {
|
|
18402
18424
|
if (!editor.widgetName) {
|
|
@@ -18712,6 +18734,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
18712
18734
|
__proto__: null,
|
|
18713
18735
|
registerWidget: registerWidget,
|
|
18714
18736
|
registerWidgets: registerWidgets,
|
|
18737
|
+
replaceWidget: replaceWidget,
|
|
18715
18738
|
registerEditors: registerEditors,
|
|
18716
18739
|
getWidget: getWidget,
|
|
18717
18740
|
getEditor: getEditor,
|
|
@@ -19494,7 +19517,7 @@ class Renderer extends React.Component {
|
|
|
19494
19517
|
paddingLeft: margin,
|
|
19495
19518
|
paddingRight: margin
|
|
19496
19519
|
};
|
|
19497
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
19520
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$z.mobileZoomableParentFix);
|
|
19498
19521
|
return /*#__PURE__*/React.createElement("div", {
|
|
19499
19522
|
key: state.key,
|
|
19500
19523
|
className: "perseus-block-math",
|
|
@@ -19615,7 +19638,7 @@ class Renderer extends React.Component {
|
|
|
19615
19638
|
paddingLeft: 0,
|
|
19616
19639
|
paddingRight: 0
|
|
19617
19640
|
};
|
|
19618
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
19641
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$z.mobileZoomableParentFix);
|
|
19619
19642
|
const wrappedOutput = /*#__PURE__*/React.createElement("div", {
|
|
19620
19643
|
style: _extends({}, mobileInnerStyle, {
|
|
19621
19644
|
overflowX: "auto"
|
|
@@ -20262,7 +20285,7 @@ Renderer.defaultProps = {
|
|
|
20262
20285
|
onSerializedStateUpdated: () => {},
|
|
20263
20286
|
linterContext: PerseusLinter.linterContextDefault
|
|
20264
20287
|
};
|
|
20265
|
-
const styles$
|
|
20288
|
+
const styles$z = {
|
|
20266
20289
|
mobileZoomableParentFix: {
|
|
20267
20290
|
// NOTE(abdul): There is an issue where transform animations will
|
|
20268
20291
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -21279,10 +21302,10 @@ class InputNumber extends React.Component {
|
|
|
21279
21302
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
21280
21303
|
// you modify this, double-check if you also need to modify that
|
|
21281
21304
|
// component.
|
|
21282
|
-
const inputStyles = [styles$
|
|
21305
|
+
const inputStyles = [styles$y.default, this.props.size === "small" ? styles$y.small : null, this.props.rightAlign ? styles$y.rightAlign : styles$y.leftAlign];
|
|
21283
21306
|
// Unanswered
|
|
21284
21307
|
if (rubric && !this.props.currentValue) {
|
|
21285
|
-
inputStyles.push(styles$
|
|
21308
|
+
inputStyles.push(styles$y.answerStateUnanswered);
|
|
21286
21309
|
}
|
|
21287
21310
|
return /*#__PURE__*/React.createElement(InputWithExamples
|
|
21288
21311
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -21367,7 +21390,7 @@ InputNumber.defaultProps = {
|
|
|
21367
21390
|
apiOptions: ApiOptions.defaults,
|
|
21368
21391
|
linterContext: linterContextDefault
|
|
21369
21392
|
};
|
|
21370
|
-
const styles$
|
|
21393
|
+
const styles$y = StyleSheet.create({
|
|
21371
21394
|
default: {
|
|
21372
21395
|
width: 80,
|
|
21373
21396
|
height: "auto"
|
|
@@ -22368,7 +22391,7 @@ const FocusRing = function FocusRing(props) {
|
|
|
22368
22391
|
};
|
|
22369
22392
|
return /*#__PURE__*/React.createElement("span", {
|
|
22370
22393
|
"data-test-id": "focus-ring",
|
|
22371
|
-
className: css(styles$
|
|
22394
|
+
className: css(styles$x.ring),
|
|
22372
22395
|
style: style
|
|
22373
22396
|
}, children);
|
|
22374
22397
|
};
|
|
@@ -22377,7 +22400,7 @@ FocusRing.defaultProps = {
|
|
|
22377
22400
|
color: kaGreen$1,
|
|
22378
22401
|
multipleSelect: false
|
|
22379
22402
|
};
|
|
22380
|
-
const styles$
|
|
22403
|
+
const styles$x = StyleSheet.create({
|
|
22381
22404
|
ring: {
|
|
22382
22405
|
margin: "auto",
|
|
22383
22406
|
display: "inline-block",
|
|
@@ -22414,7 +22437,7 @@ function getChoiceLetter(pos) {
|
|
|
22414
22437
|
}
|
|
22415
22438
|
|
|
22416
22439
|
const CHOICE_ICON_SIZE = 24;
|
|
22417
|
-
const styles$
|
|
22440
|
+
const styles$w = StyleSheet.create({
|
|
22418
22441
|
iconWrapper: {
|
|
22419
22442
|
display: "inline-block",
|
|
22420
22443
|
position: "relative"
|
|
@@ -22437,7 +22460,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
22437
22460
|
width: CROSS_OUT_LINE_SIZE,
|
|
22438
22461
|
height: CROSS_OUT_LINE_SIZE,
|
|
22439
22462
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
22440
|
-
className: css(styles$
|
|
22463
|
+
className: css(styles$v.crossOutLine),
|
|
22441
22464
|
"data-test-id": "choice-icon__cross-out-line"
|
|
22442
22465
|
}, /*#__PURE__*/React.createElement("line", {
|
|
22443
22466
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -22452,7 +22475,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
22452
22475
|
strokeLinecap: "round"
|
|
22453
22476
|
}));
|
|
22454
22477
|
};
|
|
22455
|
-
const styles$
|
|
22478
|
+
const styles$v = StyleSheet.create({
|
|
22456
22479
|
crossOutLine: {
|
|
22457
22480
|
// Center the icon within the container.
|
|
22458
22481
|
position: "absolute",
|
|
@@ -22533,7 +22556,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
22533
22556
|
} = props;
|
|
22534
22557
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
22535
22558
|
return /*#__PURE__*/React.createElement("div", {
|
|
22536
|
-
className: css(styles$
|
|
22559
|
+
className: css(styles$w.iconWrapper)
|
|
22537
22560
|
}, /*#__PURE__*/React.createElement(FocusRing, {
|
|
22538
22561
|
color: Color.blue,
|
|
22539
22562
|
visible: focused || hovered,
|
|
@@ -22542,13 +22565,13 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
22542
22565
|
// @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
22543
22566
|
style: dynamicStyles,
|
|
22544
22567
|
"data-test-id": "choice-icon__library-choice-icon",
|
|
22545
|
-
className: css(styles$
|
|
22568
|
+
className: css(styles$u.circle, showCorrectness && correct && styles$u.circleCorrect, showCorrectness && !correct && styles$u.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$u.circleIncorrectAnswered)
|
|
22546
22569
|
// used in BaseRadio editMode to check
|
|
22547
22570
|
// if we actually clicked on the radio icon
|
|
22548
22571
|
,
|
|
22549
22572
|
"data-is-radio-icon": true
|
|
22550
22573
|
}, /*#__PURE__*/React.createElement("div", {
|
|
22551
|
-
className: css(styles$
|
|
22574
|
+
className: css(styles$u.innerWrapper)
|
|
22552
22575
|
}, /*#__PURE__*/React.createElement(ChoiceInner, {
|
|
22553
22576
|
pos: pos,
|
|
22554
22577
|
showCorrectness: showCorrectness,
|
|
@@ -22557,7 +22580,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
22557
22580
|
color: dynamicStyles.borderColor
|
|
22558
22581
|
}));
|
|
22559
22582
|
};
|
|
22560
|
-
const styles$
|
|
22583
|
+
const styles$u = StyleSheet.create({
|
|
22561
22584
|
innerWrapper: {
|
|
22562
22585
|
width: CHOICE_ICON_SIZE,
|
|
22563
22586
|
height: CHOICE_ICON_SIZE,
|
|
@@ -22649,19 +22672,19 @@ const OptionStatus = function OptionStatus(props) {
|
|
|
22649
22672
|
}
|
|
22650
22673
|
let textStyle;
|
|
22651
22674
|
if (correct) {
|
|
22652
|
-
textStyle = styles$
|
|
22675
|
+
textStyle = styles$t.correct;
|
|
22653
22676
|
} else {
|
|
22654
22677
|
if (checked || previouslyAnswered) {
|
|
22655
|
-
textStyle = styles$
|
|
22678
|
+
textStyle = styles$t.incorrectAnswered;
|
|
22656
22679
|
} else {
|
|
22657
|
-
textStyle = styles$
|
|
22680
|
+
textStyle = styles$t.incorrect;
|
|
22658
22681
|
}
|
|
22659
22682
|
}
|
|
22660
22683
|
return /*#__PURE__*/React.createElement("div", {
|
|
22661
|
-
className: css(styles$
|
|
22684
|
+
className: css(styles$t.text, textStyle)
|
|
22662
22685
|
}, renderText(checked, correct, crossedOut));
|
|
22663
22686
|
};
|
|
22664
|
-
const styles$
|
|
22687
|
+
const styles$t = StyleSheet.create({
|
|
22665
22688
|
text: {
|
|
22666
22689
|
alignItems: "center",
|
|
22667
22690
|
display: "flex",
|
|
@@ -22736,8 +22759,8 @@ const Choice = function Choice(props) {
|
|
|
22736
22759
|
crossedOut: updatedCrossedOut
|
|
22737
22760
|
});
|
|
22738
22761
|
}
|
|
22739
|
-
const descriptionClassName = classNames("description", css(styles$
|
|
22740
|
-
const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$
|
|
22762
|
+
const descriptionClassName = classNames("description", css(styles$s.description));
|
|
22763
|
+
const rationaleClassName = classNames("perseus-radio-rationale-content", css(styles$s.rationale));
|
|
22741
22764
|
|
|
22742
22765
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
22743
22766
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -22897,7 +22920,7 @@ const Choice = function Choice(props) {
|
|
|
22897
22920
|
"data-test-id": `perseus-radio-rationale-content-${pos}`
|
|
22898
22921
|
}, rationale));
|
|
22899
22922
|
};
|
|
22900
|
-
const styles$
|
|
22923
|
+
const styles$s = StyleSheet.create({
|
|
22901
22924
|
description: {
|
|
22902
22925
|
display: "inline-block",
|
|
22903
22926
|
width: "100%"
|
|
@@ -23089,10 +23112,10 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23089
23112
|
const isMobile = apiOptions.isMobile;
|
|
23090
23113
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
23091
23114
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
23092
|
-
const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$
|
|
23093
|
-
const instructionsClassName = classNames("instructions", css(styles$
|
|
23115
|
+
const className = classNames("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$r.radio, styles$r.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$r.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$r.radioContainerLastHighlighted));
|
|
23116
|
+
const instructionsClassName = classNames("instructions", css(styles$r.instructions, isMobile && styles$r.instructionsMobile));
|
|
23094
23117
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect);
|
|
23095
|
-
const responsiveClassName = css(styles$
|
|
23118
|
+
const responsiveClassName = css(styles$r.responsiveFieldset);
|
|
23096
23119
|
const fieldset = /*#__PURE__*/React.createElement("fieldset", {
|
|
23097
23120
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
23098
23121
|
}, /*#__PURE__*/React.createElement("legend", {
|
|
@@ -23143,7 +23166,7 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23143
23166
|
const aphroditeClassName = checked => {
|
|
23144
23167
|
// Whether or not to show correctness borders
|
|
23145
23168
|
// for this choice and the next choice.
|
|
23146
|
-
return css(sharedStyles.aboveScratchpad, styles$
|
|
23169
|
+
return css(sharedStyles.aboveScratchpad, styles$r.item, styles$r.responsiveItem, checked && styles$r.selectedItem, checked && choice.highlighted && styles$r.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$r.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$r.nextHighlighted);
|
|
23147
23170
|
};
|
|
23148
23171
|
|
|
23149
23172
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -23217,14 +23240,14 @@ const BaseRadio = function BaseRadio(props) {
|
|
|
23217
23240
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
23218
23241
|
// an issue especially on phones.
|
|
23219
23242
|
return /*#__PURE__*/React.createElement("div", {
|
|
23220
|
-
className: css(styles$
|
|
23243
|
+
className: css(styles$r.responsiveContainer)
|
|
23221
23244
|
}, fieldset);
|
|
23222
23245
|
};
|
|
23223
23246
|
BaseRadio.defaultProps = {
|
|
23224
23247
|
editMode: false,
|
|
23225
23248
|
multipleSelect: false
|
|
23226
23249
|
};
|
|
23227
|
-
const styles$
|
|
23250
|
+
const styles$r = StyleSheet.create({
|
|
23228
23251
|
instructions: {
|
|
23229
23252
|
display: "block",
|
|
23230
23253
|
color: gray17,
|
|
@@ -23872,9 +23895,9 @@ class Categorizer extends React.Component {
|
|
|
23872
23895
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
23873
23896
|
}
|
|
23874
23897
|
const table = /*#__PURE__*/React.createElement("table", {
|
|
23875
|
-
className: "categorizer-table " + css(styles$
|
|
23898
|
+
className: "categorizer-table " + css(styles$q.mobileTable)
|
|
23876
23899
|
}, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
|
|
23877
|
-
className: css(styles$
|
|
23900
|
+
className: css(styles$q.emptyHeaderCell)
|
|
23878
23901
|
}), this.props.categories.map((category, i) => {
|
|
23879
23902
|
// Array index is the correct key here, as that's
|
|
23880
23903
|
// how category grading actually works -- no way
|
|
@@ -23882,7 +23905,7 @@ class Categorizer extends React.Component {
|
|
|
23882
23905
|
// middle. (If we later add that, this should be
|
|
23883
23906
|
// fixed.)
|
|
23884
23907
|
return /*#__PURE__*/React.createElement("th", {
|
|
23885
|
-
className: css(styles$
|
|
23908
|
+
className: css(styles$q.header),
|
|
23886
23909
|
key: i
|
|
23887
23910
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
23888
23911
|
content: category,
|
|
@@ -23902,7 +23925,7 @@ class Categorizer extends React.Component {
|
|
|
23902
23925
|
})), self.props.categories.map((catName, catNum) => {
|
|
23903
23926
|
const selected = self.props.values[itemNum] === catNum;
|
|
23904
23927
|
return /*#__PURE__*/React.createElement("td", {
|
|
23905
|
-
className: "category " + css(styles$
|
|
23928
|
+
className: "category " + css(styles$q.cell),
|
|
23906
23929
|
key: catNum
|
|
23907
23930
|
}, /*#__PURE__*/React.createElement("div", {
|
|
23908
23931
|
className: ClassNames.INTERACTIVE,
|
|
@@ -23921,7 +23944,7 @@ class Categorizer extends React.Component {
|
|
|
23921
23944
|
onChange: this.onChange.bind(this, itemNum, catNum),
|
|
23922
23945
|
onClick: e => e.stopPropagation()
|
|
23923
23946
|
}), !isMobile && /*#__PURE__*/React.createElement("span", {
|
|
23924
|
-
className: css(styles$
|
|
23947
|
+
className: css(styles$q.radioSpan, selected && styles$q.checkedRadioSpan, this.props.static && selected && styles$q.staticCheckedRadioSpan)
|
|
23925
23948
|
}, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
|
|
23926
23949
|
}));
|
|
23927
23950
|
/* eslint-enable max-len */
|
|
@@ -23933,7 +23956,7 @@ class Categorizer extends React.Component {
|
|
|
23933
23956
|
"categorizer-container": true,
|
|
23934
23957
|
"static-mode": this.props.static
|
|
23935
23958
|
});
|
|
23936
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
23959
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$q.fullBleedContainer] : [];
|
|
23937
23960
|
return /*#__PURE__*/React.createElement("div", {
|
|
23938
23961
|
className: extraClassNames + " " + css(...inlineStyles)
|
|
23939
23962
|
}, table);
|
|
@@ -23978,7 +24001,7 @@ const pageMargin = 16;
|
|
|
23978
24001
|
|
|
23979
24002
|
// Stylesheets aren't directly testable
|
|
23980
24003
|
/* c8 ignore next */
|
|
23981
|
-
const styles$
|
|
24004
|
+
const styles$q = StyleSheet.create({
|
|
23982
24005
|
mobileTable: {
|
|
23983
24006
|
[mediaQueries.smOrSmaller]: {
|
|
23984
24007
|
minWidth: "auto"
|
|
@@ -24214,7 +24237,7 @@ class CSProgram extends React.Component {
|
|
|
24214
24237
|
// creator "went wild".
|
|
24215
24238
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
24216
24239
|
return /*#__PURE__*/React.createElement("div", {
|
|
24217
|
-
className: css(styles$
|
|
24240
|
+
className: css(styles$p.widthOverride, styleContainer && styles$p.container)
|
|
24218
24241
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
24219
24242
|
sandbox: sandboxOptions,
|
|
24220
24243
|
src: url,
|
|
@@ -24243,7 +24266,7 @@ CSProgram.defaultProps = {
|
|
|
24243
24266
|
// optional message
|
|
24244
24267
|
message: null
|
|
24245
24268
|
};
|
|
24246
|
-
const styles$
|
|
24269
|
+
const styles$p = StyleSheet.create({
|
|
24247
24270
|
// Override the inherited width from the perseus paragraph class
|
|
24248
24271
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
24249
24272
|
widthOverride: {
|
|
@@ -24288,7 +24311,7 @@ class Definition extends React.Component {
|
|
|
24288
24311
|
}) => /*#__PURE__*/React.createElement(Popover, {
|
|
24289
24312
|
content: /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
24290
24313
|
color: "white",
|
|
24291
|
-
style: styles$
|
|
24314
|
+
style: styles$o.tooltipBody,
|
|
24292
24315
|
closeButtonVisible: true
|
|
24293
24316
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
24294
24317
|
apiOptions: this.props.apiOptions,
|
|
@@ -24319,7 +24342,7 @@ Definition.defaultProps = {
|
|
|
24319
24342
|
togglePrompt: "define me",
|
|
24320
24343
|
definition: "definition goes here"
|
|
24321
24344
|
};
|
|
24322
|
-
const styles$
|
|
24345
|
+
const styles$o = {
|
|
24323
24346
|
tooltipBody: {
|
|
24324
24347
|
color: Color.offBlack,
|
|
24325
24348
|
fontSize: 20,
|
|
@@ -24336,6 +24359,47 @@ var Definition$1 = {
|
|
|
24336
24359
|
transform: x => x
|
|
24337
24360
|
};
|
|
24338
24361
|
|
|
24362
|
+
// The props are type `any` on purpose so that this can receive props
|
|
24363
|
+
// from any deprecated widget
|
|
24364
|
+
class AutoCorrect extends React__default.Component {
|
|
24365
|
+
constructor(...args) {
|
|
24366
|
+
super(...args);
|
|
24367
|
+
this.getUserInput = () => {
|
|
24368
|
+
return {};
|
|
24369
|
+
};
|
|
24370
|
+
this.simpleValidate = rubric => {
|
|
24371
|
+
return AutoCorrect.validate(this.getUserInput(), rubric);
|
|
24372
|
+
};
|
|
24373
|
+
}
|
|
24374
|
+
static validate(userInput, rubric) {
|
|
24375
|
+
// Since this mean to replace an existing widget the learner
|
|
24376
|
+
// WILL earn points for this widget
|
|
24377
|
+
return {
|
|
24378
|
+
type: "points",
|
|
24379
|
+
earned: 1,
|
|
24380
|
+
total: 1,
|
|
24381
|
+
message: null
|
|
24382
|
+
};
|
|
24383
|
+
}
|
|
24384
|
+
render() {
|
|
24385
|
+
return /*#__PURE__*/React__default.createElement("div", {
|
|
24386
|
+
style: {
|
|
24387
|
+
paddingTop: 8,
|
|
24388
|
+
paddingBottom: 8
|
|
24389
|
+
}
|
|
24390
|
+
}, /*#__PURE__*/React__default.createElement(Banner, {
|
|
24391
|
+
text: i18n._("This part of the question is no-longer available. You will not be graded on this part."),
|
|
24392
|
+
kind: "warning",
|
|
24393
|
+
layout: "full-width"
|
|
24394
|
+
}));
|
|
24395
|
+
}
|
|
24396
|
+
}
|
|
24397
|
+
var DeprecatedStandin = {
|
|
24398
|
+
name: "deprecated-standin",
|
|
24399
|
+
displayName: "Deprecated Standin",
|
|
24400
|
+
widget: AutoCorrect
|
|
24401
|
+
};
|
|
24402
|
+
|
|
24339
24403
|
class Dropdown extends React.Component {
|
|
24340
24404
|
constructor(...args) {
|
|
24341
24405
|
super(...args);
|
|
@@ -24483,15 +24547,15 @@ class Explanation extends React.Component {
|
|
|
24483
24547
|
const onClick = this._onClick;
|
|
24484
24548
|
if (isMobile) {
|
|
24485
24549
|
linkContainer = /*#__PURE__*/React.createElement("div", {
|
|
24486
|
-
className: css(styles$
|
|
24550
|
+
className: css(styles$n.linkContainer)
|
|
24487
24551
|
}, /*#__PURE__*/React.createElement("a", {
|
|
24488
|
-
className: css(styles$
|
|
24552
|
+
className: css(styles$n.mobileExplanationLink),
|
|
24489
24553
|
href: href,
|
|
24490
24554
|
onClick: onClick,
|
|
24491
24555
|
role: "button",
|
|
24492
24556
|
"aria-expanded": this.state.expanded
|
|
24493
24557
|
}, linkAnchor), this.state.expanded && /*#__PURE__*/React.createElement("svg", {
|
|
24494
|
-
className: css(styles$
|
|
24558
|
+
className: css(styles$n.disclosureArrow)
|
|
24495
24559
|
}, /*#__PURE__*/React.createElement("polygon", {
|
|
24496
24560
|
style: {
|
|
24497
24561
|
fill: backgroundColor
|
|
@@ -24504,13 +24568,13 @@ class Explanation extends React.Component {
|
|
|
24504
24568
|
// an anchor tag (if rendered in a modal) or a Wonder Blocks
|
|
24505
24569
|
// link component in lesson page, see: `article-page.jsx`.
|
|
24506
24570
|
linkContainer = /*#__PURE__*/React.createElement("div", {
|
|
24507
|
-
className: css(styles$
|
|
24571
|
+
className: css(styles$n.linkContainer, styles$n.articleLink)
|
|
24508
24572
|
}, /*#__PURE__*/React.createElement(Link, {
|
|
24509
|
-
className: css(styles$
|
|
24573
|
+
className: css(styles$n.explanationLink)
|
|
24510
24574
|
// HACK(michaelpolyak): WB Link doesn't passthrough
|
|
24511
24575
|
// class name.
|
|
24512
24576
|
,
|
|
24513
|
-
style: styles$
|
|
24577
|
+
style: styles$n.explanationLink,
|
|
24514
24578
|
href: href,
|
|
24515
24579
|
onClick: onClick,
|
|
24516
24580
|
role: "button",
|
|
@@ -24520,9 +24584,9 @@ class Explanation extends React.Component {
|
|
|
24520
24584
|
// NOTE: For exercises, the baseElements `Link` is an
|
|
24521
24585
|
// anchor tag, see: `perseus-api.jsx`.
|
|
24522
24586
|
linkContainer = /*#__PURE__*/React.createElement("div", {
|
|
24523
|
-
className: css(styles$
|
|
24587
|
+
className: css(styles$n.linkContainer, styles$n.exerciseLink)
|
|
24524
24588
|
}, /*#__PURE__*/React.createElement(Link, {
|
|
24525
|
-
className: css(styles$
|
|
24589
|
+
className: css(styles$n.explanationLink),
|
|
24526
24590
|
href: href,
|
|
24527
24591
|
onClick: onClick,
|
|
24528
24592
|
role: "button",
|
|
@@ -24530,11 +24594,11 @@ class Explanation extends React.Component {
|
|
|
24530
24594
|
}, `[${linkAnchor}]`));
|
|
24531
24595
|
}
|
|
24532
24596
|
}
|
|
24533
|
-
const expandedStyle = isMobile ? styles$
|
|
24597
|
+
const expandedStyle = isMobile ? styles$n.contentExpandedMobile : styles$n.contentExpanded;
|
|
24534
24598
|
return /*#__PURE__*/React.createElement("div", {
|
|
24535
|
-
className: css(styles$
|
|
24599
|
+
className: css(styles$n.container)
|
|
24536
24600
|
}, linkContainer, this.state.expanded && /*#__PURE__*/React.createElement("div", {
|
|
24537
|
-
className: css(styles$
|
|
24601
|
+
className: css(styles$n.content, isMobile && styles$n.contentMobile, this.state.expanded && expandedStyle)
|
|
24538
24602
|
// eslint-disable-next-line react/no-string-refs
|
|
24539
24603
|
,
|
|
24540
24604
|
ref: "content"
|
|
@@ -24558,7 +24622,7 @@ const verticalContentPadding = 10;
|
|
|
24558
24622
|
const arrowWidth = 30;
|
|
24559
24623
|
const arrowHeight = 14;
|
|
24560
24624
|
const backgroundColor = gray95;
|
|
24561
|
-
const styles$
|
|
24625
|
+
const styles$n = StyleSheet.create({
|
|
24562
24626
|
container: {
|
|
24563
24627
|
display: "inline",
|
|
24564
24628
|
position: "relative"
|
|
@@ -24663,15 +24727,15 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
24663
24727
|
onCheckAnswer,
|
|
24664
24728
|
onNextQuestion
|
|
24665
24729
|
} = this.props;
|
|
24666
|
-
const answerBarStyle = _extends({}, styles$
|
|
24730
|
+
const answerBarStyle = _extends({}, styles$m.answerBar, {
|
|
24667
24731
|
backgroundColor: answerBarState === "CORRECT" ? Color.offWhite : "white",
|
|
24668
24732
|
// Center the "Correct!" message only when there's no next question
|
|
24669
24733
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
24670
24734
|
});
|
|
24671
24735
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
|
|
24672
|
-
style: styles$
|
|
24736
|
+
style: styles$m.text
|
|
24673
24737
|
}, /*#__PURE__*/React.createElement("span", {
|
|
24674
|
-
style: styles$
|
|
24738
|
+
style: styles$m.tryAgainIcon
|
|
24675
24739
|
}, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
|
|
24676
24740
|
style: {
|
|
24677
24741
|
marginLeft: 8
|
|
@@ -24690,7 +24754,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
24690
24754
|
return /*#__PURE__*/React.createElement("div", {
|
|
24691
24755
|
style: answerBarStyle
|
|
24692
24756
|
}, /*#__PURE__*/React.createElement("span", {
|
|
24693
|
-
style: styles$
|
|
24757
|
+
style: styles$m.text
|
|
24694
24758
|
}, /*#__PURE__*/React.createElement("span", {
|
|
24695
24759
|
style: {
|
|
24696
24760
|
fontSize: 28,
|
|
@@ -24712,7 +24776,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
24712
24776
|
}
|
|
24713
24777
|
}
|
|
24714
24778
|
const fontSize = 17;
|
|
24715
|
-
const styles$
|
|
24779
|
+
const styles$m = {
|
|
24716
24780
|
answerBar: {
|
|
24717
24781
|
display: "flex",
|
|
24718
24782
|
alignItems: "center",
|
|
@@ -24898,7 +24962,7 @@ class GradedGroup extends React.Component {
|
|
|
24898
24962
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
|
|
24899
24963
|
gradeStatus = i18n._("Incorrect");
|
|
24900
24964
|
}
|
|
24901
|
-
const mobileClass = this.props.inGradedGroupSet ? css(styles$
|
|
24965
|
+
const mobileClass = this.props.inGradedGroupSet ? css(styles$l.gradedGroupInSet) : css(styles$l.gradedGroup);
|
|
24902
24966
|
const classes = classNames({
|
|
24903
24967
|
[mobileClass]: apiOptions.isMobile,
|
|
24904
24968
|
"perseus-graded-group": true,
|
|
@@ -24917,7 +24981,7 @@ class GradedGroup extends React.Component {
|
|
|
24917
24981
|
return /*#__PURE__*/React.createElement("div", {
|
|
24918
24982
|
className: classes
|
|
24919
24983
|
}, !!this.props.title && /*#__PURE__*/React.createElement("div", {
|
|
24920
|
-
className: css(styles$
|
|
24984
|
+
className: css(styles$l.title)
|
|
24921
24985
|
}, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
|
|
24922
24986
|
// eslint-disable-next-line react/no-string-refs
|
|
24923
24987
|
ref: "renderer",
|
|
@@ -24949,7 +25013,7 @@ class GradedGroup extends React.Component {
|
|
|
24949
25013
|
}, i18n._("Next question")), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
|
24950
25014
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
24951
25015
|
tabIndex: "0",
|
|
24952
|
-
className: css(styles$
|
|
25016
|
+
className: css(styles$l.explanationTitle),
|
|
24953
25017
|
onClick: () => this.setState({
|
|
24954
25018
|
showHint: false
|
|
24955
25019
|
}),
|
|
@@ -24981,7 +25045,7 @@ class GradedGroup extends React.Component {
|
|
|
24981
25045
|
showHint: true
|
|
24982
25046
|
});
|
|
24983
25047
|
},
|
|
24984
|
-
className: css(styles$
|
|
25048
|
+
className: css(styles$l.showHintLink)
|
|
24985
25049
|
}, i18n._("Explain"))), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
|
|
24986
25050
|
apiOptions: apiOptions,
|
|
24987
25051
|
answerBarState: answerBarState,
|
|
@@ -25002,7 +25066,7 @@ GradedGroup.defaultProps = {
|
|
|
25002
25066
|
const traverseChildWidgets$3 = function traverseChildWidgets(props, traverseRenderer) {
|
|
25003
25067
|
return _.extend({}, props, traverseRenderer(props));
|
|
25004
25068
|
};
|
|
25005
|
-
const styles$
|
|
25069
|
+
const styles$l = StyleSheet.create({
|
|
25006
25070
|
gradedGroupInSet: {
|
|
25007
25071
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
25008
25072
|
marginLeft: 0,
|
|
@@ -25075,18 +25139,18 @@ class Indicators extends React.Component {
|
|
|
25075
25139
|
return /*#__PURE__*/React.createElement("ul", {
|
|
25076
25140
|
// reduntantly add class name for use in .less files--
|
|
25077
25141
|
// the styles object key gets hashed
|
|
25078
|
-
className: classNames(css(styles$
|
|
25142
|
+
className: classNames(css(styles$k.indicatorContainer), "indicatorContainer")
|
|
25079
25143
|
}, this.props.gradedGroups.map(({
|
|
25080
25144
|
title
|
|
25081
25145
|
}, i) => /*#__PURE__*/React.createElement("li", {
|
|
25082
|
-
className: css(styles$
|
|
25146
|
+
className: css(styles$k.indicator),
|
|
25083
25147
|
key: title
|
|
25084
25148
|
}, /*#__PURE__*/React.createElement(Clickable, {
|
|
25085
25149
|
role: "button",
|
|
25086
25150
|
"aria-label": i18n._("Skip to %(title)s", {
|
|
25087
25151
|
title
|
|
25088
25152
|
}),
|
|
25089
|
-
style: styles$
|
|
25153
|
+
style: styles$k.indicatorButton,
|
|
25090
25154
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
25091
25155
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
25092
25156
|
}, ({
|
|
@@ -25094,9 +25158,9 @@ class Indicators extends React.Component {
|
|
|
25094
25158
|
focused,
|
|
25095
25159
|
pressed
|
|
25096
25160
|
}) => /*#__PURE__*/React.createElement(View, {
|
|
25097
|
-
style: [styles$
|
|
25161
|
+
style: [styles$k.indicatorDot, (hovered || focused || pressed) && styles$k.indicatorDotFocused]
|
|
25098
25162
|
}, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
|
|
25099
|
-
style: styles$
|
|
25163
|
+
style: styles$k.indicatorDotActive
|
|
25100
25164
|
}, /*#__PURE__*/React.createElement("span", {
|
|
25101
25165
|
className: css(a11y.srOnly)
|
|
25102
25166
|
}, i18n._("Current"))))))));
|
|
@@ -25162,7 +25226,7 @@ class GradedGroupSet extends React.Component {
|
|
|
25162
25226
|
} = getDependencies();
|
|
25163
25227
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
25164
25228
|
return /*#__PURE__*/React.createElement("div", {
|
|
25165
|
-
className: css(styles$
|
|
25229
|
+
className: css(styles$k.container)
|
|
25166
25230
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
25167
25231
|
return (
|
|
25168
25232
|
/*#__PURE__*/
|
|
@@ -25185,13 +25249,13 @@ class GradedGroupSet extends React.Component {
|
|
|
25185
25249
|
const numGroups = this.props.gradedGroups.length;
|
|
25186
25250
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
25187
25251
|
return /*#__PURE__*/React.createElement("div", {
|
|
25188
|
-
className: css(styles$
|
|
25252
|
+
className: css(styles$k.container)
|
|
25189
25253
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25190
|
-
className: css(styles$
|
|
25254
|
+
className: css(styles$k.top)
|
|
25191
25255
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25192
|
-
className: css(styles$
|
|
25256
|
+
className: css(styles$k.title)
|
|
25193
25257
|
}, currentGroup.title), /*#__PURE__*/React.createElement("div", {
|
|
25194
|
-
className: css(styles$
|
|
25258
|
+
className: css(styles$k.spacer)
|
|
25195
25259
|
}), /*#__PURE__*/React.createElement(Indicators, {
|
|
25196
25260
|
currentGroup: this.state.currentGroup,
|
|
25197
25261
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -25233,7 +25297,7 @@ var GradedGroupSet$1 = {
|
|
|
25233
25297
|
tracking: "all",
|
|
25234
25298
|
isLintable: true
|
|
25235
25299
|
};
|
|
25236
|
-
const styles$
|
|
25300
|
+
const styles$k = StyleSheet.create({
|
|
25237
25301
|
top: {
|
|
25238
25302
|
display: "flex",
|
|
25239
25303
|
flexDirection: "row"
|
|
@@ -25338,7 +25402,7 @@ class ButtonGroup extends React.Component {
|
|
|
25338
25402
|
id: "" + i,
|
|
25339
25403
|
ref: "button" + i,
|
|
25340
25404
|
key: "" + i,
|
|
25341
|
-
className: css(styles$
|
|
25405
|
+
className: css(styles$j.buttonStyle, button.value === value && styles$j.selectedStyle),
|
|
25342
25406
|
onClick: () => this.toggleSelect(button.value)
|
|
25343
25407
|
}, button.content || "" + button.value);
|
|
25344
25408
|
});
|
|
@@ -25355,7 +25419,7 @@ ButtonGroup.defaultProps = {
|
|
|
25355
25419
|
value: null,
|
|
25356
25420
|
allowEmpty: true
|
|
25357
25421
|
};
|
|
25358
|
-
const styles$
|
|
25422
|
+
const styles$j = StyleSheet.create({
|
|
25359
25423
|
buttonStyle: {
|
|
25360
25424
|
backgroundColor: "white",
|
|
25361
25425
|
border: "1px solid #ccc",
|
|
@@ -30835,214 +30899,89 @@ var globalStyles = /*#__PURE__*/Object.freeze({
|
|
|
30835
30899
|
typography: typography
|
|
30836
30900
|
});
|
|
30837
30901
|
|
|
30838
|
-
|
|
30839
|
-
|
|
30840
|
-
super(...args);
|
|
30841
|
-
// The radio button or checkbox input control.
|
|
30842
|
-
this._input = void 0;
|
|
30843
|
-
this.state = {
|
|
30844
|
-
isInputFocused: false
|
|
30845
|
-
};
|
|
30846
|
-
}
|
|
30847
|
-
focusInput() {
|
|
30848
|
-
if (this._input) {
|
|
30849
|
-
this._input.focus();
|
|
30850
|
-
}
|
|
30851
|
-
}
|
|
30852
|
-
handleClick(e) {
|
|
30902
|
+
const AnswerChoices = props => {
|
|
30903
|
+
const onAnswerChange = selected => {
|
|
30853
30904
|
const {
|
|
30854
|
-
|
|
30905
|
+
choices,
|
|
30855
30906
|
onChange
|
|
30856
|
-
} =
|
|
30857
|
-
|
|
30858
|
-
|
|
30859
|
-
// We manually handle clicks, setting focus on the input control.
|
|
30860
|
-
this.focusInput();
|
|
30861
|
-
|
|
30862
|
-
// And toggling the answer selection state.
|
|
30863
|
-
onChange(!checked);
|
|
30864
|
-
}
|
|
30865
|
-
handleKeyDown(e) {
|
|
30866
|
-
const {
|
|
30867
|
-
onFocusPrevAnswer,
|
|
30868
|
-
onFocusNextAnswer
|
|
30869
|
-
} = this.props;
|
|
30907
|
+
} = props;
|
|
30908
|
+
onChange(choices.map(choice => selected.includes(choice.content)));
|
|
30909
|
+
};
|
|
30870
30910
|
|
|
30871
|
-
|
|
30872
|
-
|
|
30873
|
-
|
|
30874
|
-
|
|
30875
|
-
|
|
30876
|
-
|
|
30877
|
-
|
|
30878
|
-
|
|
30879
|
-
|
|
30880
|
-
|
|
30881
|
-
|
|
30882
|
-
|
|
30883
|
-
|
|
30884
|
-
|
|
30885
|
-
|
|
30886
|
-
|
|
30887
|
-
|
|
30888
|
-
|
|
30889
|
-
|
|
30890
|
-
|
|
30891
|
-
|
|
30892
|
-
|
|
30893
|
-
}
|
|
30894
|
-
|
|
30895
|
-
|
|
30896
|
-
|
|
30897
|
-
|
|
30898
|
-
|
|
30899
|
-
}
|
|
30900
|
-
|
|
30901
|
-
|
|
30902
|
-
|
|
30903
|
-
|
|
30904
|
-
|
|
30905
|
-
|
|
30906
|
-
|
|
30907
|
-
|
|
30908
|
-
size: 16,
|
|
30909
|
-
color: Color.offBlack
|
|
30910
|
-
}));
|
|
30911
|
-
}
|
|
30912
|
-
render() {
|
|
30913
|
-
const {
|
|
30914
|
-
content,
|
|
30915
|
-
checked,
|
|
30916
|
-
groupName,
|
|
30917
|
-
index,
|
|
30918
|
-
inputType
|
|
30919
|
-
} = this.props;
|
|
30920
|
-
const {
|
|
30921
|
-
isInputFocused
|
|
30922
|
-
} = this.state;
|
|
30923
|
-
const answerId = `${groupName}-${index}`;
|
|
30924
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
30925
|
-
className: css(styles$j.answerChoice, isInputFocused && styles$j.answerFocused),
|
|
30926
|
-
onClick: e => this.handleClick(e),
|
|
30927
|
-
onKeyDown: e => this.handleKeyDown(e)
|
|
30928
|
-
}, /*#__PURE__*/React.createElement("span", {
|
|
30929
|
-
className: css(styles$j.answerInputWrapper)
|
|
30930
|
-
}, /*#__PURE__*/React.createElement("input", {
|
|
30931
|
-
className: css(sharedStyles.perseusSrOnly),
|
|
30932
|
-
checked: checked,
|
|
30933
|
-
name: groupName,
|
|
30934
|
-
id: answerId,
|
|
30935
|
-
type: inputType,
|
|
30936
|
-
onChange: e => this.handleInputChange(e),
|
|
30937
|
-
onFocus: () => this.handleInputFocus(),
|
|
30938
|
-
onBlur: () => this.handleInputBlur(),
|
|
30939
|
-
ref: node => this._input = node
|
|
30940
|
-
}), this.renderCheckmark()), /*#__PURE__*/React.createElement("label", {
|
|
30941
|
-
htmlFor: answerId
|
|
30942
|
-
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
30943
|
-
content: content
|
|
30944
|
-
})));
|
|
30945
|
-
}
|
|
30946
|
-
}
|
|
30947
|
-
class AnswerChoices extends React.Component {
|
|
30948
|
-
constructor(props) {
|
|
30949
|
-
super(props);
|
|
30950
|
-
// The rendered answers elements.
|
|
30951
|
-
this._choices = void 0;
|
|
30952
|
-
this._choices = [];
|
|
30953
|
-
this.state = {
|
|
30954
|
-
groupName: _.uniqueId("answer_choices_")
|
|
30955
|
-
};
|
|
30956
|
-
}
|
|
30957
|
-
focusAnswer(index = 0) {
|
|
30958
|
-
const numChoices = this.props.choices.length;
|
|
30911
|
+
// WB Dropdown types only take an array of nodes, so we can't use a
|
|
30912
|
+
// functional component, which can only return a single node.
|
|
30913
|
+
const AnswerItems = choices => choices.map(({
|
|
30914
|
+
content
|
|
30915
|
+
}) => /*#__PURE__*/React.createElement(OptionItem, {
|
|
30916
|
+
key: content,
|
|
30917
|
+
value: content,
|
|
30918
|
+
label: /*#__PURE__*/React.createElement(Renderer, {
|
|
30919
|
+
content: content,
|
|
30920
|
+
inline: true
|
|
30921
|
+
})
|
|
30922
|
+
}));
|
|
30923
|
+
const selectedValues = props.choices.filter(choice => choice.checked).map(choice => choice.content);
|
|
30924
|
+
const {
|
|
30925
|
+
opener,
|
|
30926
|
+
onToggle,
|
|
30927
|
+
disabled
|
|
30928
|
+
} = props;
|
|
30929
|
+
const args = {
|
|
30930
|
+
// reset to allow child (answer pill) to control z-index
|
|
30931
|
+
style: {
|
|
30932
|
+
zIndex: "unset"
|
|
30933
|
+
},
|
|
30934
|
+
children: AnswerItems(props.choices),
|
|
30935
|
+
opener,
|
|
30936
|
+
onToggle,
|
|
30937
|
+
disabled
|
|
30938
|
+
};
|
|
30939
|
+
return props.multipleSelect ? /*#__PURE__*/React.createElement(MultiSelect, _extends({}, args, {
|
|
30940
|
+
selectedValues: selectedValues,
|
|
30941
|
+
onChange: selected => onAnswerChange(selected)
|
|
30942
|
+
})) : /*#__PURE__*/React.createElement(SingleSelect, _extends({}, args, {
|
|
30943
|
+
selectedValue: selectedValues[0],
|
|
30944
|
+
onChange: selected => onAnswerChange([selected]),
|
|
30945
|
+
placeholder: props.choices[0].content // not visible, but required
|
|
30946
|
+
}));
|
|
30947
|
+
};
|
|
30959
30948
|
|
|
30960
|
-
|
|
30961
|
-
|
|
30962
|
-
|
|
30963
|
-
} else if (index >= numChoices) {
|
|
30964
|
-
index -= numChoices;
|
|
30965
|
-
}
|
|
30966
|
-
const choice = this._choices[index];
|
|
30967
|
-
if (choice) {
|
|
30968
|
-
choice.focusInput();
|
|
30969
|
-
}
|
|
30970
|
-
}
|
|
30971
|
-
onAnswerChange(index, checked) {
|
|
30972
|
-
const {
|
|
30973
|
-
choices,
|
|
30974
|
-
multipleSelect,
|
|
30975
|
-
onChange
|
|
30976
|
-
} = this.props;
|
|
30977
|
-
const selection = [];
|
|
30949
|
+
const strings = {
|
|
30950
|
+
hideAnswersToggleLabel: i18n._("Hide answer choices")
|
|
30951
|
+
};
|
|
30978
30952
|
|
|
30979
|
-
|
|
30980
|
-
|
|
30981
|
-
|
|
30982
|
-
|
|
30983
|
-
|
|
30984
|
-
|
|
30985
|
-
}
|
|
30986
|
-
|
|
30987
|
-
|
|
30988
|
-
|
|
30989
|
-
|
|
30990
|
-
|
|
30991
|
-
|
|
30992
|
-
|
|
30993
|
-
|
|
30994
|
-
|
|
30995
|
-
|
|
30996
|
-
|
|
30997
|
-
|
|
30998
|
-
style: {
|
|
30999
|
-
border: "none",
|
|
31000
|
-
margin: 0,
|
|
31001
|
-
padding: 0
|
|
31002
|
-
}
|
|
31003
|
-
}, choices.map((choice, index) => /*#__PURE__*/React.createElement(AnswerChoice, _extends({}, choice, {
|
|
31004
|
-
key: choice.content,
|
|
31005
|
-
groupName: groupName,
|
|
31006
|
-
index: index,
|
|
31007
|
-
inputType: multipleSelect ? "checkbox" : "radio",
|
|
31008
|
-
onChange: checked => this.onAnswerChange(index, checked),
|
|
31009
|
-
onFocusPrevAnswer: () => this.onFocusAnswer(index - 1),
|
|
31010
|
-
onFocusNextAnswer: () => this.onFocusAnswer(index + 1),
|
|
31011
|
-
ref: node => this._choices[index] = node
|
|
31012
|
-
}))));
|
|
31013
|
-
}
|
|
31014
|
-
}
|
|
31015
|
-
const styles$j = StyleSheet.create({
|
|
31016
|
-
answerChoice: {
|
|
30953
|
+
const HideAnswersToggle = props => {
|
|
30954
|
+
const idFactory = useUniqueIdWithMock();
|
|
30955
|
+
const switchId = idFactory.get("hide-answers-toggle");
|
|
30956
|
+
const labelId = idFactory.get("hide-answers-label");
|
|
30957
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
30958
|
+
style: styles$i.switchWrapper
|
|
30959
|
+
}, /*#__PURE__*/React.createElement(Switch, {
|
|
30960
|
+
id: switchId,
|
|
30961
|
+
checked: props.areAnswersHidden,
|
|
30962
|
+
onChange: props.onChange,
|
|
30963
|
+
"aria-labelledby": labelId
|
|
30964
|
+
}), /*#__PURE__*/React.createElement(LabelMedium, {
|
|
30965
|
+
id: labelId,
|
|
30966
|
+
htmlFor: switchId,
|
|
30967
|
+
tag: "label"
|
|
30968
|
+
}, strings.hideAnswersToggleLabel));
|
|
30969
|
+
};
|
|
30970
|
+
const styles$i = StyleSheet.create({
|
|
30971
|
+
switchWrapper: {
|
|
31017
30972
|
display: "flex",
|
|
30973
|
+
flexDirection: "row",
|
|
30974
|
+
flexWrap: "wrap-reverse",
|
|
31018
30975
|
alignItems: "center",
|
|
31019
|
-
|
|
31020
|
-
|
|
31021
|
-
fontWeight: "bold",
|
|
31022
|
-
border: "solid 2px transparent",
|
|
31023
|
-
borderRadius: 2,
|
|
31024
|
-
":active": {
|
|
31025
|
-
backgroundColor: "rgba(33, 36, 44, 0.08)"
|
|
31026
|
-
}
|
|
31027
|
-
},
|
|
31028
|
-
answerFocused: {
|
|
31029
|
-
borderColor: "#1865f2",
|
|
31030
|
-
":active": {
|
|
31031
|
-
borderColor: "transparent"
|
|
31032
|
-
}
|
|
31033
|
-
},
|
|
31034
|
-
answerInputWrapper: {
|
|
31035
|
-
marginRight: 8
|
|
31036
|
-
},
|
|
31037
|
-
checkmarkContainer: {
|
|
31038
|
-
display: "flex",
|
|
31039
|
-
position: "relative",
|
|
31040
|
-
width: 16,
|
|
31041
|
-
height: 16,
|
|
31042
|
-
marginLeft: 8
|
|
30976
|
+
gap: "0.5em",
|
|
30977
|
+
marginTop: "1em"
|
|
31043
30978
|
}
|
|
31044
30979
|
});
|
|
31045
30980
|
|
|
30981
|
+
const BringToFront = {
|
|
30982
|
+
boxShadow: `0 8px 8px ${Color.offBlack64}`,
|
|
30983
|
+
zIndex: 1000
|
|
30984
|
+
};
|
|
31046
30985
|
const AnswerPill = props => {
|
|
31047
30986
|
const {
|
|
31048
30987
|
selectedAnswers,
|
|
@@ -31050,7 +30989,9 @@ const AnswerPill = props => {
|
|
|
31050
30989
|
markerRef,
|
|
31051
30990
|
side,
|
|
31052
30991
|
onClick,
|
|
31053
|
-
style
|
|
30992
|
+
style,
|
|
30993
|
+
focused,
|
|
30994
|
+
hovered
|
|
31054
30995
|
} = props;
|
|
31055
30996
|
const idFactory = useUniqueIdWithMock();
|
|
31056
30997
|
const answerString = selectedAnswers.length > 1 ?
|
|
@@ -31061,10 +31002,6 @@ const AnswerPill = props => {
|
|
|
31061
31002
|
// has been labeled (answered) correctly.
|
|
31062
31003
|
const correct = showCorrectness === "correct";
|
|
31063
31004
|
const incorrect = showCorrectness === "incorrect";
|
|
31064
|
-
const bringToFront = {
|
|
31065
|
-
boxShadow: `0 8px 8px ${Color.offBlack64}`,
|
|
31066
|
-
zIndex: 1000
|
|
31067
|
-
};
|
|
31068
31005
|
return /*#__PURE__*/React.createElement(Popper, {
|
|
31069
31006
|
placement: side,
|
|
31070
31007
|
referenceElement: markerRef,
|
|
@@ -31083,62 +31020,27 @@ const AnswerPill = props => {
|
|
|
31083
31020
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31084
31021
|
onClick: correct ? undefined : onClick,
|
|
31085
31022
|
ref: ref,
|
|
31086
|
-
style: [style, popperStyle,
|
|
31087
|
-
":hover": bringToFront,
|
|
31088
|
-
":focus": bringToFront
|
|
31089
|
-
}, correct && styles$i.correct, incorrect && styles$i.incorrect]
|
|
31023
|
+
style: [style, popperStyle, styles$h.relative, correct && styles$h.correct, incorrect && styles$h.incorrect, (focused || hovered) && BringToFront]
|
|
31090
31024
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
31091
31025
|
content: answerString,
|
|
31092
31026
|
inline: true
|
|
31093
31027
|
})));
|
|
31094
31028
|
};
|
|
31095
|
-
const styles$
|
|
31029
|
+
const styles$h = StyleSheet.create({
|
|
31096
31030
|
correct: {
|
|
31097
|
-
|
|
31031
|
+
// WB green darkened by 18%
|
|
31032
|
+
backgroundColor: "#00880b"
|
|
31098
31033
|
},
|
|
31099
|
-
|
|
31100
31034
|
incorrect: {
|
|
31101
31035
|
backgroundColor: Color.offBlack64
|
|
31102
31036
|
}
|
|
31103
31037
|
});
|
|
31104
31038
|
|
|
31105
|
-
const strings = {
|
|
31106
|
-
hideAnswersToggleLabel: i18n._("Hide answer choices")
|
|
31107
|
-
};
|
|
31108
|
-
|
|
31109
|
-
const HideAnswersToggle = props => {
|
|
31110
|
-
const idFactory = useUniqueIdWithMock();
|
|
31111
|
-
const switchId = idFactory.get("hide-answers-toggle");
|
|
31112
|
-
const labelId = idFactory.get("hide-answers-label");
|
|
31113
|
-
return /*#__PURE__*/React.createElement(View, {
|
|
31114
|
-
style: styles$h.switchWrapper
|
|
31115
|
-
}, /*#__PURE__*/React.createElement(Switch, {
|
|
31116
|
-
id: switchId,
|
|
31117
|
-
checked: props.areAnswersHidden,
|
|
31118
|
-
onChange: props.onChange,
|
|
31119
|
-
"aria-labelledby": labelId
|
|
31120
|
-
}), /*#__PURE__*/React.createElement(LabelMedium, {
|
|
31121
|
-
id: labelId,
|
|
31122
|
-
htmlFor: switchId,
|
|
31123
|
-
tag: "label"
|
|
31124
|
-
}, strings.hideAnswersToggleLabel));
|
|
31125
|
-
};
|
|
31126
|
-
const styles$h = StyleSheet.create({
|
|
31127
|
-
switchWrapper: {
|
|
31128
|
-
display: "flex",
|
|
31129
|
-
flexDirection: "row",
|
|
31130
|
-
flexWrap: "wrap-reverse",
|
|
31131
|
-
alignItems: "center",
|
|
31132
|
-
gap: "0.5em",
|
|
31133
|
-
marginTop: "1em"
|
|
31134
|
-
}
|
|
31135
|
-
});
|
|
31136
|
-
|
|
31137
|
-
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
31138
31039
|
function shouldReduceMotion() {
|
|
31139
31040
|
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
31140
31041
|
return !mediaQuery || mediaQuery.matches;
|
|
31141
31042
|
}
|
|
31043
|
+
const MARKER_SIZE = 24;
|
|
31142
31044
|
class Marker extends React.Component {
|
|
31143
31045
|
constructor(...args) {
|
|
31144
31046
|
super(...args);
|
|
@@ -31150,126 +31052,103 @@ class Marker extends React.Component {
|
|
|
31150
31052
|
selected,
|
|
31151
31053
|
showCorrectness,
|
|
31152
31054
|
showSelected,
|
|
31153
|
-
showPulsate
|
|
31154
|
-
focused
|
|
31055
|
+
showPulsate
|
|
31155
31056
|
} = this.props;
|
|
31156
31057
|
|
|
31157
31058
|
// Only a single marker may be "selected" at a time.
|
|
31158
31059
|
// `showSelected` is a controlled prop, that may be set to `true` for
|
|
31159
31060
|
// one marker at a time.
|
|
31160
|
-
|
|
31161
|
-
|
|
31162
|
-
// keyboard focus is given to the marker.
|
|
31163
|
-
const isSelected = showSelected || focused;
|
|
31164
|
-
let innerIcon;
|
|
31061
|
+
const isOpen = showSelected;
|
|
31062
|
+
const selectedAnswers = selected;
|
|
31165
31063
|
let iconStyles;
|
|
31064
|
+
const iconNull = {
|
|
31065
|
+
path: "",
|
|
31066
|
+
height: 1,
|
|
31067
|
+
width: 1
|
|
31068
|
+
};
|
|
31069
|
+
|
|
31070
|
+
// default dot
|
|
31071
|
+
let args = {
|
|
31072
|
+
size: MARKER_SIZE,
|
|
31073
|
+
color: Color.white,
|
|
31074
|
+
icon: iconNull
|
|
31075
|
+
};
|
|
31166
31076
|
if (showCorrectness) {
|
|
31167
|
-
|
|
31168
|
-
|
|
31169
|
-
|
|
31170
|
-
color: Color.white
|
|
31077
|
+
iconStyles = [styles$g.markerGraded, showCorrectness === "correct" ? styles$g.markerCorrect : styles$g.markerIncorrect, isOpen && styles$g.markerSelected];
|
|
31078
|
+
args = _extends({}, args, {
|
|
31079
|
+
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31171
31080
|
});
|
|
31172
|
-
|
|
31173
|
-
|
|
31174
|
-
|
|
31175
|
-
iconStyles = [styles$g.markerGraded, styles$g.markerIncorrect, isSelected && styles$g.markerSelected];
|
|
31176
|
-
}
|
|
31177
|
-
} else if (focused) {
|
|
31178
|
-
iconStyles = [styles$g.markerFocused, selected && selected.length > 0 && styles$g.markerFilled, showSelected && styles$g.markerSelected];
|
|
31179
|
-
} else if (selected && selected.length > 0) {
|
|
31180
|
-
iconStyles = [styles$g.markerFilled, isSelected && styles$g.markerSelected];
|
|
31181
|
-
} else if (isSelected) {
|
|
31081
|
+
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31082
|
+
iconStyles = [styles$g.markerFilled, isOpen && styles$g.markerSelected];
|
|
31083
|
+
} else if (isOpen) {
|
|
31182
31084
|
iconStyles = [styles$g.markerSelected];
|
|
31183
|
-
|
|
31184
|
-
iconStyles = [styles$g.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$g.markerUnfilledPulsateOnce : showPulsate && styles$g.markerUnfilledPulsateInfinite];
|
|
31185
|
-
}
|
|
31186
|
-
if (isSelected && selected && selected.length === 0) {
|
|
31187
|
-
innerIcon = /*#__PURE__*/React.createElement(Icon, {
|
|
31085
|
+
args = _extends({}, args, {
|
|
31188
31086
|
icon: iconChevronDown,
|
|
31189
|
-
size: 8
|
|
31190
|
-
color: Color.white
|
|
31087
|
+
size: 8
|
|
31191
31088
|
});
|
|
31089
|
+
} else if (showPulsate) {
|
|
31090
|
+
iconStyles = [styles$g.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$g.markerUnfilledPulsateOnce : showPulsate && styles$g.markerUnfilledPulsateInfinite];
|
|
31192
31091
|
}
|
|
31193
31092
|
return /*#__PURE__*/React.createElement(View, {
|
|
31194
31093
|
style: [styles$g.markerIcon, iconStyles],
|
|
31195
31094
|
ref: node => this._icon = node
|
|
31196
|
-
},
|
|
31095
|
+
}, /*#__PURE__*/React.createElement(Icon, args));
|
|
31197
31096
|
}
|
|
31198
31097
|
render() {
|
|
31098
|
+
var _this$_icon;
|
|
31199
31099
|
const {
|
|
31200
|
-
|
|
31201
|
-
|
|
31202
|
-
|
|
31203
|
-
|
|
31100
|
+
showCorrectness,
|
|
31101
|
+
selected,
|
|
31102
|
+
showAnswer,
|
|
31103
|
+
answerSide,
|
|
31104
|
+
answerStyles,
|
|
31105
|
+
hovered,
|
|
31106
|
+
focused
|
|
31204
31107
|
} = this.props;
|
|
31205
31108
|
|
|
31206
|
-
//
|
|
31207
|
-
//
|
|
31208
|
-
const
|
|
31209
|
-
|
|
31210
|
-
|
|
31211
|
-
|
|
31212
|
-
|
|
31213
|
-
|
|
31214
|
-
|
|
31215
|
-
|
|
31216
|
-
|
|
31217
|
-
|
|
31218
|
-
|
|
31219
|
-
|
|
31220
|
-
|
|
31221
|
-
this.props.onClick(e);
|
|
31222
|
-
},
|
|
31223
|
-
onKeyDown: e => this.props.onKeyDown(e)
|
|
31224
|
-
}, this.renderIcon());
|
|
31109
|
+
// We cannot make dropdown openers untabbable, so we isolate tabbing
|
|
31110
|
+
// to answer pills when interaction is disabled.
|
|
31111
|
+
const markerDisabled = showCorrectness === "correct";
|
|
31112
|
+
const active = hovered || focused;
|
|
31113
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
31114
|
+
style: [styles$g.marker, active && !markerDisabled && styles$g.markerActive]
|
|
31115
|
+
}, this.renderIcon()), !!selected && showAnswer && /*#__PURE__*/React.createElement(AnswerPill, {
|
|
31116
|
+
selectedAnswers: selected,
|
|
31117
|
+
showCorrectness: showCorrectness,
|
|
31118
|
+
side: answerSide,
|
|
31119
|
+
style: answerStyles,
|
|
31120
|
+
markerRef: (_this$_icon = this._icon) != null ? _this$_icon : undefined,
|
|
31121
|
+
hovered: hovered,
|
|
31122
|
+
focused: focused
|
|
31123
|
+
}));
|
|
31225
31124
|
}
|
|
31226
31125
|
}
|
|
31227
31126
|
Marker.defaultProps = {
|
|
31228
31127
|
selected: []
|
|
31229
31128
|
};
|
|
31230
|
-
const lightShadowColor = "rgba(33, 36, 44, 0.16)";
|
|
31231
|
-
const markerSize = 20;
|
|
31232
31129
|
const styles$g = StyleSheet.create({
|
|
31233
|
-
unstyledButton: {
|
|
31234
|
-
padding: 0,
|
|
31235
|
-
overflow: "visible",
|
|
31236
|
-
color: "inherit",
|
|
31237
|
-
font: "inherit",
|
|
31238
|
-
lineHeight: "normal",
|
|
31239
|
-
background: "none",
|
|
31240
|
-
border: "none"
|
|
31241
|
-
},
|
|
31242
31130
|
marker: {
|
|
31243
31131
|
position: "absolute",
|
|
31244
|
-
outline: "none",
|
|
31245
|
-
// Center marker position based on it's maximum size.
|
|
31246
|
-
width: markerSize,
|
|
31247
|
-
height: markerSize,
|
|
31248
31132
|
backgroundColor: Color.white,
|
|
31249
|
-
borderRadius:
|
|
31250
|
-
|
|
31251
|
-
|
|
31252
|
-
|
|
31253
|
-
|
|
31254
|
-
|
|
31133
|
+
borderRadius: MARKER_SIZE,
|
|
31134
|
+
// Center marker position based on its maximum size.
|
|
31135
|
+
width: MARKER_SIZE,
|
|
31136
|
+
height: MARKER_SIZE,
|
|
31137
|
+
marginLeft: MARKER_SIZE / -2,
|
|
31138
|
+
marginTop: MARKER_SIZE / -2,
|
|
31139
|
+
// Add a shadow to the marker to make it stand out from the image.
|
|
31140
|
+
boxShadow: `0 8px 8px ${Color.offBlack8}`
|
|
31255
31141
|
},
|
|
31256
31142
|
// The base and unfilled marker style.
|
|
31257
31143
|
markerIcon: {
|
|
31258
31144
|
display: "flex",
|
|
31259
31145
|
alignItems: "center",
|
|
31260
31146
|
justifyContent: "center",
|
|
31261
|
-
boxSizing: "
|
|
31262
|
-
width:
|
|
31263
|
-
height:
|
|
31264
|
-
marginLeft: 2,
|
|
31265
|
-
cursor: "pointer",
|
|
31147
|
+
boxSizing: "border-box",
|
|
31148
|
+
width: MARKER_SIZE,
|
|
31149
|
+
height: MARKER_SIZE,
|
|
31266
31150
|
border: `2px solid ${Color.offBlack64}`,
|
|
31267
|
-
borderRadius:
|
|
31268
|
-
boxShadow: `0 8px 8px ${Color.offBlack8}`,
|
|
31269
|
-
":hover": {
|
|
31270
|
-
outline: `2px solid ${Color.blue}`,
|
|
31271
|
-
outlineOffset: 2
|
|
31272
|
-
}
|
|
31151
|
+
borderRadius: MARKER_SIZE
|
|
31273
31152
|
},
|
|
31274
31153
|
// The animation that presents the marker to the learner
|
|
31275
31154
|
markerPulsateBase: {
|
|
@@ -31290,16 +31169,13 @@ const styles$g = StyleSheet.create({
|
|
|
31290
31169
|
animationIterationCount: "0"
|
|
31291
31170
|
},
|
|
31292
31171
|
markerUnfilledPulsateInfinite: {
|
|
31293
|
-
animationIterationCount: "infinite"
|
|
31294
|
-
":hover": {
|
|
31295
|
-
outline: `0px solid ${Color.blue}`
|
|
31296
|
-
}
|
|
31172
|
+
animationIterationCount: "infinite"
|
|
31297
31173
|
},
|
|
31298
31174
|
markerUnfilledPulsateOnce: {
|
|
31299
31175
|
// Doing the animation twice lets it ease-in and ease-out
|
|
31300
31176
|
animationIterationCount: "2"
|
|
31301
31177
|
},
|
|
31302
|
-
|
|
31178
|
+
markerActive: {
|
|
31303
31179
|
outline: `2px solid ${Color.blue}`,
|
|
31304
31180
|
outlineOffset: 2
|
|
31305
31181
|
},
|
|
@@ -31308,33 +31184,20 @@ const styles$g = StyleSheet.create({
|
|
|
31308
31184
|
boxShadow: `0 8px 8px ${Color.offBlack8}`,
|
|
31309
31185
|
border: `solid 4px ${Color.white}`,
|
|
31310
31186
|
backgroundColor: Color.blue,
|
|
31311
|
-
borderRadius:
|
|
31312
|
-
transform: "rotate(180deg)"
|
|
31313
|
-
":hover": {
|
|
31314
|
-
outline: `2px solid ${Color.blue}`,
|
|
31315
|
-
outlineOffset: -2
|
|
31316
|
-
}
|
|
31187
|
+
borderRadius: MARKER_SIZE,
|
|
31188
|
+
transform: "rotate(180deg)"
|
|
31317
31189
|
},
|
|
31318
31190
|
// The learner has made a selection
|
|
31319
31191
|
markerFilled: {
|
|
31320
|
-
width: markerSize - 2,
|
|
31321
|
-
height: markerSize - 2,
|
|
31322
|
-
borderRadius: markerSize - 2,
|
|
31323
31192
|
backgroundColor: "#ECF3FE",
|
|
31324
|
-
|
|
31325
|
-
marginTop: 0,
|
|
31326
|
-
border: `4px solid ${Color.blue}`,
|
|
31327
|
-
boxShadow: `0 1px 1px 0 ${lightShadowColor}`
|
|
31193
|
+
border: `4px solid ${Color.blue}`
|
|
31328
31194
|
},
|
|
31329
31195
|
markerGraded: {
|
|
31330
|
-
width:
|
|
31331
|
-
height:
|
|
31332
|
-
marginLeft: 1,
|
|
31333
|
-
marginTop: 1,
|
|
31196
|
+
width: MARKER_SIZE,
|
|
31197
|
+
height: MARKER_SIZE,
|
|
31334
31198
|
justifyContent: "center",
|
|
31335
31199
|
alignItems: "center",
|
|
31336
|
-
border: `2px solid ${Color.white}
|
|
31337
|
-
boxShadow: `0 8px 8px ${Color.offBlack8}`
|
|
31200
|
+
border: `2px solid ${Color.white}`
|
|
31338
31201
|
},
|
|
31339
31202
|
markerCorrect: {
|
|
31340
31203
|
background: "#00880b" // WB green darkened by 18%
|
|
@@ -31583,14 +31446,9 @@ class LabelImage extends React.Component {
|
|
|
31583
31446
|
super(props);
|
|
31584
31447
|
// The rendered markers on the question image for labeling.
|
|
31585
31448
|
this._markers = void 0;
|
|
31586
|
-
// The popup component containing the answer choices.
|
|
31587
|
-
this._selectedMarkerPopup = void 0;
|
|
31588
|
-
// The rendered list of answer choices for the currently selected marker.
|
|
31589
|
-
this._answerChoices = void 0;
|
|
31590
31449
|
this._markers = [];
|
|
31591
31450
|
this.state = {
|
|
31592
31451
|
activeMarkerIndex: -1,
|
|
31593
|
-
focusedMarkerIndex: -1,
|
|
31594
31452
|
markersInteracted: false,
|
|
31595
31453
|
hideAnswers: false
|
|
31596
31454
|
};
|
|
@@ -31628,26 +31486,6 @@ class LabelImage extends React.Component {
|
|
|
31628
31486
|
markers: updatedMarkers
|
|
31629
31487
|
}, null, true);
|
|
31630
31488
|
}
|
|
31631
|
-
dismissMarkerPopup() {
|
|
31632
|
-
const {
|
|
31633
|
-
activeMarkerIndex
|
|
31634
|
-
} = this.state;
|
|
31635
|
-
|
|
31636
|
-
// No popup should be open if there's no selected marker.
|
|
31637
|
-
if (activeMarkerIndex === -1) {
|
|
31638
|
-
return;
|
|
31639
|
-
}
|
|
31640
|
-
this.setState({
|
|
31641
|
-
activeMarkerIndex: -1
|
|
31642
|
-
}, () => {
|
|
31643
|
-
const marker = this._markers[activeMarkerIndex];
|
|
31644
|
-
// Set focus on the just-deselected-marker, to enable to resume
|
|
31645
|
-
// navigating between the markers using the keyboard.
|
|
31646
|
-
if (marker) {
|
|
31647
|
-
ReactDOM.findDOMNode(marker).focus();
|
|
31648
|
-
}
|
|
31649
|
-
});
|
|
31650
|
-
}
|
|
31651
31489
|
handleMarkerChange(index, marker) {
|
|
31652
31490
|
const {
|
|
31653
31491
|
markers,
|
|
@@ -31666,32 +31504,25 @@ class LabelImage extends React.Component {
|
|
|
31666
31504
|
markers: updatedMarkers
|
|
31667
31505
|
});
|
|
31668
31506
|
}
|
|
31669
|
-
activateMarker(index) {
|
|
31507
|
+
activateMarker(index, opened) {
|
|
31508
|
+
var _this$props$analytics;
|
|
31509
|
+
(_this$props$analytics = this.props.analytics) == null || _this$props$analytics.onAnalyticsEvent({
|
|
31510
|
+
type: "perseus:label-image:marker-interacted-with",
|
|
31511
|
+
payload: null
|
|
31512
|
+
});
|
|
31670
31513
|
const {
|
|
31671
31514
|
activeMarkerIndex
|
|
31672
31515
|
} = this.state;
|
|
31673
|
-
|
|
31674
|
-
|
|
31675
|
-
if (activeMarkerIndex !== index) {
|
|
31516
|
+
// Set index of opened marker
|
|
31517
|
+
if (activeMarkerIndex !== index && opened) {
|
|
31676
31518
|
this.setState({
|
|
31677
31519
|
activeMarkerIndex: index,
|
|
31678
31520
|
markersInteracted: true
|
|
31679
|
-
}, () => {
|
|
31680
|
-
// A delay is required to allow answer choices to first render
|
|
31681
|
-
// before trying to set focus on the first choice.
|
|
31682
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API
|
|
31683
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
31684
|
-
setTimeout(() => {
|
|
31685
|
-
if (this._answerChoices) {
|
|
31686
|
-
this._answerChoices.focusAnswer();
|
|
31687
|
-
}
|
|
31688
|
-
}, 100);
|
|
31689
31521
|
});
|
|
31690
31522
|
} else {
|
|
31691
|
-
|
|
31692
|
-
|
|
31693
|
-
|
|
31694
|
-
this.dismissMarkerPopup();
|
|
31523
|
+
this.setState({
|
|
31524
|
+
activeMarkerIndex: -1
|
|
31525
|
+
});
|
|
31695
31526
|
}
|
|
31696
31527
|
}
|
|
31697
31528
|
handleMarkerKeyDown(index, e) {
|
|
@@ -31739,8 +31570,7 @@ class LabelImage extends React.Component {
|
|
|
31739
31570
|
handleAnswerChoicesChangeForMarker(index, selection) {
|
|
31740
31571
|
const {
|
|
31741
31572
|
choices,
|
|
31742
|
-
markers
|
|
31743
|
-
multipleAnswers
|
|
31573
|
+
markers
|
|
31744
31574
|
} = this.props;
|
|
31745
31575
|
|
|
31746
31576
|
// Compile the user selected answer choices.
|
|
@@ -31748,36 +31578,6 @@ class LabelImage extends React.Component {
|
|
|
31748
31578
|
this.handleMarkerChange(index, _extends({}, markers[index], {
|
|
31749
31579
|
selected: selected.length ? selected : undefined
|
|
31750
31580
|
}));
|
|
31751
|
-
if (!multipleAnswers) {
|
|
31752
|
-
this.dismissMarkerPopup();
|
|
31753
|
-
}
|
|
31754
|
-
}
|
|
31755
|
-
renderAnswerChoicesForMarker(index, marker) {
|
|
31756
|
-
const {
|
|
31757
|
-
choices,
|
|
31758
|
-
multipleAnswers
|
|
31759
|
-
} = this.props;
|
|
31760
|
-
|
|
31761
|
-
// The user selected answer choices.
|
|
31762
|
-
const selected = marker.selected;
|
|
31763
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
31764
|
-
className: classNames("perseus-label-image-widget-answer-choices", css(styles$f.scrollableChoices))
|
|
31765
|
-
}, /*#__PURE__*/React.createElement(AnswerChoices, {
|
|
31766
|
-
choices: choices.map(choice => ({
|
|
31767
|
-
content: choice,
|
|
31768
|
-
checked: selected ? selected.includes(choice) : false
|
|
31769
|
-
})),
|
|
31770
|
-
multipleSelect: multipleAnswers,
|
|
31771
|
-
onChange: selection => {
|
|
31772
|
-
var _this$props$analytics;
|
|
31773
|
-
(_this$props$analytics = this.props.analytics) == null || _this$props$analytics.onAnalyticsEvent({
|
|
31774
|
-
type: "perseus:label-image:choiced-interacted-with",
|
|
31775
|
-
payload: null
|
|
31776
|
-
});
|
|
31777
|
-
this.handleAnswerChoicesChangeForMarker(index, selection);
|
|
31778
|
-
},
|
|
31779
|
-
ref: node => this._answerChoices = node
|
|
31780
|
-
}));
|
|
31781
31581
|
}
|
|
31782
31582
|
renderMarkers() {
|
|
31783
31583
|
const {
|
|
@@ -31792,41 +31592,6 @@ class LabelImage extends React.Component {
|
|
|
31792
31592
|
|
|
31793
31593
|
// Render all markers for widget.
|
|
31794
31594
|
return markers.map((marker, index) => {
|
|
31795
|
-
const score = LabelImage.gradeMarker(marker);
|
|
31796
|
-
// Once the question is answered, show markers
|
|
31797
|
-
// with correct answers, otherwise passthrough
|
|
31798
|
-
// the correctness state.
|
|
31799
|
-
const showCorrectness = questionCompleted && score.hasAnswers && score.isCorrect ? "correct" : marker.showCorrectness;
|
|
31800
|
-
const element = /*#__PURE__*/React.createElement(Marker, _extends({}, marker, {
|
|
31801
|
-
showCorrectness: showCorrectness,
|
|
31802
|
-
showSelected: index === activeMarkerIndex,
|
|
31803
|
-
showPulsate: !markersInteracted,
|
|
31804
|
-
key: `${marker.x}.${marker.y}`,
|
|
31805
|
-
onClick: () => {
|
|
31806
|
-
var _this$props$analytics2;
|
|
31807
|
-
(_this$props$analytics2 = this.props.analytics) == null || _this$props$analytics2.onAnalyticsEvent({
|
|
31808
|
-
type: "perseus:label-image:marker-interacted-with",
|
|
31809
|
-
payload: null
|
|
31810
|
-
});
|
|
31811
|
-
this.activateMarker(index);
|
|
31812
|
-
},
|
|
31813
|
-
onKeyDown: e => this.handleMarkerKeyDown(index, e),
|
|
31814
|
-
ref: node => this._markers[index] = node,
|
|
31815
|
-
focused: index === this.state.focusedMarkerIndex,
|
|
31816
|
-
onFocus: () => {
|
|
31817
|
-
this.setState({
|
|
31818
|
-
focusedMarkerIndex: index
|
|
31819
|
-
});
|
|
31820
|
-
},
|
|
31821
|
-
onBlur: () => {
|
|
31822
|
-
if (index === this.state.focusedMarkerIndex) {
|
|
31823
|
-
this.setState({
|
|
31824
|
-
focusedMarkerIndex: -1
|
|
31825
|
-
});
|
|
31826
|
-
}
|
|
31827
|
-
}
|
|
31828
|
-
}));
|
|
31829
|
-
|
|
31830
31595
|
// Determine whether page is rendered in a narrow browser window.
|
|
31831
31596
|
const isNarrowPage = window.matchMedia(mediaQueries.xsOrSmaller.replace("@media ", "")).matches;
|
|
31832
31597
|
|
|
@@ -31854,40 +31619,72 @@ class LabelImage extends React.Component {
|
|
|
31854
31619
|
bottom: "top"
|
|
31855
31620
|
}[markerPosition];
|
|
31856
31621
|
}
|
|
31857
|
-
const
|
|
31858
|
-
|
|
31859
|
-
|
|
31860
|
-
|
|
31622
|
+
const score = LabelImage.gradeMarker(marker);
|
|
31623
|
+
// Once the question is answered, show markers
|
|
31624
|
+
// with correct answers, otherwise passthrough
|
|
31625
|
+
// the correctness state.
|
|
31626
|
+
const showCorrectness = questionCompleted && score.hasAnswers && score.isCorrect ? "correct" : marker.showCorrectness;
|
|
31861
31627
|
|
|
31628
|
+
// Disable marker interaction once the question is answered correctly.
|
|
31629
|
+
const disabled = showCorrectness === "correct";
|
|
31862
31630
|
const adjustPillDistance = {
|
|
31863
|
-
[`margin${markerPosition.charAt(0).toUpperCase() + markerPosition.slice(1)}`]:
|
|
31631
|
+
[`margin${markerPosition.charAt(0).toUpperCase() + markerPosition.slice(1)}`]: 10 // move pill further from marker
|
|
31864
31632
|
};
|
|
31865
31633
|
|
|
31866
|
-
const
|
|
31867
|
-
|
|
31868
|
-
|
|
31869
|
-
|
|
31870
|
-
|
|
31871
|
-
|
|
31872
|
-
|
|
31873
|
-
|
|
31874
|
-
|
|
31875
|
-
|
|
31876
|
-
|
|
31877
|
-
|
|
31878
|
-
|
|
31879
|
-
|
|
31880
|
-
|
|
31881
|
-
|
|
31882
|
-
|
|
31883
|
-
|
|
31884
|
-
|
|
31885
|
-
|
|
31886
|
-
|
|
31887
|
-
|
|
31888
|
-
|
|
31889
|
-
|
|
31890
|
-
|
|
31634
|
+
const answerChoicesActive = index === activeMarkerIndex;
|
|
31635
|
+
const showAnswerChoice = marker.selected && !answerChoicesActive && !this.state.hideAnswers;
|
|
31636
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
31637
|
+
style: {
|
|
31638
|
+
position: "absolute",
|
|
31639
|
+
left: `${marker.x}%`,
|
|
31640
|
+
top: `${marker.y}%`,
|
|
31641
|
+
// reset to allow child (answer pill) to control z-index
|
|
31642
|
+
zIndex: "unset"
|
|
31643
|
+
}
|
|
31644
|
+
}, /*#__PURE__*/React.createElement(AnswerChoices, {
|
|
31645
|
+
key: `answers-${marker.x}.${marker.y}`,
|
|
31646
|
+
choices: this.props.choices.map(choice => ({
|
|
31647
|
+
content: choice,
|
|
31648
|
+
checked: marker.selected ? marker.selected.includes(choice) : false
|
|
31649
|
+
})),
|
|
31650
|
+
multipleSelect: this.props.multipleAnswers,
|
|
31651
|
+
onChange: selection => {
|
|
31652
|
+
var _this$props$analytics2;
|
|
31653
|
+
(_this$props$analytics2 = this.props.analytics) == null || _this$props$analytics2.onAnalyticsEvent({
|
|
31654
|
+
type: "perseus:label-image:choiced-interacted-with",
|
|
31655
|
+
payload: null
|
|
31656
|
+
});
|
|
31657
|
+
this.handleAnswerChoicesChangeForMarker(index, selection);
|
|
31658
|
+
},
|
|
31659
|
+
onToggle: opened => this.activateMarker(index, opened)
|
|
31660
|
+
// cannot change answer choices once question is answered
|
|
31661
|
+
,
|
|
31662
|
+
disabled: disabled,
|
|
31663
|
+
opener: ({
|
|
31664
|
+
opened,
|
|
31665
|
+
text
|
|
31666
|
+
}) => /*#__PURE__*/React.createElement(Clickable, {
|
|
31667
|
+
role: "button",
|
|
31668
|
+
key: `marker-${marker.x}.${marker.y}`,
|
|
31669
|
+
"aria-label":
|
|
31670
|
+
// already translated in: /widgets/graded-group.tsx
|
|
31671
|
+
showCorrectness === "correct" ? i18n._("Correct!") : marker.label
|
|
31672
|
+
}, ({
|
|
31673
|
+
hovered,
|
|
31674
|
+
focused,
|
|
31675
|
+
pressed
|
|
31676
|
+
}) => /*#__PURE__*/React.createElement(Marker, _extends({}, marker, {
|
|
31677
|
+
showCorrectness: showCorrectness,
|
|
31678
|
+
showSelected: opened,
|
|
31679
|
+
showPulsate: !markersInteracted,
|
|
31680
|
+
ref: node => this._markers[index] = node,
|
|
31681
|
+
showAnswer: showAnswerChoice,
|
|
31682
|
+
answerSide: side,
|
|
31683
|
+
answerStyles: adjustPillDistance,
|
|
31684
|
+
analytics: this.props.analytics,
|
|
31685
|
+
focused: focused || pressed,
|
|
31686
|
+
hovered: hovered
|
|
31687
|
+
})))
|
|
31891
31688
|
}));
|
|
31892
31689
|
});
|
|
31893
31690
|
}
|
|
@@ -32003,18 +31800,6 @@ const styles$f = StyleSheet.create({
|
|
|
32003
31800
|
},
|
|
32004
31801
|
imageInteractionDisabled: {
|
|
32005
31802
|
pointerEvents: "none"
|
|
32006
|
-
},
|
|
32007
|
-
scrollableChoices: {
|
|
32008
|
-
paddingTop: 8,
|
|
32009
|
-
paddingBottom: 8,
|
|
32010
|
-
// Enable scroll for answer choices within popup on mobile phones.
|
|
32011
|
-
[mediaQueries.xsOrSmaller]: {
|
|
32012
|
-
maxHeight: 250,
|
|
32013
|
-
overflowY: "auto"
|
|
32014
|
-
}
|
|
32015
|
-
},
|
|
32016
|
-
choicesPopover: {
|
|
32017
|
-
padding: 0
|
|
32018
31803
|
}
|
|
32019
31804
|
});
|
|
32020
31805
|
const LabelImageWithDependencies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
@@ -44164,7 +43949,7 @@ var Video$1 = {
|
|
|
44164
43949
|
};
|
|
44165
43950
|
|
|
44166
43951
|
/* eslint-disable import/no-named-as-default */
|
|
44167
|
-
var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1, Transformer$1, Unit, Video$1];
|
|
43952
|
+
var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1, Transformer$1, Unit, Video$1, DeprecatedStandin];
|
|
44168
43953
|
|
|
44169
43954
|
/**
|
|
44170
43955
|
* This should be called by all clients, specifying whether extra widgets are
|
|
@@ -44179,6 +43964,11 @@ const init = function init(options) {
|
|
|
44179
43964
|
registerWidgets(basicWidgets);
|
|
44180
43965
|
registerWidgets(extraWidgets);
|
|
44181
43966
|
|
|
43967
|
+
// This section replaces widgets
|
|
43968
|
+
// When it's time to replace the transformer widget
|
|
43969
|
+
// uncomment this line
|
|
43970
|
+
// Widgets.replaceWidget("transformer", "always-correct");
|
|
43971
|
+
|
|
44182
43972
|
// Pass skipMathJax: true if MathJax is already loaded and configured.
|
|
44183
43973
|
const skipMathJax = options.skipMathJax;
|
|
44184
43974
|
if (skipMathJax) {
|
|
@@ -44203,7 +43993,7 @@ const init = function init(options) {
|
|
|
44203
43993
|
|
|
44204
43994
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44205
43995
|
const libName = "@khanacademy/perseus";
|
|
44206
|
-
const libVersion = "17.6.
|
|
43996
|
+
const libVersion = "17.6.2";
|
|
44207
43997
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44208
43998
|
|
|
44209
43999
|
const apiVersion = {
|
|
@@ -45651,6 +45441,8 @@ const ItemExtras = [
|
|
|
45651
45441
|
|
|
45652
45442
|
// prettier-ignore
|
|
45653
45443
|
|
|
45444
|
+
//prettier-ignore
|
|
45445
|
+
|
|
45654
45446
|
// A background image applied to various widgets.
|
|
45655
45447
|
|
|
45656
45448
|
const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
|
|
@@ -46781,6 +46573,10 @@ function violatingWidgets(itemData) {
|
|
|
46781
46573
|
*/
|
|
46782
46574
|
const registerAllWidgetsForTesting = () => {
|
|
46783
46575
|
registerWidgets(allWidgets);
|
|
46576
|
+
|
|
46577
|
+
// When it's time to replace the transformer widget
|
|
46578
|
+
// uncomment this line
|
|
46579
|
+
// Widgets.replaceWidget("transformer", "deprecated-standin");
|
|
46784
46580
|
};
|
|
46785
46581
|
|
|
46786
46582
|
const EditorJsonify = {
|