@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/index.js
CHANGED
|
@@ -26,12 +26,13 @@ var pureMarkdown = require('@khanacademy/pure-markdown');
|
|
|
26
26
|
var wonderBlocksForm = require('@khanacademy/wonder-blocks-form');
|
|
27
27
|
var Button = require('@khanacademy/wonder-blocks-button');
|
|
28
28
|
var wonderBlocksLayout = require('@khanacademy/wonder-blocks-layout');
|
|
29
|
+
var Banner = require('@khanacademy/wonder-blocks-banner');
|
|
29
30
|
var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
|
|
30
31
|
var debounce = require('lodash.debounce');
|
|
31
|
-
var Pill = require('@khanacademy/wonder-blocks-pill');
|
|
32
|
-
var reactPopper = require('react-popper');
|
|
33
32
|
var Switch = require('@khanacademy/wonder-blocks-switch');
|
|
34
33
|
var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
|
|
34
|
+
var Pill = require('@khanacademy/wonder-blocks-pill');
|
|
35
|
+
var reactPopper = require('react-popper');
|
|
35
36
|
var createReactClass = require('create-react-class');
|
|
36
37
|
var Link = require('@khanacademy/wonder-blocks-link');
|
|
37
38
|
var perseusCore = require('@khanacademy/perseus-core');
|
|
@@ -62,6 +63,7 @@ var i18n__namespace = /*#__PURE__*/_interopNamespace(i18n);
|
|
|
62
63
|
var Tooltip__default = /*#__PURE__*/_interopDefaultLegacy(Tooltip$1);
|
|
63
64
|
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
|
|
64
65
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
66
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
65
67
|
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
66
68
|
var Clickable__default = /*#__PURE__*/_interopDefaultLegacy(Clickable);
|
|
67
69
|
var Color__default = /*#__PURE__*/_interopDefaultLegacy(Color);
|
|
@@ -72,9 +74,10 @@ var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
|
|
|
72
74
|
var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
|
|
73
75
|
var SimpleMarkdown__default = /*#__PURE__*/_interopDefaultLegacy(SimpleMarkdown);
|
|
74
76
|
var Button__default = /*#__PURE__*/_interopDefaultLegacy(Button);
|
|
77
|
+
var Banner__default = /*#__PURE__*/_interopDefaultLegacy(Banner);
|
|
75
78
|
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
|
|
76
|
-
var Pill__default = /*#__PURE__*/_interopDefaultLegacy(Pill);
|
|
77
79
|
var Switch__default = /*#__PURE__*/_interopDefaultLegacy(Switch);
|
|
80
|
+
var Pill__default = /*#__PURE__*/_interopDefaultLegacy(Pill);
|
|
78
81
|
var createReactClass__default = /*#__PURE__*/_interopDefaultLegacy(createReactClass);
|
|
79
82
|
var Link__default = /*#__PURE__*/_interopDefaultLegacy(Link);
|
|
80
83
|
|
|
@@ -274,7 +277,7 @@ class MathInput extends React__namespace.Component {
|
|
|
274
277
|
className = className + " " + this.props.className;
|
|
275
278
|
}
|
|
276
279
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
277
|
-
style: [styles$
|
|
280
|
+
style: [styles$B.outerWrapper, this.state.focused && styles$B.wrapperFocused, this.props.hasError && styles$B.wrapperError]
|
|
278
281
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
279
282
|
style: {
|
|
280
283
|
display: "flex",
|
|
@@ -301,7 +304,7 @@ class MathInput extends React__namespace.Component {
|
|
|
301
304
|
dismissEnabled: true,
|
|
302
305
|
content: () => /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
303
306
|
closeButtonVisible: true,
|
|
304
|
-
style: styles$
|
|
307
|
+
style: styles$B.popoverContent
|
|
305
308
|
}, /*#__PURE__*/React__namespace.createElement(mathInput.DesktopKeypad, _extends({
|
|
306
309
|
onAnalyticsEvent: this.props.analytics.onAnalyticsEvent,
|
|
307
310
|
extraKeys: this.props.extraKeys,
|
|
@@ -341,9 +344,9 @@ const MathInputIcon = _ref => {
|
|
|
341
344
|
color = Color__default["default"].offBlack;
|
|
342
345
|
break;
|
|
343
346
|
}
|
|
344
|
-
const dynamicClass = active || focused ? styles$
|
|
347
|
+
const dynamicClass = active || focused ? styles$B.iconActive : styles$B.iconInactive;
|
|
345
348
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
346
|
-
style: [styles$
|
|
349
|
+
style: [styles$B.iconContainer, dynamicClass]
|
|
347
350
|
}, /*#__PURE__*/React__namespace.createElement("svg", {
|
|
348
351
|
xmlns: "http://www.w3.org/2000/svg",
|
|
349
352
|
width: "16",
|
|
@@ -388,7 +391,7 @@ const inputFocused = {
|
|
|
388
391
|
borderColor: Color__default["default"].blue,
|
|
389
392
|
margin: -1
|
|
390
393
|
};
|
|
391
|
-
const styles$
|
|
394
|
+
const styles$B = aphrodite.StyleSheet.create({
|
|
392
395
|
iconContainer: {
|
|
393
396
|
display: "flex",
|
|
394
397
|
justifyContent: "center",
|
|
@@ -17624,33 +17627,33 @@ class Lint extends React__namespace.Component {
|
|
|
17624
17627
|
let warningText;
|
|
17625
17628
|
let warningTextStyle;
|
|
17626
17629
|
if (this.props.severity === Severity.Error) {
|
|
17627
|
-
severityStyle = styles$
|
|
17630
|
+
severityStyle = styles$A.indicatorError;
|
|
17628
17631
|
warningText = "Error";
|
|
17629
|
-
warningTextStyle = styles$
|
|
17632
|
+
warningTextStyle = styles$A.publishBlockingError;
|
|
17630
17633
|
} else if (this.props.severity === Severity.Warning) {
|
|
17631
|
-
severityStyle = styles$
|
|
17634
|
+
severityStyle = styles$A.indicatorWarning;
|
|
17632
17635
|
warningText = "Warning";
|
|
17633
|
-
warningTextStyle = styles$
|
|
17636
|
+
warningTextStyle = styles$A.warning;
|
|
17634
17637
|
} else {
|
|
17635
|
-
severityStyle = styles$
|
|
17638
|
+
severityStyle = styles$A.indicatorGuideline;
|
|
17636
17639
|
warningText = "Recommendation";
|
|
17637
|
-
warningTextStyle = styles$
|
|
17640
|
+
warningTextStyle = styles$A.warning;
|
|
17638
17641
|
}
|
|
17639
17642
|
return /*#__PURE__*/React__namespace.createElement("a", {
|
|
17640
17643
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
17641
17644
|
target: "lint-help-window",
|
|
17642
17645
|
className: aphrodite.css(style)
|
|
17643
17646
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
17644
|
-
className: aphrodite.css(styles$
|
|
17647
|
+
className: aphrodite.css(styles$A.indicator, severityStyle)
|
|
17645
17648
|
}, this.props.severity === 1 && /*#__PURE__*/React__namespace.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
17646
|
-
className: aphrodite.css(styles$
|
|
17649
|
+
className: aphrodite.css(styles$A.tooltip, tooltipAbove && styles$A.tooltipAbove)
|
|
17647
17650
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React__namespace.createElement("p", {
|
|
17648
17651
|
key: i,
|
|
17649
|
-
className: aphrodite.css(styles$
|
|
17652
|
+
className: aphrodite.css(styles$A.tooltipParagraph)
|
|
17650
17653
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
17651
17654
|
className: aphrodite.css(warningTextStyle)
|
|
17652
17655
|
}, warningText, ":", " "), m)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
17653
|
-
className: aphrodite.css(styles$
|
|
17656
|
+
className: aphrodite.css(styles$A.tail, tooltipAbove && styles$A.tailAbove)
|
|
17654
17657
|
})));
|
|
17655
17658
|
};
|
|
17656
17659
|
|
|
@@ -17678,20 +17681,20 @@ class Lint extends React__namespace.Component {
|
|
|
17678
17681
|
}
|
|
17679
17682
|
if (blockHighlight) {
|
|
17680
17683
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
17681
|
-
className: aphrodite.css(styles$
|
|
17682
|
-
}, this.renderLink(styles$
|
|
17684
|
+
className: aphrodite.css(styles$A.lintContainer, styles$A.lintContainerBlock)
|
|
17685
|
+
}, this.renderLink(styles$A.radioWidgetHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
17683
17686
|
}
|
|
17684
17687
|
if (inline) {
|
|
17685
17688
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
17686
|
-
className: aphrodite.css(styles$
|
|
17687
|
-
}, this.renderLink(styles$
|
|
17689
|
+
className: aphrodite.css(styles$A.lintContainer)
|
|
17690
|
+
}, this.renderLink(styles$A.inlineHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
17688
17691
|
}
|
|
17689
17692
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
17690
|
-
className: aphrodite.css(styles$
|
|
17691
|
-
}, this.renderLink(styles$
|
|
17693
|
+
className: aphrodite.css(styles$A.lintContainer)
|
|
17694
|
+
}, this.renderLink(styles$A.hoverTarget), /*#__PURE__*/React__namespace.createElement("div", null, children));
|
|
17692
17695
|
}
|
|
17693
17696
|
}
|
|
17694
|
-
const styles$
|
|
17697
|
+
const styles$A = aphrodite.StyleSheet.create({
|
|
17695
17698
|
// This is the class of the outermost element.
|
|
17696
17699
|
// We use relative positioning so that the lint indicator can be
|
|
17697
17700
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -18462,6 +18465,27 @@ const registerWidgets = widgets => {
|
|
|
18462
18465
|
});
|
|
18463
18466
|
validateAlignments();
|
|
18464
18467
|
};
|
|
18468
|
+
|
|
18469
|
+
/**
|
|
18470
|
+
*
|
|
18471
|
+
* @param name - the widget that you are trying to replace
|
|
18472
|
+
* @param replacementName - the name of the widget that takes its place
|
|
18473
|
+
*
|
|
18474
|
+
* e.g. replaceWidget("transformer", "always-correct") will make it so the
|
|
18475
|
+
* transformer widget is replaced by the always correct widget
|
|
18476
|
+
*/
|
|
18477
|
+
const replaceWidget = (name, replacementName) => {
|
|
18478
|
+
const substituteWidget = widgets[replacementName];
|
|
18479
|
+
if (!substituteWidget && Log) {
|
|
18480
|
+
const errorMsg = `Failed to replace ${name} with ${replacementName}`;
|
|
18481
|
+
Log.error(errorMsg, Errors.Internal);
|
|
18482
|
+
return;
|
|
18483
|
+
}
|
|
18484
|
+
registerWidget(name, substituteWidget);
|
|
18485
|
+
if (Log) {
|
|
18486
|
+
Log.log(`INFO: Replacing widget ${name} with ${replacementName}`);
|
|
18487
|
+
}
|
|
18488
|
+
};
|
|
18465
18489
|
const registerEditors = editorsToRegister => {
|
|
18466
18490
|
editorsToRegister.forEach(editor => {
|
|
18467
18491
|
if (!editor.widgetName) {
|
|
@@ -18780,6 +18804,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
18780
18804
|
__proto__: null,
|
|
18781
18805
|
registerWidget: registerWidget,
|
|
18782
18806
|
registerWidgets: registerWidgets,
|
|
18807
|
+
replaceWidget: replaceWidget,
|
|
18783
18808
|
registerEditors: registerEditors,
|
|
18784
18809
|
getWidget: getWidget,
|
|
18785
18810
|
getEditor: getEditor,
|
|
@@ -19740,7 +19765,7 @@ class Renderer extends React__namespace.Component {
|
|
|
19740
19765
|
};
|
|
19741
19766
|
const mobileInnerStyle = {
|
|
19742
19767
|
...innerStyle,
|
|
19743
|
-
...styles$
|
|
19768
|
+
...styles$z.mobileZoomableParentFix
|
|
19744
19769
|
};
|
|
19745
19770
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
19746
19771
|
key: state.key,
|
|
@@ -19877,7 +19902,7 @@ class Renderer extends React__namespace.Component {
|
|
|
19877
19902
|
};
|
|
19878
19903
|
const mobileInnerStyle = {
|
|
19879
19904
|
...innerStyle,
|
|
19880
|
-
...styles$
|
|
19905
|
+
...styles$z.mobileZoomableParentFix
|
|
19881
19906
|
};
|
|
19882
19907
|
const wrappedOutput = /*#__PURE__*/React__namespace.createElement("div", {
|
|
19883
19908
|
style: {
|
|
@@ -20385,7 +20410,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20385
20410
|
return this.lastRenderedMarkdown;
|
|
20386
20411
|
}
|
|
20387
20412
|
}
|
|
20388
|
-
const styles$
|
|
20413
|
+
const styles$z = {
|
|
20389
20414
|
mobileZoomableParentFix: {
|
|
20390
20415
|
// NOTE(abdul): There is an issue where transform animations will
|
|
20391
20416
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -21320,10 +21345,10 @@ class InputNumber extends React__namespace.Component {
|
|
|
21320
21345
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
21321
21346
|
// you modify this, double-check if you also need to modify that
|
|
21322
21347
|
// component.
|
|
21323
|
-
const inputStyles = [styles$
|
|
21348
|
+
const inputStyles = [styles$y.default, this.props.size === "small" ? styles$y.small : null, this.props.rightAlign ? styles$y.rightAlign : styles$y.leftAlign];
|
|
21324
21349
|
// Unanswered
|
|
21325
21350
|
if (rubric && !this.props.currentValue) {
|
|
21326
|
-
inputStyles.push(styles$
|
|
21351
|
+
inputStyles.push(styles$y.answerStateUnanswered);
|
|
21327
21352
|
}
|
|
21328
21353
|
return /*#__PURE__*/React__namespace.createElement(InputWithExamples
|
|
21329
21354
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -21471,7 +21496,7 @@ class InputNumber extends React__namespace.Component {
|
|
|
21471
21496
|
return answerString;
|
|
21472
21497
|
}
|
|
21473
21498
|
}
|
|
21474
|
-
const styles$
|
|
21499
|
+
const styles$y = aphrodite.StyleSheet.create({
|
|
21475
21500
|
default: {
|
|
21476
21501
|
width: 80,
|
|
21477
21502
|
height: "auto"
|
|
@@ -22469,7 +22494,7 @@ const FocusRing = function (props) {
|
|
|
22469
22494
|
};
|
|
22470
22495
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
22471
22496
|
"data-test-id": "focus-ring",
|
|
22472
|
-
className: aphrodite.css(styles$
|
|
22497
|
+
className: aphrodite.css(styles$x.ring),
|
|
22473
22498
|
style: style
|
|
22474
22499
|
}, children);
|
|
22475
22500
|
};
|
|
@@ -22478,7 +22503,7 @@ FocusRing.defaultProps = {
|
|
|
22478
22503
|
color: kaGreen$1,
|
|
22479
22504
|
multipleSelect: false
|
|
22480
22505
|
};
|
|
22481
|
-
const styles$
|
|
22506
|
+
const styles$x = aphrodite.StyleSheet.create({
|
|
22482
22507
|
ring: {
|
|
22483
22508
|
margin: "auto",
|
|
22484
22509
|
display: "inline-block",
|
|
@@ -22515,7 +22540,7 @@ function getChoiceLetter(pos) {
|
|
|
22515
22540
|
}
|
|
22516
22541
|
|
|
22517
22542
|
const CHOICE_ICON_SIZE = 24;
|
|
22518
|
-
const styles$
|
|
22543
|
+
const styles$w = aphrodite.StyleSheet.create({
|
|
22519
22544
|
iconWrapper: {
|
|
22520
22545
|
display: "inline-block",
|
|
22521
22546
|
position: "relative"
|
|
@@ -22538,7 +22563,7 @@ const CrossOutLine = function (props) {
|
|
|
22538
22563
|
width: CROSS_OUT_LINE_SIZE,
|
|
22539
22564
|
height: CROSS_OUT_LINE_SIZE,
|
|
22540
22565
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
22541
|
-
className: aphrodite.css(styles$
|
|
22566
|
+
className: aphrodite.css(styles$v.crossOutLine),
|
|
22542
22567
|
"data-test-id": "choice-icon__cross-out-line"
|
|
22543
22568
|
}, /*#__PURE__*/React__namespace.createElement("line", {
|
|
22544
22569
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -22553,7 +22578,7 @@ const CrossOutLine = function (props) {
|
|
|
22553
22578
|
strokeLinecap: "round"
|
|
22554
22579
|
}));
|
|
22555
22580
|
};
|
|
22556
|
-
const styles$
|
|
22581
|
+
const styles$v = aphrodite.StyleSheet.create({
|
|
22557
22582
|
crossOutLine: {
|
|
22558
22583
|
// Center the icon within the container.
|
|
22559
22584
|
position: "absolute",
|
|
@@ -22634,7 +22659,7 @@ const ChoiceIcon = function (props) {
|
|
|
22634
22659
|
} = props;
|
|
22635
22660
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
22636
22661
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
22637
|
-
className: aphrodite.css(styles$
|
|
22662
|
+
className: aphrodite.css(styles$w.iconWrapper)
|
|
22638
22663
|
}, /*#__PURE__*/React__namespace.createElement(FocusRing, {
|
|
22639
22664
|
color: Color__default["default"].blue,
|
|
22640
22665
|
visible: focused || hovered,
|
|
@@ -22643,13 +22668,13 @@ const ChoiceIcon = function (props) {
|
|
|
22643
22668
|
// @ts-expect-error - TS2322 - Type '{ backgroundColor: string | null | undefined; borderColor: string; color: string; borderRadius: number; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
22644
22669
|
style: dynamicStyles,
|
|
22645
22670
|
"data-test-id": "choice-icon__library-choice-icon",
|
|
22646
|
-
className: aphrodite.css(styles$
|
|
22671
|
+
className: aphrodite.css(styles$u.circle, showCorrectness && correct && styles$u.circleCorrect, showCorrectness && !correct && styles$u.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$u.circleIncorrectAnswered)
|
|
22647
22672
|
// used in BaseRadio editMode to check
|
|
22648
22673
|
// if we actually clicked on the radio icon
|
|
22649
22674
|
,
|
|
22650
22675
|
"data-is-radio-icon": true
|
|
22651
22676
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
22652
|
-
className: aphrodite.css(styles$
|
|
22677
|
+
className: aphrodite.css(styles$u.innerWrapper)
|
|
22653
22678
|
}, /*#__PURE__*/React__namespace.createElement(ChoiceInner, {
|
|
22654
22679
|
pos: pos,
|
|
22655
22680
|
showCorrectness: showCorrectness,
|
|
@@ -22658,7 +22683,7 @@ const ChoiceIcon = function (props) {
|
|
|
22658
22683
|
color: dynamicStyles.borderColor
|
|
22659
22684
|
}));
|
|
22660
22685
|
};
|
|
22661
|
-
const styles$
|
|
22686
|
+
const styles$u = aphrodite.StyleSheet.create({
|
|
22662
22687
|
innerWrapper: {
|
|
22663
22688
|
width: CHOICE_ICON_SIZE,
|
|
22664
22689
|
height: CHOICE_ICON_SIZE,
|
|
@@ -22750,19 +22775,19 @@ const OptionStatus = function (props) {
|
|
|
22750
22775
|
}
|
|
22751
22776
|
let textStyle;
|
|
22752
22777
|
if (correct) {
|
|
22753
|
-
textStyle = styles$
|
|
22778
|
+
textStyle = styles$t.correct;
|
|
22754
22779
|
} else {
|
|
22755
22780
|
if (checked || previouslyAnswered) {
|
|
22756
|
-
textStyle = styles$
|
|
22781
|
+
textStyle = styles$t.incorrectAnswered;
|
|
22757
22782
|
} else {
|
|
22758
|
-
textStyle = styles$
|
|
22783
|
+
textStyle = styles$t.incorrect;
|
|
22759
22784
|
}
|
|
22760
22785
|
}
|
|
22761
22786
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
22762
|
-
className: aphrodite.css(styles$
|
|
22787
|
+
className: aphrodite.css(styles$t.text, textStyle)
|
|
22763
22788
|
}, renderText(checked, correct, crossedOut));
|
|
22764
22789
|
};
|
|
22765
|
-
const styles$
|
|
22790
|
+
const styles$t = aphrodite.StyleSheet.create({
|
|
22766
22791
|
text: {
|
|
22767
22792
|
alignItems: "center",
|
|
22768
22793
|
display: "flex",
|
|
@@ -22836,8 +22861,8 @@ const Choice = function (props) {
|
|
|
22836
22861
|
crossedOut: updatedCrossedOut
|
|
22837
22862
|
});
|
|
22838
22863
|
}
|
|
22839
|
-
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$
|
|
22840
|
-
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$
|
|
22864
|
+
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$s.description));
|
|
22865
|
+
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$s.rationale));
|
|
22841
22866
|
|
|
22842
22867
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
22843
22868
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -23004,7 +23029,7 @@ const Choice = function (props) {
|
|
|
23004
23029
|
"data-test-id": `perseus-radio-rationale-content-${pos}`
|
|
23005
23030
|
}, rationale));
|
|
23006
23031
|
};
|
|
23007
|
-
const styles$
|
|
23032
|
+
const styles$s = aphrodite.StyleSheet.create({
|
|
23008
23033
|
description: {
|
|
23009
23034
|
display: "inline-block",
|
|
23010
23035
|
width: "100%"
|
|
@@ -23196,10 +23221,10 @@ const BaseRadio = function (props) {
|
|
|
23196
23221
|
const isMobile = apiOptions.isMobile;
|
|
23197
23222
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
23198
23223
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
23199
|
-
const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$
|
|
23200
|
-
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$
|
|
23224
|
+
const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$r.radio, styles$r.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$r.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$r.radioContainerLastHighlighted));
|
|
23225
|
+
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$r.instructions, isMobile && styles$r.instructionsMobile));
|
|
23201
23226
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect);
|
|
23202
|
-
const responsiveClassName = aphrodite.css(styles$
|
|
23227
|
+
const responsiveClassName = aphrodite.css(styles$r.responsiveFieldset);
|
|
23203
23228
|
const fieldset = /*#__PURE__*/React__namespace.createElement("fieldset", {
|
|
23204
23229
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
23205
23230
|
}, /*#__PURE__*/React__namespace.createElement("legend", {
|
|
@@ -23250,7 +23275,7 @@ const BaseRadio = function (props) {
|
|
|
23250
23275
|
const aphroditeClassName = checked => {
|
|
23251
23276
|
// Whether or not to show correctness borders
|
|
23252
23277
|
// for this choice and the next choice.
|
|
23253
|
-
return aphrodite.css(sharedStyles.aboveScratchpad, styles$
|
|
23278
|
+
return aphrodite.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);
|
|
23254
23279
|
};
|
|
23255
23280
|
|
|
23256
23281
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -23324,14 +23349,14 @@ const BaseRadio = function (props) {
|
|
|
23324
23349
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
23325
23350
|
// an issue especially on phones.
|
|
23326
23351
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23327
|
-
className: aphrodite.css(styles$
|
|
23352
|
+
className: aphrodite.css(styles$r.responsiveContainer)
|
|
23328
23353
|
}, fieldset);
|
|
23329
23354
|
};
|
|
23330
23355
|
BaseRadio.defaultProps = {
|
|
23331
23356
|
editMode: false,
|
|
23332
23357
|
multipleSelect: false
|
|
23333
23358
|
};
|
|
23334
|
-
const styles$
|
|
23359
|
+
const styles$r = aphrodite.StyleSheet.create({
|
|
23335
23360
|
instructions: {
|
|
23336
23361
|
display: "block",
|
|
23337
23362
|
color: gray17,
|
|
@@ -23990,9 +24015,9 @@ class Categorizer extends React__namespace.Component {
|
|
|
23990
24015
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
23991
24016
|
}
|
|
23992
24017
|
const table = /*#__PURE__*/React__namespace.createElement("table", {
|
|
23993
|
-
className: "categorizer-table " + aphrodite.css(styles$
|
|
24018
|
+
className: "categorizer-table " + aphrodite.css(styles$q.mobileTable)
|
|
23994
24019
|
}, /*#__PURE__*/React__namespace.createElement("thead", null, /*#__PURE__*/React__namespace.createElement("tr", null, /*#__PURE__*/React__namespace.createElement("td", {
|
|
23995
|
-
className: aphrodite.css(styles$
|
|
24020
|
+
className: aphrodite.css(styles$q.emptyHeaderCell)
|
|
23996
24021
|
}), this.props.categories.map((category, i) => {
|
|
23997
24022
|
// Array index is the correct key here, as that's
|
|
23998
24023
|
// how category grading actually works -- no way
|
|
@@ -24000,7 +24025,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24000
24025
|
// middle. (If we later add that, this should be
|
|
24001
24026
|
// fixed.)
|
|
24002
24027
|
return /*#__PURE__*/React__namespace.createElement("th", {
|
|
24003
|
-
className: aphrodite.css(styles$
|
|
24028
|
+
className: aphrodite.css(styles$q.header),
|
|
24004
24029
|
key: i
|
|
24005
24030
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
24006
24031
|
content: category,
|
|
@@ -24020,7 +24045,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24020
24045
|
})), self.props.categories.map((catName, catNum) => {
|
|
24021
24046
|
const selected = self.props.values[itemNum] === catNum;
|
|
24022
24047
|
return /*#__PURE__*/React__namespace.createElement("td", {
|
|
24023
|
-
className: "category " + aphrodite.css(styles$
|
|
24048
|
+
className: "category " + aphrodite.css(styles$q.cell),
|
|
24024
24049
|
key: catNum
|
|
24025
24050
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
24026
24051
|
className: ClassNames.INTERACTIVE,
|
|
@@ -24039,7 +24064,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24039
24064
|
onChange: this.onChange.bind(this, itemNum, catNum),
|
|
24040
24065
|
onClick: e => e.stopPropagation()
|
|
24041
24066
|
}), !isMobile && /*#__PURE__*/React__namespace.createElement("span", {
|
|
24042
|
-
className: aphrodite.css(styles$
|
|
24067
|
+
className: aphrodite.css(styles$q.radioSpan, selected && styles$q.checkedRadioSpan, this.props.static && selected && styles$q.staticCheckedRadioSpan)
|
|
24043
24068
|
}, selected ? /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircleThin))));
|
|
24044
24069
|
}));
|
|
24045
24070
|
/* eslint-enable max-len */
|
|
@@ -24051,7 +24076,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
24051
24076
|
"categorizer-container": true,
|
|
24052
24077
|
"static-mode": this.props.static
|
|
24053
24078
|
});
|
|
24054
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
24079
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$q.fullBleedContainer] : [];
|
|
24055
24080
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24056
24081
|
className: extraClassNames + " " + aphrodite.css(...inlineStyles)
|
|
24057
24082
|
}, table);
|
|
@@ -24100,7 +24125,7 @@ const pageMargin = 16;
|
|
|
24100
24125
|
|
|
24101
24126
|
// Stylesheets aren't directly testable
|
|
24102
24127
|
/* c8 ignore next */
|
|
24103
|
-
const styles$
|
|
24128
|
+
const styles$q = aphrodite.StyleSheet.create({
|
|
24104
24129
|
mobileTable: {
|
|
24105
24130
|
[mediaQueries.smOrSmaller]: {
|
|
24106
24131
|
minWidth: "auto"
|
|
@@ -24363,7 +24388,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
24363
24388
|
// creator "went wild".
|
|
24364
24389
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
24365
24390
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24366
|
-
className: aphrodite.css(styles$
|
|
24391
|
+
className: aphrodite.css(styles$p.widthOverride, styleContainer && styles$p.container)
|
|
24367
24392
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
24368
24393
|
sandbox: sandboxOptions,
|
|
24369
24394
|
src: url,
|
|
@@ -24373,7 +24398,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
24373
24398
|
}));
|
|
24374
24399
|
}
|
|
24375
24400
|
}
|
|
24376
|
-
const styles$
|
|
24401
|
+
const styles$p = aphrodite.StyleSheet.create({
|
|
24377
24402
|
// Override the inherited width from the perseus paragraph class
|
|
24378
24403
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
24379
24404
|
widthOverride: {
|
|
@@ -24421,7 +24446,7 @@ class Definition extends React__namespace.Component {
|
|
|
24421
24446
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.Popover, {
|
|
24422
24447
|
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
24423
24448
|
color: "white",
|
|
24424
|
-
style: styles$
|
|
24449
|
+
style: styles$o.tooltipBody,
|
|
24425
24450
|
closeButtonVisible: true
|
|
24426
24451
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
24427
24452
|
apiOptions: this.props.apiOptions,
|
|
@@ -24452,7 +24477,7 @@ class Definition extends React__namespace.Component {
|
|
|
24452
24477
|
});
|
|
24453
24478
|
}
|
|
24454
24479
|
}
|
|
24455
|
-
const styles$
|
|
24480
|
+
const styles$o = {
|
|
24456
24481
|
tooltipBody: {
|
|
24457
24482
|
color: Color__default["default"].offBlack,
|
|
24458
24483
|
fontSize: 20,
|
|
@@ -24469,6 +24494,44 @@ var Definition$1 = {
|
|
|
24469
24494
|
transform: x => x
|
|
24470
24495
|
};
|
|
24471
24496
|
|
|
24497
|
+
// The props are type `any` on purpose so that this can receive props
|
|
24498
|
+
// from any deprecated widget
|
|
24499
|
+
class AutoCorrect extends React__default["default"].Component {
|
|
24500
|
+
static validate(userInput, rubric) {
|
|
24501
|
+
// Since this mean to replace an existing widget the learner
|
|
24502
|
+
// WILL earn points for this widget
|
|
24503
|
+
return {
|
|
24504
|
+
type: "points",
|
|
24505
|
+
earned: 1,
|
|
24506
|
+
total: 1,
|
|
24507
|
+
message: null
|
|
24508
|
+
};
|
|
24509
|
+
}
|
|
24510
|
+
getUserInput = () => {
|
|
24511
|
+
return {};
|
|
24512
|
+
};
|
|
24513
|
+
simpleValidate = rubric => {
|
|
24514
|
+
return AutoCorrect.validate(this.getUserInput(), rubric);
|
|
24515
|
+
};
|
|
24516
|
+
render() {
|
|
24517
|
+
return /*#__PURE__*/React__default["default"].createElement("div", {
|
|
24518
|
+
style: {
|
|
24519
|
+
paddingTop: 8,
|
|
24520
|
+
paddingBottom: 8
|
|
24521
|
+
}
|
|
24522
|
+
}, /*#__PURE__*/React__default["default"].createElement(Banner__default["default"], {
|
|
24523
|
+
text: i18n__namespace._("This part of the question is no-longer available. You will not be graded on this part."),
|
|
24524
|
+
kind: "warning",
|
|
24525
|
+
layout: "full-width"
|
|
24526
|
+
}));
|
|
24527
|
+
}
|
|
24528
|
+
}
|
|
24529
|
+
var DeprecatedStandin = {
|
|
24530
|
+
name: "deprecated-standin",
|
|
24531
|
+
displayName: "Deprecated Standin",
|
|
24532
|
+
widget: AutoCorrect
|
|
24533
|
+
};
|
|
24534
|
+
|
|
24472
24535
|
class Dropdown extends React__namespace.Component {
|
|
24473
24536
|
static defaultProps = {
|
|
24474
24537
|
choices: [],
|
|
@@ -24617,15 +24680,15 @@ class Explanation extends React__namespace.Component {
|
|
|
24617
24680
|
const onClick = this._onClick;
|
|
24618
24681
|
if (isMobile) {
|
|
24619
24682
|
linkContainer = /*#__PURE__*/React__namespace.createElement("div", {
|
|
24620
|
-
className: aphrodite.css(styles$
|
|
24683
|
+
className: aphrodite.css(styles$n.linkContainer)
|
|
24621
24684
|
}, /*#__PURE__*/React__namespace.createElement("a", {
|
|
24622
|
-
className: aphrodite.css(styles$
|
|
24685
|
+
className: aphrodite.css(styles$n.mobileExplanationLink),
|
|
24623
24686
|
href: href,
|
|
24624
24687
|
onClick: onClick,
|
|
24625
24688
|
role: "button",
|
|
24626
24689
|
"aria-expanded": this.state.expanded
|
|
24627
24690
|
}, linkAnchor), this.state.expanded && /*#__PURE__*/React__namespace.createElement("svg", {
|
|
24628
|
-
className: aphrodite.css(styles$
|
|
24691
|
+
className: aphrodite.css(styles$n.disclosureArrow)
|
|
24629
24692
|
}, /*#__PURE__*/React__namespace.createElement("polygon", {
|
|
24630
24693
|
style: {
|
|
24631
24694
|
fill: backgroundColor
|
|
@@ -24638,13 +24701,13 @@ class Explanation extends React__namespace.Component {
|
|
|
24638
24701
|
// an anchor tag (if rendered in a modal) or a Wonder Blocks
|
|
24639
24702
|
// link component in lesson page, see: `article-page.jsx`.
|
|
24640
24703
|
linkContainer = /*#__PURE__*/React__namespace.createElement("div", {
|
|
24641
|
-
className: aphrodite.css(styles$
|
|
24704
|
+
className: aphrodite.css(styles$n.linkContainer, styles$n.articleLink)
|
|
24642
24705
|
}, /*#__PURE__*/React__namespace.createElement(Link, {
|
|
24643
|
-
className: aphrodite.css(styles$
|
|
24706
|
+
className: aphrodite.css(styles$n.explanationLink)
|
|
24644
24707
|
// HACK(michaelpolyak): WB Link doesn't passthrough
|
|
24645
24708
|
// class name.
|
|
24646
24709
|
,
|
|
24647
|
-
style: styles$
|
|
24710
|
+
style: styles$n.explanationLink,
|
|
24648
24711
|
href: href,
|
|
24649
24712
|
onClick: onClick,
|
|
24650
24713
|
role: "button",
|
|
@@ -24654,9 +24717,9 @@ class Explanation extends React__namespace.Component {
|
|
|
24654
24717
|
// NOTE: For exercises, the baseElements `Link` is an
|
|
24655
24718
|
// anchor tag, see: `perseus-api.jsx`.
|
|
24656
24719
|
linkContainer = /*#__PURE__*/React__namespace.createElement("div", {
|
|
24657
|
-
className: aphrodite.css(styles$
|
|
24720
|
+
className: aphrodite.css(styles$n.linkContainer, styles$n.exerciseLink)
|
|
24658
24721
|
}, /*#__PURE__*/React__namespace.createElement(Link, {
|
|
24659
|
-
className: aphrodite.css(styles$
|
|
24722
|
+
className: aphrodite.css(styles$n.explanationLink),
|
|
24660
24723
|
href: href,
|
|
24661
24724
|
onClick: onClick,
|
|
24662
24725
|
role: "button",
|
|
@@ -24664,11 +24727,11 @@ class Explanation extends React__namespace.Component {
|
|
|
24664
24727
|
}, `[${linkAnchor}]`));
|
|
24665
24728
|
}
|
|
24666
24729
|
}
|
|
24667
|
-
const expandedStyle = isMobile ? styles$
|
|
24730
|
+
const expandedStyle = isMobile ? styles$n.contentExpandedMobile : styles$n.contentExpanded;
|
|
24668
24731
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24669
|
-
className: aphrodite.css(styles$
|
|
24732
|
+
className: aphrodite.css(styles$n.container)
|
|
24670
24733
|
}, linkContainer, this.state.expanded && /*#__PURE__*/React__namespace.createElement("div", {
|
|
24671
|
-
className: aphrodite.css(styles$
|
|
24734
|
+
className: aphrodite.css(styles$n.content, isMobile && styles$n.contentMobile, this.state.expanded && expandedStyle)
|
|
24672
24735
|
// eslint-disable-next-line react/no-string-refs
|
|
24673
24736
|
,
|
|
24674
24737
|
ref: "content"
|
|
@@ -24691,7 +24754,7 @@ const verticalContentPadding = 10;
|
|
|
24691
24754
|
const arrowWidth = 30;
|
|
24692
24755
|
const arrowHeight = 14;
|
|
24693
24756
|
const backgroundColor = gray95;
|
|
24694
|
-
const styles$
|
|
24757
|
+
const styles$n = aphrodite.StyleSheet.create({
|
|
24695
24758
|
container: {
|
|
24696
24759
|
display: "inline",
|
|
24697
24760
|
position: "relative"
|
|
@@ -24797,15 +24860,15 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
24797
24860
|
onNextQuestion
|
|
24798
24861
|
} = this.props;
|
|
24799
24862
|
const answerBarStyle = {
|
|
24800
|
-
...styles$
|
|
24863
|
+
...styles$m.answerBar,
|
|
24801
24864
|
backgroundColor: answerBarState === "CORRECT" ? Color__default["default"].offWhite : "white",
|
|
24802
24865
|
// Center the "Correct!" message only when there's no next question
|
|
24803
24866
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
24804
24867
|
};
|
|
24805
24868
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React__namespace.createElement("span", {
|
|
24806
|
-
style: styles$
|
|
24869
|
+
style: styles$m.text
|
|
24807
24870
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
24808
|
-
style: styles$
|
|
24871
|
+
style: styles$m.tryAgainIcon
|
|
24809
24872
|
}, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React__namespace.createElement("span", {
|
|
24810
24873
|
style: {
|
|
24811
24874
|
marginLeft: 8
|
|
@@ -24824,7 +24887,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
24824
24887
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24825
24888
|
style: answerBarStyle
|
|
24826
24889
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
24827
|
-
style: styles$
|
|
24890
|
+
style: styles$m.text
|
|
24828
24891
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
24829
24892
|
style: {
|
|
24830
24893
|
fontSize: 28,
|
|
@@ -24846,7 +24909,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
24846
24909
|
}
|
|
24847
24910
|
}
|
|
24848
24911
|
const fontSize = 17;
|
|
24849
|
-
const styles$
|
|
24912
|
+
const styles$m = {
|
|
24850
24913
|
answerBar: {
|
|
24851
24914
|
display: "flex",
|
|
24852
24915
|
alignItems: "center",
|
|
@@ -25046,7 +25109,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25046
25109
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
|
|
25047
25110
|
gradeStatus = i18n__namespace._("Incorrect");
|
|
25048
25111
|
}
|
|
25049
|
-
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$
|
|
25112
|
+
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$l.gradedGroupInSet) : aphrodite.css(styles$l.gradedGroup);
|
|
25050
25113
|
const classes = classNames__default["default"]({
|
|
25051
25114
|
[mobileClass]: apiOptions.isMobile,
|
|
25052
25115
|
"perseus-graded-group": true,
|
|
@@ -25065,7 +25128,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25065
25128
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25066
25129
|
className: classes
|
|
25067
25130
|
}, !!this.props.title && /*#__PURE__*/React__namespace.createElement("div", {
|
|
25068
|
-
className: aphrodite.css(styles$
|
|
25131
|
+
className: aphrodite.css(styles$l.title)
|
|
25069
25132
|
}, this.props.title), /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, this.props, {
|
|
25070
25133
|
// eslint-disable-next-line react/no-string-refs
|
|
25071
25134
|
ref: "renderer",
|
|
@@ -25098,7 +25161,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25098
25161
|
}, i18n__namespace._("Next question")), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("button", {
|
|
25099
25162
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
25100
25163
|
tabIndex: "0",
|
|
25101
|
-
className: aphrodite.css(styles$
|
|
25164
|
+
className: aphrodite.css(styles$l.explanationTitle),
|
|
25102
25165
|
onClick: () => this.setState({
|
|
25103
25166
|
showHint: false
|
|
25104
25167
|
}),
|
|
@@ -25130,7 +25193,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25130
25193
|
showHint: true
|
|
25131
25194
|
});
|
|
25132
25195
|
},
|
|
25133
|
-
className: aphrodite.css(styles$
|
|
25196
|
+
className: aphrodite.css(styles$l.showHintLink)
|
|
25134
25197
|
}, i18n__namespace._("Explain"))), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React__namespace.createElement(GradedGroupAnswerBar, {
|
|
25135
25198
|
apiOptions: apiOptions,
|
|
25136
25199
|
answerBarState: answerBarState,
|
|
@@ -25142,7 +25205,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
25142
25205
|
const traverseChildWidgets$3 = function (props, traverseRenderer) {
|
|
25143
25206
|
return ___default["default"].extend({}, props, traverseRenderer(props));
|
|
25144
25207
|
};
|
|
25145
|
-
const styles$
|
|
25208
|
+
const styles$l = aphrodite.StyleSheet.create({
|
|
25146
25209
|
gradedGroupInSet: {
|
|
25147
25210
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
25148
25211
|
marginLeft: 0,
|
|
@@ -25212,20 +25275,20 @@ class Indicators extends React__namespace.Component {
|
|
|
25212
25275
|
return /*#__PURE__*/React__namespace.createElement("ul", {
|
|
25213
25276
|
// reduntantly add class name for use in .less files--
|
|
25214
25277
|
// the styles object key gets hashed
|
|
25215
|
-
className: classNames__default["default"](aphrodite.css(styles$
|
|
25278
|
+
className: classNames__default["default"](aphrodite.css(styles$k.indicatorContainer), "indicatorContainer")
|
|
25216
25279
|
}, this.props.gradedGroups.map((_ref, i) => {
|
|
25217
25280
|
let {
|
|
25218
25281
|
title
|
|
25219
25282
|
} = _ref;
|
|
25220
25283
|
return /*#__PURE__*/React__namespace.createElement("li", {
|
|
25221
|
-
className: aphrodite.css(styles$
|
|
25284
|
+
className: aphrodite.css(styles$k.indicator),
|
|
25222
25285
|
key: title
|
|
25223
25286
|
}, /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
25224
25287
|
role: "button",
|
|
25225
25288
|
"aria-label": i18n__namespace._("Skip to %(title)s", {
|
|
25226
25289
|
title
|
|
25227
25290
|
}),
|
|
25228
|
-
style: styles$
|
|
25291
|
+
style: styles$k.indicatorButton,
|
|
25229
25292
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
25230
25293
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
25231
25294
|
}, _ref2 => {
|
|
@@ -25235,9 +25298,9 @@ class Indicators extends React__namespace.Component {
|
|
|
25235
25298
|
pressed
|
|
25236
25299
|
} = _ref2;
|
|
25237
25300
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25238
|
-
style: [styles$
|
|
25301
|
+
style: [styles$k.indicatorDot, (hovered || focused || pressed) && styles$k.indicatorDotFocused]
|
|
25239
25302
|
}, i === this.props.currentGroup && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
25240
|
-
style: styles$
|
|
25303
|
+
style: styles$k.indicatorDotActive
|
|
25241
25304
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
25242
25305
|
className: aphrodite.css(a11y.srOnly)
|
|
25243
25306
|
}, i18n__namespace._("Current"))));
|
|
@@ -25313,7 +25376,7 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
25313
25376
|
} = getDependencies();
|
|
25314
25377
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
25315
25378
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25316
|
-
className: aphrodite.css(styles$
|
|
25379
|
+
className: aphrodite.css(styles$k.container)
|
|
25317
25380
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
25318
25381
|
return (
|
|
25319
25382
|
/*#__PURE__*/
|
|
@@ -25336,13 +25399,13 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
25336
25399
|
const numGroups = this.props.gradedGroups.length;
|
|
25337
25400
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
25338
25401
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25339
|
-
className: aphrodite.css(styles$
|
|
25402
|
+
className: aphrodite.css(styles$k.container)
|
|
25340
25403
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
25341
|
-
className: aphrodite.css(styles$
|
|
25404
|
+
className: aphrodite.css(styles$k.top)
|
|
25342
25405
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
25343
|
-
className: aphrodite.css(styles$
|
|
25406
|
+
className: aphrodite.css(styles$k.title)
|
|
25344
25407
|
}, currentGroup.title), /*#__PURE__*/React__namespace.createElement("div", {
|
|
25345
|
-
className: aphrodite.css(styles$
|
|
25408
|
+
className: aphrodite.css(styles$k.spacer)
|
|
25346
25409
|
}), /*#__PURE__*/React__namespace.createElement(Indicators, {
|
|
25347
25410
|
currentGroup: this.state.currentGroup,
|
|
25348
25411
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -25380,7 +25443,7 @@ var GradedGroupSet$1 = {
|
|
|
25380
25443
|
tracking: "all",
|
|
25381
25444
|
isLintable: true
|
|
25382
25445
|
};
|
|
25383
|
-
const styles$
|
|
25446
|
+
const styles$k = aphrodite.StyleSheet.create({
|
|
25384
25447
|
top: {
|
|
25385
25448
|
display: "flex",
|
|
25386
25449
|
flexDirection: "row"
|
|
@@ -25485,7 +25548,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
25485
25548
|
id: "" + i,
|
|
25486
25549
|
ref: "button" + i,
|
|
25487
25550
|
key: "" + i,
|
|
25488
|
-
className: aphrodite.css(styles$
|
|
25551
|
+
className: aphrodite.css(styles$j.buttonStyle, button.value === value && styles$j.selectedStyle),
|
|
25489
25552
|
onClick: () => this.toggleSelect(button.value)
|
|
25490
25553
|
}, button.content || "" + button.value);
|
|
25491
25554
|
});
|
|
@@ -25498,7 +25561,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
25498
25561
|
}, buttons);
|
|
25499
25562
|
}
|
|
25500
25563
|
}
|
|
25501
|
-
const styles$
|
|
25564
|
+
const styles$j = aphrodite.StyleSheet.create({
|
|
25502
25565
|
buttonStyle: {
|
|
25503
25566
|
backgroundColor: "white",
|
|
25504
25567
|
border: "1px solid #ccc",
|
|
@@ -30962,212 +31025,92 @@ var globalStyles = /*#__PURE__*/Object.freeze({
|
|
|
30962
31025
|
typography: typography
|
|
30963
31026
|
});
|
|
30964
31027
|
|
|
30965
|
-
|
|
30966
|
-
|
|
30967
|
-
|
|
30968
|
-
state = {
|
|
30969
|
-
isInputFocused: false
|
|
30970
|
-
};
|
|
30971
|
-
focusInput() {
|
|
30972
|
-
if (this._input) {
|
|
30973
|
-
this._input.focus();
|
|
30974
|
-
}
|
|
30975
|
-
}
|
|
30976
|
-
handleClick(e) {
|
|
31028
|
+
const AnswerChoices = props => {
|
|
31029
|
+
const onAnswerChange = selected => {
|
|
30977
31030
|
const {
|
|
30978
|
-
|
|
31031
|
+
choices,
|
|
30979
31032
|
onChange
|
|
30980
|
-
} =
|
|
30981
|
-
|
|
30982
|
-
|
|
30983
|
-
// We manually handle clicks, setting focus on the input control.
|
|
30984
|
-
this.focusInput();
|
|
30985
|
-
|
|
30986
|
-
// And toggling the answer selection state.
|
|
30987
|
-
onChange(!checked);
|
|
30988
|
-
}
|
|
30989
|
-
handleKeyDown(e) {
|
|
30990
|
-
const {
|
|
30991
|
-
onFocusPrevAnswer,
|
|
30992
|
-
onFocusNextAnswer
|
|
30993
|
-
} = this.props;
|
|
31033
|
+
} = props;
|
|
31034
|
+
onChange(choices.map(choice => selected.includes(choice.content)));
|
|
31035
|
+
};
|
|
30994
31036
|
|
|
30995
|
-
|
|
30996
|
-
|
|
30997
|
-
|
|
30998
|
-
|
|
30999
|
-
|
|
31000
|
-
|
|
31001
|
-
|
|
31002
|
-
|
|
31003
|
-
|
|
31004
|
-
|
|
31005
|
-
|
|
31006
|
-
|
|
31007
|
-
|
|
31008
|
-
}
|
|
31009
|
-
handleInputChange(e) {
|
|
31010
|
-
// Prevent answer selection from double-toggling, as `handleClick` is
|
|
31011
|
-
// handling changes to selection state.
|
|
31012
|
-
e.preventDefault();
|
|
31013
|
-
}
|
|
31014
|
-
handleInputFocus() {
|
|
31015
|
-
this.setState({
|
|
31016
|
-
isInputFocused: true
|
|
31017
|
-
});
|
|
31018
|
-
}
|
|
31019
|
-
handleInputBlur() {
|
|
31020
|
-
this.setState({
|
|
31021
|
-
isInputFocused: false
|
|
31037
|
+
// WB Dropdown types only take an array of nodes, so we can't use a
|
|
31038
|
+
// functional component, which can only return a single node.
|
|
31039
|
+
const AnswerItems = choices => choices.map(_ref => {
|
|
31040
|
+
let {
|
|
31041
|
+
content
|
|
31042
|
+
} = _ref;
|
|
31043
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
31044
|
+
key: content,
|
|
31045
|
+
value: content,
|
|
31046
|
+
label: /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31047
|
+
content: content,
|
|
31048
|
+
inline: true
|
|
31049
|
+
})
|
|
31022
31050
|
});
|
|
31023
|
-
}
|
|
31024
|
-
|
|
31025
|
-
|
|
31026
|
-
|
|
31027
|
-
|
|
31028
|
-
|
|
31029
|
-
|
|
31030
|
-
|
|
31031
|
-
|
|
31032
|
-
|
|
31033
|
-
|
|
31034
|
-
}
|
|
31035
|
-
|
|
31036
|
-
|
|
31037
|
-
|
|
31038
|
-
|
|
31039
|
-
|
|
31040
|
-
|
|
31041
|
-
|
|
31042
|
-
|
|
31043
|
-
|
|
31044
|
-
|
|
31045
|
-
|
|
31046
|
-
|
|
31047
|
-
|
|
31048
|
-
|
|
31049
|
-
className: aphrodite.css(styles$j.answerChoice, isInputFocused && styles$j.answerFocused),
|
|
31050
|
-
onClick: e => this.handleClick(e),
|
|
31051
|
-
onKeyDown: e => this.handleKeyDown(e)
|
|
31052
|
-
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
31053
|
-
className: aphrodite.css(styles$j.answerInputWrapper)
|
|
31054
|
-
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
31055
|
-
className: aphrodite.css(sharedStyles.perseusSrOnly),
|
|
31056
|
-
checked: checked,
|
|
31057
|
-
name: groupName,
|
|
31058
|
-
id: answerId,
|
|
31059
|
-
type: inputType,
|
|
31060
|
-
onChange: e => this.handleInputChange(e),
|
|
31061
|
-
onFocus: () => this.handleInputFocus(),
|
|
31062
|
-
onBlur: () => this.handleInputBlur(),
|
|
31063
|
-
ref: node => this._input = node
|
|
31064
|
-
}), this.renderCheckmark()), /*#__PURE__*/React__namespace.createElement("label", {
|
|
31065
|
-
htmlFor: answerId
|
|
31066
|
-
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31067
|
-
content: content
|
|
31068
|
-
})));
|
|
31069
|
-
}
|
|
31070
|
-
}
|
|
31071
|
-
class AnswerChoices extends React__namespace.Component {
|
|
31072
|
-
// The rendered answers elements.
|
|
31073
|
-
|
|
31074
|
-
constructor(props) {
|
|
31075
|
-
super(props);
|
|
31076
|
-
this._choices = [];
|
|
31077
|
-
this.state = {
|
|
31078
|
-
groupName: ___default["default"].uniqueId("answer_choices_")
|
|
31079
|
-
};
|
|
31080
|
-
}
|
|
31081
|
-
focusAnswer() {
|
|
31082
|
-
let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
31083
|
-
const numChoices = this.props.choices.length;
|
|
31051
|
+
});
|
|
31052
|
+
const selectedValues = props.choices.filter(choice => choice.checked).map(choice => choice.content);
|
|
31053
|
+
const {
|
|
31054
|
+
opener,
|
|
31055
|
+
onToggle,
|
|
31056
|
+
disabled
|
|
31057
|
+
} = props;
|
|
31058
|
+
const args = {
|
|
31059
|
+
// reset to allow child (answer pill) to control z-index
|
|
31060
|
+
style: {
|
|
31061
|
+
zIndex: "unset"
|
|
31062
|
+
},
|
|
31063
|
+
children: AnswerItems(props.choices),
|
|
31064
|
+
opener,
|
|
31065
|
+
onToggle,
|
|
31066
|
+
disabled
|
|
31067
|
+
};
|
|
31068
|
+
return props.multipleSelect ? /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.MultiSelect, _extends({}, args, {
|
|
31069
|
+
selectedValues: selectedValues,
|
|
31070
|
+
onChange: selected => onAnswerChange(selected)
|
|
31071
|
+
})) : /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, _extends({}, args, {
|
|
31072
|
+
selectedValue: selectedValues[0],
|
|
31073
|
+
onChange: selected => onAnswerChange([selected]),
|
|
31074
|
+
placeholder: props.choices[0].content // not visible, but required
|
|
31075
|
+
}));
|
|
31076
|
+
};
|
|
31084
31077
|
|
|
31085
|
-
|
|
31086
|
-
|
|
31087
|
-
|
|
31088
|
-
} else if (index >= numChoices) {
|
|
31089
|
-
index -= numChoices;
|
|
31090
|
-
}
|
|
31091
|
-
const choice = this._choices[index];
|
|
31092
|
-
if (choice) {
|
|
31093
|
-
choice.focusInput();
|
|
31094
|
-
}
|
|
31095
|
-
}
|
|
31096
|
-
onAnswerChange(index, checked) {
|
|
31097
|
-
const {
|
|
31098
|
-
choices,
|
|
31099
|
-
multipleSelect,
|
|
31100
|
-
onChange
|
|
31101
|
-
} = this.props;
|
|
31102
|
-
const selection = [];
|
|
31078
|
+
const strings = {
|
|
31079
|
+
hideAnswersToggleLabel: i18n__namespace._("Hide answer choices")
|
|
31080
|
+
};
|
|
31103
31081
|
|
|
31104
|
-
|
|
31105
|
-
|
|
31106
|
-
|
|
31107
|
-
|
|
31108
|
-
|
|
31109
|
-
|
|
31110
|
-
}
|
|
31111
|
-
|
|
31112
|
-
|
|
31113
|
-
|
|
31114
|
-
|
|
31115
|
-
|
|
31116
|
-
|
|
31117
|
-
|
|
31118
|
-
|
|
31119
|
-
|
|
31120
|
-
|
|
31121
|
-
|
|
31122
|
-
|
|
31123
|
-
style: {
|
|
31124
|
-
border: "none",
|
|
31125
|
-
margin: 0,
|
|
31126
|
-
padding: 0
|
|
31127
|
-
}
|
|
31128
|
-
}, choices.map((choice, index) => /*#__PURE__*/React__namespace.createElement(AnswerChoice, _extends({}, choice, {
|
|
31129
|
-
key: choice.content,
|
|
31130
|
-
groupName: groupName,
|
|
31131
|
-
index: index,
|
|
31132
|
-
inputType: multipleSelect ? "checkbox" : "radio",
|
|
31133
|
-
onChange: checked => this.onAnswerChange(index, checked),
|
|
31134
|
-
onFocusPrevAnswer: () => this.onFocusAnswer(index - 1),
|
|
31135
|
-
onFocusNextAnswer: () => this.onFocusAnswer(index + 1),
|
|
31136
|
-
ref: node => this._choices[index] = node
|
|
31137
|
-
}))));
|
|
31138
|
-
}
|
|
31139
|
-
}
|
|
31140
|
-
const styles$j = aphrodite.StyleSheet.create({
|
|
31141
|
-
answerChoice: {
|
|
31082
|
+
const HideAnswersToggle = props => {
|
|
31083
|
+
const idFactory = wonderBlocksCore.useUniqueIdWithMock();
|
|
31084
|
+
const switchId = idFactory.get("hide-answers-toggle");
|
|
31085
|
+
const labelId = idFactory.get("hide-answers-label");
|
|
31086
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31087
|
+
style: styles$i.switchWrapper
|
|
31088
|
+
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
31089
|
+
id: switchId,
|
|
31090
|
+
checked: props.areAnswersHidden,
|
|
31091
|
+
onChange: props.onChange,
|
|
31092
|
+
"aria-labelledby": labelId
|
|
31093
|
+
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
31094
|
+
id: labelId,
|
|
31095
|
+
htmlFor: switchId,
|
|
31096
|
+
tag: "label"
|
|
31097
|
+
}, strings.hideAnswersToggleLabel));
|
|
31098
|
+
};
|
|
31099
|
+
const styles$i = aphrodite.StyleSheet.create({
|
|
31100
|
+
switchWrapper: {
|
|
31142
31101
|
display: "flex",
|
|
31102
|
+
flexDirection: "row",
|
|
31103
|
+
flexWrap: "wrap-reverse",
|
|
31143
31104
|
alignItems: "center",
|
|
31144
|
-
|
|
31145
|
-
|
|
31146
|
-
fontWeight: "bold",
|
|
31147
|
-
border: "solid 2px transparent",
|
|
31148
|
-
borderRadius: 2,
|
|
31149
|
-
":active": {
|
|
31150
|
-
backgroundColor: "rgba(33, 36, 44, 0.08)"
|
|
31151
|
-
}
|
|
31152
|
-
},
|
|
31153
|
-
answerFocused: {
|
|
31154
|
-
borderColor: "#1865f2",
|
|
31155
|
-
":active": {
|
|
31156
|
-
borderColor: "transparent"
|
|
31157
|
-
}
|
|
31158
|
-
},
|
|
31159
|
-
answerInputWrapper: {
|
|
31160
|
-
marginRight: 8
|
|
31161
|
-
},
|
|
31162
|
-
checkmarkContainer: {
|
|
31163
|
-
display: "flex",
|
|
31164
|
-
position: "relative",
|
|
31165
|
-
width: 16,
|
|
31166
|
-
height: 16,
|
|
31167
|
-
marginLeft: 8
|
|
31105
|
+
gap: "0.5em",
|
|
31106
|
+
marginTop: "1em"
|
|
31168
31107
|
}
|
|
31169
31108
|
});
|
|
31170
31109
|
|
|
31110
|
+
const BringToFront = {
|
|
31111
|
+
boxShadow: `0 8px 8px ${Color__default["default"].offBlack64}`,
|
|
31112
|
+
zIndex: 1000
|
|
31113
|
+
};
|
|
31171
31114
|
const AnswerPill = props => {
|
|
31172
31115
|
const {
|
|
31173
31116
|
selectedAnswers,
|
|
@@ -31175,7 +31118,9 @@ const AnswerPill = props => {
|
|
|
31175
31118
|
markerRef,
|
|
31176
31119
|
side,
|
|
31177
31120
|
onClick,
|
|
31178
|
-
style
|
|
31121
|
+
style,
|
|
31122
|
+
focused,
|
|
31123
|
+
hovered
|
|
31179
31124
|
} = props;
|
|
31180
31125
|
const idFactory = wonderBlocksCore.useUniqueIdWithMock();
|
|
31181
31126
|
const answerString = selectedAnswers.length > 1 ?
|
|
@@ -31186,10 +31131,6 @@ const AnswerPill = props => {
|
|
|
31186
31131
|
// has been labeled (answered) correctly.
|
|
31187
31132
|
const correct = showCorrectness === "correct";
|
|
31188
31133
|
const incorrect = showCorrectness === "incorrect";
|
|
31189
|
-
const bringToFront = {
|
|
31190
|
-
boxShadow: `0 8px 8px ${Color__default["default"].offBlack64}`,
|
|
31191
|
-
zIndex: 1000
|
|
31192
|
-
};
|
|
31193
31134
|
return /*#__PURE__*/React__namespace.createElement(reactPopper.Popper, {
|
|
31194
31135
|
placement: side,
|
|
31195
31136
|
referenceElement: markerRef,
|
|
@@ -31210,63 +31151,29 @@ const AnswerPill = props => {
|
|
|
31210
31151
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31211
31152
|
onClick: correct ? undefined : onClick,
|
|
31212
31153
|
ref: ref,
|
|
31213
|
-
style: [style, popperStyle,
|
|
31214
|
-
":hover": bringToFront,
|
|
31215
|
-
":focus": bringToFront
|
|
31216
|
-
}, correct && styles$i.correct, incorrect && styles$i.incorrect]
|
|
31154
|
+
style: [style, popperStyle, styles$h.relative, correct && styles$h.correct, incorrect && styles$h.incorrect, (focused || hovered) && BringToFront]
|
|
31217
31155
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31218
31156
|
content: answerString,
|
|
31219
31157
|
inline: true
|
|
31220
31158
|
}));
|
|
31221
31159
|
});
|
|
31222
31160
|
};
|
|
31223
|
-
const styles$
|
|
31161
|
+
const styles$h = aphrodite.StyleSheet.create({
|
|
31224
31162
|
correct: {
|
|
31225
|
-
|
|
31163
|
+
// WB green darkened by 18%
|
|
31164
|
+
backgroundColor: "#00880b"
|
|
31226
31165
|
},
|
|
31227
|
-
|
|
31228
31166
|
incorrect: {
|
|
31229
31167
|
backgroundColor: Color__default["default"].offBlack64
|
|
31230
31168
|
}
|
|
31231
31169
|
});
|
|
31232
31170
|
|
|
31233
|
-
const strings = {
|
|
31234
|
-
hideAnswersToggleLabel: i18n__namespace._("Hide answer choices")
|
|
31235
|
-
};
|
|
31236
|
-
|
|
31237
|
-
const HideAnswersToggle = props => {
|
|
31238
|
-
const idFactory = wonderBlocksCore.useUniqueIdWithMock();
|
|
31239
|
-
const switchId = idFactory.get("hide-answers-toggle");
|
|
31240
|
-
const labelId = idFactory.get("hide-answers-label");
|
|
31241
|
-
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31242
|
-
style: styles$h.switchWrapper
|
|
31243
|
-
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
31244
|
-
id: switchId,
|
|
31245
|
-
checked: props.areAnswersHidden,
|
|
31246
|
-
onChange: props.onChange,
|
|
31247
|
-
"aria-labelledby": labelId
|
|
31248
|
-
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
31249
|
-
id: labelId,
|
|
31250
|
-
htmlFor: switchId,
|
|
31251
|
-
tag: "label"
|
|
31252
|
-
}, strings.hideAnswersToggleLabel));
|
|
31253
|
-
};
|
|
31254
|
-
const styles$h = aphrodite.StyleSheet.create({
|
|
31255
|
-
switchWrapper: {
|
|
31256
|
-
display: "flex",
|
|
31257
|
-
flexDirection: "row",
|
|
31258
|
-
flexWrap: "wrap-reverse",
|
|
31259
|
-
alignItems: "center",
|
|
31260
|
-
gap: "0.5em",
|
|
31261
|
-
marginTop: "1em"
|
|
31262
|
-
}
|
|
31263
|
-
});
|
|
31264
|
-
|
|
31265
31171
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
31266
31172
|
function shouldReduceMotion() {
|
|
31267
31173
|
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
31268
31174
|
return !mediaQuery || mediaQuery.matches;
|
|
31269
31175
|
}
|
|
31176
|
+
const MARKER_SIZE = 24;
|
|
31270
31177
|
class Marker extends React__namespace.Component {
|
|
31271
31178
|
// The marker icon element.
|
|
31272
31179
|
|
|
@@ -31278,123 +31185,101 @@ class Marker extends React__namespace.Component {
|
|
|
31278
31185
|
selected,
|
|
31279
31186
|
showCorrectness,
|
|
31280
31187
|
showSelected,
|
|
31281
|
-
showPulsate
|
|
31282
|
-
focused
|
|
31188
|
+
showPulsate
|
|
31283
31189
|
} = this.props;
|
|
31284
31190
|
|
|
31285
31191
|
// Only a single marker may be "selected" at a time.
|
|
31286
31192
|
// `showSelected` is a controlled prop, that may be set to `true` for
|
|
31287
31193
|
// one marker at a time.
|
|
31288
|
-
|
|
31289
|
-
|
|
31290
|
-
// keyboard focus is given to the marker.
|
|
31291
|
-
const isSelected = showSelected || focused;
|
|
31292
|
-
let innerIcon;
|
|
31194
|
+
const isOpen = showSelected;
|
|
31195
|
+
const selectedAnswers = selected;
|
|
31293
31196
|
let iconStyles;
|
|
31197
|
+
const iconNull = {
|
|
31198
|
+
path: "",
|
|
31199
|
+
height: 1,
|
|
31200
|
+
width: 1
|
|
31201
|
+
};
|
|
31202
|
+
|
|
31203
|
+
// default dot
|
|
31204
|
+
let args = {
|
|
31205
|
+
size: MARKER_SIZE,
|
|
31206
|
+
color: Color__default["default"].white,
|
|
31207
|
+
icon: iconNull
|
|
31208
|
+
};
|
|
31294
31209
|
if (showCorrectness) {
|
|
31295
|
-
|
|
31296
|
-
|
|
31297
|
-
|
|
31298
|
-
|
|
31299
|
-
}
|
|
31300
|
-
|
|
31301
|
-
|
|
31302
|
-
|
|
31303
|
-
iconStyles = [styles$g.markerGraded, styles$g.markerIncorrect, isSelected && styles$g.markerSelected];
|
|
31304
|
-
}
|
|
31305
|
-
} else if (focused) {
|
|
31306
|
-
iconStyles = [styles$g.markerFocused, selected && selected.length > 0 && styles$g.markerFilled, showSelected && styles$g.markerSelected];
|
|
31307
|
-
} else if (selected && selected.length > 0) {
|
|
31308
|
-
iconStyles = [styles$g.markerFilled, isSelected && styles$g.markerSelected];
|
|
31309
|
-
} else if (isSelected) {
|
|
31210
|
+
iconStyles = [styles$g.markerGraded, showCorrectness === "correct" ? styles$g.markerCorrect : styles$g.markerIncorrect, isOpen && styles$g.markerSelected];
|
|
31211
|
+
args = {
|
|
31212
|
+
...args,
|
|
31213
|
+
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31214
|
+
};
|
|
31215
|
+
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31216
|
+
iconStyles = [styles$g.markerFilled, isOpen && styles$g.markerSelected];
|
|
31217
|
+
} else if (isOpen) {
|
|
31310
31218
|
iconStyles = [styles$g.markerSelected];
|
|
31311
|
-
|
|
31312
|
-
|
|
31313
|
-
}
|
|
31314
|
-
if (isSelected && selected && selected.length === 0) {
|
|
31315
|
-
innerIcon = /*#__PURE__*/React__namespace.createElement(Icon, {
|
|
31219
|
+
args = {
|
|
31220
|
+
...args,
|
|
31316
31221
|
icon: iconChevronDown,
|
|
31317
|
-
size: 8
|
|
31318
|
-
|
|
31319
|
-
|
|
31222
|
+
size: 8
|
|
31223
|
+
};
|
|
31224
|
+
} else if (showPulsate) {
|
|
31225
|
+
iconStyles = [styles$g.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$g.markerUnfilledPulsateOnce : showPulsate && styles$g.markerUnfilledPulsateInfinite];
|
|
31320
31226
|
}
|
|
31321
31227
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31322
31228
|
style: [styles$g.markerIcon, iconStyles],
|
|
31323
31229
|
ref: node => this._icon = node
|
|
31324
|
-
},
|
|
31230
|
+
}, /*#__PURE__*/React__namespace.createElement(Icon, args));
|
|
31325
31231
|
}
|
|
31326
31232
|
render() {
|
|
31327
31233
|
const {
|
|
31328
|
-
|
|
31329
|
-
|
|
31330
|
-
|
|
31331
|
-
|
|
31234
|
+
showCorrectness,
|
|
31235
|
+
selected,
|
|
31236
|
+
showAnswer,
|
|
31237
|
+
answerSide,
|
|
31238
|
+
answerStyles,
|
|
31239
|
+
hovered,
|
|
31240
|
+
focused
|
|
31332
31241
|
} = this.props;
|
|
31333
31242
|
|
|
31334
|
-
//
|
|
31335
|
-
//
|
|
31336
|
-
const
|
|
31337
|
-
|
|
31338
|
-
|
|
31339
|
-
|
|
31340
|
-
|
|
31341
|
-
|
|
31342
|
-
|
|
31343
|
-
|
|
31344
|
-
|
|
31345
|
-
|
|
31346
|
-
|
|
31347
|
-
|
|
31348
|
-
|
|
31349
|
-
this.props.onClick(e);
|
|
31350
|
-
},
|
|
31351
|
-
onKeyDown: e => this.props.onKeyDown(e)
|
|
31352
|
-
}, this.renderIcon());
|
|
31243
|
+
// We cannot make dropdown openers untabbable, so we isolate tabbing
|
|
31244
|
+
// to answer pills when interaction is disabled.
|
|
31245
|
+
const markerDisabled = showCorrectness === "correct";
|
|
31246
|
+
const active = hovered || focused;
|
|
31247
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31248
|
+
style: [styles$g.marker, active && !markerDisabled && styles$g.markerActive]
|
|
31249
|
+
}, this.renderIcon()), !!selected && showAnswer && /*#__PURE__*/React__namespace.createElement(AnswerPill, {
|
|
31250
|
+
selectedAnswers: selected,
|
|
31251
|
+
showCorrectness: showCorrectness,
|
|
31252
|
+
side: answerSide,
|
|
31253
|
+
style: answerStyles,
|
|
31254
|
+
markerRef: this._icon ?? undefined,
|
|
31255
|
+
hovered: hovered,
|
|
31256
|
+
focused: focused
|
|
31257
|
+
}));
|
|
31353
31258
|
}
|
|
31354
31259
|
}
|
|
31355
|
-
const lightShadowColor = "rgba(33, 36, 44, 0.16)";
|
|
31356
|
-
const markerSize = 20;
|
|
31357
31260
|
const styles$g = aphrodite.StyleSheet.create({
|
|
31358
|
-
unstyledButton: {
|
|
31359
|
-
padding: 0,
|
|
31360
|
-
overflow: "visible",
|
|
31361
|
-
color: "inherit",
|
|
31362
|
-
font: "inherit",
|
|
31363
|
-
lineHeight: "normal",
|
|
31364
|
-
background: "none",
|
|
31365
|
-
border: "none"
|
|
31366
|
-
},
|
|
31367
31261
|
marker: {
|
|
31368
31262
|
position: "absolute",
|
|
31369
|
-
outline: "none",
|
|
31370
|
-
// Center marker position based on it's maximum size.
|
|
31371
|
-
width: markerSize,
|
|
31372
|
-
height: markerSize,
|
|
31373
31263
|
backgroundColor: Color__default["default"].white,
|
|
31374
|
-
borderRadius:
|
|
31375
|
-
|
|
31376
|
-
|
|
31377
|
-
|
|
31378
|
-
|
|
31379
|
-
|
|
31264
|
+
borderRadius: MARKER_SIZE,
|
|
31265
|
+
// Center marker position based on its maximum size.
|
|
31266
|
+
width: MARKER_SIZE,
|
|
31267
|
+
height: MARKER_SIZE,
|
|
31268
|
+
marginLeft: MARKER_SIZE / -2,
|
|
31269
|
+
marginTop: MARKER_SIZE / -2,
|
|
31270
|
+
// Add a shadow to the marker to make it stand out from the image.
|
|
31271
|
+
boxShadow: `0 8px 8px ${Color__default["default"].offBlack8}`
|
|
31380
31272
|
},
|
|
31381
31273
|
// The base and unfilled marker style.
|
|
31382
31274
|
markerIcon: {
|
|
31383
31275
|
display: "flex",
|
|
31384
31276
|
alignItems: "center",
|
|
31385
31277
|
justifyContent: "center",
|
|
31386
|
-
boxSizing: "
|
|
31387
|
-
width:
|
|
31388
|
-
height:
|
|
31389
|
-
marginLeft: 2,
|
|
31390
|
-
cursor: "pointer",
|
|
31278
|
+
boxSizing: "border-box",
|
|
31279
|
+
width: MARKER_SIZE,
|
|
31280
|
+
height: MARKER_SIZE,
|
|
31391
31281
|
border: `2px solid ${Color__default["default"].offBlack64}`,
|
|
31392
|
-
borderRadius:
|
|
31393
|
-
boxShadow: `0 8px 8px ${Color__default["default"].offBlack8}`,
|
|
31394
|
-
":hover": {
|
|
31395
|
-
outline: `2px solid ${Color__default["default"].blue}`,
|
|
31396
|
-
outlineOffset: 2
|
|
31397
|
-
}
|
|
31282
|
+
borderRadius: MARKER_SIZE
|
|
31398
31283
|
},
|
|
31399
31284
|
// The animation that presents the marker to the learner
|
|
31400
31285
|
markerPulsateBase: {
|
|
@@ -31415,16 +31300,13 @@ const styles$g = aphrodite.StyleSheet.create({
|
|
|
31415
31300
|
animationIterationCount: "0"
|
|
31416
31301
|
},
|
|
31417
31302
|
markerUnfilledPulsateInfinite: {
|
|
31418
|
-
animationIterationCount: "infinite"
|
|
31419
|
-
":hover": {
|
|
31420
|
-
outline: `0px solid ${Color__default["default"].blue}`
|
|
31421
|
-
}
|
|
31303
|
+
animationIterationCount: "infinite"
|
|
31422
31304
|
},
|
|
31423
31305
|
markerUnfilledPulsateOnce: {
|
|
31424
31306
|
// Doing the animation twice lets it ease-in and ease-out
|
|
31425
31307
|
animationIterationCount: "2"
|
|
31426
31308
|
},
|
|
31427
|
-
|
|
31309
|
+
markerActive: {
|
|
31428
31310
|
outline: `2px solid ${Color__default["default"].blue}`,
|
|
31429
31311
|
outlineOffset: 2
|
|
31430
31312
|
},
|
|
@@ -31433,33 +31315,20 @@ const styles$g = aphrodite.StyleSheet.create({
|
|
|
31433
31315
|
boxShadow: `0 8px 8px ${Color__default["default"].offBlack8}`,
|
|
31434
31316
|
border: `solid 4px ${Color__default["default"].white}`,
|
|
31435
31317
|
backgroundColor: Color__default["default"].blue,
|
|
31436
|
-
borderRadius:
|
|
31437
|
-
transform: "rotate(180deg)"
|
|
31438
|
-
":hover": {
|
|
31439
|
-
outline: `2px solid ${Color__default["default"].blue}`,
|
|
31440
|
-
outlineOffset: -2
|
|
31441
|
-
}
|
|
31318
|
+
borderRadius: MARKER_SIZE,
|
|
31319
|
+
transform: "rotate(180deg)"
|
|
31442
31320
|
},
|
|
31443
31321
|
// The learner has made a selection
|
|
31444
31322
|
markerFilled: {
|
|
31445
|
-
width: markerSize - 2,
|
|
31446
|
-
height: markerSize - 2,
|
|
31447
|
-
borderRadius: markerSize - 2,
|
|
31448
31323
|
backgroundColor: "#ECF3FE",
|
|
31449
|
-
|
|
31450
|
-
marginTop: 0,
|
|
31451
|
-
border: `4px solid ${Color__default["default"].blue}`,
|
|
31452
|
-
boxShadow: `0 1px 1px 0 ${lightShadowColor}`
|
|
31324
|
+
border: `4px solid ${Color__default["default"].blue}`
|
|
31453
31325
|
},
|
|
31454
31326
|
markerGraded: {
|
|
31455
|
-
width:
|
|
31456
|
-
height:
|
|
31457
|
-
marginLeft: 1,
|
|
31458
|
-
marginTop: 1,
|
|
31327
|
+
width: MARKER_SIZE,
|
|
31328
|
+
height: MARKER_SIZE,
|
|
31459
31329
|
justifyContent: "center",
|
|
31460
31330
|
alignItems: "center",
|
|
31461
|
-
border: `2px solid ${Color__default["default"].white}
|
|
31462
|
-
boxShadow: `0 8px 8px ${Color__default["default"].offBlack8}`
|
|
31331
|
+
border: `2px solid ${Color__default["default"].white}`
|
|
31463
31332
|
},
|
|
31464
31333
|
markerCorrect: {
|
|
31465
31334
|
background: "#00880b" // WB green darkened by 18%
|
|
@@ -31478,10 +31347,6 @@ const styles$g = aphrodite.StyleSheet.create({
|
|
|
31478
31347
|
class LabelImage extends React__namespace.Component {
|
|
31479
31348
|
// The rendered markers on the question image for labeling.
|
|
31480
31349
|
|
|
31481
|
-
// The popup component containing the answer choices.
|
|
31482
|
-
|
|
31483
|
-
// The rendered list of answer choices for the currently selected marker.
|
|
31484
|
-
|
|
31485
31350
|
static gradeMarker(marker) {
|
|
31486
31351
|
const score = {
|
|
31487
31352
|
hasAnswers: false,
|
|
@@ -31715,7 +31580,6 @@ class LabelImage extends React__namespace.Component {
|
|
|
31715
31580
|
this._markers = [];
|
|
31716
31581
|
this.state = {
|
|
31717
31582
|
activeMarkerIndex: -1,
|
|
31718
|
-
focusedMarkerIndex: -1,
|
|
31719
31583
|
markersInteracted: false,
|
|
31720
31584
|
hideAnswers: false
|
|
31721
31585
|
};
|
|
@@ -31754,26 +31618,6 @@ class LabelImage extends React__namespace.Component {
|
|
|
31754
31618
|
markers: updatedMarkers
|
|
31755
31619
|
}, null, true);
|
|
31756
31620
|
}
|
|
31757
|
-
dismissMarkerPopup() {
|
|
31758
|
-
const {
|
|
31759
|
-
activeMarkerIndex
|
|
31760
|
-
} = this.state;
|
|
31761
|
-
|
|
31762
|
-
// No popup should be open if there's no selected marker.
|
|
31763
|
-
if (activeMarkerIndex === -1) {
|
|
31764
|
-
return;
|
|
31765
|
-
}
|
|
31766
|
-
this.setState({
|
|
31767
|
-
activeMarkerIndex: -1
|
|
31768
|
-
}, () => {
|
|
31769
|
-
const marker = this._markers[activeMarkerIndex];
|
|
31770
|
-
// Set focus on the just-deselected-marker, to enable to resume
|
|
31771
|
-
// navigating between the markers using the keyboard.
|
|
31772
|
-
if (marker) {
|
|
31773
|
-
ReactDOM__namespace.findDOMNode(marker).focus();
|
|
31774
|
-
}
|
|
31775
|
-
});
|
|
31776
|
-
}
|
|
31777
31621
|
handleMarkerChange(index, marker) {
|
|
31778
31622
|
const {
|
|
31779
31623
|
markers,
|
|
@@ -31793,32 +31637,24 @@ class LabelImage extends React__namespace.Component {
|
|
|
31793
31637
|
markers: updatedMarkers
|
|
31794
31638
|
});
|
|
31795
31639
|
}
|
|
31796
|
-
activateMarker(index) {
|
|
31640
|
+
activateMarker(index, opened) {
|
|
31641
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
31642
|
+
type: "perseus:label-image:marker-interacted-with",
|
|
31643
|
+
payload: null
|
|
31644
|
+
});
|
|
31797
31645
|
const {
|
|
31798
31646
|
activeMarkerIndex
|
|
31799
31647
|
} = this.state;
|
|
31800
|
-
|
|
31801
|
-
|
|
31802
|
-
if (activeMarkerIndex !== index) {
|
|
31648
|
+
// Set index of opened marker
|
|
31649
|
+
if (activeMarkerIndex !== index && opened) {
|
|
31803
31650
|
this.setState({
|
|
31804
31651
|
activeMarkerIndex: index,
|
|
31805
31652
|
markersInteracted: true
|
|
31806
|
-
}, () => {
|
|
31807
|
-
// A delay is required to allow answer choices to first render
|
|
31808
|
-
// before trying to set focus on the first choice.
|
|
31809
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API
|
|
31810
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
31811
|
-
setTimeout(() => {
|
|
31812
|
-
if (this._answerChoices) {
|
|
31813
|
-
this._answerChoices.focusAnswer();
|
|
31814
|
-
}
|
|
31815
|
-
}, 100);
|
|
31816
31653
|
});
|
|
31817
31654
|
} else {
|
|
31818
|
-
|
|
31819
|
-
|
|
31820
|
-
|
|
31821
|
-
this.dismissMarkerPopup();
|
|
31655
|
+
this.setState({
|
|
31656
|
+
activeMarkerIndex: -1
|
|
31657
|
+
});
|
|
31822
31658
|
}
|
|
31823
31659
|
}
|
|
31824
31660
|
handleMarkerKeyDown(index, e) {
|
|
@@ -31866,8 +31702,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
31866
31702
|
handleAnswerChoicesChangeForMarker(index, selection) {
|
|
31867
31703
|
const {
|
|
31868
31704
|
choices,
|
|
31869
|
-
markers
|
|
31870
|
-
multipleAnswers
|
|
31705
|
+
markers
|
|
31871
31706
|
} = this.props;
|
|
31872
31707
|
|
|
31873
31708
|
// Compile the user selected answer choices.
|
|
@@ -31876,35 +31711,6 @@ class LabelImage extends React__namespace.Component {
|
|
|
31876
31711
|
...markers[index],
|
|
31877
31712
|
selected: selected.length ? selected : undefined
|
|
31878
31713
|
});
|
|
31879
|
-
if (!multipleAnswers) {
|
|
31880
|
-
this.dismissMarkerPopup();
|
|
31881
|
-
}
|
|
31882
|
-
}
|
|
31883
|
-
renderAnswerChoicesForMarker(index, marker) {
|
|
31884
|
-
const {
|
|
31885
|
-
choices,
|
|
31886
|
-
multipleAnswers
|
|
31887
|
-
} = this.props;
|
|
31888
|
-
|
|
31889
|
-
// The user selected answer choices.
|
|
31890
|
-
const selected = marker.selected;
|
|
31891
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
31892
|
-
className: classNames__default["default"]("perseus-label-image-widget-answer-choices", aphrodite.css(styles$f.scrollableChoices))
|
|
31893
|
-
}, /*#__PURE__*/React__namespace.createElement(AnswerChoices, {
|
|
31894
|
-
choices: choices.map(choice => ({
|
|
31895
|
-
content: choice,
|
|
31896
|
-
checked: selected ? selected.includes(choice) : false
|
|
31897
|
-
})),
|
|
31898
|
-
multipleSelect: multipleAnswers,
|
|
31899
|
-
onChange: selection => {
|
|
31900
|
-
this.props.analytics?.onAnalyticsEvent({
|
|
31901
|
-
type: "perseus:label-image:choiced-interacted-with",
|
|
31902
|
-
payload: null
|
|
31903
|
-
});
|
|
31904
|
-
this.handleAnswerChoicesChangeForMarker(index, selection);
|
|
31905
|
-
},
|
|
31906
|
-
ref: node => this._answerChoices = node
|
|
31907
|
-
}));
|
|
31908
31714
|
}
|
|
31909
31715
|
renderMarkers() {
|
|
31910
31716
|
const {
|
|
@@ -31919,40 +31725,6 @@ class LabelImage extends React__namespace.Component {
|
|
|
31919
31725
|
|
|
31920
31726
|
// Render all markers for widget.
|
|
31921
31727
|
return markers.map((marker, index) => {
|
|
31922
|
-
const score = LabelImage.gradeMarker(marker);
|
|
31923
|
-
// Once the question is answered, show markers
|
|
31924
|
-
// with correct answers, otherwise passthrough
|
|
31925
|
-
// the correctness state.
|
|
31926
|
-
const showCorrectness = questionCompleted && score.hasAnswers && score.isCorrect ? "correct" : marker.showCorrectness;
|
|
31927
|
-
const element = /*#__PURE__*/React__namespace.createElement(Marker, _extends({}, marker, {
|
|
31928
|
-
showCorrectness: showCorrectness,
|
|
31929
|
-
showSelected: index === activeMarkerIndex,
|
|
31930
|
-
showPulsate: !markersInteracted,
|
|
31931
|
-
key: `${marker.x}.${marker.y}`,
|
|
31932
|
-
onClick: () => {
|
|
31933
|
-
this.props.analytics?.onAnalyticsEvent({
|
|
31934
|
-
type: "perseus:label-image:marker-interacted-with",
|
|
31935
|
-
payload: null
|
|
31936
|
-
});
|
|
31937
|
-
this.activateMarker(index);
|
|
31938
|
-
},
|
|
31939
|
-
onKeyDown: e => this.handleMarkerKeyDown(index, e),
|
|
31940
|
-
ref: node => this._markers[index] = node,
|
|
31941
|
-
focused: index === this.state.focusedMarkerIndex,
|
|
31942
|
-
onFocus: () => {
|
|
31943
|
-
this.setState({
|
|
31944
|
-
focusedMarkerIndex: index
|
|
31945
|
-
});
|
|
31946
|
-
},
|
|
31947
|
-
onBlur: () => {
|
|
31948
|
-
if (index === this.state.focusedMarkerIndex) {
|
|
31949
|
-
this.setState({
|
|
31950
|
-
focusedMarkerIndex: -1
|
|
31951
|
-
});
|
|
31952
|
-
}
|
|
31953
|
-
}
|
|
31954
|
-
}));
|
|
31955
|
-
|
|
31956
31728
|
// Determine whether page is rendered in a narrow browser window.
|
|
31957
31729
|
const isNarrowPage = window.matchMedia(mediaQueries.xsOrSmaller.replace("@media ", "")).matches;
|
|
31958
31730
|
|
|
@@ -31980,40 +31752,77 @@ class LabelImage extends React__namespace.Component {
|
|
|
31980
31752
|
bottom: "top"
|
|
31981
31753
|
}[markerPosition];
|
|
31982
31754
|
}
|
|
31983
|
-
const
|
|
31984
|
-
|
|
31985
|
-
|
|
31986
|
-
|
|
31755
|
+
const score = LabelImage.gradeMarker(marker);
|
|
31756
|
+
// Once the question is answered, show markers
|
|
31757
|
+
// with correct answers, otherwise passthrough
|
|
31758
|
+
// the correctness state.
|
|
31759
|
+
const showCorrectness = questionCompleted && score.hasAnswers && score.isCorrect ? "correct" : marker.showCorrectness;
|
|
31987
31760
|
|
|
31761
|
+
// Disable marker interaction once the question is answered correctly.
|
|
31762
|
+
const disabled = showCorrectness === "correct";
|
|
31988
31763
|
const adjustPillDistance = {
|
|
31989
|
-
[`margin${markerPosition.charAt(0).toUpperCase() + markerPosition.slice(1)}`]:
|
|
31764
|
+
[`margin${markerPosition.charAt(0).toUpperCase() + markerPosition.slice(1)}`]: 10 // move pill further from marker
|
|
31990
31765
|
};
|
|
31991
31766
|
|
|
31992
|
-
const
|
|
31993
|
-
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
|
|
31997
|
-
|
|
31998
|
-
|
|
31999
|
-
|
|
32000
|
-
|
|
32001
|
-
|
|
32002
|
-
|
|
32003
|
-
|
|
32004
|
-
|
|
32005
|
-
|
|
32006
|
-
|
|
32007
|
-
|
|
32008
|
-
|
|
32009
|
-
|
|
32010
|
-
|
|
32011
|
-
|
|
32012
|
-
|
|
32013
|
-
|
|
32014
|
-
|
|
32015
|
-
|
|
32016
|
-
|
|
31767
|
+
const answerChoicesActive = index === activeMarkerIndex;
|
|
31768
|
+
const showAnswerChoice = marker.selected && !answerChoicesActive && !this.state.hideAnswers;
|
|
31769
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31770
|
+
style: {
|
|
31771
|
+
position: "absolute",
|
|
31772
|
+
left: `${marker.x}%`,
|
|
31773
|
+
top: `${marker.y}%`,
|
|
31774
|
+
// reset to allow child (answer pill) to control z-index
|
|
31775
|
+
zIndex: "unset"
|
|
31776
|
+
}
|
|
31777
|
+
}, /*#__PURE__*/React__namespace.createElement(AnswerChoices, {
|
|
31778
|
+
key: `answers-${marker.x}.${marker.y}`,
|
|
31779
|
+
choices: this.props.choices.map(choice => ({
|
|
31780
|
+
content: choice,
|
|
31781
|
+
checked: marker.selected ? marker.selected.includes(choice) : false
|
|
31782
|
+
})),
|
|
31783
|
+
multipleSelect: this.props.multipleAnswers,
|
|
31784
|
+
onChange: selection => {
|
|
31785
|
+
this.props.analytics?.onAnalyticsEvent({
|
|
31786
|
+
type: "perseus:label-image:choiced-interacted-with",
|
|
31787
|
+
payload: null
|
|
31788
|
+
});
|
|
31789
|
+
this.handleAnswerChoicesChangeForMarker(index, selection);
|
|
31790
|
+
},
|
|
31791
|
+
onToggle: opened => this.activateMarker(index, opened)
|
|
31792
|
+
// cannot change answer choices once question is answered
|
|
31793
|
+
,
|
|
31794
|
+
disabled: disabled,
|
|
31795
|
+
opener: _ref => {
|
|
31796
|
+
let {
|
|
31797
|
+
opened,
|
|
31798
|
+
text
|
|
31799
|
+
} = _ref;
|
|
31800
|
+
return /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
31801
|
+
role: "button",
|
|
31802
|
+
key: `marker-${marker.x}.${marker.y}`,
|
|
31803
|
+
"aria-label":
|
|
31804
|
+
// already translated in: /widgets/graded-group.tsx
|
|
31805
|
+
showCorrectness === "correct" ? i18n__namespace._("Correct!") : marker.label
|
|
31806
|
+
}, _ref2 => {
|
|
31807
|
+
let {
|
|
31808
|
+
hovered,
|
|
31809
|
+
focused,
|
|
31810
|
+
pressed
|
|
31811
|
+
} = _ref2;
|
|
31812
|
+
return /*#__PURE__*/React__namespace.createElement(Marker, _extends({}, marker, {
|
|
31813
|
+
showCorrectness: showCorrectness,
|
|
31814
|
+
showSelected: opened,
|
|
31815
|
+
showPulsate: !markersInteracted,
|
|
31816
|
+
ref: node => this._markers[index] = node,
|
|
31817
|
+
showAnswer: showAnswerChoice,
|
|
31818
|
+
answerSide: side,
|
|
31819
|
+
answerStyles: adjustPillDistance,
|
|
31820
|
+
analytics: this.props.analytics,
|
|
31821
|
+
focused: focused || pressed,
|
|
31822
|
+
hovered: hovered
|
|
31823
|
+
}));
|
|
31824
|
+
});
|
|
31825
|
+
}
|
|
32017
31826
|
}));
|
|
32018
31827
|
});
|
|
32019
31828
|
}
|
|
@@ -32066,10 +31875,10 @@ class LabelImage extends React__namespace.Component {
|
|
|
32066
31875
|
// than its rendered in the widget, this would
|
|
32067
31876
|
// result in a zoom of the image.
|
|
32068
31877
|
activeMarkerIndex !== -1 && styles$f.imageInteractionDisabled)
|
|
32069
|
-
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null,
|
|
31878
|
+
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref3 => {
|
|
32070
31879
|
let {
|
|
32071
31880
|
setAssetStatus
|
|
32072
|
-
} =
|
|
31881
|
+
} = _ref3;
|
|
32073
31882
|
return /*#__PURE__*/React__namespace.createElement(SvgImage, {
|
|
32074
31883
|
alt: imageAlt,
|
|
32075
31884
|
src: imageUrl,
|
|
@@ -32132,18 +31941,6 @@ const styles$f = aphrodite.StyleSheet.create({
|
|
|
32132
31941
|
},
|
|
32133
31942
|
imageInteractionDisabled: {
|
|
32134
31943
|
pointerEvents: "none"
|
|
32135
|
-
},
|
|
32136
|
-
scrollableChoices: {
|
|
32137
|
-
paddingTop: 8,
|
|
32138
|
-
paddingBottom: 8,
|
|
32139
|
-
// Enable scroll for answer choices within popup on mobile phones.
|
|
32140
|
-
[mediaQueries.xsOrSmaller]: {
|
|
32141
|
-
maxHeight: 250,
|
|
32142
|
-
overflowY: "auto"
|
|
32143
|
-
}
|
|
32144
|
-
},
|
|
32145
|
-
choicesPopover: {
|
|
32146
|
-
padding: 0
|
|
32147
31944
|
}
|
|
32148
31945
|
});
|
|
32149
31946
|
const LabelImageWithDependencies = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
@@ -44299,7 +44096,7 @@ var Video$1 = {
|
|
|
44299
44096
|
};
|
|
44300
44097
|
|
|
44301
44098
|
/* eslint-disable import/no-named-as-default */
|
|
44302
|
-
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];
|
|
44099
|
+
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];
|
|
44303
44100
|
|
|
44304
44101
|
/**
|
|
44305
44102
|
* This should be called by all clients, specifying whether extra widgets are
|
|
@@ -44314,6 +44111,11 @@ const init = function (options) {
|
|
|
44314
44111
|
registerWidgets(basicWidgets);
|
|
44315
44112
|
registerWidgets(extraWidgets);
|
|
44316
44113
|
|
|
44114
|
+
// This section replaces widgets
|
|
44115
|
+
// When it's time to replace the transformer widget
|
|
44116
|
+
// uncomment this line
|
|
44117
|
+
// Widgets.replaceWidget("transformer", "always-correct");
|
|
44118
|
+
|
|
44317
44119
|
// Pass skipMathJax: true if MathJax is already loaded and configured.
|
|
44318
44120
|
const skipMathJax = options.skipMathJax;
|
|
44319
44121
|
if (skipMathJax) {
|
|
@@ -44338,7 +44140,7 @@ const init = function (options) {
|
|
|
44338
44140
|
|
|
44339
44141
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44340
44142
|
const libName = "@khanacademy/perseus";
|
|
44341
|
-
const libVersion = "17.6.
|
|
44143
|
+
const libVersion = "17.6.2";
|
|
44342
44144
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44343
44145
|
|
|
44344
44146
|
const apiVersion = {
|
|
@@ -45785,6 +45587,8 @@ const ItemExtras = [
|
|
|
45785
45587
|
|
|
45786
45588
|
// prettier-ignore
|
|
45787
45589
|
|
|
45590
|
+
//prettier-ignore
|
|
45591
|
+
|
|
45788
45592
|
// A background image applied to various widgets.
|
|
45789
45593
|
|
|
45790
45594
|
const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
|
|
@@ -46907,6 +46711,10 @@ function violatingWidgets(itemData) {
|
|
|
46907
46711
|
*/
|
|
46908
46712
|
const registerAllWidgetsForTesting = () => {
|
|
46909
46713
|
registerWidgets(allWidgets);
|
|
46714
|
+
|
|
46715
|
+
// When it's time to replace the transformer widget
|
|
46716
|
+
// uncomment this line
|
|
46717
|
+
// Widgets.replaceWidget("transformer", "deprecated-standin");
|
|
46910
46718
|
};
|
|
46911
46719
|
|
|
46912
46720
|
const EditorJsonify = {
|