@khanacademy/perseus 46.0.0 → 47.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +1 -1
- package/dist/es/index.js +195 -1363
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +3 -13
- package/dist/index.js +180 -1357
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +0 -11
- package/dist/types.d.ts +0 -2
- package/dist/widget-type-utils.d.ts +0 -2
- package/package.json +1 -1
- package/dist/multi-items/item-types.d.ts +0 -33
- package/dist/multi-items/items.d.ts +0 -53
- package/dist/multi-items/multi-renderer.d.ts +0 -159
- package/dist/multi-items/prop-type-builders.d.ts +0 -14
- package/dist/multi-items/shape-types.d.ts +0 -47
- package/dist/multi-items/shapes.d.ts +0 -23
- package/dist/multi-items/tree-types.d.ts +0 -34
- package/dist/multi-items/trees.d.ts +0 -146
- package/dist/multi-items.d.ts +0 -73
package/dist/index.js
CHANGED
|
@@ -649,7 +649,7 @@ class InnerMathInput extends React__namespace.Component {
|
|
|
649
649
|
className = className + " " + this.props.className;
|
|
650
650
|
}
|
|
651
651
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
652
|
-
style: [styles$
|
|
652
|
+
style: [styles$D.outerWrapper, this.state.focused && styles$D.wrapperFocused, this.props.hasError && styles$D.wrapperError]
|
|
653
653
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
654
654
|
style: {
|
|
655
655
|
display: "flex",
|
|
@@ -685,7 +685,7 @@ class InnerMathInput extends React__namespace.Component {
|
|
|
685
685
|
style: a11y.srOnly
|
|
686
686
|
}, this.context.strings.mathInputDescription), /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
687
687
|
closeButtonVisible: true,
|
|
688
|
-
style: styles$
|
|
688
|
+
style: styles$D.popoverContent
|
|
689
689
|
}, /*#__PURE__*/React__namespace.createElement(mathInput.DesktopKeypad, _extends({
|
|
690
690
|
onAnalyticsEvent: this.props.onAnalyticsEvent,
|
|
691
691
|
extraKeys: this.props.extraKeys,
|
|
@@ -750,9 +750,9 @@ const MathInputIcon = _ref => {
|
|
|
750
750
|
fillColor = wonderBlocksTokens.color.offBlack;
|
|
751
751
|
break;
|
|
752
752
|
}
|
|
753
|
-
const dynamicClass = active || focused ? styles$
|
|
753
|
+
const dynamicClass = active || focused ? styles$D.iconActive : styles$D.iconInactive;
|
|
754
754
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
755
|
-
style: [styles$
|
|
755
|
+
style: [styles$D.iconContainer, dynamicClass]
|
|
756
756
|
}, /*#__PURE__*/React__namespace.createElement("svg", {
|
|
757
757
|
xmlns: "http://www.w3.org/2000/svg",
|
|
758
758
|
width: "16",
|
|
@@ -797,7 +797,7 @@ const inputFocused = {
|
|
|
797
797
|
borderColor: wonderBlocksTokens.color.blue,
|
|
798
798
|
margin: -1
|
|
799
799
|
};
|
|
800
|
-
const styles$
|
|
800
|
+
const styles$D = aphrodite.StyleSheet.create({
|
|
801
801
|
iconContainer: {
|
|
802
802
|
display: "flex",
|
|
803
803
|
justifyContent: "center",
|
|
@@ -2603,7 +2603,7 @@ class Expression extends React__namespace.Component {
|
|
|
2603
2603
|
render() {
|
|
2604
2604
|
if (this.props.apiOptions.customKeypad) {
|
|
2605
2605
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
2606
|
-
className: aphrodite.css(styles$
|
|
2606
|
+
className: aphrodite.css(styles$C.mobileLabelInputWrapper)
|
|
2607
2607
|
}, !!this.props.visibleLabel && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
2608
2608
|
htmlFor: this._textareaId,
|
|
2609
2609
|
tag: "label"
|
|
@@ -2637,7 +2637,7 @@ class Expression extends React__namespace.Component {
|
|
|
2637
2637
|
ERROR_TITLE
|
|
2638
2638
|
} = this.context.strings;
|
|
2639
2639
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
2640
|
-
className: aphrodite.css(styles$
|
|
2640
|
+
className: aphrodite.css(styles$C.desktopLabelInputWrapper)
|
|
2641
2641
|
}, !!this.props.visibleLabel && /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.LabelSmall, {
|
|
2642
2642
|
htmlFor: this._textareaId,
|
|
2643
2643
|
tag: "label"
|
|
@@ -2676,7 +2676,7 @@ class Expression extends React__namespace.Component {
|
|
|
2676
2676
|
}))));
|
|
2677
2677
|
}
|
|
2678
2678
|
}
|
|
2679
|
-
const styles$
|
|
2679
|
+
const styles$C = aphrodite.StyleSheet.create({
|
|
2680
2680
|
mobileLabelInputWrapper: {
|
|
2681
2681
|
padding: "15px 4px 0"
|
|
2682
2682
|
},
|
|
@@ -18124,33 +18124,33 @@ class Lint extends React__namespace.Component {
|
|
|
18124
18124
|
let warningText;
|
|
18125
18125
|
let warningTextStyle;
|
|
18126
18126
|
if (this.props.severity === Severity.Error) {
|
|
18127
|
-
severityStyle = styles$
|
|
18127
|
+
severityStyle = styles$B.indicatorError;
|
|
18128
18128
|
warningText = "Error";
|
|
18129
|
-
warningTextStyle = styles$
|
|
18129
|
+
warningTextStyle = styles$B.publishBlockingError;
|
|
18130
18130
|
} else if (this.props.severity === Severity.Warning) {
|
|
18131
|
-
severityStyle = styles$
|
|
18131
|
+
severityStyle = styles$B.indicatorWarning;
|
|
18132
18132
|
warningText = "Warning";
|
|
18133
|
-
warningTextStyle = styles$
|
|
18133
|
+
warningTextStyle = styles$B.warning;
|
|
18134
18134
|
} else {
|
|
18135
|
-
severityStyle = styles$
|
|
18135
|
+
severityStyle = styles$B.indicatorGuideline;
|
|
18136
18136
|
warningText = "Recommendation";
|
|
18137
|
-
warningTextStyle = styles$
|
|
18137
|
+
warningTextStyle = styles$B.warning;
|
|
18138
18138
|
}
|
|
18139
18139
|
return /*#__PURE__*/React__namespace.createElement("a", {
|
|
18140
18140
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
18141
18141
|
target: "lint-help-window",
|
|
18142
18142
|
className: aphrodite.css(style)
|
|
18143
18143
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
18144
|
-
className: aphrodite.css(styles$
|
|
18144
|
+
className: aphrodite.css(styles$B.indicator, severityStyle)
|
|
18145
18145
|
}, this.props.severity === 1 && /*#__PURE__*/React__namespace.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
18146
|
-
className: aphrodite.css(styles$
|
|
18146
|
+
className: aphrodite.css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
|
|
18147
18147
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React__namespace.createElement("p", {
|
|
18148
18148
|
key: i,
|
|
18149
|
-
className: aphrodite.css(styles$
|
|
18149
|
+
className: aphrodite.css(styles$B.tooltipParagraph)
|
|
18150
18150
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
18151
18151
|
className: aphrodite.css(warningTextStyle)
|
|
18152
18152
|
}, warningText, ":", " "), m)), /*#__PURE__*/React__namespace.createElement("div", {
|
|
18153
|
-
className: aphrodite.css(styles$
|
|
18153
|
+
className: aphrodite.css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
|
|
18154
18154
|
})));
|
|
18155
18155
|
};
|
|
18156
18156
|
|
|
@@ -18178,20 +18178,20 @@ class Lint extends React__namespace.Component {
|
|
|
18178
18178
|
}
|
|
18179
18179
|
if (blockHighlight) {
|
|
18180
18180
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
18181
|
-
className: aphrodite.css(styles$
|
|
18182
|
-
}, this.renderLink(styles$
|
|
18181
|
+
className: aphrodite.css(styles$B.lintContainer, styles$B.lintContainerBlock)
|
|
18182
|
+
}, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
18183
18183
|
}
|
|
18184
18184
|
if (inline) {
|
|
18185
18185
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
18186
|
-
className: aphrodite.css(styles$
|
|
18187
|
-
}, this.renderLink(styles$
|
|
18186
|
+
className: aphrodite.css(styles$B.lintContainer)
|
|
18187
|
+
}, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React__namespace.createElement("span", null, children));
|
|
18188
18188
|
}
|
|
18189
18189
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
18190
|
-
className: aphrodite.css(styles$
|
|
18191
|
-
}, this.renderLink(styles$
|
|
18190
|
+
className: aphrodite.css(styles$B.lintContainer)
|
|
18191
|
+
}, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React__namespace.createElement("div", null, children));
|
|
18192
18192
|
}
|
|
18193
18193
|
}
|
|
18194
|
-
const styles$
|
|
18194
|
+
const styles$B = aphrodite.StyleSheet.create({
|
|
18195
18195
|
// This is the class of the outermost element.
|
|
18196
18196
|
// We use relative positioning so that the lint indicator can be
|
|
18197
18197
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -19012,8 +19012,6 @@ function getWidgetFromWidgetMap(widgetId, widgetMap) {
|
|
|
19012
19012
|
|
|
19013
19013
|
/**
|
|
19014
19014
|
* Get select widgets from a widget map.
|
|
19015
|
-
* Useful for multi-items that needs to split
|
|
19016
|
-
* one PerseusItem into several
|
|
19017
19015
|
*
|
|
19018
19016
|
* @param {ReadonlyArray<string>} widgetIds to extract
|
|
19019
19017
|
* @param {PerseusWidgetsMap} widgetMap to extract from
|
|
@@ -20618,7 +20616,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20618
20616
|
};
|
|
20619
20617
|
const mobileInnerStyle = {
|
|
20620
20618
|
...innerStyle,
|
|
20621
|
-
...styles$
|
|
20619
|
+
...styles$A.mobileZoomableParentFix
|
|
20622
20620
|
};
|
|
20623
20621
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
20624
20622
|
key: state.key,
|
|
@@ -20758,7 +20756,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20758
20756
|
};
|
|
20759
20757
|
const mobileInnerStyle = {
|
|
20760
20758
|
...innerStyle,
|
|
20761
|
-
...styles$
|
|
20759
|
+
...styles$A.mobileZoomableParentFix
|
|
20762
20760
|
};
|
|
20763
20761
|
const wrappedOutput = /*#__PURE__*/React__namespace.createElement("div", {
|
|
20764
20762
|
style: {
|
|
@@ -21221,7 +21219,7 @@ class Renderer extends React__namespace.Component {
|
|
|
21221
21219
|
return this.lastRenderedMarkdown;
|
|
21222
21220
|
}
|
|
21223
21221
|
}
|
|
21224
|
-
const styles$
|
|
21222
|
+
const styles$A = {
|
|
21225
21223
|
mobileZoomableParentFix: {
|
|
21226
21224
|
// NOTE(abdul): There is an issue where transform animations will
|
|
21227
21225
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -22187,10 +22185,10 @@ class InputNumber extends React__namespace.Component {
|
|
|
22187
22185
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
22188
22186
|
// you modify this, double-check if you also need to modify that
|
|
22189
22187
|
// component.
|
|
22190
|
-
const inputStyles = [styles$
|
|
22188
|
+
const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
|
|
22191
22189
|
// Unanswered
|
|
22192
22190
|
if (this.props.reviewMode && !this.props.currentValue) {
|
|
22193
|
-
inputStyles.push(styles$
|
|
22191
|
+
inputStyles.push(styles$z.answerStateUnanswered);
|
|
22194
22192
|
}
|
|
22195
22193
|
return /*#__PURE__*/React__namespace.createElement(InputWithExamples
|
|
22196
22194
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -22209,7 +22207,7 @@ class InputNumber extends React__namespace.Component {
|
|
|
22209
22207
|
});
|
|
22210
22208
|
}
|
|
22211
22209
|
}
|
|
22212
|
-
const styles$
|
|
22210
|
+
const styles$z = aphrodite.StyleSheet.create({
|
|
22213
22211
|
default: {
|
|
22214
22212
|
width: 80,
|
|
22215
22213
|
height: "auto"
|
|
@@ -23377,7 +23375,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
23377
23375
|
const rects = this.state.cachedHighlightRects;
|
|
23378
23376
|
return /*#__PURE__*/React__namespace.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
23379
23377
|
key: index,
|
|
23380
|
-
className: aphrodite.css(styles$
|
|
23378
|
+
className: aphrodite.css(styles$y.highlightRect),
|
|
23381
23379
|
style: {
|
|
23382
23380
|
// NOTE(mdr): We apply `position: absolute` here
|
|
23383
23381
|
// rather than in Aphrodite styles, because
|
|
@@ -23396,7 +23394,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
23396
23394
|
})));
|
|
23397
23395
|
}
|
|
23398
23396
|
}
|
|
23399
|
-
const styles$
|
|
23397
|
+
const styles$y = aphrodite.StyleSheet.create({
|
|
23400
23398
|
highlightRect: {
|
|
23401
23399
|
background: "#fffabe" // highlighter yellow :)
|
|
23402
23400
|
}
|
|
@@ -23477,7 +23475,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
23477
23475
|
// TooltipContent wouldn't let me overwrite
|
|
23478
23476
|
// user-select and onClick
|
|
23479
23477
|
const content = /*#__PURE__*/React__namespace.createElement("div", {
|
|
23480
|
-
className: aphrodite.css(styles$
|
|
23478
|
+
className: aphrodite.css(styles$x.tooltipLabel),
|
|
23481
23479
|
onClick: this.props.onClick
|
|
23482
23480
|
}, this.props.label);
|
|
23483
23481
|
const style = {
|
|
@@ -23497,7 +23495,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
23497
23495
|
}, /*#__PURE__*/React__namespace.createElement("div", null)));
|
|
23498
23496
|
}
|
|
23499
23497
|
}
|
|
23500
|
-
const styles$
|
|
23498
|
+
const styles$x = aphrodite.StyleSheet.create({
|
|
23501
23499
|
tooltipLabel: {
|
|
23502
23500
|
// Unlike most tooltip contents, we don't want this label to be
|
|
23503
23501
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -24055,7 +24053,7 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
24055
24053
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
24056
24054
|
const buildHighlight = r => this._buildHighlight(r);
|
|
24057
24055
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24058
|
-
className: aphrodite.css(styles$
|
|
24056
|
+
className: aphrodite.css(styles$w.container),
|
|
24059
24057
|
ref: container => this._container = container
|
|
24060
24058
|
}, /*#__PURE__*/React__namespace.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React__namespace.createElement(HighlightingUI, {
|
|
24061
24059
|
buildHighlight: buildHighlight,
|
|
@@ -24076,14 +24074,14 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
24076
24074
|
onAddHighlight: this._handleAddHighlight,
|
|
24077
24075
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
24078
24076
|
})), /*#__PURE__*/React__namespace.createElement("div", {
|
|
24079
|
-
className: aphrodite.css(styles$
|
|
24077
|
+
className: aphrodite.css(styles$w.content),
|
|
24080
24078
|
ref: content => this._content = content
|
|
24081
24079
|
}, /*#__PURE__*/React__namespace.createElement(WordIndexer, {
|
|
24082
24080
|
onWordsUpdate: this._handleWordsUpdate
|
|
24083
24081
|
}, this.props.children)));
|
|
24084
24082
|
}
|
|
24085
24083
|
}
|
|
24086
|
-
const styles$
|
|
24084
|
+
const styles$w = aphrodite.StyleSheet.create({
|
|
24087
24085
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
24088
24086
|
// content will receive the browser's native pointer events. (Highlights
|
|
24089
24087
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -24505,7 +24503,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
24505
24503
|
}
|
|
24506
24504
|
render() {
|
|
24507
24505
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
24508
|
-
className: aphrodite.css(styles$
|
|
24506
|
+
className: aphrodite.css(styles$v.measurer),
|
|
24509
24507
|
"aria-hidden": "true"
|
|
24510
24508
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
24511
24509
|
ref: ref => this._line = ref,
|
|
@@ -24513,7 +24511,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
24513
24511
|
}, "Line Height Measurement"));
|
|
24514
24512
|
}
|
|
24515
24513
|
}
|
|
24516
|
-
const styles$
|
|
24514
|
+
const styles$v = aphrodite.StyleSheet.create({
|
|
24517
24515
|
measurer: {
|
|
24518
24516
|
position: "absolute",
|
|
24519
24517
|
top: 0,
|
|
@@ -25494,11 +25492,11 @@ const FocusRing = function (_ref) {
|
|
|
25494
25492
|
};
|
|
25495
25493
|
return /*#__PURE__*/React__namespace.createElement("span", {
|
|
25496
25494
|
"data-testid": "focus-ring",
|
|
25497
|
-
className: aphrodite.css(styles$
|
|
25495
|
+
className: aphrodite.css(styles$u.ring),
|
|
25498
25496
|
style: style
|
|
25499
25497
|
}, children);
|
|
25500
25498
|
};
|
|
25501
|
-
const styles$
|
|
25499
|
+
const styles$u = aphrodite.StyleSheet.create({
|
|
25502
25500
|
ring: {
|
|
25503
25501
|
margin: "auto",
|
|
25504
25502
|
display: "inline-block",
|
|
@@ -25525,7 +25523,7 @@ function getChoiceLetter(pos, strings) {
|
|
|
25525
25523
|
}
|
|
25526
25524
|
|
|
25527
25525
|
const CHOICE_ICON_SIZE = 24;
|
|
25528
|
-
const styles$
|
|
25526
|
+
const styles$t = aphrodite.StyleSheet.create({
|
|
25529
25527
|
iconWrapper: {
|
|
25530
25528
|
display: "inline-block",
|
|
25531
25529
|
position: "relative"
|
|
@@ -25548,7 +25546,7 @@ const CrossOutLine = function (props) {
|
|
|
25548
25546
|
width: CROSS_OUT_LINE_SIZE,
|
|
25549
25547
|
height: CROSS_OUT_LINE_SIZE,
|
|
25550
25548
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
25551
|
-
className: aphrodite.css(styles$
|
|
25549
|
+
className: aphrodite.css(styles$s.crossOutLine),
|
|
25552
25550
|
"data-testid": "choice-icon__cross-out-line"
|
|
25553
25551
|
}, /*#__PURE__*/React__namespace.createElement("line", {
|
|
25554
25552
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -25563,7 +25561,7 @@ const CrossOutLine = function (props) {
|
|
|
25563
25561
|
strokeLinecap: "round"
|
|
25564
25562
|
}));
|
|
25565
25563
|
};
|
|
25566
|
-
const styles$
|
|
25564
|
+
const styles$s = aphrodite.StyleSheet.create({
|
|
25567
25565
|
crossOutLine: {
|
|
25568
25566
|
// Center the icon within the container.
|
|
25569
25567
|
position: "absolute",
|
|
@@ -25647,7 +25645,7 @@ const ChoiceIcon = function (props) {
|
|
|
25647
25645
|
} = props;
|
|
25648
25646
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
25649
25647
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25650
|
-
className: aphrodite.css(styles$
|
|
25648
|
+
className: aphrodite.css(styles$t.iconWrapper)
|
|
25651
25649
|
}, /*#__PURE__*/React__namespace.createElement(FocusRing, {
|
|
25652
25650
|
color: wonderBlocksTokens.color.blue,
|
|
25653
25651
|
visible: focused || hovered,
|
|
@@ -25655,13 +25653,13 @@ const ChoiceIcon = function (props) {
|
|
|
25655
25653
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
25656
25654
|
style: dynamicStyles,
|
|
25657
25655
|
"data-testid": "choice-icon__library-choice-icon",
|
|
25658
|
-
className: aphrodite.css(styles$
|
|
25656
|
+
className: aphrodite.css(styles$r.circle, showCorrectness && correct && styles$r.circleCorrect, showCorrectness && !correct && styles$r.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$r.circleIncorrectAnswered)
|
|
25659
25657
|
// used in BaseRadio editMode to check
|
|
25660
25658
|
// if we actually clicked on the radio icon
|
|
25661
25659
|
,
|
|
25662
25660
|
"data-is-radio-icon": true
|
|
25663
25661
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
25664
|
-
className: aphrodite.css(styles$
|
|
25662
|
+
className: aphrodite.css(styles$r.innerWrapper)
|
|
25665
25663
|
}, /*#__PURE__*/React__namespace.createElement(ChoiceInner, {
|
|
25666
25664
|
pos: pos,
|
|
25667
25665
|
showCorrectness: showCorrectness,
|
|
@@ -25670,7 +25668,7 @@ const ChoiceIcon = function (props) {
|
|
|
25670
25668
|
color: dynamicStyles.borderColor
|
|
25671
25669
|
}));
|
|
25672
25670
|
};
|
|
25673
|
-
const styles$
|
|
25671
|
+
const styles$r = aphrodite.StyleSheet.create({
|
|
25674
25672
|
innerWrapper: {
|
|
25675
25673
|
width: CHOICE_ICON_SIZE,
|
|
25676
25674
|
height: CHOICE_ICON_SIZE,
|
|
@@ -25765,19 +25763,19 @@ const OptionStatus = function (props) {
|
|
|
25765
25763
|
}
|
|
25766
25764
|
let textStyle;
|
|
25767
25765
|
if (correct) {
|
|
25768
|
-
textStyle = styles$
|
|
25766
|
+
textStyle = styles$q.correct;
|
|
25769
25767
|
} else {
|
|
25770
25768
|
if (checked || previouslyAnswered) {
|
|
25771
|
-
textStyle = styles$
|
|
25769
|
+
textStyle = styles$q.incorrectAnswered;
|
|
25772
25770
|
} else {
|
|
25773
|
-
textStyle = styles$
|
|
25771
|
+
textStyle = styles$q.incorrect;
|
|
25774
25772
|
}
|
|
25775
25773
|
}
|
|
25776
25774
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
25777
|
-
className: aphrodite.css(styles$
|
|
25775
|
+
className: aphrodite.css(styles$q.text, textStyle)
|
|
25778
25776
|
}, renderText(checked, correct, crossedOut, strings));
|
|
25779
25777
|
};
|
|
25780
|
-
const styles$
|
|
25778
|
+
const styles$q = aphrodite.StyleSheet.create({
|
|
25781
25779
|
text: {
|
|
25782
25780
|
alignItems: "center",
|
|
25783
25781
|
display: "flex",
|
|
@@ -25846,8 +25844,8 @@ const Choice = function (props) {
|
|
|
25846
25844
|
crossedOut: updatedCrossedOut
|
|
25847
25845
|
});
|
|
25848
25846
|
}
|
|
25849
|
-
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$
|
|
25850
|
-
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$
|
|
25847
|
+
const descriptionClassName = classNames__default["default"]("description", aphrodite.css(styles$p.description));
|
|
25848
|
+
const rationaleClassName = classNames__default["default"]("perseus-radio-rationale-content", aphrodite.css(styles$p.rationale));
|
|
25851
25849
|
|
|
25852
25850
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
25853
25851
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -26014,7 +26012,7 @@ const Choice = function (props) {
|
|
|
26014
26012
|
"data-testid": `perseus-radio-rationale-content-${pos}`
|
|
26015
26013
|
}, rationale));
|
|
26016
26014
|
};
|
|
26017
|
-
const styles$
|
|
26015
|
+
const styles$p = aphrodite.StyleSheet.create({
|
|
26018
26016
|
description: {
|
|
26019
26017
|
display: "inline-block",
|
|
26020
26018
|
width: "100%"
|
|
@@ -26205,10 +26203,10 @@ const BaseRadio = function (_ref) {
|
|
|
26205
26203
|
const isMobile = apiOptions.isMobile;
|
|
26206
26204
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
26207
26205
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
26208
|
-
const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$
|
|
26209
|
-
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$
|
|
26206
|
+
const className = classNames__default["default"]("perseus-widget-radio", !editMode && "perseus-rendered-radio", aphrodite.css(styles$o.radio, styles$o.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$o.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$o.radioContainerLastHighlighted));
|
|
26207
|
+
const instructionsClassName = classNames__default["default"]("instructions", aphrodite.css(styles$o.instructions, isMobile && styles$o.instructionsMobile));
|
|
26210
26208
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
26211
|
-
const responsiveClassName = aphrodite.css(styles$
|
|
26209
|
+
const responsiveClassName = aphrodite.css(styles$o.responsiveFieldset);
|
|
26212
26210
|
const fieldset = /*#__PURE__*/React__namespace.createElement("fieldset", {
|
|
26213
26211
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
26214
26212
|
}, /*#__PURE__*/React__namespace.createElement("legend", {
|
|
@@ -26259,7 +26257,7 @@ const BaseRadio = function (_ref) {
|
|
|
26259
26257
|
const aphroditeClassName = checked => {
|
|
26260
26258
|
// Whether or not to show correctness borders
|
|
26261
26259
|
// for this choice and the next choice.
|
|
26262
|
-
return aphrodite.css(sharedStyles.aboveScratchpad, styles$
|
|
26260
|
+
return aphrodite.css(sharedStyles.aboveScratchpad, styles$o.item, styles$o.responsiveItem, checked && styles$o.selectedItem, checked && choice.highlighted && styles$o.aboveBackdrop, checked && choice.highlighted && apiOptions.isMobile && styles$o.aboveBackdropMobile, nextChoiceHighlighted && apiOptions.isMobile && styles$o.nextHighlighted);
|
|
26263
26261
|
};
|
|
26264
26262
|
|
|
26265
26263
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -26324,10 +26322,10 @@ const BaseRadio = function (_ref) {
|
|
|
26324
26322
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
26325
26323
|
// an issue especially on phones.
|
|
26326
26324
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
26327
|
-
className: aphrodite.css(styles$
|
|
26325
|
+
className: aphrodite.css(styles$o.responsiveContainer)
|
|
26328
26326
|
}, fieldset);
|
|
26329
26327
|
};
|
|
26330
|
-
const styles$
|
|
26328
|
+
const styles$o = aphrodite.StyleSheet.create({
|
|
26331
26329
|
instructions: {
|
|
26332
26330
|
display: "block",
|
|
26333
26331
|
color: gray17,
|
|
@@ -27059,9 +27057,9 @@ class Categorizer extends React__namespace.Component {
|
|
|
27059
27057
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
27060
27058
|
}
|
|
27061
27059
|
const table = /*#__PURE__*/React__namespace.createElement("table", {
|
|
27062
|
-
className: "categorizer-table " + aphrodite.css(styles$
|
|
27060
|
+
className: "categorizer-table " + aphrodite.css(styles$n.mobileTable)
|
|
27063
27061
|
}, /*#__PURE__*/React__namespace.createElement("thead", null, /*#__PURE__*/React__namespace.createElement("tr", null, /*#__PURE__*/React__namespace.createElement("td", {
|
|
27064
|
-
className: aphrodite.css(styles$
|
|
27062
|
+
className: aphrodite.css(styles$n.emptyHeaderCell)
|
|
27065
27063
|
}), this.props.categories.map((category, i) => {
|
|
27066
27064
|
// Array index is the correct key here, as that's
|
|
27067
27065
|
// how category grading actually works -- no way
|
|
@@ -27069,7 +27067,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
27069
27067
|
// middle. (If we later add that, this should be
|
|
27070
27068
|
// fixed.)
|
|
27071
27069
|
return /*#__PURE__*/React__namespace.createElement("th", {
|
|
27072
|
-
className: aphrodite.css(styles$
|
|
27070
|
+
className: aphrodite.css(styles$n.header),
|
|
27073
27071
|
key: i
|
|
27074
27072
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27075
27073
|
content: category,
|
|
@@ -27091,7 +27089,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
27091
27089
|
})), self.props.categories.map((catName, catNum) => {
|
|
27092
27090
|
const selected = self.props.values[itemNum] === catNum;
|
|
27093
27091
|
return /*#__PURE__*/React__namespace.createElement("td", {
|
|
27094
|
-
className: "category " + aphrodite.css(styles$
|
|
27092
|
+
className: "category " + aphrodite.css(styles$n.cell),
|
|
27095
27093
|
key: catNum
|
|
27096
27094
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
27097
27095
|
className: ClassNames.INTERACTIVE,
|
|
@@ -27106,7 +27104,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
27106
27104
|
onChange: () => this.onChange(itemNum, catNum),
|
|
27107
27105
|
onClick: e => e.stopPropagation()
|
|
27108
27106
|
}), !isMobile && /*#__PURE__*/React__namespace.createElement("span", {
|
|
27109
|
-
className: aphrodite.css(styles$
|
|
27107
|
+
className: aphrodite.css(styles$n.radioSpan, selected && styles$n.checkedRadioSpan, this.props.static && selected && styles$n.staticCheckedRadioSpan)
|
|
27110
27108
|
}, selected ? /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React__namespace.createElement(InlineIcon, iconCircleThin))));
|
|
27111
27109
|
}));
|
|
27112
27110
|
/* eslint-enable max-len */
|
|
@@ -27118,7 +27116,7 @@ class Categorizer extends React__namespace.Component {
|
|
|
27118
27116
|
"categorizer-container": true,
|
|
27119
27117
|
"static-mode": this.props.static
|
|
27120
27118
|
});
|
|
27121
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
27119
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$n.fullBleedContainer] : [];
|
|
27122
27120
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
27123
27121
|
className: extraClassNames + " " + aphrodite.css(...inlineStyles)
|
|
27124
27122
|
}, table);
|
|
@@ -27130,7 +27128,7 @@ const pageMargin = 16;
|
|
|
27130
27128
|
|
|
27131
27129
|
// Stylesheets aren't directly testable
|
|
27132
27130
|
/* c8 ignore next */
|
|
27133
|
-
const styles$
|
|
27131
|
+
const styles$n = aphrodite.StyleSheet.create({
|
|
27134
27132
|
mobileTable: {
|
|
27135
27133
|
[mediaQueries.smOrSmaller]: {
|
|
27136
27134
|
minWidth: "auto"
|
|
@@ -27399,7 +27397,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
27399
27397
|
// creator "went wild".
|
|
27400
27398
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
27401
27399
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
27402
|
-
className: aphrodite.css(styles$
|
|
27400
|
+
className: aphrodite.css(styles$m.widthOverride, styleContainer && styles$m.container)
|
|
27403
27401
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
27404
27402
|
sandbox: sandboxOptions,
|
|
27405
27403
|
src: url,
|
|
@@ -27409,7 +27407,7 @@ class CSProgram extends React__namespace.Component {
|
|
|
27409
27407
|
}));
|
|
27410
27408
|
}
|
|
27411
27409
|
}
|
|
27412
|
-
const styles$
|
|
27410
|
+
const styles$m = aphrodite.StyleSheet.create({
|
|
27413
27411
|
// Override the inherited width from the perseus paragraph class
|
|
27414
27412
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
27415
27413
|
widthOverride: {
|
|
@@ -27460,7 +27458,7 @@ class Definition extends React__namespace.Component {
|
|
|
27460
27458
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.Popover, {
|
|
27461
27459
|
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
27462
27460
|
color: "white",
|
|
27463
|
-
style: styles$
|
|
27461
|
+
style: styles$l.tooltipBody,
|
|
27464
27462
|
closeButtonVisible: true
|
|
27465
27463
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27466
27464
|
apiOptions: this.props.apiOptions,
|
|
@@ -27492,7 +27490,7 @@ class Definition extends React__namespace.Component {
|
|
|
27492
27490
|
});
|
|
27493
27491
|
}
|
|
27494
27492
|
}
|
|
27495
|
-
const styles$
|
|
27493
|
+
const styles$l = {
|
|
27496
27494
|
tooltipBody: {
|
|
27497
27495
|
color: wonderBlocksTokens.color.offBlack,
|
|
27498
27496
|
fontSize: 20,
|
|
@@ -27761,7 +27759,7 @@ class Explanation extends React__namespace.Component {
|
|
|
27761
27759
|
marginRight: "-6px",
|
|
27762
27760
|
"white-space": "normal"
|
|
27763
27761
|
};
|
|
27764
|
-
const contentStyling = [styles$
|
|
27762
|
+
const contentStyling = [styles$k.content, this.state.expanded ? styles$k.contentExpanded : styles$k.contentCollapsed, allowTransition && (this.state.expanded ? styles$k.transitionExpanded : styles$k.transitionCollapsed)];
|
|
27765
27763
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.UniqueIDProvider, {
|
|
27766
27764
|
mockOnFirstRender: true,
|
|
27767
27765
|
scope: "explanation-widget"
|
|
@@ -27780,7 +27778,7 @@ class Explanation extends React__namespace.Component {
|
|
|
27780
27778
|
"aria-hidden": !this.state.expanded,
|
|
27781
27779
|
testId: "content-container"
|
|
27782
27780
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
27783
|
-
style: styles$
|
|
27781
|
+
style: styles$k.contentWrapper
|
|
27784
27782
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27785
27783
|
apiOptions: this.props.apiOptions,
|
|
27786
27784
|
content: this.props.explanation,
|
|
@@ -27793,7 +27791,7 @@ class Explanation extends React__namespace.Component {
|
|
|
27793
27791
|
const leftBorderSpacing = 23;
|
|
27794
27792
|
const verticalContentPadding = 10;
|
|
27795
27793
|
const arrowHeight = 14;
|
|
27796
|
-
const styles$
|
|
27794
|
+
const styles$k = aphrodite.StyleSheet.create({
|
|
27797
27795
|
content: {
|
|
27798
27796
|
borderLeft: "0px solid #ccc",
|
|
27799
27797
|
display: "inline-grid",
|
|
@@ -27879,15 +27877,15 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
27879
27877
|
nextQuestion
|
|
27880
27878
|
} = this.context.strings;
|
|
27881
27879
|
const answerBarStyle = {
|
|
27882
|
-
...styles$
|
|
27880
|
+
...styles$j.answerBar,
|
|
27883
27881
|
backgroundColor: answerBarState === "CORRECT" ? wonderBlocksTokens.color.offWhite : "white",
|
|
27884
27882
|
// Center the "Correct!" message only when there's no next question
|
|
27885
27883
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
27886
27884
|
};
|
|
27887
27885
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React__namespace.createElement("span", {
|
|
27888
|
-
style: styles$
|
|
27886
|
+
style: styles$j.text
|
|
27889
27887
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
27890
|
-
style: styles$
|
|
27888
|
+
style: styles$j.tryAgainIcon
|
|
27891
27889
|
}, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React__namespace.createElement("span", {
|
|
27892
27890
|
style: {
|
|
27893
27891
|
marginLeft: 8
|
|
@@ -27906,7 +27904,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
27906
27904
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
27907
27905
|
style: answerBarStyle
|
|
27908
27906
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
27909
|
-
style: styles$
|
|
27907
|
+
style: styles$j.text
|
|
27910
27908
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
27911
27909
|
style: {
|
|
27912
27910
|
fontSize: 28,
|
|
@@ -27928,7 +27926,7 @@ class GradedGroupAnswerBar extends React__namespace.Component {
|
|
|
27928
27926
|
}
|
|
27929
27927
|
}
|
|
27930
27928
|
const fontSize = 17;
|
|
27931
|
-
const styles$
|
|
27929
|
+
const styles$j = {
|
|
27932
27930
|
answerBar: {
|
|
27933
27931
|
display: "flex",
|
|
27934
27932
|
alignItems: "center",
|
|
@@ -28121,7 +28119,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
28121
28119
|
}));
|
|
28122
28120
|
gradeStatus = this.context.strings.incorrect;
|
|
28123
28121
|
}
|
|
28124
|
-
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$
|
|
28122
|
+
const mobileClass = this.props.inGradedGroupSet ? aphrodite.css(styles$i.gradedGroupInSet) : aphrodite.css(styles$i.gradedGroup);
|
|
28125
28123
|
const classes = classNames__default["default"]({
|
|
28126
28124
|
[mobileClass]: apiOptions.isMobile,
|
|
28127
28125
|
"perseus-graded-group": true,
|
|
@@ -28140,7 +28138,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
28140
28138
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28141
28139
|
className: classes
|
|
28142
28140
|
}, !!this.props.title && /*#__PURE__*/React__namespace.createElement("div", {
|
|
28143
|
-
className: aphrodite.css(styles$
|
|
28141
|
+
className: aphrodite.css(styles$i.title)
|
|
28144
28142
|
}, this.props.title), /*#__PURE__*/React__namespace.createElement(Renderer, _extends({}, this.props, {
|
|
28145
28143
|
ref: this.rendererRef,
|
|
28146
28144
|
apiOptions: {
|
|
@@ -28173,7 +28171,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
28173
28171
|
}, this.context.strings.nextQuestion), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement("button", {
|
|
28174
28172
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
28175
28173
|
tabIndex: "0",
|
|
28176
|
-
className: aphrodite.css(styles$
|
|
28174
|
+
className: aphrodite.css(styles$i.explanationTitle),
|
|
28177
28175
|
onClick: () => this.setState({
|
|
28178
28176
|
showHint: false
|
|
28179
28177
|
}),
|
|
@@ -28205,7 +28203,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
28205
28203
|
showHint: true
|
|
28206
28204
|
});
|
|
28207
28205
|
},
|
|
28208
|
-
className: aphrodite.css(styles$
|
|
28206
|
+
className: aphrodite.css(styles$i.showHintLink)
|
|
28209
28207
|
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React__namespace.createElement(GradedGroupAnswerBar, {
|
|
28210
28208
|
apiOptions: apiOptions,
|
|
28211
28209
|
answerBarState: answerBarState,
|
|
@@ -28217,7 +28215,7 @@ class GradedGroup extends React__namespace.Component {
|
|
|
28217
28215
|
const traverseChildWidgets$2 = function (props, traverseRenderer) {
|
|
28218
28216
|
return ___default["default"].extend({}, props, traverseRenderer(props));
|
|
28219
28217
|
};
|
|
28220
|
-
const styles$
|
|
28218
|
+
const styles$i = aphrodite.StyleSheet.create({
|
|
28221
28219
|
gradedGroupInSet: {
|
|
28222
28220
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
28223
28221
|
marginLeft: 0,
|
|
@@ -28298,20 +28296,20 @@ class Indicators extends React__namespace.Component {
|
|
|
28298
28296
|
return /*#__PURE__*/React__namespace.createElement("ul", {
|
|
28299
28297
|
// reduntantly add class name for use in .less files--
|
|
28300
28298
|
// the styles object key gets hashed
|
|
28301
|
-
className: classNames__default["default"](aphrodite.css(styles$
|
|
28299
|
+
className: classNames__default["default"](aphrodite.css(styles$h.indicatorContainer), "indicatorContainer")
|
|
28302
28300
|
}, this.props.gradedGroups.map((_ref, i) => {
|
|
28303
28301
|
let {
|
|
28304
28302
|
title
|
|
28305
28303
|
} = _ref;
|
|
28306
28304
|
return /*#__PURE__*/React__namespace.createElement("li", {
|
|
28307
|
-
className: aphrodite.css(styles$
|
|
28305
|
+
className: aphrodite.css(styles$h.indicator),
|
|
28308
28306
|
key: title
|
|
28309
28307
|
}, /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
28310
28308
|
role: "button",
|
|
28311
28309
|
"aria-label": this.context.strings.skipToTitle({
|
|
28312
28310
|
title
|
|
28313
28311
|
}),
|
|
28314
|
-
style: styles$
|
|
28312
|
+
style: styles$h.indicatorButton,
|
|
28315
28313
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
28316
28314
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
28317
28315
|
}, _ref2 => {
|
|
@@ -28321,9 +28319,9 @@ class Indicators extends React__namespace.Component {
|
|
|
28321
28319
|
pressed
|
|
28322
28320
|
} = _ref2;
|
|
28323
28321
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
28324
|
-
style: [styles$
|
|
28322
|
+
style: [styles$h.indicatorDot, (hovered || focused || pressed) && styles$h.indicatorDotFocused]
|
|
28325
28323
|
}, i === this.props.currentGroup && /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
28326
|
-
style: styles$
|
|
28324
|
+
style: styles$h.indicatorDotActive
|
|
28327
28325
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
28328
28326
|
className: aphrodite.css(a11y.srOnly)
|
|
28329
28327
|
}, this.context.strings.current)));
|
|
@@ -28403,7 +28401,7 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
28403
28401
|
} = getDependencies();
|
|
28404
28402
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
28405
28403
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28406
|
-
className: aphrodite.css(styles$
|
|
28404
|
+
className: aphrodite.css(styles$h.container)
|
|
28407
28405
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
28408
28406
|
return (
|
|
28409
28407
|
/*#__PURE__*/
|
|
@@ -28426,13 +28424,13 @@ class GradedGroupSet extends React__namespace.Component {
|
|
|
28426
28424
|
const numGroups = this.props.gradedGroups.length;
|
|
28427
28425
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
28428
28426
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28429
|
-
className: aphrodite.css(styles$
|
|
28427
|
+
className: aphrodite.css(styles$h.container)
|
|
28430
28428
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
28431
|
-
className: aphrodite.css(styles$
|
|
28429
|
+
className: aphrodite.css(styles$h.top)
|
|
28432
28430
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
28433
|
-
className: aphrodite.css(styles$
|
|
28431
|
+
className: aphrodite.css(styles$h.title)
|
|
28434
28432
|
}, currentGroup.title), /*#__PURE__*/React__namespace.createElement("div", {
|
|
28435
|
-
className: aphrodite.css(styles$
|
|
28433
|
+
className: aphrodite.css(styles$h.spacer)
|
|
28436
28434
|
}), /*#__PURE__*/React__namespace.createElement(Indicators, {
|
|
28437
28435
|
currentGroup: this.state.currentGroup,
|
|
28438
28436
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -28470,7 +28468,7 @@ var GradedGroupSet$1 = {
|
|
|
28470
28468
|
tracking: "all",
|
|
28471
28469
|
isLintable: true
|
|
28472
28470
|
};
|
|
28473
|
-
const styles$
|
|
28471
|
+
const styles$h = aphrodite.StyleSheet.create({
|
|
28474
28472
|
top: {
|
|
28475
28473
|
display: "flex",
|
|
28476
28474
|
flexDirection: "row"
|
|
@@ -28576,7 +28574,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
28576
28574
|
id: "" + i,
|
|
28577
28575
|
ref: "button" + i,
|
|
28578
28576
|
key: "" + i,
|
|
28579
|
-
className: aphrodite.css(styles$
|
|
28577
|
+
className: aphrodite.css(styles$g.buttonStyle, button.value === value && styles$g.selectedStyle),
|
|
28580
28578
|
onClick: () => this.toggleSelect(button.value)
|
|
28581
28579
|
}, button.content || "" + button.value);
|
|
28582
28580
|
});
|
|
@@ -28589,7 +28587,7 @@ class ButtonGroup extends React__namespace.Component {
|
|
|
28589
28587
|
}, buttons);
|
|
28590
28588
|
}
|
|
28591
28589
|
}
|
|
28592
|
-
const styles$
|
|
28590
|
+
const styles$g = aphrodite.StyleSheet.create({
|
|
28593
28591
|
buttonStyle: {
|
|
28594
28592
|
backgroundColor: "white",
|
|
28595
28593
|
border: "1px solid #ccc",
|
|
@@ -31967,7 +31965,7 @@ const VisibleIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
|
31967
31965
|
width: "24",
|
|
31968
31966
|
height: "24",
|
|
31969
31967
|
viewBox: "0 0 24 24",
|
|
31970
|
-
className: aphrodite.css(styles$
|
|
31968
|
+
className: aphrodite.css(styles$f.icon)
|
|
31971
31969
|
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
31972
31970
|
id: "a",
|
|
31973
31971
|
d: "M7.401 10.035c-1.424.748-2.599 1.905-3.544 " + "3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 " + "12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 " + "1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-" + "3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 " + "0 0 0 0 6z"
|
|
@@ -31998,7 +31996,7 @@ const HiddenIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
|
31998
31996
|
width: "24",
|
|
31999
31997
|
height: "24",
|
|
32000
31998
|
viewBox: "0 0 24 24",
|
|
32001
|
-
className: aphrodite.css(styles$
|
|
31999
|
+
className: aphrodite.css(styles$f.icon)
|
|
32002
32000
|
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
32003
32001
|
id: "a",
|
|
32004
32002
|
d: "M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 " + "7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 " + "1.028c-.945-1.574-2.12-2.73-3.544-3.48.258." + "604.401 1.268.401 1.966 0 1.02-.305 " + "1.967-.828 2.757l2.535 2.536a1 1 0 0 " + "1-1.414 1.414l-12-12a1 1 0 0 1 " + "1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 " + "0-4.001-4.001l4 4.001zM6.072 8.486l2.976 " + "2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 " + "0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 " + "3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 " + "2.363-3.085 3.929-4z"
|
|
@@ -32037,20 +32035,20 @@ const HUD = _ref => {
|
|
|
32037
32035
|
let state;
|
|
32038
32036
|
let icon;
|
|
32039
32037
|
if (enabled) {
|
|
32040
|
-
state = styles$
|
|
32038
|
+
state = styles$f.enabled;
|
|
32041
32039
|
icon = /*#__PURE__*/React__namespace.createElement(VisibleIcon, null);
|
|
32042
32040
|
} else {
|
|
32043
|
-
state = styles$
|
|
32041
|
+
state = styles$f.disabled;
|
|
32044
32042
|
icon = /*#__PURE__*/React__namespace.createElement(HiddenIcon, null);
|
|
32045
32043
|
}
|
|
32046
32044
|
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
32047
|
-
className: aphrodite.css(styles$
|
|
32045
|
+
className: aphrodite.css(styles$f.hud, fixedPosition && styles$f.hudFixedPosition, state),
|
|
32048
32046
|
onClick: e => {
|
|
32049
32047
|
onClick();
|
|
32050
32048
|
}
|
|
32051
32049
|
}, icon, message);
|
|
32052
32050
|
};
|
|
32053
|
-
const styles$
|
|
32051
|
+
const styles$f = aphrodite.StyleSheet.create({
|
|
32054
32052
|
hud: {
|
|
32055
32053
|
boxSizing: "border-box",
|
|
32056
32054
|
height: 36,
|
|
@@ -32103,16 +32101,16 @@ const styles$g = aphrodite.StyleSheet.create({
|
|
|
32103
32101
|
const InfoTipBase = props => {
|
|
32104
32102
|
return /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
32105
32103
|
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.Body, {
|
|
32106
|
-
style: styles$
|
|
32104
|
+
style: styles$e.body
|
|
32107
32105
|
}, props.children),
|
|
32108
32106
|
placement: "right"
|
|
32109
32107
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
|
|
32110
32108
|
size: "small",
|
|
32111
32109
|
icon: questionIcon__default["default"],
|
|
32112
|
-
style: styles$
|
|
32110
|
+
style: styles$e.spacingLeft
|
|
32113
32111
|
}));
|
|
32114
32112
|
};
|
|
32115
|
-
const styles$
|
|
32113
|
+
const styles$e = aphrodite.StyleSheet.create({
|
|
32116
32114
|
spacingLeft: {
|
|
32117
32115
|
marginInlineStart: wonderBlocksTokens.spacing.xxxSmall_4
|
|
32118
32116
|
},
|
|
@@ -32188,7 +32186,7 @@ class MultiButtonGroup extends React__namespace.Component {
|
|
|
32188
32186
|
id: "" + i,
|
|
32189
32187
|
key: "" + i,
|
|
32190
32188
|
ref: "button" + i,
|
|
32191
|
-
className: aphrodite.css(styles$
|
|
32189
|
+
className: aphrodite.css(styles$d.buttonStyle, selected && styles$d.selectedStyle),
|
|
32192
32190
|
onClick: () => this.toggleSelect(button.value)
|
|
32193
32191
|
}, button.content || "" + button.value);
|
|
32194
32192
|
});
|
|
@@ -32201,7 +32199,7 @@ class MultiButtonGroup extends React__namespace.Component {
|
|
|
32201
32199
|
}, buttons);
|
|
32202
32200
|
}
|
|
32203
32201
|
}
|
|
32204
|
-
const styles$
|
|
32202
|
+
const styles$d = aphrodite.StyleSheet.create({
|
|
32205
32203
|
buttonStyle: {
|
|
32206
32204
|
backgroundColor: "white",
|
|
32207
32205
|
border: "1px solid #ccc",
|
|
@@ -32605,14 +32603,6 @@ const LegacyGrid = _ref => {
|
|
|
32605
32603
|
* A "PerseusArticle" is an item that is meant to be rendered as an article.
|
|
32606
32604
|
* This item is never scored and is rendered by the `ArticleRenderer`.
|
|
32607
32605
|
*/
|
|
32608
|
-
/**
|
|
32609
|
-
* A "MultiItem" is an advanced Perseus item. It is rendered by the
|
|
32610
|
-
* `MultiRenderer` and you can control the layout of individual parts of the
|
|
32611
|
-
* item.
|
|
32612
|
-
*
|
|
32613
|
-
* @deprecated MultiItem support is slated for removal in a future Perseus
|
|
32614
|
-
* release.
|
|
32615
|
-
*/
|
|
32616
32606
|
const ItemExtras = [
|
|
32617
32607
|
// The user might benefit from using a Scientific Calculator. Provided on Khan Academy when true
|
|
32618
32608
|
"calculator",
|
|
@@ -39071,7 +39061,7 @@ const HideAnswersToggle = props => {
|
|
|
39071
39061
|
strings
|
|
39072
39062
|
} = usePerseusI18n();
|
|
39073
39063
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
39074
|
-
style: styles$
|
|
39064
|
+
style: styles$c.switchWrapper
|
|
39075
39065
|
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
39076
39066
|
id: switchId,
|
|
39077
39067
|
checked: props.areAnswersHidden,
|
|
@@ -39083,7 +39073,7 @@ const HideAnswersToggle = props => {
|
|
|
39083
39073
|
tag: "label"
|
|
39084
39074
|
}, strings.hideAnswersToggleLabel));
|
|
39085
39075
|
};
|
|
39086
|
-
const styles$
|
|
39076
|
+
const styles$c = aphrodite.StyleSheet.create({
|
|
39087
39077
|
switchWrapper: {
|
|
39088
39078
|
display: "flex",
|
|
39089
39079
|
flexDirection: "row",
|
|
@@ -39141,7 +39131,7 @@ const AnswerPill = props => {
|
|
|
39141
39131
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
39142
39132
|
onClick: correct ? undefined : onClick,
|
|
39143
39133
|
ref: ref,
|
|
39144
|
-
style: [style, popperStyle, styles$
|
|
39134
|
+
style: [style, popperStyle, styles$b.pill, correct && styles$b.correct, incorrect && styles$b.incorrect, (focused || hovered) && BringToFront]
|
|
39145
39135
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
39146
39136
|
content: answerString,
|
|
39147
39137
|
strings: strings,
|
|
@@ -39149,7 +39139,7 @@ const AnswerPill = props => {
|
|
|
39149
39139
|
}));
|
|
39150
39140
|
});
|
|
39151
39141
|
};
|
|
39152
|
-
const styles$
|
|
39142
|
+
const styles$b = aphrodite.StyleSheet.create({
|
|
39153
39143
|
correct: {
|
|
39154
39144
|
// WB green darkened by 18%
|
|
39155
39145
|
backgroundColor: "#00880b"
|
|
@@ -39215,25 +39205,25 @@ class Marker extends React__namespace.Component {
|
|
|
39215
39205
|
icon: iconNull
|
|
39216
39206
|
};
|
|
39217
39207
|
if (showCorrectness) {
|
|
39218
|
-
iconStyles = [styles$
|
|
39208
|
+
iconStyles = [styles$a.markerGraded, showCorrectness === "correct" ? styles$a.markerCorrect : styles$a.markerIncorrect, isOpen && styles$a.markerSelected];
|
|
39219
39209
|
args = {
|
|
39220
39210
|
...args,
|
|
39221
39211
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
39222
39212
|
};
|
|
39223
39213
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
39224
|
-
iconStyles = [styles$
|
|
39214
|
+
iconStyles = [styles$a.markerFilled, isOpen && styles$a.markerSelected];
|
|
39225
39215
|
} else if (isOpen) {
|
|
39226
|
-
iconStyles = [styles$
|
|
39216
|
+
iconStyles = [styles$a.markerSelected];
|
|
39227
39217
|
args = {
|
|
39228
39218
|
...args,
|
|
39229
39219
|
icon: iconChevronDown,
|
|
39230
39220
|
size: 8
|
|
39231
39221
|
};
|
|
39232
39222
|
} else if (showPulsate) {
|
|
39233
|
-
iconStyles = [styles$
|
|
39223
|
+
iconStyles = [styles$a.markerPulsateBase, this._mounted && shouldReduceMotion() ? showPulsate && styles$a.markerUnfilledPulsateOnce : showPulsate && styles$a.markerUnfilledPulsateInfinite];
|
|
39234
39224
|
}
|
|
39235
39225
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
39236
|
-
style: [styles$
|
|
39226
|
+
style: [styles$a.markerIcon, iconStyles],
|
|
39237
39227
|
ref: node => this._icon = node
|
|
39238
39228
|
}, /*#__PURE__*/React__namespace.createElement(Icon, args));
|
|
39239
39229
|
}
|
|
@@ -39254,7 +39244,7 @@ class Marker extends React__namespace.Component {
|
|
|
39254
39244
|
const markerDisabled = showCorrectness === "correct";
|
|
39255
39245
|
const active = hovered || focused;
|
|
39256
39246
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
39257
|
-
style: [styles$
|
|
39247
|
+
style: [styles$a.marker, active && !markerDisabled && styles$a.markerActive],
|
|
39258
39248
|
"aria-label": markerDisabled ? this.context.strings.correctExcited : label
|
|
39259
39249
|
}, this.renderIcon()), !!selected && showAnswer && /*#__PURE__*/React__namespace.createElement(AnswerPill, {
|
|
39260
39250
|
selectedAnswers: selected,
|
|
@@ -39267,7 +39257,7 @@ class Marker extends React__namespace.Component {
|
|
|
39267
39257
|
}));
|
|
39268
39258
|
}
|
|
39269
39259
|
}
|
|
39270
|
-
const styles$
|
|
39260
|
+
const styles$a = aphrodite.StyleSheet.create({
|
|
39271
39261
|
marker: {
|
|
39272
39262
|
position: "absolute",
|
|
39273
39263
|
backgroundColor: wonderBlocksTokens.color.white,
|
|
@@ -39861,13 +39851,13 @@ class LabelImage extends React__namespace.Component {
|
|
|
39861
39851
|
const promptString = isMobile ? multipleAnswers ? strings.tapMultiple : strings.tapSingle : multipleAnswers ? strings.clickMultiple : strings.clickSingle;
|
|
39862
39852
|
const choicesString = strings.choices;
|
|
39863
39853
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
39864
|
-
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$
|
|
39854
|
+
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$9.instructions))
|
|
39865
39855
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
39866
|
-
className: aphrodite.css(styles$
|
|
39856
|
+
className: aphrodite.css(styles$9.instructionsCaption)
|
|
39867
39857
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React__namespace.createElement("div", {
|
|
39868
|
-
className: aphrodite.css(styles$
|
|
39858
|
+
className: aphrodite.css(styles$9.instructionsChoices)
|
|
39869
39859
|
}, choices.map((choice, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
39870
|
-
className: aphrodite.css(styles$
|
|
39860
|
+
className: aphrodite.css(styles$9.instructionsChoice),
|
|
39871
39861
|
key: index
|
|
39872
39862
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
39873
39863
|
content: choice,
|
|
@@ -39885,20 +39875,20 @@ class LabelImage extends React__namespace.Component {
|
|
|
39885
39875
|
activeMarkerIndex
|
|
39886
39876
|
} = this.state;
|
|
39887
39877
|
return /*#__PURE__*/React__namespace.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React__namespace.createElement("div", {
|
|
39888
|
-
className: aphrodite.css(styles$
|
|
39878
|
+
className: aphrodite.css(styles$9.markersCanvas),
|
|
39889
39879
|
style: {
|
|
39890
39880
|
maxWidth: imageWidth,
|
|
39891
39881
|
maxHeight: imageHeight
|
|
39892
39882
|
}
|
|
39893
39883
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
39894
|
-
className: aphrodite.css(styles$
|
|
39884
|
+
className: aphrodite.css(styles$9.imageContainer,
|
|
39895
39885
|
// Ensure image interaction is disabled while answer
|
|
39896
39886
|
// choices popup is visible. This addresses specific
|
|
39897
39887
|
// case where user may click on question image to
|
|
39898
39888
|
// dismiss the popup. If the image is larger in size
|
|
39899
39889
|
// than its rendered in the widget, this would
|
|
39900
39890
|
// result in a zoom of the image.
|
|
39901
|
-
activeMarkerIndex !== -1 && styles$
|
|
39891
|
+
activeMarkerIndex !== -1 && styles$9.imageInteractionDisabled)
|
|
39902
39892
|
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref3 => {
|
|
39903
39893
|
let {
|
|
39904
39894
|
setAssetStatus
|
|
@@ -39924,7 +39914,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
39924
39914
|
}));
|
|
39925
39915
|
}
|
|
39926
39916
|
}
|
|
39927
|
-
const styles$
|
|
39917
|
+
const styles$9 = aphrodite.StyleSheet.create({
|
|
39928
39918
|
instructions: {
|
|
39929
39919
|
paddingBottom: 16
|
|
39930
39920
|
},
|
|
@@ -40012,7 +40002,7 @@ class Placeholder extends React__namespace.Component {
|
|
|
40012
40002
|
const {
|
|
40013
40003
|
layout
|
|
40014
40004
|
} = this.props;
|
|
40015
|
-
const className = aphrodite.css(styles$
|
|
40005
|
+
const className = aphrodite.css(styles$8.card, styles$8.placeholder, layout === "horizontal" && styles$8.horizontalCard);
|
|
40016
40006
|
const style = {
|
|
40017
40007
|
width: this.props.width,
|
|
40018
40008
|
height: this.props.height
|
|
@@ -40219,7 +40209,7 @@ class Draggable extends React__namespace.Component {
|
|
|
40219
40209
|
// We need to keep backwards compatbility with rules specified directly
|
|
40220
40210
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
40221
40211
|
// See sortable.less for details.
|
|
40222
|
-
let className = aphrodite.css(styles$
|
|
40212
|
+
let className = aphrodite.css(styles$8.card, styles$8.draggable, layout === "horizontal" && styles$8.horizontalCard, layout === "vertical" && styles$8.verticalCard, type === ItemState.DRAGGING && styles$8.dragging, type === ItemState.DISABLED && styles$8.disabled, !includePadding && styles$8.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
|
|
40223
40213
|
if (!includePadding) {
|
|
40224
40214
|
className += " perseus-sortable-draggable-unpadded";
|
|
40225
40215
|
}
|
|
@@ -40557,7 +40547,7 @@ class Sortable extends React__namespace.Component {
|
|
|
40557
40547
|
} = this.props;
|
|
40558
40548
|
// We need to keep backwards compatbility with rules specified directly
|
|
40559
40549
|
// in CSS. See sortable.less for details.
|
|
40560
|
-
const className = aphrodite.css(styles$
|
|
40550
|
+
const className = aphrodite.css(styles$8.sortable) + " perseus-sortable";
|
|
40561
40551
|
const syncWidth = this.props.constraints?.width || layout === "vertical";
|
|
40562
40552
|
const syncHeight = this.props.constraints?.height || layout === "horizontal";
|
|
40563
40553
|
___default["default"].each(this.state.items, function (item, i, items) {
|
|
@@ -40643,7 +40633,7 @@ class Sortable extends React__namespace.Component {
|
|
|
40643
40633
|
}, cards);
|
|
40644
40634
|
}
|
|
40645
40635
|
}
|
|
40646
|
-
const styles$
|
|
40636
|
+
const styles$8 = aphrodite.StyleSheet.create({
|
|
40647
40637
|
sortable: {
|
|
40648
40638
|
boxSizing: "border-box",
|
|
40649
40639
|
float: "left",
|
|
@@ -40839,25 +40829,25 @@ class Matcher extends React__namespace.Component {
|
|
|
40839
40829
|
};
|
|
40840
40830
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
40841
40831
|
return /*#__PURE__*/React__namespace.createElement("table", {
|
|
40842
|
-
className: aphrodite.css(styles$
|
|
40832
|
+
className: aphrodite.css(styles$7.widget) + " " + HACKY_CSS_CLASSNAME
|
|
40843
40833
|
}, /*#__PURE__*/React__namespace.createElement("tbody", null, showLabels && /*#__PURE__*/React__namespace.createElement("tr", {
|
|
40844
|
-
className: aphrodite.css(styles$
|
|
40834
|
+
className: aphrodite.css(styles$7.row)
|
|
40845
40835
|
}, /*#__PURE__*/React__namespace.createElement("th", {
|
|
40846
|
-
className: aphrodite.css(styles$
|
|
40836
|
+
className: aphrodite.css(styles$7.column, styles$7.columnLabel)
|
|
40847
40837
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
40848
40838
|
content: this.props.labels[0] || "...",
|
|
40849
40839
|
linterContext: this.props.linterContext,
|
|
40850
40840
|
strings: this.context.strings
|
|
40851
40841
|
})), /*#__PURE__*/React__namespace.createElement("th", {
|
|
40852
|
-
className: aphrodite.css(styles$
|
|
40842
|
+
className: aphrodite.css(styles$7.column, styles$7.columnRight, styles$7.columnLabel)
|
|
40853
40843
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
40854
40844
|
content: this.props.labels[1] || "...",
|
|
40855
40845
|
linterContext: this.props.linterContext,
|
|
40856
40846
|
strings: this.context.strings
|
|
40857
40847
|
}))), /*#__PURE__*/React__namespace.createElement("tr", {
|
|
40858
|
-
className: aphrodite.css(styles$
|
|
40848
|
+
className: aphrodite.css(styles$7.row)
|
|
40859
40849
|
}, /*#__PURE__*/React__namespace.createElement("td", {
|
|
40860
|
-
className: aphrodite.css(styles$
|
|
40850
|
+
className: aphrodite.css(styles$7.column)
|
|
40861
40851
|
}, /*#__PURE__*/React__namespace.createElement(Sortable, {
|
|
40862
40852
|
options: left,
|
|
40863
40853
|
layout: "vertical",
|
|
@@ -40872,7 +40862,7 @@ class Matcher extends React__namespace.Component {
|
|
|
40872
40862
|
,
|
|
40873
40863
|
ref: "left"
|
|
40874
40864
|
})), /*#__PURE__*/React__namespace.createElement("td", {
|
|
40875
|
-
className: aphrodite.css(styles$
|
|
40865
|
+
className: aphrodite.css(styles$7.column, styles$7.columnRight)
|
|
40876
40866
|
}, /*#__PURE__*/React__namespace.createElement(Sortable, {
|
|
40877
40867
|
options: right,
|
|
40878
40868
|
layout: "vertical",
|
|
@@ -40890,7 +40880,7 @@ class Matcher extends React__namespace.Component {
|
|
|
40890
40880
|
}
|
|
40891
40881
|
const padding = 5;
|
|
40892
40882
|
const border = "1px solid #444";
|
|
40893
|
-
const styles$
|
|
40883
|
+
const styles$7 = aphrodite.StyleSheet.create({
|
|
40894
40884
|
widget: {
|
|
40895
40885
|
paddingTop: padding,
|
|
40896
40886
|
maxWidth: "100%",
|
|
@@ -41581,9 +41571,9 @@ function drawText(ctx, item) {
|
|
|
41581
41571
|
if (item.value === null) {
|
|
41582
41572
|
return;
|
|
41583
41573
|
}
|
|
41584
|
-
ctx.fillStyle = styles$
|
|
41585
|
-
ctx.font = styles$
|
|
41586
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
41574
|
+
ctx.fillStyle = styles$6.fgColor;
|
|
41575
|
+
ctx.font = styles$6.font;
|
|
41576
|
+
ctx.fillText(item.value, item.pos[0] - styles$6.fontSizePx / 2 + 1, item.pos[1] + styles$6.fontSizePx / 2);
|
|
41587
41577
|
}
|
|
41588
41578
|
|
|
41589
41579
|
/**
|
|
@@ -41604,16 +41594,16 @@ function drawText(ctx, item) {
|
|
|
41604
41594
|
function drawDoubleLine(ctx, item) {
|
|
41605
41595
|
// Outer line that forms both of the bond lines.
|
|
41606
41596
|
let path = new Path2D();
|
|
41607
|
-
ctx.lineWidth = 5 * styles$
|
|
41608
|
-
ctx.strokeStyle = styles$
|
|
41597
|
+
ctx.lineWidth = 5 * styles$6.lineWidth;
|
|
41598
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41609
41599
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41610
41600
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41611
41601
|
ctx.stroke(path);
|
|
41612
41602
|
|
|
41613
41603
|
// Inner white line that separates the two bond lines.
|
|
41614
41604
|
path = new Path2D();
|
|
41615
|
-
ctx.lineWidth = 3 * styles$
|
|
41616
|
-
ctx.strokeStyle = styles$
|
|
41605
|
+
ctx.lineWidth = 3 * styles$6.lineWidth;
|
|
41606
|
+
ctx.strokeStyle = styles$6.bgColor;
|
|
41617
41607
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41618
41608
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41619
41609
|
ctx.stroke(path);
|
|
@@ -41640,16 +41630,16 @@ function drawTripleLine(ctx, item) {
|
|
|
41640
41630
|
|
|
41641
41631
|
// Outer line that will form the two outer bond lines.
|
|
41642
41632
|
let path = new Path2D();
|
|
41643
|
-
ctx.lineWidth = 7 * styles$
|
|
41644
|
-
ctx.strokeStyle = styles$
|
|
41633
|
+
ctx.lineWidth = 7 * styles$6.lineWidth;
|
|
41634
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41645
41635
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41646
41636
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41647
41637
|
ctx.stroke(path);
|
|
41648
41638
|
|
|
41649
41639
|
// Middle white line that separates the bonds
|
|
41650
41640
|
path = new Path2D();
|
|
41651
|
-
ctx.lineWidth = 5 * styles$
|
|
41652
|
-
ctx.strokeStyle = styles$
|
|
41641
|
+
ctx.lineWidth = 5 * styles$6.lineWidth;
|
|
41642
|
+
ctx.strokeStyle = styles$6.bgColor;
|
|
41653
41643
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41654
41644
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41655
41645
|
ctx.stroke(path);
|
|
@@ -41671,8 +41661,8 @@ function drawTripleLine(ctx, item) {
|
|
|
41671
41661
|
*/
|
|
41672
41662
|
function drawLine(ctx, item) {
|
|
41673
41663
|
const path = new Path2D();
|
|
41674
|
-
ctx.lineWidth = styles$
|
|
41675
|
-
ctx.strokeStyle = styles$
|
|
41664
|
+
ctx.lineWidth = styles$6.lineWidth;
|
|
41665
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41676
41666
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41677
41667
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41678
41668
|
ctx.stroke(path);
|
|
@@ -41724,7 +41714,7 @@ function compareElements(item0, item1) {
|
|
|
41724
41714
|
function draw(ctx, items) {
|
|
41725
41715
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
41726
41716
|
}
|
|
41727
|
-
const styles$
|
|
41717
|
+
const styles$6 = {
|
|
41728
41718
|
bgColor: "rgb(255, 255, 255)",
|
|
41729
41719
|
fgColor: "rgb(0, 0, 0)",
|
|
41730
41720
|
fontSizePx: 12,
|
|
@@ -43851,7 +43841,7 @@ class PhetSimulation extends React__namespace.Component {
|
|
|
43851
43841
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
43852
43842
|
const sandboxProperties = "allow-same-origin allow-scripts";
|
|
43853
43843
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
43854
|
-
style: styles$
|
|
43844
|
+
style: styles$5.widgetContainer
|
|
43855
43845
|
}, this.state.banner !== null &&
|
|
43856
43846
|
/*#__PURE__*/
|
|
43857
43847
|
// TODO(anna): Make this banner focusable
|
|
@@ -43864,12 +43854,12 @@ class PhetSimulation extends React__namespace.Component {
|
|
|
43864
43854
|
kind: this.state.banner.kind,
|
|
43865
43855
|
text: this.state.banner.message
|
|
43866
43856
|
})), /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
43867
|
-
style: styles$
|
|
43857
|
+
style: styles$5.iframeContainer
|
|
43868
43858
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
43869
43859
|
ref: this.iframeRef,
|
|
43870
43860
|
title: this.props.description,
|
|
43871
43861
|
sandbox: sandboxProperties,
|
|
43872
|
-
className: aphrodite.css(styles$
|
|
43862
|
+
className: aphrodite.css(styles$5.iframeResponsive),
|
|
43873
43863
|
src: this.state.url?.toString(),
|
|
43874
43864
|
allow: "fullscreen"
|
|
43875
43865
|
})), this.state.url !== null && /*#__PURE__*/React__namespace.createElement(IconButton__default["default"], {
|
|
@@ -43900,7 +43890,7 @@ const makeSafeUrl = (urlString, locale) => {
|
|
|
43900
43890
|
url.searchParams.set("locale", locale);
|
|
43901
43891
|
return url;
|
|
43902
43892
|
};
|
|
43903
|
-
const styles$
|
|
43893
|
+
const styles$5 = aphrodite.StyleSheet.create({
|
|
43904
43894
|
widgetContainer: {
|
|
43905
43895
|
borderRadius: 6,
|
|
43906
43896
|
borderWidth: 1,
|
|
@@ -44823,7 +44813,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
44823
44813
|
// creator "went wild".
|
|
44824
44814
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
44825
44815
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
44826
|
-
style: styles$
|
|
44816
|
+
style: styles$4.container
|
|
44827
44817
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
44828
44818
|
sandbox: sandboxOptions,
|
|
44829
44819
|
src: url,
|
|
@@ -44832,7 +44822,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
44832
44822
|
}));
|
|
44833
44823
|
}
|
|
44834
44824
|
}
|
|
44835
|
-
const styles$
|
|
44825
|
+
const styles$4 = aphrodite.StyleSheet.create({
|
|
44836
44826
|
container: {
|
|
44837
44827
|
margin: "auto",
|
|
44838
44828
|
width: "100%"
|
|
@@ -45318,7 +45308,7 @@ const VideoTranscriptLink = props => {
|
|
|
45318
45308
|
{
|
|
45319
45309
|
const video = result.data?.video;
|
|
45320
45310
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
45321
|
-
style: styles$
|
|
45311
|
+
style: styles$3.transcriptLink
|
|
45322
45312
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.Text, null, video?.title), /*#__PURE__*/React__namespace.createElement(wonderBlocksLayout.Strut, {
|
|
45323
45313
|
size: 10
|
|
45324
45314
|
}), /*#__PURE__*/React__namespace.createElement(Link__default["default"], {
|
|
@@ -45335,7 +45325,7 @@ const VideoTranscriptLink = props => {
|
|
|
45335
45325
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, strings.somethingWrong);
|
|
45336
45326
|
}
|
|
45337
45327
|
};
|
|
45338
|
-
const styles$
|
|
45328
|
+
const styles$3 = aphrodite.StyleSheet.create({
|
|
45339
45329
|
transcriptLink: {
|
|
45340
45330
|
flexDirection: "row",
|
|
45341
45331
|
width: "100%",
|
|
@@ -45456,7 +45446,7 @@ const init = function () {
|
|
|
45456
45446
|
|
|
45457
45447
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45458
45448
|
const libName = "@khanacademy/perseus";
|
|
45459
|
-
const libVersion = "
|
|
45449
|
+
const libVersion = "47.0.0";
|
|
45460
45450
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45461
45451
|
|
|
45462
45452
|
const apiVersion = {
|
|
@@ -45673,7 +45663,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
45673
45663
|
const {
|
|
45674
45664
|
isMobile
|
|
45675
45665
|
} = apiOptions;
|
|
45676
|
-
const classNames = classNames__default["default"]("hint", !isMobile && "perseus-hint-renderer", isMobile && aphrodite.css(styles$
|
|
45666
|
+
const classNames = classNames__default["default"]("hint", !isMobile && "perseus-hint-renderer", isMobile && aphrodite.css(styles$2.newHint), isMobile && lastRendered && aphrodite.css(styles$2.lastRenderedNewHint), lastHint && "last-hint", lastRendered && "last-rendered", className);
|
|
45677
45667
|
|
|
45678
45668
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
45679
45669
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -45715,7 +45705,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
45715
45705
|
);
|
|
45716
45706
|
}
|
|
45717
45707
|
}
|
|
45718
|
-
const styles$
|
|
45708
|
+
const styles$2 = aphrodite.StyleSheet.create({
|
|
45719
45709
|
newHint: {
|
|
45720
45710
|
marginBottom: 1.5 * baseUnitPx,
|
|
45721
45711
|
borderLeftColor: gray97,
|
|
@@ -45892,14 +45882,14 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
45892
45882
|
} = apiOptions;
|
|
45893
45883
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
45894
45884
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
45895
|
-
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$
|
|
45885
|
+
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$1.mobileHintStylesHintsRenderer));
|
|
45896
45886
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
45897
45887
|
className: classNames
|
|
45898
45888
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React__namespace.createElement("div", {
|
|
45899
|
-
className: aphrodite.css(styles$
|
|
45889
|
+
className: aphrodite.css(styles$1.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
45900
45890
|
}, this.context.strings.hints), hints, showGetAnotherHint && /*#__PURE__*/React__namespace.createElement("button", {
|
|
45901
45891
|
rel: "button",
|
|
45902
|
-
className: aphrodite.css(styles$
|
|
45892
|
+
className: aphrodite.css(styles$1.linkButton, styles$1.getAnotherHintButton, apiOptions.isMobile && styles$1.mobileHintStylesGetAnotherHintButton),
|
|
45903
45893
|
onClick: evt => {
|
|
45904
45894
|
evt.preventDefault();
|
|
45905
45895
|
evt.stopPropagation();
|
|
@@ -45908,14 +45898,14 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
45908
45898
|
}
|
|
45909
45899
|
}
|
|
45910
45900
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
45911
|
-
className: aphrodite.css(styles$
|
|
45901
|
+
className: aphrodite.css(styles$1.plusText, apiOptions.isMobile && styles$1.mobileHintStylesPlusText)
|
|
45912
45902
|
}, "+"), /*#__PURE__*/React__namespace.createElement("span", {
|
|
45913
|
-
className: aphrodite.css(styles$
|
|
45903
|
+
className: aphrodite.css(styles$1.getAnotherHintText)
|
|
45914
45904
|
}, this.context.strings.getAnotherHint, " ", hintRatioCopy)));
|
|
45915
45905
|
}
|
|
45916
45906
|
}
|
|
45917
45907
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
45918
|
-
const styles$
|
|
45908
|
+
const styles$1 = aphrodite.StyleSheet.create({
|
|
45919
45909
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
45920
45910
|
rendererMargins: {
|
|
45921
45911
|
marginTop: baseUnitPx
|
|
@@ -46335,11 +46325,11 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
46335
46325
|
// mobile hint styles, which are flush to the left.
|
|
46336
46326
|
// NOTE(charlie): We may still want to apply this
|
|
46337
46327
|
// padding for desktop exercises.
|
|
46338
|
-
apiOptions.isMobile ? undefined : aphrodite.css(styles
|
|
46328
|
+
apiOptions.isMobile ? undefined : aphrodite.css(styles.hintsContainer)
|
|
46339
46329
|
}, hintsRenderer)));
|
|
46340
46330
|
}
|
|
46341
46331
|
}
|
|
46342
|
-
const styles
|
|
46332
|
+
const styles = aphrodite.StyleSheet.create({
|
|
46343
46333
|
hintsContainer: {
|
|
46344
46334
|
marginLeft: 50
|
|
46345
46335
|
}
|
|
@@ -46446,1148 +46436,6 @@ const traverse = function (rendererOptions, contentCallback, widgetCallback, opt
|
|
|
46446
46436
|
return traverseRenderer$1(rendererOptions, contentCallback, deepCallbackFor(contentCallback, widgetCallback, optionsCallback), optionsCallback);
|
|
46447
46437
|
};
|
|
46448
46438
|
|
|
46449
|
-
/**
|
|
46450
|
-
* Utility functions for constructing and inferring multi-item shapes.
|
|
46451
|
-
*
|
|
46452
|
-
* A shape is an object that serves as a runtime type declaration: it specifies
|
|
46453
|
-
* a tree structure for a particular class of multi-item. See shape-types.js
|
|
46454
|
-
* for further discussion.
|
|
46455
|
-
*
|
|
46456
|
-
* This module allows you to construct arbitrary Shape trees, by combining
|
|
46457
|
-
* leaf node shapes like `content` and `hint` into composite shapes like
|
|
46458
|
-
* `arrayOf(shape({foo: content, bar: hint}))`.
|
|
46459
|
-
*/
|
|
46460
|
-
|
|
46461
|
-
/**
|
|
46462
|
-
* These tools allow you to construct arbirtary shapes, by combining simple
|
|
46463
|
-
* leaf shapes like `content` and `hint` into composite shapes like
|
|
46464
|
-
* `arrayOf(shape({question: content, hints: arrayOf(hint)}))`.
|
|
46465
|
-
*/
|
|
46466
|
-
const contentShape = {
|
|
46467
|
-
type: "content"
|
|
46468
|
-
};
|
|
46469
|
-
const hintShape = {
|
|
46470
|
-
type: "hint"
|
|
46471
|
-
};
|
|
46472
|
-
const tagsShape = {
|
|
46473
|
-
type: "tags"
|
|
46474
|
-
};
|
|
46475
|
-
const buildArrayShape = elementShape => ({
|
|
46476
|
-
type: "array",
|
|
46477
|
-
elementShape
|
|
46478
|
-
});
|
|
46479
|
-
const buildObjectShape = shape => ({
|
|
46480
|
-
type: "object",
|
|
46481
|
-
shape
|
|
46482
|
-
});
|
|
46483
|
-
const hintsShape = buildArrayShape(hintShape);
|
|
46484
|
-
var shapes = {
|
|
46485
|
-
content: contentShape,
|
|
46486
|
-
hint: hintShape,
|
|
46487
|
-
hints: hintsShape,
|
|
46488
|
-
tags: tagsShape,
|
|
46489
|
-
arrayOf: buildArrayShape,
|
|
46490
|
-
shape: buildObjectShape
|
|
46491
|
-
};
|
|
46492
|
-
|
|
46493
|
-
/**
|
|
46494
|
-
* Utility functions for manipulating multi-item-shaped trees.
|
|
46495
|
-
*
|
|
46496
|
-
* Multi-items are trees! But we also often have other trees that are shaped
|
|
46497
|
-
* like multi-items - for example, if we map a multi-item tree into a tree of
|
|
46498
|
-
* renderer info and state, and then map that again into a tree of just the
|
|
46499
|
-
* renderer nodes, like we do in MultiRenderer. See tree-types.js for further
|
|
46500
|
-
* discussion.
|
|
46501
|
-
*
|
|
46502
|
-
* These functions enable us to manipulate generic multi-item-shaped trees,
|
|
46503
|
-
* regardless of what type of data they contain at their leaves. You can use
|
|
46504
|
-
* the mapper functions to transform a tree into another tree of the same
|
|
46505
|
-
* shape, or to discover all the nodes of a particular type.
|
|
46506
|
-
*
|
|
46507
|
-
* We expose two simple mapper functions (mapContentNodes and mapHintNodes),
|
|
46508
|
-
* and also a more complex interface for creating a mapping over all of a
|
|
46509
|
-
* tree's node types simultaneously:
|
|
46510
|
-
*
|
|
46511
|
-
* `buildMapper()` returns a TreeMapper object that allows you to build your
|
|
46512
|
-
* mapper object one node type at a time. Then, you can execute your mapping by
|
|
46513
|
-
* calling the `mapTree` method.
|
|
46514
|
-
*
|
|
46515
|
-
* For example:
|
|
46516
|
-
* const renderers = buildMapper()
|
|
46517
|
-
* .setContentMapper(this.renderContentNode)
|
|
46518
|
-
* .setHintMapper(this.renderHintNode)
|
|
46519
|
-
* .setTagsMapper(this.renderTagsNode)
|
|
46520
|
-
* .setArrayMapper(this.hideSkippedQuestions)
|
|
46521
|
-
* .mapTree(tree, shape);
|
|
46522
|
-
*
|
|
46523
|
-
* This will copy the given tree, apply the given transformations to the
|
|
46524
|
-
* content, hint, and array nodes respectively, and return the resulting tree.
|
|
46525
|
-
*
|
|
46526
|
-
* For node types whose mappers aren't specified, we default to the identity
|
|
46527
|
-
* function. (This builder interface enables us to implement that default
|
|
46528
|
-
* behavior in a provably type-safe way, while not requiring the call site to
|
|
46529
|
-
* be aware of all the node types. Hooray!)
|
|
46530
|
-
*
|
|
46531
|
-
* The call to `setArrayMapper` must come last, because the array mapper's
|
|
46532
|
-
* argument types depend on the other mappers' types. See ArrayMapper for more
|
|
46533
|
-
* details.
|
|
46534
|
-
*
|
|
46535
|
-
* WARNING: These functions trust that the provided tree conforms to the
|
|
46536
|
-
* provided shape. If not, behavior is undefined and may not respect the type
|
|
46537
|
-
* signatures specified here.
|
|
46538
|
-
*/
|
|
46539
|
-
|
|
46540
|
-
/**
|
|
46541
|
-
* The sequence of edges that lead to a particular node in a Tree.
|
|
46542
|
-
* Elements can be `string` to correspond to an ObjectNode key, or `number` to
|
|
46543
|
-
* correspond to an ArrayNode index.
|
|
46544
|
-
*/
|
|
46545
|
-
|
|
46546
|
-
/**
|
|
46547
|
-
* These are function interfaces for mapping over various types of tree nodes.
|
|
46548
|
-
*
|
|
46549
|
-
* ArrayMapper is a bit more complicated than the leaf node mappers. It's
|
|
46550
|
-
* executed in the context of a `mapTree` call, after we've finished mapping
|
|
46551
|
-
* its child nodes, so the function has access to both the resulting array
|
|
46552
|
-
* (with mapped elements) and the original array (with the original untouched
|
|
46553
|
-
* elements).
|
|
46554
|
-
*
|
|
46555
|
-
* The ArrayMapper then has the opportunity to apply a final transformation to
|
|
46556
|
-
* the resulting array, like filtering certain elements or (in the hacky
|
|
46557
|
-
* MultiRenderer case) attaching a `renderHints` method to arrays of hint
|
|
46558
|
-
* renderers :)
|
|
46559
|
-
*
|
|
46560
|
-
* This is why `TreeMapper#setArrayMapper` must be called last: ArrayMapper's
|
|
46561
|
-
* types depend on the ContentMapper and HintMapper's types. And, since you can
|
|
46562
|
-
* only specify one mapper at a time in this builder interface (which is
|
|
46563
|
-
* necessary to provide default mappers in a type-safe way), you need your
|
|
46564
|
-
* dependencies to already be in place by the time you call `setArrayMapper`.
|
|
46565
|
-
* Otherwise, we'd have to set the ArrayMapper and *hope* that you *eventually*
|
|
46566
|
-
* provide a compatible ContentMapper and HintMapper, which is difficult to
|
|
46567
|
-
* prove at compile time.
|
|
46568
|
-
*
|
|
46569
|
-
* There's no ObjectMapper here, but not for any particular reason. We just
|
|
46570
|
-
* don't have a use case for it yet, so we haven't built it yet.
|
|
46571
|
-
*/
|
|
46572
|
-
|
|
46573
|
-
/**
|
|
46574
|
-
* A TreeMapper is a collection of node mappers, which, together, compose the
|
|
46575
|
-
* behavior for mapping over an entire tree.
|
|
46576
|
-
*
|
|
46577
|
-
* This serves as the interface for the two TreeMapper classes, including both
|
|
46578
|
-
* the internal mapper properties that we care about, and the `mapTree`
|
|
46579
|
-
* function that the call site will use.
|
|
46580
|
-
*/
|
|
46581
|
-
|
|
46582
|
-
/**
|
|
46583
|
-
* This is a TreeMapper that only has mappers specified for its leaf nodes; its
|
|
46584
|
-
* array mapper is the identity function.
|
|
46585
|
-
*
|
|
46586
|
-
* This is the TreeMapper initially returned by `buildMapper`. It allows you to
|
|
46587
|
-
* change the types of your ContentMapper and HintMapper, which is safe because
|
|
46588
|
-
* none of the other mappers that depend on those types (aka ArrayMapper) have
|
|
46589
|
-
* been specified yet. (Or, more specifically, the ArrayMapper is currently
|
|
46590
|
-
* `identity`, which can trivially vary with the ContentMapper and HintMapper's
|
|
46591
|
-
* types.)
|
|
46592
|
-
*
|
|
46593
|
-
* Once you call `setArrayMapper`, however, we move to the other class:
|
|
46594
|
-
* TreeMapperForLeavesAndCollections.
|
|
46595
|
-
*/
|
|
46596
|
-
class TreeMapperJustForLeaves {
|
|
46597
|
-
content;
|
|
46598
|
-
hint;
|
|
46599
|
-
tags;
|
|
46600
|
-
array;
|
|
46601
|
-
constructor(content, hint, tags) {
|
|
46602
|
-
this.content = content;
|
|
46603
|
-
this.hint = hint;
|
|
46604
|
-
this.tags = tags;
|
|
46605
|
-
this.array = identity;
|
|
46606
|
-
}
|
|
46607
|
-
setContentMapper(newContentMapper) {
|
|
46608
|
-
return new TreeMapperJustForLeaves(newContentMapper, this.hint, this.tags);
|
|
46609
|
-
}
|
|
46610
|
-
setHintMapper(newHintMapper) {
|
|
46611
|
-
return new TreeMapperJustForLeaves(this.content, newHintMapper, this.tags);
|
|
46612
|
-
}
|
|
46613
|
-
setTagsMapper(newTagsMapper) {
|
|
46614
|
-
return new TreeMapperJustForLeaves(this.content, this.hint, newTagsMapper);
|
|
46615
|
-
}
|
|
46616
|
-
setArrayMapper(newArrayMapper) {
|
|
46617
|
-
return new TreeMapperForLeavesAndCollections(this.content, this.hint, this.tags, newArrayMapper);
|
|
46618
|
-
}
|
|
46619
|
-
|
|
46620
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic. | TS2315 - Type 'Tree' is not generic.
|
|
46621
|
-
mapTree(tree, shape) {
|
|
46622
|
-
return mapTree(tree, shape, [], this);
|
|
46623
|
-
}
|
|
46624
|
-
}
|
|
46625
|
-
|
|
46626
|
-
/**
|
|
46627
|
-
* This is a TreeMapper that already has an ArrayMapper specified, so its
|
|
46628
|
-
* ContentMapper and HintMapper are now locked in.
|
|
46629
|
-
*/
|
|
46630
|
-
class TreeMapperForLeavesAndCollections {
|
|
46631
|
-
content;
|
|
46632
|
-
hint;
|
|
46633
|
-
tags;
|
|
46634
|
-
array;
|
|
46635
|
-
constructor(content, hint, tags, array) {
|
|
46636
|
-
this.content = content;
|
|
46637
|
-
this.hint = hint;
|
|
46638
|
-
this.tags = tags;
|
|
46639
|
-
this.array = array;
|
|
46640
|
-
}
|
|
46641
|
-
setArrayMapper(newArrayMapper) {
|
|
46642
|
-
return new TreeMapperForLeavesAndCollections(this.content, this.hint, this.tags, newArrayMapper);
|
|
46643
|
-
}
|
|
46644
|
-
|
|
46645
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic. | TS2315 - Type 'Tree' is not generic.
|
|
46646
|
-
mapTree(tree, shape) {
|
|
46647
|
-
return mapTree(tree, shape, [], this);
|
|
46648
|
-
}
|
|
46649
|
-
}
|
|
46650
|
-
function identity(x) {
|
|
46651
|
-
return x;
|
|
46652
|
-
}
|
|
46653
|
-
|
|
46654
|
-
/**
|
|
46655
|
-
* Return a new TreeMapper that will perform a no-op transformation on an input
|
|
46656
|
-
* tree. To make it useful, chain any combination of `setContentMapper`,
|
|
46657
|
-
* `setHintMapper`, `setTagMapper`, and `setArrayMapper` to specify
|
|
46658
|
-
* transformations for the individual node types.
|
|
46659
|
-
*/
|
|
46660
|
-
// @ts-expect-error - TS2300 - Duplicate identifier 'C'. | TS2300 - Duplicate identifier 'H'. | TS2300 - Duplicate identifier 'T'.
|
|
46661
|
-
function buildMapper() {
|
|
46662
|
-
return new TreeMapperJustForLeaves(identity, identity, identity);
|
|
46663
|
-
}
|
|
46664
|
-
|
|
46665
|
-
/**
|
|
46666
|
-
* Copy the given tree, apply the corresponding transformation specified in the
|
|
46667
|
-
* TreeMapper to each node, and return the resulting tree.
|
|
46668
|
-
*/
|
|
46669
|
-
function mapTree(
|
|
46670
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46671
|
-
tree, shape, path, mappers
|
|
46672
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46673
|
-
) {
|
|
46674
|
-
// We trust the shape of the multi-item to match the shape provided at
|
|
46675
|
-
// runtime. Therefore, in each shape branch, we cast the node to `any` and
|
|
46676
|
-
// reinterpret it as the expected node type.
|
|
46677
|
-
if (shape.type === "content") {
|
|
46678
|
-
const content = tree;
|
|
46679
|
-
return mappers.content(content, shape, path);
|
|
46680
|
-
}
|
|
46681
|
-
if (shape.type === "hint") {
|
|
46682
|
-
const hint = tree;
|
|
46683
|
-
return mappers.hint(hint, shape, path);
|
|
46684
|
-
}
|
|
46685
|
-
if (shape.type === "tags") {
|
|
46686
|
-
const tags = tree;
|
|
46687
|
-
return mappers.tags(tags, shape, path);
|
|
46688
|
-
}
|
|
46689
|
-
if (shape.type === "array") {
|
|
46690
|
-
// @ts-expect-error - TS2315 - Type 'ArrayNode' is not generic.
|
|
46691
|
-
const array = tree;
|
|
46692
|
-
if (!Array.isArray(array)) {
|
|
46693
|
-
throw new perseusCore.PerseusError(`Invalid object of type "${typeof array}" found at path ` +
|
|
46694
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46695
|
-
`${["<root>"].concat(path).join(".")}. Expected array.`, perseusCore.Errors.Internal);
|
|
46696
|
-
}
|
|
46697
|
-
const elementShape = shape.elementShape;
|
|
46698
|
-
// @ts-expect-error - TS2315 - Type 'ArrayNode' is not generic.
|
|
46699
|
-
const mappedElements = array.map((inner, i) => mapTree(inner, elementShape, path.concat(i), mappers));
|
|
46700
|
-
return mappers.array(mappedElements, array, shape, path);
|
|
46701
|
-
}
|
|
46702
|
-
if (shape.type === "object") {
|
|
46703
|
-
const object = tree;
|
|
46704
|
-
if (object && typeof object !== "object") {
|
|
46705
|
-
throw new perseusCore.PerseusError(`Invalid object of type "${typeof object}" found at ` +
|
|
46706
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46707
|
-
`path ${["<root>"].concat(path).join(".")}. Expected ` + `"object" type.`, perseusCore.Errors.InvalidInput);
|
|
46708
|
-
}
|
|
46709
|
-
const valueShapes = shape.shape;
|
|
46710
|
-
if (!valueShapes) {
|
|
46711
|
-
throw new perseusCore.PerseusError(`Unexpected shape ${JSON.stringify(shape)} at path ` +
|
|
46712
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46713
|
-
`${["<root>"].concat(path).join(".")}.`, perseusCore.Errors.InvalidInput);
|
|
46714
|
-
}
|
|
46715
|
-
const newObject = {};
|
|
46716
|
-
Object.keys(valueShapes).forEach(key => {
|
|
46717
|
-
if (!(key in object)) {
|
|
46718
|
-
throw new perseusCore.PerseusError(`Key "${key}" is missing from shape at path ` +
|
|
46719
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46720
|
-
`${["<root>"].concat(path).join(".")}.`, perseusCore.Errors.InvalidInput);
|
|
46721
|
-
}
|
|
46722
|
-
newObject[key] = mapTree(object[key], valueShapes[key], path.concat(key), mappers);
|
|
46723
|
-
});
|
|
46724
|
-
return newObject;
|
|
46725
|
-
}
|
|
46726
|
-
throw new perseusCore.PerseusError(
|
|
46727
|
-
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
46728
|
-
`unexpected shape type ${shape.type}`, perseusCore.Errors.InvalidInput);
|
|
46729
|
-
}
|
|
46730
|
-
|
|
46731
|
-
/**
|
|
46732
|
-
* Utility functions for constructing and manipulating multi-items.
|
|
46733
|
-
*
|
|
46734
|
-
* These functions apply *specifically* to Items and ItemTrees - things that
|
|
46735
|
-
* actually semantically *are* multi-items. For more general functions for
|
|
46736
|
-
* traversing and manipulating *anything* shaped like a multi-item (like a
|
|
46737
|
-
* renderer tree or a score tree or, well, a multi-item), see trees.js.
|
|
46738
|
-
*/
|
|
46739
|
-
/**
|
|
46740
|
-
* Return a semantically empty ItemTree that conforms to the given shape.
|
|
46741
|
-
*
|
|
46742
|
-
* - An empty content node has an empty content string and no widgets/images.
|
|
46743
|
-
* - An empty hint node has an empty content string and no widgets/images.
|
|
46744
|
-
* - An empty array node has no elements.
|
|
46745
|
-
* - An empty object node has a semantically empty node for each of its keys.
|
|
46746
|
-
* (That is, we recursively call buildEmptyItemTreeForShape for each key.)
|
|
46747
|
-
*/
|
|
46748
|
-
function buildEmptyItemTreeForShape(shape) {
|
|
46749
|
-
if (shape.type === "content") {
|
|
46750
|
-
return {
|
|
46751
|
-
__type: "content",
|
|
46752
|
-
content: "",
|
|
46753
|
-
images: {},
|
|
46754
|
-
widgets: {}
|
|
46755
|
-
};
|
|
46756
|
-
}
|
|
46757
|
-
if (shape.type === "hint") {
|
|
46758
|
-
return {
|
|
46759
|
-
__type: "hint",
|
|
46760
|
-
replace: false,
|
|
46761
|
-
content: "",
|
|
46762
|
-
images: {},
|
|
46763
|
-
widgets: {}
|
|
46764
|
-
};
|
|
46765
|
-
}
|
|
46766
|
-
if (shape.type === "tags") {
|
|
46767
|
-
return [];
|
|
46768
|
-
}
|
|
46769
|
-
if (shape.type === "array") {
|
|
46770
|
-
return [];
|
|
46771
|
-
}
|
|
46772
|
-
if (shape.type === "object") {
|
|
46773
|
-
const valueShapes = shape.shape;
|
|
46774
|
-
const object = {};
|
|
46775
|
-
Object.keys(valueShapes).forEach(key => {
|
|
46776
|
-
object[key] = buildEmptyItemTreeForShape(valueShapes[key]);
|
|
46777
|
-
});
|
|
46778
|
-
return object;
|
|
46779
|
-
}
|
|
46780
|
-
throw new perseusCore.PerseusError(
|
|
46781
|
-
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
46782
|
-
`unexpected shape type ${shape.type}`, perseusCore.Errors.InvalidInput);
|
|
46783
|
-
}
|
|
46784
|
-
|
|
46785
|
-
/**
|
|
46786
|
-
* Return a semantically empty Item that conforms to the given shape.
|
|
46787
|
-
*
|
|
46788
|
-
* - An empty content node has an empty content string and no widgets/images.
|
|
46789
|
-
* - An empty hint node has an empty content string and no widgets/images.
|
|
46790
|
-
* - An empty array node has no elements.
|
|
46791
|
-
* - An empty object node has a semantically empty node for each of its keys.
|
|
46792
|
-
* (That is, we recursively call buildEmptyItemTreeForShape for each key.)
|
|
46793
|
-
*/
|
|
46794
|
-
function buildEmptyItemForShape(shape) {
|
|
46795
|
-
return treeToItem(buildEmptyItemTreeForShape(shape));
|
|
46796
|
-
}
|
|
46797
|
-
|
|
46798
|
-
/**
|
|
46799
|
-
* Given an Item and its Shape, yield all of its content nodes to the callback.
|
|
46800
|
-
*/
|
|
46801
|
-
function findContentNodesInItem$2(item, shape, callback) {
|
|
46802
|
-
const itemTree = itemToTree(item);
|
|
46803
|
-
buildMapper().setContentMapper(callback).mapTree(itemTree, shape);
|
|
46804
|
-
}
|
|
46805
|
-
|
|
46806
|
-
/**
|
|
46807
|
-
* Given an Item and its Shape, yield all of its hint nodes to the callback.
|
|
46808
|
-
*/
|
|
46809
|
-
function findHintNodesInItem(item, shape, callback) {
|
|
46810
|
-
const itemTree = itemToTree(item);
|
|
46811
|
-
buildMapper().setHintMapper(callback).mapTree(itemTree, shape);
|
|
46812
|
-
}
|
|
46813
|
-
|
|
46814
|
-
/**
|
|
46815
|
-
* Given an ItemTree, return a Shape that it conforms to.
|
|
46816
|
-
*
|
|
46817
|
-
* The Shape might not be complete or correct Shape that this Item was designed
|
|
46818
|
-
* for. If you have access to the intended Shape, use that instead.
|
|
46819
|
-
*/
|
|
46820
|
-
function inferItemShape$2(item) {
|
|
46821
|
-
const itemTree = itemToTree(item);
|
|
46822
|
-
return inferItemTreeShape(itemTree);
|
|
46823
|
-
}
|
|
46824
|
-
function inferItemTreeShape(node) {
|
|
46825
|
-
if (Array.isArray(node)) {
|
|
46826
|
-
if (node.length) {
|
|
46827
|
-
if (typeof node[0] === "string") {
|
|
46828
|
-
// There's no ItemTree that can manifest as a string.
|
|
46829
|
-
// So, an array of strings must be a TagsNode, not ArrayNode.
|
|
46830
|
-
return shapes.tags;
|
|
46831
|
-
}
|
|
46832
|
-
// Otherwise, assume that this is a valid ArrayNode, and
|
|
46833
|
-
// therefore the shape of the first element applies to all
|
|
46834
|
-
// elements in the array.
|
|
46835
|
-
return shapes.arrayOf(inferItemTreeShape(node[0]));
|
|
46836
|
-
}
|
|
46837
|
-
// The array is empty, so we arbitrarily guess that it's a content
|
|
46838
|
-
// array. As discussed in the docstring, this might be incorrect,
|
|
46839
|
-
// and you shouldn't depend on it.
|
|
46840
|
-
return shapes.arrayOf(shapes.content);
|
|
46841
|
-
}
|
|
46842
|
-
if (
|
|
46843
|
-
// TODO(mdr): Remove #LegacyContentNode support.
|
|
46844
|
-
typeof node === "object" && (node.__type === "content" || node.__type === "item")) {
|
|
46845
|
-
return shapes.content;
|
|
46846
|
-
}
|
|
46847
|
-
if (typeof node === "object" && node.__type === "hint") {
|
|
46848
|
-
return shapes.hint;
|
|
46849
|
-
}
|
|
46850
|
-
if (typeof node === "object") {
|
|
46851
|
-
const valueShapes = {};
|
|
46852
|
-
Object.keys(node).forEach(key => {
|
|
46853
|
-
valueShapes[key] = inferItemTreeShape(node[key]);
|
|
46854
|
-
});
|
|
46855
|
-
return shapes.shape(valueShapes);
|
|
46856
|
-
}
|
|
46857
|
-
throw new perseusCore.PerseusError(`unexpected multi-item node ${JSON.stringify(node)}`, perseusCore.Errors.InvalidInput);
|
|
46858
|
-
}
|
|
46859
|
-
|
|
46860
|
-
/**
|
|
46861
|
-
* Convert the given Item to an ItemTree, by unwrapping the `_multi` key.
|
|
46862
|
-
*/
|
|
46863
|
-
function itemToTree(item) {
|
|
46864
|
-
return item._multi;
|
|
46865
|
-
}
|
|
46866
|
-
|
|
46867
|
-
/**
|
|
46868
|
-
* Convert the given ItemTree to an Item, by wrapping it in the `_multi` key.
|
|
46869
|
-
*/
|
|
46870
|
-
function treeToItem(node) {
|
|
46871
|
-
return {
|
|
46872
|
-
_multi: node
|
|
46873
|
-
};
|
|
46874
|
-
}
|
|
46875
|
-
|
|
46876
|
-
var isObject$1 = function (obj) {
|
|
46877
|
-
return obj === Object(obj);
|
|
46878
|
-
};
|
|
46879
|
-
var merge = function () {
|
|
46880
|
-
var obj = {};
|
|
46881
|
-
for (var i = 0; i < arguments.length; i++) {
|
|
46882
|
-
var source = arguments[i];
|
|
46883
|
-
if (source) {
|
|
46884
|
-
for (var prop in source) {
|
|
46885
|
-
obj[prop] = source[prop];
|
|
46886
|
-
}
|
|
46887
|
-
}
|
|
46888
|
-
}
|
|
46889
|
-
return obj;
|
|
46890
|
-
};
|
|
46891
|
-
var clone = function (obj) {
|
|
46892
|
-
if (!isObject$1(obj)) {
|
|
46893
|
-
return obj;
|
|
46894
|
-
}
|
|
46895
|
-
return Array.isArray(obj) ? obj.slice() : merge(obj);
|
|
46896
|
-
};
|
|
46897
|
-
|
|
46898
|
-
/* TODO batch *all* mutations
|
|
46899
|
-
* idea: freeze / thaw implementations for all types
|
|
46900
|
-
* lens constructor thaws, freeze delegates to type's freeze
|
|
46901
|
-
*/
|
|
46902
|
-
|
|
46903
|
-
// equivalents, without requiring it
|
|
46904
|
-
// find the implementation to use for a given object
|
|
46905
|
-
var dispatch = function (x) {
|
|
46906
|
-
if (Array.isArray(x)) {
|
|
46907
|
-
return arr;
|
|
46908
|
-
} else if (isObject$1(x)) {
|
|
46909
|
-
return obj;
|
|
46910
|
-
} else if (typeof x === "string") {
|
|
46911
|
-
return str;
|
|
46912
|
-
}
|
|
46913
|
-
};
|
|
46914
|
-
|
|
46915
|
-
// This is underscore with a different name
|
|
46916
|
-
var lens = function (obj) {
|
|
46917
|
-
if (obj instanceof lens) {
|
|
46918
|
-
return obj;
|
|
46919
|
-
}
|
|
46920
|
-
if (!(this instanceof lens)) {
|
|
46921
|
-
return new lens(obj);
|
|
46922
|
-
}
|
|
46923
|
-
var ops = dispatch(obj);
|
|
46924
|
-
this._wrapped = ops.thaw ? ops.thaw(obj) : obj;
|
|
46925
|
-
};
|
|
46926
|
-
lens.prototype.freeze = function () {
|
|
46927
|
-
var obj = this._wrapped;
|
|
46928
|
-
var ops = dispatch(obj);
|
|
46929
|
-
return ops.freeze ? ops.freeze(obj) : obj;
|
|
46930
|
-
};
|
|
46931
|
-
lens.prototype.zoom = function (lensArr) {
|
|
46932
|
-
if (this._zoomStack === undefined) {
|
|
46933
|
-
this._zoomStack = [];
|
|
46934
|
-
}
|
|
46935
|
-
this._zoomStack.push({
|
|
46936
|
-
zoom: lensArr,
|
|
46937
|
-
wrapped: this._wrapped
|
|
46938
|
-
});
|
|
46939
|
-
this._wrapped = lens(this._wrapped).get(lensArr);
|
|
46940
|
-
return this;
|
|
46941
|
-
};
|
|
46942
|
-
lens.prototype.deZoom = function () {
|
|
46943
|
-
var frame = this._zoomStack.pop();
|
|
46944
|
-
this._wrapped = lens(frame.wrapped).set(frame.zoom, this._wrapped).freeze();
|
|
46945
|
-
return this;
|
|
46946
|
-
};
|
|
46947
|
-
lens.prototype.get = function (lensArr) {
|
|
46948
|
-
var obj = this._wrapped;
|
|
46949
|
-
for (var i = 0; i < lensArr.length; i++) {
|
|
46950
|
-
obj = dispatch(obj).get(obj, lensArr[i]);
|
|
46951
|
-
}
|
|
46952
|
-
return obj;
|
|
46953
|
-
};
|
|
46954
|
-
lens.prototype.mod = function (lensArr, f) {
|
|
46955
|
-
var obj = this._wrapped;
|
|
46956
|
-
var newObj = clone(obj);
|
|
46957
|
-
var ops = dispatch(obj);
|
|
46958
|
-
if (lensArr.length === 0) {
|
|
46959
|
-
this._wrapped = f(this._wrapped);
|
|
46960
|
-
} else if (lensArr.length === 1) {
|
|
46961
|
-
this._wrapped = ops.mod(newObj, lensArr[0], f);
|
|
46962
|
-
} else {
|
|
46963
|
-
var monocle = lensArr[0];
|
|
46964
|
-
var shortLens = lensArr.slice(1);
|
|
46965
|
-
|
|
46966
|
-
// newObj = ops.mod(obj[monocle], shortLens, f);
|
|
46967
|
-
|
|
46968
|
-
newObj[monocle] = lens(obj[monocle]).mod(shortLens, f).freeze();
|
|
46969
|
-
this._wrapped = newObj;
|
|
46970
|
-
}
|
|
46971
|
-
return this;
|
|
46972
|
-
};
|
|
46973
|
-
|
|
46974
|
-
// TODO - move to individual files
|
|
46975
|
-
lens.prototype.merge = function (lensArr, props) {
|
|
46976
|
-
this._wrapped = lens(this._wrapped).mod(lensArr, function (oldProps) {
|
|
46977
|
-
return merge(oldProps, props);
|
|
46978
|
-
}).freeze();
|
|
46979
|
-
return this;
|
|
46980
|
-
};
|
|
46981
|
-
|
|
46982
|
-
// Lens must have length >= 1 or there would be nothing to return
|
|
46983
|
-
lens.prototype.del = function (lensArr) {
|
|
46984
|
-
var obj = this._wrapped;
|
|
46985
|
-
var ops = dispatch(obj);
|
|
46986
|
-
if (lensArr.length === 1) {
|
|
46987
|
-
this._wrapped = ops.del(obj, lensArr[0]);
|
|
46988
|
-
} else {
|
|
46989
|
-
var monocle = lensArr[0];
|
|
46990
|
-
var shortLens = lensArr.slice(1);
|
|
46991
|
-
var newObj = clone(obj);
|
|
46992
|
-
newObj[monocle] = lens(obj[monocle]).del(shortLens).freeze();
|
|
46993
|
-
this._wrapped = newObj;
|
|
46994
|
-
}
|
|
46995
|
-
return this;
|
|
46996
|
-
};
|
|
46997
|
-
lens.prototype.set = function (lensArr, set) {
|
|
46998
|
-
return this.mod(lensArr, function () {
|
|
46999
|
-
return set;
|
|
47000
|
-
});
|
|
47001
|
-
};
|
|
47002
|
-
|
|
47003
|
-
// ARRAY FUNCTIONS
|
|
47004
|
-
|
|
47005
|
-
const arr = {
|
|
47006
|
-
get: function (arr, monocle) {
|
|
47007
|
-
return arr[monocle];
|
|
47008
|
-
},
|
|
47009
|
-
set: function (arr, monocle, val) {
|
|
47010
|
-
var newArr = arr.splice();
|
|
47011
|
-
newArr[monocle] = val;
|
|
47012
|
-
return newArr;
|
|
47013
|
-
},
|
|
47014
|
-
mod: function (arr, monocle, f) {
|
|
47015
|
-
var newArr = arr.slice();
|
|
47016
|
-
newArr[monocle] = f(arr[monocle]);
|
|
47017
|
-
return newArr;
|
|
47018
|
-
},
|
|
47019
|
-
del: function (arr, monocle) {
|
|
47020
|
-
var newArr = arr.slice();
|
|
47021
|
-
newArr.splice(monocle, 1);
|
|
47022
|
-
return newArr;
|
|
47023
|
-
}
|
|
47024
|
-
};
|
|
47025
|
-
|
|
47026
|
-
/*
|
|
47027
|
-
// Lens must point to a member of an array. We'll insert into that array.
|
|
47028
|
-
lens.prototype.insertAt = function(lensArr, toInsert) {
|
|
47029
|
-
var obj = this._wrapped;
|
|
47030
|
-
|
|
47031
|
-
var arrLens = lensArr.slice(0, -1);
|
|
47032
|
-
var arr = lens(obj).get(arrLens).slice(); // slice to copy
|
|
47033
|
-
|
|
47034
|
-
var arrIdx = lensArr[lensArr.length-1];
|
|
47035
|
-
arr.splice(arrIdx, 0, toInsert);
|
|
47036
|
-
return lens(obj).set(arrLens, arr);
|
|
47037
|
-
};
|
|
47038
|
-
|
|
47039
|
-
lens.prototype.insertBefore = lens.prototype.insertAt;
|
|
47040
|
-
lens.prototype.insertAfter = function(lensArr, toInsert) {
|
|
47041
|
-
var newLens = lensArr.slice();
|
|
47042
|
-
newLens[newLens.length-1] += 1;
|
|
47043
|
-
return lens(this._wrapped).insertAt(newLens, toInsert);
|
|
47044
|
-
};
|
|
47045
|
-
*/
|
|
47046
|
-
|
|
47047
|
-
// OBJECT FUNCTIONS
|
|
47048
|
-
|
|
47049
|
-
const obj = {
|
|
47050
|
-
get: function (obj, monocle) {
|
|
47051
|
-
return obj[monocle];
|
|
47052
|
-
},
|
|
47053
|
-
set: function (obj, monocle, val) {
|
|
47054
|
-
var newObj = clone(obj);
|
|
47055
|
-
newObj[monocle] = val;
|
|
47056
|
-
return newObj;
|
|
47057
|
-
},
|
|
47058
|
-
mod: function (obj, monocle, f) {
|
|
47059
|
-
var newObj = clone(obj);
|
|
47060
|
-
newObj[monocle] = f(obj[monocle]);
|
|
47061
|
-
return newObj;
|
|
47062
|
-
},
|
|
47063
|
-
del: function (obj, monocle) {
|
|
47064
|
-
var newObj = clone(obj);
|
|
47065
|
-
delete newObj[monocle];
|
|
47066
|
-
return newObj;
|
|
47067
|
-
}
|
|
47068
|
-
};
|
|
47069
|
-
|
|
47070
|
-
// STRING FUNCTIONS
|
|
47071
|
-
|
|
47072
|
-
const str = {
|
|
47073
|
-
get: function (arr, monocle) {
|
|
47074
|
-
return arr[monocle];
|
|
47075
|
-
},
|
|
47076
|
-
set: function (arr, monocle, val) {
|
|
47077
|
-
var newArr = arr.splice();
|
|
47078
|
-
newArr[monocle] = val;
|
|
47079
|
-
return newArr;
|
|
47080
|
-
},
|
|
47081
|
-
mod: function (arr, monocle, f) {
|
|
47082
|
-
var newArr = arr.splice();
|
|
47083
|
-
newArr[monocle] = f(arr[monocle]);
|
|
47084
|
-
return newArr;
|
|
47085
|
-
},
|
|
47086
|
-
del: function (arr, monocle) {
|
|
47087
|
-
var newArr = arr.slice();
|
|
47088
|
-
newArr.splice(monocle);
|
|
47089
|
-
return newArr;
|
|
47090
|
-
}
|
|
47091
|
-
};
|
|
47092
|
-
|
|
47093
|
-
// TODO(mdr)
|
|
47094
|
-
// TODO(mdr)
|
|
47095
|
-
// TODO(mdr)
|
|
47096
|
-
|
|
47097
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
47098
|
-
|
|
47099
|
-
/**
|
|
47100
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
47101
|
-
* Some usage of this type somewhere is causing TypeScript to believe that these
|
|
47102
|
-
* elements should be components. Don't know where that is, to fix it up
|
|
47103
|
-
* properly. In reality, these types are just too hard to use and aren't
|
|
47104
|
-
* really helping us out as I now have to suppress this rather than
|
|
47105
|
-
* get value from the type. :(
|
|
47106
|
-
*/ // @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
47107
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
47108
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
47109
|
-
class MultiRenderer extends React__namespace.Component {
|
|
47110
|
-
static contextType = PerseusI18nContext;
|
|
47111
|
-
rendererDataTreeMapper;
|
|
47112
|
-
getRenderersMapper;
|
|
47113
|
-
constructor(props) {
|
|
47114
|
-
super(props);
|
|
47115
|
-
this.rendererDataTreeMapper = buildMapper()
|
|
47116
|
-
// @ts-expect-error - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'ContentNode'.
|
|
47117
|
-
.setContentMapper((c, _, p) => this._makeContentRendererData(c, p))
|
|
47118
|
-
// @ts-expect-error - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'HintNode'.
|
|
47119
|
-
.setHintMapper(h => this._makeHintRendererData(h)).setTagsMapper(t => null);
|
|
47120
|
-
|
|
47121
|
-
// @ts-expect-error - TS2322 - Type 'TreeMapperForLeavesAndCollections<unknown, any, unknown, any, unknown, unknown>' is not assignable to type 'TreeMapper<ContentRendererData, ContentRendererElement, HintRendererData, HintRendererElement, null, null>'.
|
|
47122
|
-
this.getRenderersMapper = buildMapper()
|
|
47123
|
-
// @ts-expect-error - TS2571 - Object is of type 'unknown'.
|
|
47124
|
-
.setContentMapper(c => c.makeRenderer())
|
|
47125
|
-
// @ts-expect-error - TS2571 - Object is of type 'unknown'.
|
|
47126
|
-
.setHintMapper(h => h.makeRenderer()).setArrayMapper((renderers, data, shape) => this._annotateRendererArray(renderers, data, shape));
|
|
47127
|
-
|
|
47128
|
-
// Keep state in sync with props.
|
|
47129
|
-
this.state = this._tryMakeRendererState(this.props);
|
|
47130
|
-
}
|
|
47131
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
47132
|
-
// Keep state in sync with props.
|
|
47133
|
-
if (nextProps.item !== this.props.item) {
|
|
47134
|
-
this.setState(this._tryMakeRendererState(nextProps));
|
|
47135
|
-
}
|
|
47136
|
-
}
|
|
47137
|
-
|
|
47138
|
-
/**
|
|
47139
|
-
* Attempt to build a State that includes a renderer tree corresponding to
|
|
47140
|
-
* the item provided in props. On error, return a state with `renderError`
|
|
47141
|
-
* set instead.
|
|
47142
|
-
*/
|
|
47143
|
-
_tryMakeRendererState(props) {
|
|
47144
|
-
try {
|
|
47145
|
-
return {
|
|
47146
|
-
rendererDataTree: this._makeRendererDataTree(props.item, props.shape),
|
|
47147
|
-
renderError: null
|
|
47148
|
-
};
|
|
47149
|
-
} catch (e) {
|
|
47150
|
-
Log.error("Error building tree state", perseusCore.Errors.Internal, {
|
|
47151
|
-
cause: e
|
|
47152
|
-
});
|
|
47153
|
-
return {
|
|
47154
|
-
rendererDataTree: null,
|
|
47155
|
-
renderError: e
|
|
47156
|
-
};
|
|
47157
|
-
}
|
|
47158
|
-
}
|
|
47159
|
-
_handleSerializedStateUpdated = (path, newState) => {
|
|
47160
|
-
const {
|
|
47161
|
-
onSerializedStateUpdated
|
|
47162
|
-
} = this.props;
|
|
47163
|
-
if (onSerializedStateUpdated) {
|
|
47164
|
-
const oldState = this._getSerializedState(this.props.serializedState);
|
|
47165
|
-
onSerializedStateUpdated(lens(oldState).set(path, newState).freeze());
|
|
47166
|
-
}
|
|
47167
|
-
};
|
|
47168
|
-
|
|
47169
|
-
/**
|
|
47170
|
-
* Props that aren't directly used by the MultiRenderer are delegated to
|
|
47171
|
-
* the underlying Renderers.
|
|
47172
|
-
*/
|
|
47173
|
-
_getRendererProps() {
|
|
47174
|
-
// `item`, `children`, and others are unused. I'm
|
|
47175
|
-
// explicitly pulling them out of `this.props` so I don't pass them to
|
|
47176
|
-
// `<Renderer>`. I'm not sure how else to do this.
|
|
47177
|
-
const {
|
|
47178
|
-
item: _,
|
|
47179
|
-
children: __,
|
|
47180
|
-
shape: ___,
|
|
47181
|
-
serializedState: ____,
|
|
47182
|
-
onSerializedStateUpdated: _____,
|
|
47183
|
-
...otherProps
|
|
47184
|
-
} = this.props;
|
|
47185
|
-
return {
|
|
47186
|
-
...otherProps,
|
|
47187
|
-
strings: this.context.strings
|
|
47188
|
-
};
|
|
47189
|
-
}
|
|
47190
|
-
|
|
47191
|
-
/**
|
|
47192
|
-
* Construct a Renderer and a ref placeholder for the given ContentNode.
|
|
47193
|
-
*/
|
|
47194
|
-
_makeContentRendererData(content, path) {
|
|
47195
|
-
// NOTE(emily): The `findExternalWidgets` function here is computed
|
|
47196
|
-
// inline and thus changes each time we run this function. If it
|
|
47197
|
-
// were to change every render, it would cause the Renderer to
|
|
47198
|
-
// re-render a lot more than is necessary. Don't re-compute this
|
|
47199
|
-
// element unless it is necessary!
|
|
47200
|
-
// HACK(mdr): TypeScript can't prove that this is a ContentRendererData,
|
|
47201
|
-
// because of how we awkwardly construct it in order to obtain a
|
|
47202
|
-
// circular reference. But it is, I promise.
|
|
47203
|
-
const data = {
|
|
47204
|
-
ref: null,
|
|
47205
|
-
makeRenderer: null
|
|
47206
|
-
};
|
|
47207
|
-
const refFunc = e => data.ref = e;
|
|
47208
|
-
const findExternalWidgets = criterion => this._findWidgets(data, criterion);
|
|
47209
|
-
const handleSerializedState = state => this._handleSerializedStateUpdated(path, state);
|
|
47210
|
-
data.makeRenderer = () =>
|
|
47211
|
-
/*#__PURE__*/
|
|
47212
|
-
/**
|
|
47213
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
47214
|
-
* `content` contains props that Renderer doesn't have. However,
|
|
47215
|
-
* since the type for `content` is not exact, it's hard to know
|
|
47216
|
-
* if this spread is including undocumented props so mapping
|
|
47217
|
-
* one to one could introduce a bug. Need to work out the exact
|
|
47218
|
-
* type for ContentNode and then fix this.
|
|
47219
|
-
*/
|
|
47220
|
-
// @ts-expect-error - TS2322 - Type '{ ref: (e: any) => any; findExternalWidgets: (criterion: any) => readonly (Widget | null | undefined)[]; serializedState: any; onSerializedStateUpdated: (state: any) => void; __type: "content" | "item"; ... 9 more ...; reviewMode?: boolean | ... 1 more ... | undefined; }' is not assignable to type 'InexactPartial<Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "content" | "images" | "onRender" | "linterContext" | "widgets" | "alwaysUpdate" | ... 6 more ... | "serializedState">>'.
|
|
47221
|
-
React__namespace.createElement(Renderer, _extends({}, this._getRendererProps(), content, {
|
|
47222
|
-
ref: refFunc,
|
|
47223
|
-
findExternalWidgets: findExternalWidgets,
|
|
47224
|
-
serializedState: this.props.serializedState ? lens(this.props.serializedState).get(path) : null,
|
|
47225
|
-
onSerializedStateUpdated: handleSerializedState
|
|
47226
|
-
}));
|
|
47227
|
-
return data;
|
|
47228
|
-
}
|
|
47229
|
-
|
|
47230
|
-
/**
|
|
47231
|
-
* Construct a Renderer for the given HintNode, and keep track of the hint
|
|
47232
|
-
* itself for future use, too.
|
|
47233
|
-
*/
|
|
47234
|
-
_makeHintRendererData(hint) {
|
|
47235
|
-
// TODO(mdr): Once HintsRenderer supports inter-widget communication,
|
|
47236
|
-
// give it a ref. Until then, leave the ref null forever, to avoid
|
|
47237
|
-
// confusing the findWidgets functions.
|
|
47238
|
-
//
|
|
47239
|
-
// NOTE(davidflanagan): As a partial step toward inter-widget
|
|
47240
|
-
// communication we're going to pass a findExternalWidgets function
|
|
47241
|
-
// (using a dummy data object). This allows passage-ref widgets in
|
|
47242
|
-
// hints to use findWidget() to find the passage widgets they reference.
|
|
47243
|
-
// Note that this is one-way only, however. It does not allow
|
|
47244
|
-
// widgets in the question to find widgets in the hints, for example.
|
|
47245
|
-
const findExternalWidgets = criterion => this._findWidgets({}, criterion);
|
|
47246
|
-
return {
|
|
47247
|
-
hint,
|
|
47248
|
-
findExternalWidgets,
|
|
47249
|
-
// _annotateRendererArray() needs this
|
|
47250
|
-
ref: null,
|
|
47251
|
-
makeRenderer: () => /*#__PURE__*/React__namespace.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
47252
|
-
findExternalWidgets: findExternalWidgets
|
|
47253
|
-
// Note(Jeremy): The MultiRenderer codebase types are
|
|
47254
|
-
// slightly different from the rest of the codebase.
|
|
47255
|
-
// Ideally `HintNode` would spread the `Hint` type into it,
|
|
47256
|
-
// but there is a difference in optionality of `widgets`
|
|
47257
|
-
// and `images` and that causes a huge cascade of type
|
|
47258
|
-
// errors (they are truly optional, but most of our code
|
|
47259
|
-
// assumes they're provided/set). Ignoring this for now.
|
|
47260
|
-
// @ts-expect-error - TS2769 - Type 'HintNode' is not assignable to type 'Hint'.
|
|
47261
|
-
,
|
|
47262
|
-
hints: [hint]
|
|
47263
|
-
}))
|
|
47264
|
-
};
|
|
47265
|
-
}
|
|
47266
|
-
|
|
47267
|
-
/**
|
|
47268
|
-
* Construct a tree of interconnected RendererDatas, corresponding to the
|
|
47269
|
-
* given item. Called in `_tryMakeRendererState`, in order to store this
|
|
47270
|
-
* tree in the component state.
|
|
47271
|
-
*/
|
|
47272
|
-
_makeRendererDataTree(item, shape) {
|
|
47273
|
-
const itemTree = itemToTree(item);
|
|
47274
|
-
return this.rendererDataTreeMapper.mapTree(itemTree, shape);
|
|
47275
|
-
}
|
|
47276
|
-
|
|
47277
|
-
/**
|
|
47278
|
-
* Return all widgets that meet the given criterion, from all Renderers
|
|
47279
|
-
* except the Renderer that triggered this call.
|
|
47280
|
-
*
|
|
47281
|
-
* This function is provided to each Renderer's `findExternalWidgets` prop,
|
|
47282
|
-
* which enables widgets in different Renderers to discover each other and
|
|
47283
|
-
* communicate.
|
|
47284
|
-
*/
|
|
47285
|
-
_findWidgets(callingData, filterCriterion) {
|
|
47286
|
-
const results = [];
|
|
47287
|
-
this._mapRenderers(data => {
|
|
47288
|
-
if (callingData !== data && data.ref) {
|
|
47289
|
-
results.push(...data.ref.findInternalWidgets(filterCriterion));
|
|
47290
|
-
}
|
|
47291
|
-
});
|
|
47292
|
-
return results;
|
|
47293
|
-
}
|
|
47294
|
-
|
|
47295
|
-
/**
|
|
47296
|
-
* Copy the renderer tree, apply the given transformation to the leaf nodes
|
|
47297
|
-
* and the optional given transformation to the array nodes, and return the
|
|
47298
|
-
* result.
|
|
47299
|
-
*
|
|
47300
|
-
* Used to provide structured data to the call site (the Renderer tree on
|
|
47301
|
-
* `render`, the Score tree on `getScores`, etc.), and to traverse the
|
|
47302
|
-
* renderer tree even when we disregard the output (like in
|
|
47303
|
-
* `_findWidgets`).
|
|
47304
|
-
*/
|
|
47305
|
-
_mapRenderers(
|
|
47306
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
47307
|
-
leafMapper
|
|
47308
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
47309
|
-
) {
|
|
47310
|
-
const {
|
|
47311
|
-
rendererDataTree
|
|
47312
|
-
} = this.state;
|
|
47313
|
-
if (!rendererDataTree) {
|
|
47314
|
-
return null;
|
|
47315
|
-
}
|
|
47316
|
-
const mapper = buildMapper().setContentMapper(leafMapper).setHintMapper(leafMapper);
|
|
47317
|
-
return mapper.mapTree(rendererDataTree, this.props.shape);
|
|
47318
|
-
}
|
|
47319
|
-
_scoreFromRef(ref) {
|
|
47320
|
-
if (!ref) {
|
|
47321
|
-
return null;
|
|
47322
|
-
}
|
|
47323
|
-
const [guess, score] = ref.guessAndScore();
|
|
47324
|
-
let state;
|
|
47325
|
-
if (ref.getSerializedState) {
|
|
47326
|
-
state = ref.getSerializedState();
|
|
47327
|
-
}
|
|
47328
|
-
return keScoreFromPerseusScore(score, guess, state);
|
|
47329
|
-
}
|
|
47330
|
-
|
|
47331
|
-
/**
|
|
47332
|
-
* Return a tree in the shape of the multi-item, with scores at each of
|
|
47333
|
-
* the content nodes and `null` at the other leaf nodes.
|
|
47334
|
-
*/
|
|
47335
|
-
getScores() {
|
|
47336
|
-
return this._mapRenderers(data => this._scoreFromRef(data.ref));
|
|
47337
|
-
}
|
|
47338
|
-
|
|
47339
|
-
/**
|
|
47340
|
-
* Return a single composite score for all rendered content nodes.
|
|
47341
|
-
* The `guess` is a tree in the shape of the multi-item, with an individual
|
|
47342
|
-
* guess at each content node and `null` at the other leaf nodes.
|
|
47343
|
-
*/
|
|
47344
|
-
score() {
|
|
47345
|
-
const scores = [];
|
|
47346
|
-
const state = [];
|
|
47347
|
-
const guess = this._mapRenderers(data => {
|
|
47348
|
-
if (!data.ref) {
|
|
47349
|
-
return null;
|
|
47350
|
-
}
|
|
47351
|
-
if (data.ref.getSerializedState) {
|
|
47352
|
-
state.push(data.ref.getSerializedState());
|
|
47353
|
-
}
|
|
47354
|
-
scores.push(data.ref.score());
|
|
47355
|
-
return data.ref?.getUserInput();
|
|
47356
|
-
});
|
|
47357
|
-
const combinedScore = scores.reduce(combineScores);
|
|
47358
|
-
return keScoreFromPerseusScore(combinedScore, guess, state);
|
|
47359
|
-
}
|
|
47360
|
-
|
|
47361
|
-
/**
|
|
47362
|
-
* Return a tree in the shape of the multi-item, with serialized state at
|
|
47363
|
-
* each of the content nodes and `null` at the other leaf nodes.
|
|
47364
|
-
*
|
|
47365
|
-
* If the lastSerializedState argument is supplied, this function will fill
|
|
47366
|
-
* in the state of not-currently-rendered content and hint nodes with the
|
|
47367
|
-
* values from the previous serialized state. If no lastSerializedState is
|
|
47368
|
-
* supplied, `null` will be returned for not-currently-rendered content and
|
|
47369
|
-
* hint nodes.
|
|
47370
|
-
*/
|
|
47371
|
-
_getSerializedState(lastSerializedState) {
|
|
47372
|
-
return this._mapRenderers((data, _, path) => {
|
|
47373
|
-
if (data.ref) {
|
|
47374
|
-
return data.ref.getSerializedState();
|
|
47375
|
-
}
|
|
47376
|
-
if (lastSerializedState) {
|
|
47377
|
-
return lens(lastSerializedState).get(path);
|
|
47378
|
-
}
|
|
47379
|
-
return null;
|
|
47380
|
-
});
|
|
47381
|
-
}
|
|
47382
|
-
|
|
47383
|
-
/**
|
|
47384
|
-
* Given a tree in the shape of the multi-item, with serialized state at
|
|
47385
|
-
* each of the content nodes, restore each state to the corresponding
|
|
47386
|
-
* renderer if currently mounted.
|
|
47387
|
-
*/
|
|
47388
|
-
restoreSerializedState(serializedState, callback) {
|
|
47389
|
-
// We want to call our async callback only once all of the childrens'
|
|
47390
|
-
// callbacks have run. We add one to this counter before we call out to
|
|
47391
|
-
// each renderer and decrement it when it runs our callback.
|
|
47392
|
-
let numCallbacks = 0;
|
|
47393
|
-
const countCallback = () => {
|
|
47394
|
-
numCallbacks--;
|
|
47395
|
-
if (callback && numCallbacks === 0) {
|
|
47396
|
-
callback();
|
|
47397
|
-
}
|
|
47398
|
-
};
|
|
47399
|
-
this._mapRenderers((data, _, path) => {
|
|
47400
|
-
if (!data.ref) {
|
|
47401
|
-
return;
|
|
47402
|
-
}
|
|
47403
|
-
const state = lens(serializedState).get(path);
|
|
47404
|
-
if (!state) {
|
|
47405
|
-
return;
|
|
47406
|
-
}
|
|
47407
|
-
numCallbacks++;
|
|
47408
|
-
data.ref?.restoreSerializedState(state, countCallback);
|
|
47409
|
-
});
|
|
47410
|
-
}
|
|
47411
|
-
|
|
47412
|
-
/**
|
|
47413
|
-
* Given an array of renderers, if it happens to be an array of *hint*
|
|
47414
|
-
* renderers, then attach a `firstN` method to the array, which allows the
|
|
47415
|
-
* layout to render the hints together in one HintsRenderer.
|
|
47416
|
-
*/
|
|
47417
|
-
_annotateRendererArray(renderers, rendererDatas, shape) {
|
|
47418
|
-
if (shape.elementShape.type === "hint") {
|
|
47419
|
-
// The shape says that these are HintRendererDatas, even though
|
|
47420
|
-
// it's not provable at compile time, so perform a cast.
|
|
47421
|
-
const hintRendererDatas = rendererDatas;
|
|
47422
|
-
renderers = [...renderers];
|
|
47423
|
-
renderers.firstN = n => /*#__PURE__*/React__namespace.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
47424
|
-
findExternalWidgets: hintRendererDatas[0] ? hintRendererDatas[0].findExternalWidgets : undefined,
|
|
47425
|
-
hints: hintRendererDatas.map(d => d.hint),
|
|
47426
|
-
hintsVisible: n
|
|
47427
|
-
}));
|
|
47428
|
-
}
|
|
47429
|
-
return renderers;
|
|
47430
|
-
}
|
|
47431
|
-
|
|
47432
|
-
/**
|
|
47433
|
-
* Return a tree in the shape of the multi-item, with a Renderer at each
|
|
47434
|
-
* content node and a HintRenderer at each hint node.
|
|
47435
|
-
*
|
|
47436
|
-
* This is generated by running each of the `makeRenderer` functions at the
|
|
47437
|
-
* leaf nodes.
|
|
47438
|
-
*/
|
|
47439
|
-
_getRenderers() {
|
|
47440
|
-
return this.getRenderersMapper.mapTree(this.state.rendererDataTree, this.props.shape);
|
|
47441
|
-
}
|
|
47442
|
-
render() {
|
|
47443
|
-
if (this.state.renderError) {
|
|
47444
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
47445
|
-
className: aphrodite.css(styles.error)
|
|
47446
|
-
}, this.context.strings.errorRendering({
|
|
47447
|
-
error: String(this.state.renderError)
|
|
47448
|
-
}));
|
|
47449
|
-
}
|
|
47450
|
-
|
|
47451
|
-
// Pass the renderer tree to the `children` function, which will
|
|
47452
|
-
// determine the actual content of this component.
|
|
47453
|
-
return /*#__PURE__*/React__namespace.createElement(DependenciesContext.Provider, {
|
|
47454
|
-
value: this.props.dependencies
|
|
47455
|
-
}, this.props.children({
|
|
47456
|
-
renderers: this._getRenderers()
|
|
47457
|
-
}));
|
|
47458
|
-
}
|
|
47459
|
-
}
|
|
47460
|
-
const styles = aphrodite.StyleSheet.create({
|
|
47461
|
-
error: {
|
|
47462
|
-
color: "red"
|
|
47463
|
-
}
|
|
47464
|
-
});
|
|
47465
|
-
|
|
47466
|
-
/**
|
|
47467
|
-
* Utility functions to build React PropTypes for multi-items and shapes.
|
|
47468
|
-
*
|
|
47469
|
-
* If you're writing new components, though, consider using the Item and Shape
|
|
47470
|
-
* types instead.
|
|
47471
|
-
*/
|
|
47472
|
-
/**
|
|
47473
|
-
* Return a PropType that accepts Items of the given shape, and rejects other
|
|
47474
|
-
* objects.
|
|
47475
|
-
*
|
|
47476
|
-
* Usage: `propTypes: {item: buildPropTypeForShape(myShape)}`
|
|
47477
|
-
*/
|
|
47478
|
-
function buildPropTypeForShape(shape) {
|
|
47479
|
-
return PropTypes__default["default"].oneOfType([PropTypes__default["default"].shape({
|
|
47480
|
-
_multi: buildTreePropTypeForShape(shape)
|
|
47481
|
-
}), PropTypes__default["default"].oneOf([null, undefined])]);
|
|
47482
|
-
}
|
|
47483
|
-
|
|
47484
|
-
/**
|
|
47485
|
-
* Return a PropType that accepts ItemTrees of the given shape, and rejects
|
|
47486
|
-
* other objects.
|
|
47487
|
-
*/
|
|
47488
|
-
function buildTreePropTypeForShape(shape) {
|
|
47489
|
-
if (shape.type === "content") {
|
|
47490
|
-
return PropTypes__default["default"].shape({
|
|
47491
|
-
// TODO(mdr): Remove #LegacyContentNode support.
|
|
47492
|
-
__type: PropTypes__default["default"].oneOf(["content", "item"]).isRequired,
|
|
47493
|
-
content: PropTypes__default["default"].string,
|
|
47494
|
-
images: PropTypes__default["default"].objectOf(PropTypes__default["default"].any),
|
|
47495
|
-
widgets: PropTypes__default["default"].objectOf(PropTypes__default["default"].any)
|
|
47496
|
-
});
|
|
47497
|
-
}
|
|
47498
|
-
if (shape.type === "hint") {
|
|
47499
|
-
return PropTypes__default["default"].shape({
|
|
47500
|
-
__type: PropTypes__default["default"].oneOf(["hint"]).isRequired,
|
|
47501
|
-
content: PropTypes__default["default"].string,
|
|
47502
|
-
images: PropTypes__default["default"].objectOf(PropTypes__default["default"].any),
|
|
47503
|
-
widgets: PropTypes__default["default"].objectOf(PropTypes__default["default"].any),
|
|
47504
|
-
replace: PropTypes__default["default"].bool
|
|
47505
|
-
});
|
|
47506
|
-
}
|
|
47507
|
-
if (shape.type === "tags") {
|
|
47508
|
-
return PropTypes__default["default"].arrayOf(PropTypes__default["default"].string.isRequired);
|
|
47509
|
-
}
|
|
47510
|
-
if (shape.type === "array") {
|
|
47511
|
-
const elementPropType = buildTreePropTypeForShape(shape.elementShape);
|
|
47512
|
-
return PropTypes__default["default"].arrayOf(elementPropType.isRequired);
|
|
47513
|
-
}
|
|
47514
|
-
if (shape.type === "object") {
|
|
47515
|
-
const valueShapes = shape.shape;
|
|
47516
|
-
const propTypeShape = {};
|
|
47517
|
-
Object.keys(valueShapes).forEach(key => {
|
|
47518
|
-
propTypeShape[key] = buildTreePropTypeForShape(valueShapes[key]).isRequired;
|
|
47519
|
-
});
|
|
47520
|
-
return PropTypes__default["default"].shape(propTypeShape);
|
|
47521
|
-
}
|
|
47522
|
-
throw new perseusCore.PerseusError(
|
|
47523
|
-
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
47524
|
-
`unexpected shape type ${shape.type}`, perseusCore.Errors.InvalidInput);
|
|
47525
|
-
}
|
|
47526
|
-
|
|
47527
|
-
/**
|
|
47528
|
-
* This library provides support for Perseus multi-items: structured Perseus
|
|
47529
|
-
* content that content creators can easily create, and that applications can
|
|
47530
|
-
* easily render into different parts of the layout.
|
|
47531
|
-
*
|
|
47532
|
-
* For more details about application and motivation, see:
|
|
47533
|
-
* https://sites.google.com/a/khanacademy.org/forge/for-developers/perseus-items-and-multi-items
|
|
47534
|
-
*
|
|
47535
|
-
* This file primarily exposes the `MultiRenderer` component, which performs
|
|
47536
|
-
* multi-rendering. To multi-render a question, pass in the content of the item
|
|
47537
|
-
* to the `MultiRenderer` component as a props. Then, pass in a function which
|
|
47538
|
-
* takes an object of renderers (in the same structure as the content), and
|
|
47539
|
-
* return a render tree. The `MultiRenderer` component will allow you to
|
|
47540
|
-
* combine scores, serialized state, etc. without having to manually call on
|
|
47541
|
-
* each of the functions. It also handles inter-widgets requests between the
|
|
47542
|
-
* different renderers.
|
|
47543
|
-
* For more details, see `multi-items/multi-renderer.jsx`.
|
|
47544
|
-
*
|
|
47545
|
-
* Example:
|
|
47546
|
-
*
|
|
47547
|
-
* item = {_multi: {
|
|
47548
|
-
* left: <content data>,
|
|
47549
|
-
* right: [<content data>, <content data>],
|
|
47550
|
-
* }}
|
|
47551
|
-
* shape = shapes.shape({
|
|
47552
|
-
* left: shapes.content,
|
|
47553
|
-
* right: shapes.arrayOf(shapes.content),
|
|
47554
|
-
* })
|
|
47555
|
-
*
|
|
47556
|
-
* <MultiRenderer item={item} shape={shape}>
|
|
47557
|
-
* {({renderers}) =>
|
|
47558
|
-
* <div>
|
|
47559
|
-
* <div id="left">{renderers.left}</div>
|
|
47560
|
-
* <ul id="right">
|
|
47561
|
-
* {renderers.right.map(r => <li>{r}</li>)}
|
|
47562
|
-
* </ul>
|
|
47563
|
-
* </div>
|
|
47564
|
-
* }
|
|
47565
|
-
* </MultiRenderer>
|
|
47566
|
-
*
|
|
47567
|
-
* This file also exposes `shapes`, which helps you construct a runtime type
|
|
47568
|
-
* declaration for your particular class of multi-item. This can then be used
|
|
47569
|
-
* to create a MultirendererEditor for your multi-item shape, and to validate
|
|
47570
|
-
* that a multi-item conforms to the shape via `buildPropTypeForShape`.
|
|
47571
|
-
* For more details, see `multi-items/shapes.js`.
|
|
47572
|
-
*
|
|
47573
|
-
* This file also exposes some utility functions for working with generic
|
|
47574
|
-
* multi-items, like `findContentNodesInItem`, `findHintNodesInItem`,
|
|
47575
|
-
* `inferItemShape`, and `buildEmptyItemForShape`.
|
|
47576
|
-
* For more details, see `multi-items/items.js`.
|
|
47577
|
-
*/
|
|
47578
|
-
var MultiItems = {
|
|
47579
|
-
// Tools for rendering your multi-items
|
|
47580
|
-
MultiRenderer,
|
|
47581
|
-
// Tools for declaring your multi-item shapes
|
|
47582
|
-
shapes,
|
|
47583
|
-
buildPropTypeForShape,
|
|
47584
|
-
// Tools for generically manipulating multi-items
|
|
47585
|
-
buildEmptyItemForShape,
|
|
47586
|
-
findContentNodesInItem: findContentNodesInItem$2,
|
|
47587
|
-
findHintNodesInItem,
|
|
47588
|
-
inferItemShape: inferItemShape$2
|
|
47589
|
-
};
|
|
47590
|
-
|
|
47591
46439
|
/**
|
|
47592
46440
|
* Calculates whether a perseus item is renderable by a specific
|
|
47593
46441
|
* perseus-item-data version.
|
|
@@ -47597,10 +46445,6 @@ var MultiItems = {
|
|
|
47597
46445
|
* This supports widgets that contain renderers, such as the
|
|
47598
46446
|
* group or sequence widgets.
|
|
47599
46447
|
*/
|
|
47600
|
-
const {
|
|
47601
|
-
findContentNodesInItem: findContentNodesInItem$1,
|
|
47602
|
-
inferItemShape: inferItemShape$1
|
|
47603
|
-
} = MultiItems;
|
|
47604
46448
|
const isUpgradedWidgetInfoRenderableBy = function (widgetInfo, widgetRendererVersion) {
|
|
47605
46449
|
if (widgetRendererVersion == null) {
|
|
47606
46450
|
// If the widget does not exist in this version, this will
|
|
@@ -47646,17 +46490,6 @@ const isItemRenderableByVersion = function (itemData, rendererContentVersion) {
|
|
|
47646
46490
|
if (itemData == null || rendererContentVersion == null) {
|
|
47647
46491
|
throw new perseusCore.PerseusError("missing parameter to Perseus.isRenderable.item", perseusCore.Errors.InvalidInput);
|
|
47648
46492
|
}
|
|
47649
|
-
if (itemData._multi) {
|
|
47650
|
-
const shape = inferItemShape$1(itemData);
|
|
47651
|
-
let isRenderable = true;
|
|
47652
|
-
findContentNodesInItem$1(itemData, shape, node => {
|
|
47653
|
-
const nodeIsRenderable = isRendererContentRenderableBy(node, rendererContentVersion);
|
|
47654
|
-
if (!nodeIsRenderable) {
|
|
47655
|
-
isRenderable = false;
|
|
47656
|
-
}
|
|
47657
|
-
});
|
|
47658
|
-
return isRenderable;
|
|
47659
|
-
}
|
|
47660
46493
|
return isRendererContentRenderableBy(itemData.question, rendererContentVersion);
|
|
47661
46494
|
};
|
|
47662
46495
|
|
|
@@ -47664,10 +46497,6 @@ const isItemRenderableByVersion = function (itemData, rendererContentVersion) {
|
|
|
47664
46497
|
* Identifies whether or not a given perseus item requires the use of a mouse
|
|
47665
46498
|
* or screen, based on the widgets it contains.
|
|
47666
46499
|
*/
|
|
47667
|
-
const {
|
|
47668
|
-
findContentNodesInItem,
|
|
47669
|
-
inferItemShape
|
|
47670
|
-
} = MultiItems;
|
|
47671
46500
|
|
|
47672
46501
|
// Iterate over a single Perseus renderer, mutating `widgets` by appending
|
|
47673
46502
|
// violating widget types discovered in this item.
|
|
@@ -47688,12 +46517,7 @@ function traverseRenderer(itemData, widgets) {
|
|
|
47688
46517
|
function violatingWidgets(itemData) {
|
|
47689
46518
|
// TODO(jordan): Hints as well
|
|
47690
46519
|
const widgets = [];
|
|
47691
|
-
|
|
47692
|
-
const shape = inferItemShape(itemData);
|
|
47693
|
-
findContentNodesInItem(itemData, shape, content => traverseRenderer(content, widgets));
|
|
47694
|
-
} else {
|
|
47695
|
-
traverseRenderer(itemData.question, widgets);
|
|
47696
|
-
}
|
|
46520
|
+
traverseRenderer(itemData.question, widgets);
|
|
47697
46521
|
|
|
47698
46522
|
// Uniquify the list of widgets (by type)
|
|
47699
46523
|
return ___default["default"].uniq(widgets);
|
|
@@ -50216,6 +49040,10 @@ const ScoringUtil = {
|
|
|
50216
49040
|
keScoreFromPerseusScore
|
|
50217
49041
|
};
|
|
50218
49042
|
|
|
49043
|
+
/**
|
|
49044
|
+
* Types
|
|
49045
|
+
*/
|
|
49046
|
+
|
|
50219
49047
|
exports.ApiOptions = ApiOptions;
|
|
50220
49048
|
exports.ArticleRenderer = ArticleRenderer;
|
|
50221
49049
|
exports.BaseRadio = BaseRadio;
|
|
@@ -50238,7 +49066,6 @@ exports.KhanMath = KhanMath;
|
|
|
50238
49066
|
exports.LoadingContext = context;
|
|
50239
49067
|
exports.Log = Log;
|
|
50240
49068
|
exports.MatrixWidget = Matrix$1;
|
|
50241
|
-
exports.MultiItems = MultiItems;
|
|
50242
49069
|
exports.NumericInput = NumericInput$1;
|
|
50243
49070
|
exports.PerseusExpressionAnswerFormConsidered = PerseusExpressionAnswerFormConsidered;
|
|
50244
49071
|
exports.PerseusI18nContext = PerseusI18nContext;
|
|
@@ -50257,8 +49084,6 @@ exports.Widgets = widgets$1;
|
|
|
50257
49084
|
exports.addWidget = addWidget;
|
|
50258
49085
|
exports.apiVersion = apiVersion;
|
|
50259
49086
|
exports.bodyXsmallBold = bodyXsmallBold;
|
|
50260
|
-
exports.buildEmptyItemTreeForShape = buildEmptyItemTreeForShape;
|
|
50261
|
-
exports.buildMapper = buildMapper;
|
|
50262
49087
|
exports.components = components;
|
|
50263
49088
|
exports.containerSizeClass = containerSizeClass;
|
|
50264
49089
|
exports.contentHasWidgetType = contentHasWidgetType;
|
|
@@ -50302,7 +49127,6 @@ exports.isItemRenderableByVersion = isItemRenderableByVersion;
|
|
|
50302
49127
|
exports.isWidgetIdInContent = isWidgetIdInContent;
|
|
50303
49128
|
exports.isWrongAnswerSupported = isWrongAnswerSupported;
|
|
50304
49129
|
exports.itemDataVersion = itemDataVersion;
|
|
50305
|
-
exports.itemToTree = itemToTree;
|
|
50306
49130
|
exports.itemVersion = ItemVersion;
|
|
50307
49131
|
exports.libVersion = libVersion;
|
|
50308
49132
|
exports.lockedFigureColors = lockedFigureColors;
|
|
@@ -50315,7 +49139,6 @@ exports.plotterPlotTypes = plotterPlotTypes;
|
|
|
50315
49139
|
exports.preprocessTex = preprocessTex;
|
|
50316
49140
|
exports.registerAllWidgetsForTesting = registerAllWidgetsForTesting;
|
|
50317
49141
|
exports.scorePerseusItem = scorePerseusItem;
|
|
50318
|
-
exports.shapes = shapes;
|
|
50319
49142
|
exports.shouldHaveIndividualAnswer = shouldHaveIndividualAnswer;
|
|
50320
49143
|
exports.traverse = traverse;
|
|
50321
49144
|
exports.usePerseusI18n = usePerseusI18n;
|