@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/es/index.js
CHANGED
|
@@ -508,7 +508,7 @@ class InnerMathInput extends React.Component {
|
|
|
508
508
|
className = className + " " + this.props.className;
|
|
509
509
|
}
|
|
510
510
|
return /*#__PURE__*/React.createElement(View, {
|
|
511
|
-
style: [styles$
|
|
511
|
+
style: [styles$D.outerWrapper, this.state.focused && styles$D.wrapperFocused, this.props.hasError && styles$D.wrapperError]
|
|
512
512
|
}, /*#__PURE__*/React.createElement("div", {
|
|
513
513
|
style: {
|
|
514
514
|
display: "flex",
|
|
@@ -546,7 +546,7 @@ class InnerMathInput extends React.Component {
|
|
|
546
546
|
style: a11y.srOnly
|
|
547
547
|
}, this.context.strings.mathInputDescription), /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
548
548
|
closeButtonVisible: true,
|
|
549
|
-
style: styles$
|
|
549
|
+
style: styles$D.popoverContent
|
|
550
550
|
}, /*#__PURE__*/React.createElement(DesktopKeypad, _extends({
|
|
551
551
|
onAnalyticsEvent: this.props.onAnalyticsEvent,
|
|
552
552
|
extraKeys: this.props.extraKeys,
|
|
@@ -622,9 +622,9 @@ const MathInputIcon = ({
|
|
|
622
622
|
fillColor = color.offBlack;
|
|
623
623
|
break;
|
|
624
624
|
}
|
|
625
|
-
const dynamicClass = active || focused ? styles$
|
|
625
|
+
const dynamicClass = active || focused ? styles$D.iconActive : styles$D.iconInactive;
|
|
626
626
|
return /*#__PURE__*/React.createElement(View, {
|
|
627
|
-
style: [styles$
|
|
627
|
+
style: [styles$D.iconContainer, dynamicClass]
|
|
628
628
|
}, /*#__PURE__*/React.createElement("svg", {
|
|
629
629
|
xmlns: "http://www.w3.org/2000/svg",
|
|
630
630
|
width: "16",
|
|
@@ -669,7 +669,7 @@ const inputFocused = {
|
|
|
669
669
|
borderColor: color.blue,
|
|
670
670
|
margin: -1
|
|
671
671
|
};
|
|
672
|
-
const styles$
|
|
672
|
+
const styles$D = StyleSheet.create({
|
|
673
673
|
iconContainer: {
|
|
674
674
|
display: "flex",
|
|
675
675
|
justifyContent: "center",
|
|
@@ -2469,7 +2469,7 @@ class Expression extends React.Component {
|
|
|
2469
2469
|
var _this$props$keypadCon, _this$props$analytics2, _this$props$analytics3;
|
|
2470
2470
|
if (this.props.apiOptions.customKeypad) {
|
|
2471
2471
|
return /*#__PURE__*/React.createElement(View, {
|
|
2472
|
-
className: css(styles$
|
|
2472
|
+
className: css(styles$C.mobileLabelInputWrapper)
|
|
2473
2473
|
}, !!this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelSmall, {
|
|
2474
2474
|
htmlFor: this._textareaId,
|
|
2475
2475
|
tag: "label"
|
|
@@ -2504,7 +2504,7 @@ class Expression extends React.Component {
|
|
|
2504
2504
|
ERROR_TITLE
|
|
2505
2505
|
} = this.context.strings;
|
|
2506
2506
|
return /*#__PURE__*/React.createElement(View, {
|
|
2507
|
-
className: css(styles$
|
|
2507
|
+
className: css(styles$C.desktopLabelInputWrapper)
|
|
2508
2508
|
}, !!this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelSmall, {
|
|
2509
2509
|
htmlFor: this._textareaId,
|
|
2510
2510
|
tag: "label"
|
|
@@ -2554,7 +2554,7 @@ Expression.defaultProps = {
|
|
|
2554
2554
|
apiOptions: ApiOptions.defaults,
|
|
2555
2555
|
linterContext: linterContextDefault
|
|
2556
2556
|
};
|
|
2557
|
-
const styles$
|
|
2557
|
+
const styles$C = StyleSheet.create({
|
|
2558
2558
|
mobileLabelInputWrapper: {
|
|
2559
2559
|
padding: "15px 4px 0"
|
|
2560
2560
|
},
|
|
@@ -17930,33 +17930,33 @@ class Lint extends React.Component {
|
|
|
17930
17930
|
let warningText;
|
|
17931
17931
|
let warningTextStyle;
|
|
17932
17932
|
if (this.props.severity === Severity.Error) {
|
|
17933
|
-
severityStyle = styles$
|
|
17933
|
+
severityStyle = styles$B.indicatorError;
|
|
17934
17934
|
warningText = "Error";
|
|
17935
|
-
warningTextStyle = styles$
|
|
17935
|
+
warningTextStyle = styles$B.publishBlockingError;
|
|
17936
17936
|
} else if (this.props.severity === Severity.Warning) {
|
|
17937
|
-
severityStyle = styles$
|
|
17937
|
+
severityStyle = styles$B.indicatorWarning;
|
|
17938
17938
|
warningText = "Warning";
|
|
17939
|
-
warningTextStyle = styles$
|
|
17939
|
+
warningTextStyle = styles$B.warning;
|
|
17940
17940
|
} else {
|
|
17941
|
-
severityStyle = styles$
|
|
17941
|
+
severityStyle = styles$B.indicatorGuideline;
|
|
17942
17942
|
warningText = "Recommendation";
|
|
17943
|
-
warningTextStyle = styles$
|
|
17943
|
+
warningTextStyle = styles$B.warning;
|
|
17944
17944
|
}
|
|
17945
17945
|
return /*#__PURE__*/React.createElement("a", {
|
|
17946
17946
|
href: `https://khanacademy.org/r/linter-rules#${this.props.ruleName}`,
|
|
17947
17947
|
target: "lint-help-window",
|
|
17948
17948
|
className: css(style)
|
|
17949
17949
|
}, /*#__PURE__*/React.createElement("span", {
|
|
17950
|
-
className: css(styles$
|
|
17950
|
+
className: css(styles$B.indicator, severityStyle)
|
|
17951
17951
|
}, this.props.severity === 1 && /*#__PURE__*/React.createElement(InlineIcon, exclamationIcon)), /*#__PURE__*/React.createElement("div", {
|
|
17952
|
-
className: css(styles$
|
|
17952
|
+
className: css(styles$B.tooltip, tooltipAbove && styles$B.tooltipAbove)
|
|
17953
17953
|
}, this.props.message.split("\n\n").map((m, i) => /*#__PURE__*/React.createElement("p", {
|
|
17954
17954
|
key: i,
|
|
17955
|
-
className: css(styles$
|
|
17955
|
+
className: css(styles$B.tooltipParagraph)
|
|
17956
17956
|
}, /*#__PURE__*/React.createElement("span", {
|
|
17957
17957
|
className: css(warningTextStyle)
|
|
17958
17958
|
}, warningText, ":", " "), m)), /*#__PURE__*/React.createElement("div", {
|
|
17959
|
-
className: css(styles$
|
|
17959
|
+
className: css(styles$B.tail, tooltipAbove && styles$B.tailAbove)
|
|
17960
17960
|
})));
|
|
17961
17961
|
};
|
|
17962
17962
|
}
|
|
@@ -17994,20 +17994,20 @@ class Lint extends React.Component {
|
|
|
17994
17994
|
}
|
|
17995
17995
|
if (blockHighlight) {
|
|
17996
17996
|
return /*#__PURE__*/React.createElement("span", {
|
|
17997
|
-
className: css(styles$
|
|
17998
|
-
}, this.renderLink(styles$
|
|
17997
|
+
className: css(styles$B.lintContainer, styles$B.lintContainerBlock)
|
|
17998
|
+
}, this.renderLink(styles$B.radioWidgetHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
17999
17999
|
}
|
|
18000
18000
|
if (inline) {
|
|
18001
18001
|
return /*#__PURE__*/React.createElement("span", {
|
|
18002
|
-
className: css(styles$
|
|
18003
|
-
}, this.renderLink(styles$
|
|
18002
|
+
className: css(styles$B.lintContainer)
|
|
18003
|
+
}, this.renderLink(styles$B.inlineHoverTarget), /*#__PURE__*/React.createElement("span", null, children));
|
|
18004
18004
|
}
|
|
18005
18005
|
return /*#__PURE__*/React.createElement("div", {
|
|
18006
|
-
className: css(styles$
|
|
18007
|
-
}, this.renderLink(styles$
|
|
18006
|
+
className: css(styles$B.lintContainer)
|
|
18007
|
+
}, this.renderLink(styles$B.hoverTarget), /*#__PURE__*/React.createElement("div", null, children));
|
|
18008
18008
|
}
|
|
18009
18009
|
}
|
|
18010
|
-
const styles$
|
|
18010
|
+
const styles$B = StyleSheet.create({
|
|
18011
18011
|
// This is the class of the outermost element.
|
|
18012
18012
|
// We use relative positioning so that the lint indicator can be
|
|
18013
18013
|
// positioned absolutely relative to the position of the linty container.
|
|
@@ -18814,8 +18814,6 @@ function getWidgetFromWidgetMap(widgetId, widgetMap) {
|
|
|
18814
18814
|
|
|
18815
18815
|
/**
|
|
18816
18816
|
* Get select widgets from a widget map.
|
|
18817
|
-
* Useful for multi-items that needs to split
|
|
18818
|
-
* one PerseusItem into several
|
|
18819
18817
|
*
|
|
18820
18818
|
* @param {ReadonlyArray<string>} widgetIds to extract
|
|
18821
18819
|
* @param {PerseusWidgetsMap} widgetMap to extract from
|
|
@@ -20200,7 +20198,7 @@ class Renderer extends React.Component {
|
|
|
20200
20198
|
paddingLeft: margin,
|
|
20201
20199
|
paddingRight: margin
|
|
20202
20200
|
};
|
|
20203
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
20201
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
|
|
20204
20202
|
return /*#__PURE__*/React.createElement("div", {
|
|
20205
20203
|
key: state.key,
|
|
20206
20204
|
className: "perseus-block-math",
|
|
@@ -20324,7 +20322,7 @@ class Renderer extends React.Component {
|
|
|
20324
20322
|
paddingLeft: 0,
|
|
20325
20323
|
paddingRight: 0
|
|
20326
20324
|
};
|
|
20327
|
-
const mobileInnerStyle = _extends({}, innerStyle, styles$
|
|
20325
|
+
const mobileInnerStyle = _extends({}, innerStyle, styles$A.mobileZoomableParentFix);
|
|
20328
20326
|
const wrappedOutput = /*#__PURE__*/React.createElement("div", {
|
|
20329
20327
|
style: _extends({}, mobileInnerStyle, {
|
|
20330
20328
|
overflowX: "auto"
|
|
@@ -20965,7 +20963,7 @@ Renderer.defaultProps = {
|
|
|
20965
20963
|
onSerializedStateUpdated: () => {},
|
|
20966
20964
|
linterContext: PerseusLinter.linterContextDefault
|
|
20967
20965
|
};
|
|
20968
|
-
const styles$
|
|
20966
|
+
const styles$A = {
|
|
20969
20967
|
mobileZoomableParentFix: {
|
|
20970
20968
|
// NOTE(abdul): There is an issue where transform animations will
|
|
20971
20969
|
// cause the Zoomable component to disappear when running on the
|
|
@@ -21073,7 +21071,7 @@ function _objectWithoutPropertiesLoose(r, e) {
|
|
|
21073
21071
|
return t;
|
|
21074
21072
|
}
|
|
21075
21073
|
|
|
21076
|
-
const _excluded$
|
|
21074
|
+
const _excluded$7 = ["position", "visibility", "left", "top"];
|
|
21077
21075
|
const zIndex = 10;
|
|
21078
21076
|
let HorizontalDirection = /*#__PURE__*/function (HorizontalDirection) {
|
|
21079
21077
|
HorizontalDirection["Left"] = "left";
|
|
@@ -21124,7 +21122,7 @@ const TooltipArrow = _ref => {
|
|
|
21124
21122
|
left = 100,
|
|
21125
21123
|
top = 0
|
|
21126
21124
|
} = _ref,
|
|
21127
|
-
props = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
21125
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded$7);
|
|
21128
21126
|
// TODO(aria): Think about adding a box-shadow to the triangle here
|
|
21129
21127
|
// See http://css-tricks.com/triangle-with-shadow/
|
|
21130
21128
|
|
|
@@ -21498,7 +21496,7 @@ InputWithExamples.defaultProps = {
|
|
|
21498
21496
|
className: ""
|
|
21499
21497
|
};
|
|
21500
21498
|
|
|
21501
|
-
const _excluded$
|
|
21499
|
+
const _excluded$6 = ["keypadElement", "onFocus", "value"];
|
|
21502
21500
|
class SimpleKeypadInput extends React.Component {
|
|
21503
21501
|
constructor(...args) {
|
|
21504
21502
|
super(...args);
|
|
@@ -21543,7 +21541,7 @@ class SimpleKeypadInput extends React.Component {
|
|
|
21543
21541
|
onFocus,
|
|
21544
21542
|
value
|
|
21545
21543
|
} = _this$props,
|
|
21546
|
-
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$
|
|
21544
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$6);
|
|
21547
21545
|
return (
|
|
21548
21546
|
/*#__PURE__*/
|
|
21549
21547
|
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
@@ -21948,10 +21946,10 @@ class InputNumber extends React.Component {
|
|
|
21948
21946
|
// Note: This is _very_ similar to what `numeric-input.jsx` does. If
|
|
21949
21947
|
// you modify this, double-check if you also need to modify that
|
|
21950
21948
|
// component.
|
|
21951
|
-
const inputStyles = [styles$
|
|
21949
|
+
const inputStyles = [styles$z.default, this.props.size === "small" ? styles$z.small : null, this.props.rightAlign ? styles$z.rightAlign : styles$z.leftAlign];
|
|
21952
21950
|
// Unanswered
|
|
21953
21951
|
if (this.props.reviewMode && !this.props.currentValue) {
|
|
21954
|
-
inputStyles.push(styles$
|
|
21952
|
+
inputStyles.push(styles$z.answerStateUnanswered);
|
|
21955
21953
|
}
|
|
21956
21954
|
return /*#__PURE__*/React.createElement(InputWithExamples
|
|
21957
21955
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -21981,7 +21979,7 @@ InputNumber.defaultProps = {
|
|
|
21981
21979
|
apiOptions: ApiOptions.defaults,
|
|
21982
21980
|
linterContext: linterContextDefault
|
|
21983
21981
|
};
|
|
21984
|
-
const styles$
|
|
21982
|
+
const styles$z = StyleSheet.create({
|
|
21985
21983
|
default: {
|
|
21986
21984
|
width: 80,
|
|
21987
21985
|
height: "auto"
|
|
@@ -23152,7 +23150,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
23152
23150
|
const rects = this.state.cachedHighlightRects;
|
|
23153
23151
|
return /*#__PURE__*/React.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React.createElement("div", {
|
|
23154
23152
|
key: index,
|
|
23155
|
-
className: css(styles$
|
|
23153
|
+
className: css(styles$y.highlightRect),
|
|
23156
23154
|
style: {
|
|
23157
23155
|
// NOTE(mdr): We apply `position: absolute` here
|
|
23158
23156
|
// rather than in Aphrodite styles, because
|
|
@@ -23171,7 +23169,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
23171
23169
|
})));
|
|
23172
23170
|
}
|
|
23173
23171
|
}
|
|
23174
|
-
const styles$
|
|
23172
|
+
const styles$y = StyleSheet.create({
|
|
23175
23173
|
highlightRect: {
|
|
23176
23174
|
background: "#fffabe" // highlighter yellow :)
|
|
23177
23175
|
}
|
|
@@ -23252,7 +23250,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
23252
23250
|
// TooltipContent wouldn't let me overwrite
|
|
23253
23251
|
// user-select and onClick
|
|
23254
23252
|
const content = /*#__PURE__*/React.createElement("div", {
|
|
23255
|
-
className: css(styles$
|
|
23253
|
+
className: css(styles$x.tooltipLabel),
|
|
23256
23254
|
onClick: this.props.onClick
|
|
23257
23255
|
}, this.props.label);
|
|
23258
23256
|
const style = {
|
|
@@ -23272,7 +23270,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
23272
23270
|
}, /*#__PURE__*/React.createElement("div", null)));
|
|
23273
23271
|
}
|
|
23274
23272
|
}
|
|
23275
|
-
const styles$
|
|
23273
|
+
const styles$x = StyleSheet.create({
|
|
23276
23274
|
tooltipLabel: {
|
|
23277
23275
|
// Unlike most tooltip contents, we don't want this label to be
|
|
23278
23276
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -23823,7 +23821,7 @@ class HighlightableContent extends React.PureComponent {
|
|
|
23823
23821
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
23824
23822
|
const buildHighlight = r => this._buildHighlight(r);
|
|
23825
23823
|
return /*#__PURE__*/React.createElement("div", {
|
|
23826
|
-
className: css(styles$
|
|
23824
|
+
className: css(styles$w.container),
|
|
23827
23825
|
ref: container => this._container = container
|
|
23828
23826
|
}, /*#__PURE__*/React.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React.createElement(HighlightingUI, {
|
|
23829
23827
|
buildHighlight: buildHighlight,
|
|
@@ -23844,14 +23842,14 @@ class HighlightableContent extends React.PureComponent {
|
|
|
23844
23842
|
onAddHighlight: this._handleAddHighlight,
|
|
23845
23843
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
23846
23844
|
})), /*#__PURE__*/React.createElement("div", {
|
|
23847
|
-
className: css(styles$
|
|
23845
|
+
className: css(styles$w.content),
|
|
23848
23846
|
ref: content => this._content = content
|
|
23849
23847
|
}, /*#__PURE__*/React.createElement(WordIndexer, {
|
|
23850
23848
|
onWordsUpdate: this._handleWordsUpdate
|
|
23851
23849
|
}, this.props.children)));
|
|
23852
23850
|
}
|
|
23853
23851
|
}
|
|
23854
|
-
const styles$
|
|
23852
|
+
const styles$w = StyleSheet.create({
|
|
23855
23853
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
23856
23854
|
// content will receive the browser's native pointer events. (Highlights
|
|
23857
23855
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -24277,7 +24275,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
24277
24275
|
}
|
|
24278
24276
|
render() {
|
|
24279
24277
|
return /*#__PURE__*/React.createElement("div", {
|
|
24280
|
-
className: css(styles$
|
|
24278
|
+
className: css(styles$v.measurer),
|
|
24281
24279
|
"aria-hidden": "true"
|
|
24282
24280
|
}, /*#__PURE__*/React.createElement("div", {
|
|
24283
24281
|
ref: ref => this._line = ref,
|
|
@@ -24285,7 +24283,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
24285
24283
|
}, "Line Height Measurement"));
|
|
24286
24284
|
}
|
|
24287
24285
|
}
|
|
24288
|
-
const styles$
|
|
24286
|
+
const styles$v = StyleSheet.create({
|
|
24289
24287
|
measurer: {
|
|
24290
24288
|
position: "absolute",
|
|
24291
24289
|
top: 0,
|
|
@@ -25262,11 +25260,11 @@ const FocusRing = function FocusRing({
|
|
|
25262
25260
|
};
|
|
25263
25261
|
return /*#__PURE__*/React.createElement("span", {
|
|
25264
25262
|
"data-testid": "focus-ring",
|
|
25265
|
-
className: css(styles$
|
|
25263
|
+
className: css(styles$u.ring),
|
|
25266
25264
|
style: style
|
|
25267
25265
|
}, children);
|
|
25268
25266
|
};
|
|
25269
|
-
const styles$
|
|
25267
|
+
const styles$u = StyleSheet.create({
|
|
25270
25268
|
ring: {
|
|
25271
25269
|
margin: "auto",
|
|
25272
25270
|
display: "inline-block",
|
|
@@ -25293,7 +25291,7 @@ function getChoiceLetter(pos, strings) {
|
|
|
25293
25291
|
}
|
|
25294
25292
|
|
|
25295
25293
|
const CHOICE_ICON_SIZE = 24;
|
|
25296
|
-
const styles$
|
|
25294
|
+
const styles$t = StyleSheet.create({
|
|
25297
25295
|
iconWrapper: {
|
|
25298
25296
|
display: "inline-block",
|
|
25299
25297
|
position: "relative"
|
|
@@ -25316,7 +25314,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
25316
25314
|
width: CROSS_OUT_LINE_SIZE,
|
|
25317
25315
|
height: CROSS_OUT_LINE_SIZE,
|
|
25318
25316
|
viewBox: `0 0 ${CROSS_OUT_LINE_SIZE} ${CROSS_OUT_LINE_SIZE}`,
|
|
25319
|
-
className: css(styles$
|
|
25317
|
+
className: css(styles$s.crossOutLine),
|
|
25320
25318
|
"data-testid": "choice-icon__cross-out-line"
|
|
25321
25319
|
}, /*#__PURE__*/React.createElement("line", {
|
|
25322
25320
|
// The line stretches from the bottom-left to top-right.
|
|
@@ -25331,7 +25329,7 @@ const CrossOutLine = function CrossOutLine(props) {
|
|
|
25331
25329
|
strokeLinecap: "round"
|
|
25332
25330
|
}));
|
|
25333
25331
|
};
|
|
25334
|
-
const styles$
|
|
25332
|
+
const styles$s = StyleSheet.create({
|
|
25335
25333
|
crossOutLine: {
|
|
25336
25334
|
// Center the icon within the container.
|
|
25337
25335
|
position: "absolute",
|
|
@@ -25415,7 +25413,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
25415
25413
|
} = props;
|
|
25416
25414
|
const dynamicStyles = getDynamicStyles(checked, showCorrectness, pressed, multipleSelect, correct);
|
|
25417
25415
|
return /*#__PURE__*/React.createElement("div", {
|
|
25418
|
-
className: css(styles$
|
|
25416
|
+
className: css(styles$t.iconWrapper)
|
|
25419
25417
|
}, /*#__PURE__*/React.createElement(FocusRing, {
|
|
25420
25418
|
color: color.blue,
|
|
25421
25419
|
visible: focused || hovered,
|
|
@@ -25423,13 +25421,13 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
25423
25421
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25424
25422
|
style: dynamicStyles,
|
|
25425
25423
|
"data-testid": "choice-icon__library-choice-icon",
|
|
25426
|
-
className: css(styles$
|
|
25424
|
+
className: css(styles$r.circle, showCorrectness && correct && styles$r.circleCorrect, showCorrectness && !correct && styles$r.circleIncorrect, showCorrectness && !correct && (checked || previouslyAnswered) && styles$r.circleIncorrectAnswered)
|
|
25427
25425
|
// used in BaseRadio editMode to check
|
|
25428
25426
|
// if we actually clicked on the radio icon
|
|
25429
25427
|
,
|
|
25430
25428
|
"data-is-radio-icon": true
|
|
25431
25429
|
}, /*#__PURE__*/React.createElement("div", {
|
|
25432
|
-
className: css(styles$
|
|
25430
|
+
className: css(styles$r.innerWrapper)
|
|
25433
25431
|
}, /*#__PURE__*/React.createElement(ChoiceInner, {
|
|
25434
25432
|
pos: pos,
|
|
25435
25433
|
showCorrectness: showCorrectness,
|
|
@@ -25438,7 +25436,7 @@ const ChoiceIcon = function ChoiceIcon(props) {
|
|
|
25438
25436
|
color: dynamicStyles.borderColor
|
|
25439
25437
|
}));
|
|
25440
25438
|
};
|
|
25441
|
-
const styles$
|
|
25439
|
+
const styles$r = StyleSheet.create({
|
|
25442
25440
|
innerWrapper: {
|
|
25443
25441
|
width: CHOICE_ICON_SIZE,
|
|
25444
25442
|
height: CHOICE_ICON_SIZE,
|
|
@@ -25533,19 +25531,19 @@ const OptionStatus = function OptionStatus(props) {
|
|
|
25533
25531
|
}
|
|
25534
25532
|
let textStyle;
|
|
25535
25533
|
if (correct) {
|
|
25536
|
-
textStyle = styles$
|
|
25534
|
+
textStyle = styles$q.correct;
|
|
25537
25535
|
} else {
|
|
25538
25536
|
if (checked || previouslyAnswered) {
|
|
25539
|
-
textStyle = styles$
|
|
25537
|
+
textStyle = styles$q.incorrectAnswered;
|
|
25540
25538
|
} else {
|
|
25541
|
-
textStyle = styles$
|
|
25539
|
+
textStyle = styles$q.incorrect;
|
|
25542
25540
|
}
|
|
25543
25541
|
}
|
|
25544
25542
|
return /*#__PURE__*/React.createElement("div", {
|
|
25545
|
-
className: css(styles$
|
|
25543
|
+
className: css(styles$q.text, textStyle)
|
|
25546
25544
|
}, renderText(checked, correct, crossedOut, strings));
|
|
25547
25545
|
};
|
|
25548
|
-
const styles$
|
|
25546
|
+
const styles$q = StyleSheet.create({
|
|
25549
25547
|
text: {
|
|
25550
25548
|
alignItems: "center",
|
|
25551
25549
|
display: "flex",
|
|
@@ -25615,8 +25613,8 @@ const Choice = function Choice(props) {
|
|
|
25615
25613
|
crossedOut: updatedCrossedOut
|
|
25616
25614
|
});
|
|
25617
25615
|
}
|
|
25618
|
-
const descriptionClassName = classNames$1("description", css(styles$
|
|
25619
|
-
const rationaleClassName = classNames$1("perseus-radio-rationale-content", css(styles$
|
|
25616
|
+
const descriptionClassName = classNames$1("description", css(styles$p.description));
|
|
25617
|
+
const rationaleClassName = classNames$1("perseus-radio-rationale-content", css(styles$p.rationale));
|
|
25620
25618
|
|
|
25621
25619
|
// We want to show the choices as dimmed out when the choices are disabled.
|
|
25622
25620
|
// However, we don't want to do this when we're in review mode in the
|
|
@@ -25776,7 +25774,7 @@ const Choice = function Choice(props) {
|
|
|
25776
25774
|
"data-testid": `perseus-radio-rationale-content-${pos}`
|
|
25777
25775
|
}, rationale));
|
|
25778
25776
|
};
|
|
25779
|
-
const styles$
|
|
25777
|
+
const styles$p = StyleSheet.create({
|
|
25780
25778
|
description: {
|
|
25781
25779
|
display: "inline-block",
|
|
25782
25780
|
width: "100%"
|
|
@@ -25797,14 +25795,14 @@ var Choice$1 = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.
|
|
|
25797
25795
|
forwardedRef: ref
|
|
25798
25796
|
})));
|
|
25799
25797
|
|
|
25800
|
-
const _excluded$
|
|
25798
|
+
const _excluded$5 = ["content", "forwardedRef", "showContent"];
|
|
25801
25799
|
const ChoiceNoneAbove = function ChoiceNoneAbove(_ref) {
|
|
25802
25800
|
let {
|
|
25803
25801
|
content,
|
|
25804
25802
|
forwardedRef,
|
|
25805
25803
|
showContent = true
|
|
25806
25804
|
} = _ref,
|
|
25807
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
25805
|
+
rest = _objectWithoutPropertiesLoose(_ref, _excluded$5);
|
|
25808
25806
|
const {
|
|
25809
25807
|
strings
|
|
25810
25808
|
} = usePerseusI18n();
|
|
@@ -25966,10 +25964,10 @@ const BaseRadio = function BaseRadio({
|
|
|
25966
25964
|
const isMobile = apiOptions.isMobile;
|
|
25967
25965
|
const firstChoiceHighlighted = choices[0].highlighted;
|
|
25968
25966
|
const lastChoiceHighlighted = choices[choices.length - 1].highlighted;
|
|
25969
|
-
const className = classNames$1("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$
|
|
25970
|
-
const instructionsClassName = classNames$1("instructions", css(styles$
|
|
25967
|
+
const className = classNames$1("perseus-widget-radio", !editMode && "perseus-rendered-radio", css(styles$o.radio, styles$o.responsiveRadioContainer, firstChoiceHighlighted && isMobile && styles$o.radioContainerFirstHighlighted, lastChoiceHighlighted && isMobile && styles$o.radioContainerLastHighlighted));
|
|
25968
|
+
const instructionsClassName = classNames$1("instructions", css(styles$o.instructions, isMobile && styles$o.instructionsMobile));
|
|
25971
25969
|
const instructions = getInstructionsText(multipleSelect, countChoices, numCorrect, strings);
|
|
25972
|
-
const responsiveClassName = css(styles$
|
|
25970
|
+
const responsiveClassName = css(styles$o.responsiveFieldset);
|
|
25973
25971
|
const fieldset = /*#__PURE__*/React.createElement("fieldset", {
|
|
25974
25972
|
className: `perseus-widget-radio-fieldset ${responsiveClassName}`
|
|
25975
25973
|
}, /*#__PURE__*/React.createElement("legend", {
|
|
@@ -26020,7 +26018,7 @@ const BaseRadio = function BaseRadio({
|
|
|
26020
26018
|
const aphroditeClassName = checked => {
|
|
26021
26019
|
// Whether or not to show correctness borders
|
|
26022
26020
|
// for this choice and the next choice.
|
|
26023
|
-
return css(sharedStyles.aboveScratchpad, styles$
|
|
26021
|
+
return 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);
|
|
26024
26022
|
};
|
|
26025
26023
|
|
|
26026
26024
|
// HACK(abdulrahman): Preloads the selection-state
|
|
@@ -26085,10 +26083,10 @@ const BaseRadio = function BaseRadio({
|
|
|
26085
26083
|
// Allow for horizontal scrolling if content is too wide, which may be
|
|
26086
26084
|
// an issue especially on phones.
|
|
26087
26085
|
return /*#__PURE__*/React.createElement("div", {
|
|
26088
|
-
className: css(styles$
|
|
26086
|
+
className: css(styles$o.responsiveContainer)
|
|
26089
26087
|
}, fieldset);
|
|
26090
26088
|
};
|
|
26091
|
-
const styles$
|
|
26089
|
+
const styles$o = StyleSheet.create({
|
|
26092
26090
|
instructions: {
|
|
26093
26091
|
display: "block",
|
|
26094
26092
|
color: gray17,
|
|
@@ -26580,7 +26578,7 @@ Radio$1.defaultProps = {
|
|
|
26580
26578
|
showSolutions: "none"
|
|
26581
26579
|
};
|
|
26582
26580
|
|
|
26583
|
-
const _excluded$
|
|
26581
|
+
const _excluded$4 = ["noneOfTheAbove"];
|
|
26584
26582
|
const {
|
|
26585
26583
|
shuffle: shuffle$2,
|
|
26586
26584
|
random
|
|
@@ -26672,7 +26670,7 @@ const propUpgrades$1 = {
|
|
|
26672
26670
|
const {
|
|
26673
26671
|
noneOfTheAbove
|
|
26674
26672
|
} = v0props,
|
|
26675
|
-
rest = _objectWithoutPropertiesLoose(v0props, _excluded$
|
|
26673
|
+
rest = _objectWithoutPropertiesLoose(v0props, _excluded$4);
|
|
26676
26674
|
if (noneOfTheAbove) {
|
|
26677
26675
|
throw new Error("radio widget v0 no longer supports auto noneOfTheAbove");
|
|
26678
26676
|
}
|
|
@@ -26795,9 +26793,9 @@ class Categorizer extends React.Component {
|
|
|
26795
26793
|
indexedItems = Util.shuffle(indexedItems, this.props.problemNum);
|
|
26796
26794
|
}
|
|
26797
26795
|
const table = /*#__PURE__*/React.createElement("table", {
|
|
26798
|
-
className: "categorizer-table " + css(styles$
|
|
26796
|
+
className: "categorizer-table " + css(styles$n.mobileTable)
|
|
26799
26797
|
}, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
|
|
26800
|
-
className: css(styles$
|
|
26798
|
+
className: css(styles$n.emptyHeaderCell)
|
|
26801
26799
|
}), this.props.categories.map((category, i) => {
|
|
26802
26800
|
// Array index is the correct key here, as that's
|
|
26803
26801
|
// how category grading actually works -- no way
|
|
@@ -26805,7 +26803,7 @@ class Categorizer extends React.Component {
|
|
|
26805
26803
|
// middle. (If we later add that, this should be
|
|
26806
26804
|
// fixed.)
|
|
26807
26805
|
return /*#__PURE__*/React.createElement("th", {
|
|
26808
|
-
className: css(styles$
|
|
26806
|
+
className: css(styles$n.header),
|
|
26809
26807
|
key: i
|
|
26810
26808
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
26811
26809
|
content: category,
|
|
@@ -26827,7 +26825,7 @@ class Categorizer extends React.Component {
|
|
|
26827
26825
|
})), self.props.categories.map((catName, catNum) => {
|
|
26828
26826
|
const selected = self.props.values[itemNum] === catNum;
|
|
26829
26827
|
return /*#__PURE__*/React.createElement("td", {
|
|
26830
|
-
className: "category " + css(styles$
|
|
26828
|
+
className: "category " + css(styles$n.cell),
|
|
26831
26829
|
key: catNum
|
|
26832
26830
|
}, /*#__PURE__*/React.createElement("div", {
|
|
26833
26831
|
className: ClassNames.INTERACTIVE,
|
|
@@ -26842,7 +26840,7 @@ class Categorizer extends React.Component {
|
|
|
26842
26840
|
onChange: () => this.onChange(itemNum, catNum),
|
|
26843
26841
|
onClick: e => e.stopPropagation()
|
|
26844
26842
|
}), !isMobile && /*#__PURE__*/React.createElement("span", {
|
|
26845
|
-
className: css(styles$
|
|
26843
|
+
className: css(styles$n.radioSpan, selected && styles$n.checkedRadioSpan, this.props.static && selected && styles$n.staticCheckedRadioSpan)
|
|
26846
26844
|
}, selected ? /*#__PURE__*/React.createElement(InlineIcon, iconCircle) : /*#__PURE__*/React.createElement(InlineIcon, iconCircleThin))));
|
|
26847
26845
|
}));
|
|
26848
26846
|
/* eslint-enable max-len */
|
|
@@ -26854,7 +26852,7 @@ class Categorizer extends React.Component {
|
|
|
26854
26852
|
"categorizer-container": true,
|
|
26855
26853
|
"static-mode": this.props.static
|
|
26856
26854
|
});
|
|
26857
|
-
const inlineStyles = this.props.apiOptions.isMobile ? [styles$
|
|
26855
|
+
const inlineStyles = this.props.apiOptions.isMobile ? [styles$n.fullBleedContainer] : [];
|
|
26858
26856
|
return /*#__PURE__*/React.createElement("div", {
|
|
26859
26857
|
className: extraClassNames + " " + css(...inlineStyles)
|
|
26860
26858
|
}, table);
|
|
@@ -26873,7 +26871,7 @@ const pageMargin = 16;
|
|
|
26873
26871
|
|
|
26874
26872
|
// Stylesheets aren't directly testable
|
|
26875
26873
|
/* c8 ignore next */
|
|
26876
|
-
const styles$
|
|
26874
|
+
const styles$n = StyleSheet.create({
|
|
26877
26875
|
mobileTable: {
|
|
26878
26876
|
[mediaQueries.smOrSmaller]: {
|
|
26879
26877
|
minWidth: "auto"
|
|
@@ -27131,7 +27129,7 @@ class CSProgram extends React.Component {
|
|
|
27131
27129
|
// creator "went wild".
|
|
27132
27130
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
27133
27131
|
return /*#__PURE__*/React.createElement("div", {
|
|
27134
|
-
className: css(styles$
|
|
27132
|
+
className: css(styles$m.widthOverride, styleContainer && styles$m.container)
|
|
27135
27133
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
27136
27134
|
sandbox: sandboxOptions,
|
|
27137
27135
|
src: url,
|
|
@@ -27148,7 +27146,7 @@ CSProgram.defaultProps = {
|
|
|
27148
27146
|
// optional message
|
|
27149
27147
|
message: null
|
|
27150
27148
|
};
|
|
27151
|
-
const styles$
|
|
27149
|
+
const styles$m = StyleSheet.create({
|
|
27152
27150
|
// Override the inherited width from the perseus paragraph class
|
|
27153
27151
|
// 820 is minimum width for 420px editor and 400px canvas
|
|
27154
27152
|
widthOverride: {
|
|
@@ -27194,7 +27192,7 @@ class Definition extends React.Component {
|
|
|
27194
27192
|
}) => /*#__PURE__*/React.createElement(Popover, {
|
|
27195
27193
|
content: /*#__PURE__*/React.createElement(PopoverContentCore, {
|
|
27196
27194
|
color: "white",
|
|
27197
|
-
style: styles$
|
|
27195
|
+
style: styles$l.tooltipBody,
|
|
27198
27196
|
closeButtonVisible: true
|
|
27199
27197
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
27200
27198
|
apiOptions: this.props.apiOptions,
|
|
@@ -27227,7 +27225,7 @@ Definition.defaultProps = {
|
|
|
27227
27225
|
togglePrompt: "define me",
|
|
27228
27226
|
definition: "definition goes here"
|
|
27229
27227
|
};
|
|
27230
|
-
const styles$
|
|
27228
|
+
const styles$l = {
|
|
27231
27229
|
tooltipBody: {
|
|
27232
27230
|
color: color.offBlack,
|
|
27233
27231
|
fontSize: 20,
|
|
@@ -27490,7 +27488,7 @@ class Explanation extends React.Component {
|
|
|
27490
27488
|
marginRight: "-6px",
|
|
27491
27489
|
"white-space": "normal"
|
|
27492
27490
|
};
|
|
27493
|
-
const contentStyling = [styles$
|
|
27491
|
+
const contentStyling = [styles$k.content, this.state.expanded ? styles$k.contentExpanded : styles$k.contentCollapsed, allowTransition && (this.state.expanded ? styles$k.transitionExpanded : styles$k.transitionCollapsed)];
|
|
27494
27492
|
return /*#__PURE__*/React.createElement(UniqueIDProvider, {
|
|
27495
27493
|
mockOnFirstRender: true,
|
|
27496
27494
|
scope: "explanation-widget"
|
|
@@ -27509,7 +27507,7 @@ class Explanation extends React.Component {
|
|
|
27509
27507
|
"aria-hidden": !this.state.expanded,
|
|
27510
27508
|
testId: "content-container"
|
|
27511
27509
|
}, /*#__PURE__*/React.createElement(View, {
|
|
27512
|
-
style: styles$
|
|
27510
|
+
style: styles$k.contentWrapper
|
|
27513
27511
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
27514
27512
|
apiOptions: this.props.apiOptions,
|
|
27515
27513
|
content: this.props.explanation,
|
|
@@ -27530,7 +27528,7 @@ Explanation.defaultProps = {
|
|
|
27530
27528
|
const leftBorderSpacing = 23;
|
|
27531
27529
|
const verticalContentPadding = 10;
|
|
27532
27530
|
const arrowHeight = 14;
|
|
27533
|
-
const styles$
|
|
27531
|
+
const styles$k = StyleSheet.create({
|
|
27534
27532
|
content: {
|
|
27535
27533
|
borderLeft: "0px solid #ccc",
|
|
27536
27534
|
display: "inline-grid",
|
|
@@ -27613,15 +27611,15 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
27613
27611
|
correctExcited,
|
|
27614
27612
|
nextQuestion
|
|
27615
27613
|
} = this.context.strings;
|
|
27616
|
-
const answerBarStyle = _extends({}, styles$
|
|
27614
|
+
const answerBarStyle = _extends({}, styles$j.answerBar, {
|
|
27617
27615
|
backgroundColor: answerBarState === "CORRECT" ? color.offWhite : "white",
|
|
27618
27616
|
// Center the "Correct!" message only when there's no next question
|
|
27619
27617
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
27620
27618
|
});
|
|
27621
27619
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
|
|
27622
|
-
style: styles$
|
|
27620
|
+
style: styles$j.text
|
|
27623
27621
|
}, /*#__PURE__*/React.createElement("span", {
|
|
27624
|
-
style: styles$
|
|
27622
|
+
style: styles$j.tryAgainIcon
|
|
27625
27623
|
}, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
|
|
27626
27624
|
style: {
|
|
27627
27625
|
marginLeft: 8
|
|
@@ -27640,7 +27638,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
27640
27638
|
return /*#__PURE__*/React.createElement("div", {
|
|
27641
27639
|
style: answerBarStyle
|
|
27642
27640
|
}, /*#__PURE__*/React.createElement("span", {
|
|
27643
|
-
style: styles$
|
|
27641
|
+
style: styles$j.text
|
|
27644
27642
|
}, /*#__PURE__*/React.createElement("span", {
|
|
27645
27643
|
style: {
|
|
27646
27644
|
fontSize: 28,
|
|
@@ -27663,7 +27661,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
27663
27661
|
}
|
|
27664
27662
|
GradedGroupAnswerBar.contextType = PerseusI18nContext;
|
|
27665
27663
|
const fontSize = 17;
|
|
27666
|
-
const styles$
|
|
27664
|
+
const styles$j = {
|
|
27667
27665
|
answerBar: {
|
|
27668
27666
|
display: "flex",
|
|
27669
27667
|
alignItems: "center",
|
|
@@ -27848,7 +27846,7 @@ class GradedGroup extends React.Component {
|
|
|
27848
27846
|
}));
|
|
27849
27847
|
gradeStatus = this.context.strings.incorrect;
|
|
27850
27848
|
}
|
|
27851
|
-
const mobileClass = this.props.inGradedGroupSet ? css(styles$
|
|
27849
|
+
const mobileClass = this.props.inGradedGroupSet ? css(styles$i.gradedGroupInSet) : css(styles$i.gradedGroup);
|
|
27852
27850
|
const classes = classNames$1({
|
|
27853
27851
|
[mobileClass]: apiOptions.isMobile,
|
|
27854
27852
|
"perseus-graded-group": true,
|
|
@@ -27867,7 +27865,7 @@ class GradedGroup extends React.Component {
|
|
|
27867
27865
|
return /*#__PURE__*/React.createElement("div", {
|
|
27868
27866
|
className: classes
|
|
27869
27867
|
}, !!this.props.title && /*#__PURE__*/React.createElement("div", {
|
|
27870
|
-
className: css(styles$
|
|
27868
|
+
className: css(styles$i.title)
|
|
27871
27869
|
}, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
|
|
27872
27870
|
ref: this.rendererRef,
|
|
27873
27871
|
apiOptions: _extends({}, apiOptions, {
|
|
@@ -27899,7 +27897,7 @@ class GradedGroup extends React.Component {
|
|
|
27899
27897
|
}, this.context.strings.nextQuestion), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
|
27900
27898
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
27901
27899
|
tabIndex: "0",
|
|
27902
|
-
className: css(styles$
|
|
27900
|
+
className: css(styles$i.explanationTitle),
|
|
27903
27901
|
onClick: () => this.setState({
|
|
27904
27902
|
showHint: false
|
|
27905
27903
|
}),
|
|
@@ -27931,7 +27929,7 @@ class GradedGroup extends React.Component {
|
|
|
27931
27929
|
showHint: true
|
|
27932
27930
|
});
|
|
27933
27931
|
},
|
|
27934
|
-
className: css(styles$
|
|
27932
|
+
className: css(styles$i.showHintLink)
|
|
27935
27933
|
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
|
|
27936
27934
|
apiOptions: apiOptions,
|
|
27937
27935
|
answerBarState: answerBarState,
|
|
@@ -27953,7 +27951,7 @@ GradedGroup.defaultProps = {
|
|
|
27953
27951
|
const traverseChildWidgets$2 = function traverseChildWidgets(props, traverseRenderer) {
|
|
27954
27952
|
return _.extend({}, props, traverseRenderer(props));
|
|
27955
27953
|
};
|
|
27956
|
-
const styles$
|
|
27954
|
+
const styles$i = StyleSheet.create({
|
|
27957
27955
|
gradedGroupInSet: {
|
|
27958
27956
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
27959
27957
|
marginLeft: 0,
|
|
@@ -28036,18 +28034,18 @@ class Indicators extends React.Component {
|
|
|
28036
28034
|
return /*#__PURE__*/React.createElement("ul", {
|
|
28037
28035
|
// reduntantly add class name for use in .less files--
|
|
28038
28036
|
// the styles object key gets hashed
|
|
28039
|
-
className: classNames$1(css(styles$
|
|
28037
|
+
className: classNames$1(css(styles$h.indicatorContainer), "indicatorContainer")
|
|
28040
28038
|
}, this.props.gradedGroups.map(({
|
|
28041
28039
|
title
|
|
28042
28040
|
}, i) => /*#__PURE__*/React.createElement("li", {
|
|
28043
|
-
className: css(styles$
|
|
28041
|
+
className: css(styles$h.indicator),
|
|
28044
28042
|
key: title
|
|
28045
28043
|
}, /*#__PURE__*/React.createElement(Clickable, {
|
|
28046
28044
|
role: "button",
|
|
28047
28045
|
"aria-label": this.context.strings.skipToTitle({
|
|
28048
28046
|
title
|
|
28049
28047
|
}),
|
|
28050
|
-
style: styles$
|
|
28048
|
+
style: styles$h.indicatorButton,
|
|
28051
28049
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
28052
28050
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
28053
28051
|
}, ({
|
|
@@ -28055,9 +28053,9 @@ class Indicators extends React.Component {
|
|
|
28055
28053
|
focused,
|
|
28056
28054
|
pressed
|
|
28057
28055
|
}) => /*#__PURE__*/React.createElement(View, {
|
|
28058
|
-
style: [styles$
|
|
28056
|
+
style: [styles$h.indicatorDot, (hovered || focused || pressed) && styles$h.indicatorDotFocused]
|
|
28059
28057
|
}, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
|
|
28060
|
-
style: styles$
|
|
28058
|
+
style: styles$h.indicatorDotActive
|
|
28061
28059
|
}, /*#__PURE__*/React.createElement("span", {
|
|
28062
28060
|
className: css(a11y.srOnly)
|
|
28063
28061
|
}, this.context.strings.current)))))));
|
|
@@ -28125,7 +28123,7 @@ class GradedGroupSet extends React.Component {
|
|
|
28125
28123
|
} = getDependencies();
|
|
28126
28124
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
28127
28125
|
return /*#__PURE__*/React.createElement("div", {
|
|
28128
|
-
className: css(styles$
|
|
28126
|
+
className: css(styles$h.container)
|
|
28129
28127
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
28130
28128
|
return (
|
|
28131
28129
|
/*#__PURE__*/
|
|
@@ -28148,13 +28146,13 @@ class GradedGroupSet extends React.Component {
|
|
|
28148
28146
|
const numGroups = this.props.gradedGroups.length;
|
|
28149
28147
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
28150
28148
|
return /*#__PURE__*/React.createElement("div", {
|
|
28151
|
-
className: css(styles$
|
|
28149
|
+
className: css(styles$h.container)
|
|
28152
28150
|
}, /*#__PURE__*/React.createElement("div", {
|
|
28153
|
-
className: css(styles$
|
|
28151
|
+
className: css(styles$h.top)
|
|
28154
28152
|
}, /*#__PURE__*/React.createElement("div", {
|
|
28155
|
-
className: css(styles$
|
|
28153
|
+
className: css(styles$h.title)
|
|
28156
28154
|
}, currentGroup.title), /*#__PURE__*/React.createElement("div", {
|
|
28157
|
-
className: css(styles$
|
|
28155
|
+
className: css(styles$h.spacer)
|
|
28158
28156
|
}), /*#__PURE__*/React.createElement(Indicators, {
|
|
28159
28157
|
currentGroup: this.state.currentGroup,
|
|
28160
28158
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -28196,7 +28194,7 @@ var GradedGroupSet$1 = {
|
|
|
28196
28194
|
tracking: "all",
|
|
28197
28195
|
isLintable: true
|
|
28198
28196
|
};
|
|
28199
|
-
const styles$
|
|
28197
|
+
const styles$h = StyleSheet.create({
|
|
28200
28198
|
top: {
|
|
28201
28199
|
display: "flex",
|
|
28202
28200
|
flexDirection: "row"
|
|
@@ -28301,7 +28299,7 @@ class ButtonGroup extends React.Component {
|
|
|
28301
28299
|
id: "" + i,
|
|
28302
28300
|
ref: "button" + i,
|
|
28303
28301
|
key: "" + i,
|
|
28304
|
-
className: css(styles$
|
|
28302
|
+
className: css(styles$g.buttonStyle, button.value === value && styles$g.selectedStyle),
|
|
28305
28303
|
onClick: () => this.toggleSelect(button.value)
|
|
28306
28304
|
}, button.content || "" + button.value);
|
|
28307
28305
|
});
|
|
@@ -28318,7 +28316,7 @@ ButtonGroup.defaultProps = {
|
|
|
28318
28316
|
value: null,
|
|
28319
28317
|
allowEmpty: true
|
|
28320
28318
|
};
|
|
28321
|
-
const styles$
|
|
28319
|
+
const styles$g = StyleSheet.create({
|
|
28322
28320
|
buttonStyle: {
|
|
28323
28321
|
backgroundColor: "white",
|
|
28324
28322
|
border: "1px solid #ccc",
|
|
@@ -31659,7 +31657,7 @@ const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
31659
31657
|
width: "24",
|
|
31660
31658
|
height: "24",
|
|
31661
31659
|
viewBox: "0 0 24 24",
|
|
31662
|
-
className: css(styles$
|
|
31660
|
+
className: css(styles$f.icon)
|
|
31663
31661
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
31664
31662
|
id: "a",
|
|
31665
31663
|
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"
|
|
@@ -31690,7 +31688,7 @@ const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
31690
31688
|
width: "24",
|
|
31691
31689
|
height: "24",
|
|
31692
31690
|
viewBox: "0 0 24 24",
|
|
31693
|
-
className: css(styles$
|
|
31691
|
+
className: css(styles$f.icon)
|
|
31694
31692
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
31695
31693
|
id: "a",
|
|
31696
31694
|
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"
|
|
@@ -31728,20 +31726,20 @@ const HUD = ({
|
|
|
31728
31726
|
let state;
|
|
31729
31727
|
let icon;
|
|
31730
31728
|
if (enabled) {
|
|
31731
|
-
state = styles$
|
|
31729
|
+
state = styles$f.enabled;
|
|
31732
31730
|
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
31733
31731
|
} else {
|
|
31734
|
-
state = styles$
|
|
31732
|
+
state = styles$f.disabled;
|
|
31735
31733
|
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
31736
31734
|
}
|
|
31737
31735
|
return /*#__PURE__*/React.createElement("button", {
|
|
31738
|
-
className: css(styles$
|
|
31736
|
+
className: css(styles$f.hud, _fixedPosition && styles$f.hudFixedPosition, state),
|
|
31739
31737
|
onClick: e => {
|
|
31740
31738
|
onClick();
|
|
31741
31739
|
}
|
|
31742
31740
|
}, icon, message);
|
|
31743
31741
|
};
|
|
31744
|
-
const styles$
|
|
31742
|
+
const styles$f = StyleSheet.create({
|
|
31745
31743
|
hud: {
|
|
31746
31744
|
boxSizing: "border-box",
|
|
31747
31745
|
height: 36,
|
|
@@ -31794,16 +31792,16 @@ const styles$g = StyleSheet.create({
|
|
|
31794
31792
|
const InfoTipBase = props => {
|
|
31795
31793
|
return /*#__PURE__*/React.createElement(Tooltip$1, {
|
|
31796
31794
|
content: /*#__PURE__*/React.createElement(Body, {
|
|
31797
|
-
style: styles$
|
|
31795
|
+
style: styles$e.body
|
|
31798
31796
|
}, props.children),
|
|
31799
31797
|
placement: "right"
|
|
31800
31798
|
}, /*#__PURE__*/React.createElement(PhosphorIcon, {
|
|
31801
31799
|
size: "small",
|
|
31802
31800
|
icon: questionIcon,
|
|
31803
|
-
style: styles$
|
|
31801
|
+
style: styles$e.spacingLeft
|
|
31804
31802
|
}));
|
|
31805
31803
|
};
|
|
31806
|
-
const styles$
|
|
31804
|
+
const styles$e = StyleSheet.create({
|
|
31807
31805
|
spacingLeft: {
|
|
31808
31806
|
marginInlineStart: spacing.xxxSmall_4
|
|
31809
31807
|
},
|
|
@@ -31882,7 +31880,7 @@ class MultiButtonGroup extends React.Component {
|
|
|
31882
31880
|
id: "" + i,
|
|
31883
31881
|
key: "" + i,
|
|
31884
31882
|
ref: "button" + i,
|
|
31885
|
-
className: css(styles$
|
|
31883
|
+
className: css(styles$d.buttonStyle, selected && styles$d.selectedStyle),
|
|
31886
31884
|
onClick: () => this.toggleSelect(button.value)
|
|
31887
31885
|
}, button.content || "" + button.value);
|
|
31888
31886
|
});
|
|
@@ -31899,7 +31897,7 @@ MultiButtonGroup.defaultProps = {
|
|
|
31899
31897
|
values: [],
|
|
31900
31898
|
allowEmpty: true
|
|
31901
31899
|
};
|
|
31902
|
-
const styles$
|
|
31900
|
+
const styles$d = StyleSheet.create({
|
|
31903
31901
|
buttonStyle: {
|
|
31904
31902
|
backgroundColor: "white",
|
|
31905
31903
|
border: "1px solid #ccc",
|
|
@@ -31932,7 +31930,7 @@ const styles$e = StyleSheet.create({
|
|
|
31932
31930
|
}
|
|
31933
31931
|
});
|
|
31934
31932
|
|
|
31935
|
-
const _excluded$
|
|
31933
|
+
const _excluded$3 = ["onFormatChange", "checkValidity", "useArrowKeys"];
|
|
31936
31934
|
const {
|
|
31937
31935
|
firstNumericalParse,
|
|
31938
31936
|
captureScratchpadTouchStart
|
|
@@ -32086,7 +32084,7 @@ class NumberInput extends React.Component {
|
|
|
32086
32084
|
classes = classes + " " + this.props.className;
|
|
32087
32085
|
}
|
|
32088
32086
|
const _this$props = this.props,
|
|
32089
|
-
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$
|
|
32087
|
+
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
|
|
32090
32088
|
return /*#__PURE__*/React.createElement("input", _extends({}, restProps, {
|
|
32091
32089
|
className: classes,
|
|
32092
32090
|
type: "text",
|
|
@@ -32296,14 +32294,6 @@ const LegacyGrid = ({
|
|
|
32296
32294
|
* A "PerseusArticle" is an item that is meant to be rendered as an article.
|
|
32297
32295
|
* This item is never scored and is rendered by the `ArticleRenderer`.
|
|
32298
32296
|
*/
|
|
32299
|
-
/**
|
|
32300
|
-
* A "MultiItem" is an advanced Perseus item. It is rendered by the
|
|
32301
|
-
* `MultiRenderer` and you can control the layout of individual parts of the
|
|
32302
|
-
* item.
|
|
32303
|
-
*
|
|
32304
|
-
* @deprecated MultiItem support is slated for removal in a future Perseus
|
|
32305
|
-
* release.
|
|
32306
|
-
*/
|
|
32307
32297
|
const ItemExtras = [
|
|
32308
32298
|
// The user might benefit from using a Scientific Calculator. Provided on Khan Academy when true
|
|
32309
32299
|
"calculator",
|
|
@@ -33076,12 +33066,12 @@ const MafsCssTransformWrapper = ({
|
|
|
33076
33066
|
}
|
|
33077
33067
|
}, children);
|
|
33078
33068
|
|
|
33079
|
-
const _excluded$
|
|
33069
|
+
const _excluded$2 = ["children"];
|
|
33080
33070
|
const TextLabel = _ref => {
|
|
33081
33071
|
let {
|
|
33082
33072
|
children
|
|
33083
33073
|
} = _ref,
|
|
33084
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
33074
|
+
rest = _objectWithoutPropertiesLoose(_ref, _excluded$2);
|
|
33085
33075
|
return /*#__PURE__*/React__default.createElement(Text$1, _extends({
|
|
33086
33076
|
size: 16,
|
|
33087
33077
|
svgTextProps: {
|
|
@@ -38711,7 +38701,7 @@ const HideAnswersToggle = props => {
|
|
|
38711
38701
|
strings
|
|
38712
38702
|
} = usePerseusI18n();
|
|
38713
38703
|
return /*#__PURE__*/React.createElement(View, {
|
|
38714
|
-
style: styles$
|
|
38704
|
+
style: styles$c.switchWrapper
|
|
38715
38705
|
}, /*#__PURE__*/React.createElement(Switch, {
|
|
38716
38706
|
id: switchId,
|
|
38717
38707
|
checked: props.areAnswersHidden,
|
|
@@ -38723,7 +38713,7 @@ const HideAnswersToggle = props => {
|
|
|
38723
38713
|
tag: "label"
|
|
38724
38714
|
}, strings.hideAnswersToggleLabel));
|
|
38725
38715
|
};
|
|
38726
|
-
const styles$
|
|
38716
|
+
const styles$c = StyleSheet.create({
|
|
38727
38717
|
switchWrapper: {
|
|
38728
38718
|
display: "flex",
|
|
38729
38719
|
flexDirection: "row",
|
|
@@ -38779,14 +38769,14 @@ const AnswerPill = props => {
|
|
|
38779
38769
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
38780
38770
|
onClick: correct ? undefined : onClick,
|
|
38781
38771
|
ref: ref,
|
|
38782
|
-
style: [style, popperStyle, styles$
|
|
38772
|
+
style: [style, popperStyle, styles$b.pill, correct && styles$b.correct, incorrect && styles$b.incorrect, (focused || hovered) && BringToFront]
|
|
38783
38773
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
38784
38774
|
content: answerString,
|
|
38785
38775
|
strings: strings,
|
|
38786
38776
|
inline: true
|
|
38787
38777
|
})));
|
|
38788
38778
|
};
|
|
38789
|
-
const styles$
|
|
38779
|
+
const styles$b = StyleSheet.create({
|
|
38790
38780
|
correct: {
|
|
38791
38781
|
// WB green darkened by 18%
|
|
38792
38782
|
backgroundColor: "#00880b"
|
|
@@ -38850,23 +38840,23 @@ class Marker extends React.Component {
|
|
|
38850
38840
|
icon: iconNull
|
|
38851
38841
|
};
|
|
38852
38842
|
if (showCorrectness) {
|
|
38853
|
-
iconStyles = [styles$
|
|
38843
|
+
iconStyles = [styles$a.markerGraded, showCorrectness === "correct" ? styles$a.markerCorrect : styles$a.markerIncorrect, isOpen && styles$a.markerSelected];
|
|
38854
38844
|
args = _extends({}, args, {
|
|
38855
38845
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
38856
38846
|
});
|
|
38857
38847
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
38858
|
-
iconStyles = [styles$
|
|
38848
|
+
iconStyles = [styles$a.markerFilled, isOpen && styles$a.markerSelected];
|
|
38859
38849
|
} else if (isOpen) {
|
|
38860
|
-
iconStyles = [styles$
|
|
38850
|
+
iconStyles = [styles$a.markerSelected];
|
|
38861
38851
|
args = _extends({}, args, {
|
|
38862
38852
|
icon: iconChevronDown,
|
|
38863
38853
|
size: 8
|
|
38864
38854
|
});
|
|
38865
38855
|
} else if (showPulsate) {
|
|
38866
|
-
iconStyles = [styles$
|
|
38856
|
+
iconStyles = [styles$a.markerPulsateBase, this._mounted && shouldReduceMotion() ? showPulsate && styles$a.markerUnfilledPulsateOnce : showPulsate && styles$a.markerUnfilledPulsateInfinite];
|
|
38867
38857
|
}
|
|
38868
38858
|
return /*#__PURE__*/React.createElement(View, {
|
|
38869
|
-
style: [styles$
|
|
38859
|
+
style: [styles$a.markerIcon, iconStyles],
|
|
38870
38860
|
ref: node => this._icon = node
|
|
38871
38861
|
}, /*#__PURE__*/React.createElement(Icon, args));
|
|
38872
38862
|
}
|
|
@@ -38888,7 +38878,7 @@ class Marker extends React.Component {
|
|
|
38888
38878
|
const markerDisabled = showCorrectness === "correct";
|
|
38889
38879
|
const active = hovered || focused;
|
|
38890
38880
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
38891
|
-
style: [styles$
|
|
38881
|
+
style: [styles$a.marker, active && !markerDisabled && styles$a.markerActive],
|
|
38892
38882
|
"aria-label": markerDisabled ? this.context.strings.correctExcited : label
|
|
38893
38883
|
}, this.renderIcon()), !!selected && showAnswer && /*#__PURE__*/React.createElement(AnswerPill, {
|
|
38894
38884
|
selectedAnswers: selected,
|
|
@@ -38905,7 +38895,7 @@ Marker.contextType = PerseusI18nContext;
|
|
|
38905
38895
|
Marker.defaultProps = {
|
|
38906
38896
|
selected: []
|
|
38907
38897
|
};
|
|
38908
|
-
const styles$
|
|
38898
|
+
const styles$a = StyleSheet.create({
|
|
38909
38899
|
marker: {
|
|
38910
38900
|
position: "absolute",
|
|
38911
38901
|
backgroundColor: color.white,
|
|
@@ -39490,13 +39480,13 @@ class LabelImage extends React.Component {
|
|
|
39490
39480
|
const promptString = isMobile ? multipleAnswers ? strings.tapMultiple : strings.tapSingle : multipleAnswers ? strings.clickMultiple : strings.clickSingle;
|
|
39491
39481
|
const choicesString = strings.choices;
|
|
39492
39482
|
return /*#__PURE__*/React.createElement("div", {
|
|
39493
|
-
className: classNames$1("perseus-label-image-widget-instructions", css(styles$
|
|
39483
|
+
className: classNames$1("perseus-label-image-widget-instructions", css(styles$9.instructions))
|
|
39494
39484
|
}, /*#__PURE__*/React.createElement("div", {
|
|
39495
|
-
className: css(styles$
|
|
39485
|
+
className: css(styles$9.instructionsCaption)
|
|
39496
39486
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React.createElement("div", {
|
|
39497
|
-
className: css(styles$
|
|
39487
|
+
className: css(styles$9.instructionsChoices)
|
|
39498
39488
|
}, choices.map((choice, index) => /*#__PURE__*/React.createElement("div", {
|
|
39499
|
-
className: css(styles$
|
|
39489
|
+
className: css(styles$9.instructionsChoice),
|
|
39500
39490
|
key: index
|
|
39501
39491
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
39502
39492
|
content: choice,
|
|
@@ -39514,20 +39504,20 @@ class LabelImage extends React.Component {
|
|
|
39514
39504
|
activeMarkerIndex
|
|
39515
39505
|
} = this.state;
|
|
39516
39506
|
return /*#__PURE__*/React.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React.createElement("div", {
|
|
39517
|
-
className: css(styles$
|
|
39507
|
+
className: css(styles$9.markersCanvas),
|
|
39518
39508
|
style: {
|
|
39519
39509
|
maxWidth: imageWidth,
|
|
39520
39510
|
maxHeight: imageHeight
|
|
39521
39511
|
}
|
|
39522
39512
|
}, /*#__PURE__*/React.createElement("div", {
|
|
39523
|
-
className: css(styles$
|
|
39513
|
+
className: css(styles$9.imageContainer,
|
|
39524
39514
|
// Ensure image interaction is disabled while answer
|
|
39525
39515
|
// choices popup is visible. This addresses specific
|
|
39526
39516
|
// case where user may click on question image to
|
|
39527
39517
|
// dismiss the popup. If the image is larger in size
|
|
39528
39518
|
// than its rendered in the widget, this would
|
|
39529
39519
|
// result in a zoom of the image.
|
|
39530
|
-
activeMarkerIndex !== -1 && styles$
|
|
39520
|
+
activeMarkerIndex !== -1 && styles$9.imageInteractionDisabled)
|
|
39531
39521
|
}, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
|
|
39532
39522
|
setAssetStatus
|
|
39533
39523
|
}) => /*#__PURE__*/React.createElement(SvgImage, {
|
|
@@ -39552,7 +39542,7 @@ class LabelImage extends React.Component {
|
|
|
39552
39542
|
}
|
|
39553
39543
|
}
|
|
39554
39544
|
LabelImage.contextType = PerseusI18nContext;
|
|
39555
|
-
const styles$
|
|
39545
|
+
const styles$9 = StyleSheet.create({
|
|
39556
39546
|
instructions: {
|
|
39557
39547
|
paddingBottom: 16
|
|
39558
39548
|
},
|
|
@@ -39638,7 +39628,7 @@ class Placeholder extends React.Component {
|
|
|
39638
39628
|
const {
|
|
39639
39629
|
layout
|
|
39640
39630
|
} = this.props;
|
|
39641
|
-
const className = css(styles$
|
|
39631
|
+
const className = css(styles$8.card, styles$8.placeholder, layout === "horizontal" && styles$8.horizontalCard);
|
|
39642
39632
|
const style = {
|
|
39643
39633
|
width: this.props.width,
|
|
39644
39634
|
height: this.props.height
|
|
@@ -39842,7 +39832,7 @@ class Draggable extends React.Component {
|
|
|
39842
39832
|
// We need to keep backwards compatbility with rules specified directly
|
|
39843
39833
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
39844
39834
|
// See sortable.less for details.
|
|
39845
|
-
let className = css(styles$
|
|
39835
|
+
let className = 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";
|
|
39846
39836
|
if (!includePadding) {
|
|
39847
39837
|
className += " perseus-sortable-draggable-unpadded";
|
|
39848
39838
|
}
|
|
@@ -40175,7 +40165,7 @@ class Sortable extends React.Component {
|
|
|
40175
40165
|
} = this.props;
|
|
40176
40166
|
// We need to keep backwards compatbility with rules specified directly
|
|
40177
40167
|
// in CSS. See sortable.less for details.
|
|
40178
|
-
const className = css(styles$
|
|
40168
|
+
const className = css(styles$8.sortable) + " perseus-sortable";
|
|
40179
40169
|
const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === "vertical";
|
|
40180
40170
|
const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === "horizontal";
|
|
40181
40171
|
_.each(this.state.items, function (item, i, items) {
|
|
@@ -40272,7 +40262,7 @@ Sortable.defaultProps = {
|
|
|
40272
40262
|
linterContext: PerseusLinter.linterContextDefault,
|
|
40273
40263
|
waitForTexRendererToLoad: true
|
|
40274
40264
|
};
|
|
40275
|
-
const styles$
|
|
40265
|
+
const styles$8 = StyleSheet.create({
|
|
40276
40266
|
sortable: {
|
|
40277
40267
|
boxSizing: "border-box",
|
|
40278
40268
|
float: "left",
|
|
@@ -40458,25 +40448,25 @@ class Matcher extends React.Component {
|
|
|
40458
40448
|
};
|
|
40459
40449
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
40460
40450
|
return /*#__PURE__*/React.createElement("table", {
|
|
40461
|
-
className: css(styles$
|
|
40451
|
+
className: css(styles$7.widget) + " " + HACKY_CSS_CLASSNAME
|
|
40462
40452
|
}, /*#__PURE__*/React.createElement("tbody", null, showLabels && /*#__PURE__*/React.createElement("tr", {
|
|
40463
|
-
className: css(styles$
|
|
40453
|
+
className: css(styles$7.row)
|
|
40464
40454
|
}, /*#__PURE__*/React.createElement("th", {
|
|
40465
|
-
className: css(styles$
|
|
40455
|
+
className: css(styles$7.column, styles$7.columnLabel)
|
|
40466
40456
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
40467
40457
|
content: this.props.labels[0] || "...",
|
|
40468
40458
|
linterContext: this.props.linterContext,
|
|
40469
40459
|
strings: this.context.strings
|
|
40470
40460
|
})), /*#__PURE__*/React.createElement("th", {
|
|
40471
|
-
className: css(styles$
|
|
40461
|
+
className: css(styles$7.column, styles$7.columnRight, styles$7.columnLabel)
|
|
40472
40462
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
40473
40463
|
content: this.props.labels[1] || "...",
|
|
40474
40464
|
linterContext: this.props.linterContext,
|
|
40475
40465
|
strings: this.context.strings
|
|
40476
40466
|
}))), /*#__PURE__*/React.createElement("tr", {
|
|
40477
|
-
className: css(styles$
|
|
40467
|
+
className: css(styles$7.row)
|
|
40478
40468
|
}, /*#__PURE__*/React.createElement("td", {
|
|
40479
|
-
className: css(styles$
|
|
40469
|
+
className: css(styles$7.column)
|
|
40480
40470
|
}, /*#__PURE__*/React.createElement(Sortable, {
|
|
40481
40471
|
options: left,
|
|
40482
40472
|
layout: "vertical",
|
|
@@ -40491,7 +40481,7 @@ class Matcher extends React.Component {
|
|
|
40491
40481
|
,
|
|
40492
40482
|
ref: "left"
|
|
40493
40483
|
})), /*#__PURE__*/React.createElement("td", {
|
|
40494
|
-
className: css(styles$
|
|
40484
|
+
className: css(styles$7.column, styles$7.columnRight)
|
|
40495
40485
|
}, /*#__PURE__*/React.createElement(Sortable, {
|
|
40496
40486
|
options: right,
|
|
40497
40487
|
layout: "vertical",
|
|
@@ -40520,7 +40510,7 @@ Matcher.defaultProps = {
|
|
|
40520
40510
|
};
|
|
40521
40511
|
const padding = 5;
|
|
40522
40512
|
const border = "1px solid #444";
|
|
40523
|
-
const styles$
|
|
40513
|
+
const styles$7 = StyleSheet.create({
|
|
40524
40514
|
widget: {
|
|
40525
40515
|
paddingTop: padding,
|
|
40526
40516
|
maxWidth: "100%",
|
|
@@ -41062,7 +41052,7 @@ const getPromptJSON$7 = () => {
|
|
|
41062
41052
|
return getUnsupportedPromptJSON("measurer");
|
|
41063
41053
|
};
|
|
41064
41054
|
|
|
41065
|
-
const _excluded$
|
|
41055
|
+
const _excluded$1 = ["imageUrl", "imageTop", "imageLeft"];
|
|
41066
41056
|
const defaultImage = {
|
|
41067
41057
|
url: null,
|
|
41068
41058
|
top: 0,
|
|
@@ -41174,7 +41164,7 @@ const propUpgrades = {
|
|
|
41174
41164
|
imageTop,
|
|
41175
41165
|
imageLeft
|
|
41176
41166
|
} = v0props,
|
|
41177
|
-
rest = _objectWithoutPropertiesLoose(v0props, _excluded$
|
|
41167
|
+
rest = _objectWithoutPropertiesLoose(v0props, _excluded$1);
|
|
41178
41168
|
return _extends({}, rest, {
|
|
41179
41169
|
image: {
|
|
41180
41170
|
url: imageUrl,
|
|
@@ -41214,9 +41204,9 @@ function drawText(ctx, item) {
|
|
|
41214
41204
|
if (item.value === null) {
|
|
41215
41205
|
return;
|
|
41216
41206
|
}
|
|
41217
|
-
ctx.fillStyle = styles$
|
|
41218
|
-
ctx.font = styles$
|
|
41219
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
41207
|
+
ctx.fillStyle = styles$6.fgColor;
|
|
41208
|
+
ctx.font = styles$6.font;
|
|
41209
|
+
ctx.fillText(item.value, item.pos[0] - styles$6.fontSizePx / 2 + 1, item.pos[1] + styles$6.fontSizePx / 2);
|
|
41220
41210
|
}
|
|
41221
41211
|
|
|
41222
41212
|
/**
|
|
@@ -41237,16 +41227,16 @@ function drawText(ctx, item) {
|
|
|
41237
41227
|
function drawDoubleLine(ctx, item) {
|
|
41238
41228
|
// Outer line that forms both of the bond lines.
|
|
41239
41229
|
let path = new Path2D();
|
|
41240
|
-
ctx.lineWidth = 5 * styles$
|
|
41241
|
-
ctx.strokeStyle = styles$
|
|
41230
|
+
ctx.lineWidth = 5 * styles$6.lineWidth;
|
|
41231
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41242
41232
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41243
41233
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41244
41234
|
ctx.stroke(path);
|
|
41245
41235
|
|
|
41246
41236
|
// Inner white line that separates the two bond lines.
|
|
41247
41237
|
path = new Path2D();
|
|
41248
|
-
ctx.lineWidth = 3 * styles$
|
|
41249
|
-
ctx.strokeStyle = styles$
|
|
41238
|
+
ctx.lineWidth = 3 * styles$6.lineWidth;
|
|
41239
|
+
ctx.strokeStyle = styles$6.bgColor;
|
|
41250
41240
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41251
41241
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41252
41242
|
ctx.stroke(path);
|
|
@@ -41273,16 +41263,16 @@ function drawTripleLine(ctx, item) {
|
|
|
41273
41263
|
|
|
41274
41264
|
// Outer line that will form the two outer bond lines.
|
|
41275
41265
|
let path = new Path2D();
|
|
41276
|
-
ctx.lineWidth = 7 * styles$
|
|
41277
|
-
ctx.strokeStyle = styles$
|
|
41266
|
+
ctx.lineWidth = 7 * styles$6.lineWidth;
|
|
41267
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41278
41268
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41279
41269
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41280
41270
|
ctx.stroke(path);
|
|
41281
41271
|
|
|
41282
41272
|
// Middle white line that separates the bonds
|
|
41283
41273
|
path = new Path2D();
|
|
41284
|
-
ctx.lineWidth = 5 * styles$
|
|
41285
|
-
ctx.strokeStyle = styles$
|
|
41274
|
+
ctx.lineWidth = 5 * styles$6.lineWidth;
|
|
41275
|
+
ctx.strokeStyle = styles$6.bgColor;
|
|
41286
41276
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41287
41277
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41288
41278
|
ctx.stroke(path);
|
|
@@ -41304,8 +41294,8 @@ function drawTripleLine(ctx, item) {
|
|
|
41304
41294
|
*/
|
|
41305
41295
|
function drawLine(ctx, item) {
|
|
41306
41296
|
const path = new Path2D();
|
|
41307
|
-
ctx.lineWidth = styles$
|
|
41308
|
-
ctx.strokeStyle = styles$
|
|
41297
|
+
ctx.lineWidth = styles$6.lineWidth;
|
|
41298
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41309
41299
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41310
41300
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41311
41301
|
ctx.stroke(path);
|
|
@@ -41357,7 +41347,7 @@ function compareElements(item0, item1) {
|
|
|
41357
41347
|
function draw(ctx, items) {
|
|
41358
41348
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
41359
41349
|
}
|
|
41360
|
-
const styles$
|
|
41350
|
+
const styles$6 = {
|
|
41361
41351
|
bgColor: "rgb(255, 255, 255)",
|
|
41362
41352
|
fgColor: "rgb(0, 0, 0)",
|
|
41363
41353
|
fontSizePx: 12,
|
|
@@ -43477,7 +43467,7 @@ class PhetSimulation extends React.Component {
|
|
|
43477
43467
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
43478
43468
|
const sandboxProperties = "allow-same-origin allow-scripts";
|
|
43479
43469
|
return /*#__PURE__*/React.createElement(View, {
|
|
43480
|
-
style: styles$
|
|
43470
|
+
style: styles$5.widgetContainer
|
|
43481
43471
|
}, this.state.banner !== null &&
|
|
43482
43472
|
/*#__PURE__*/
|
|
43483
43473
|
// TODO(anna): Make this banner focusable
|
|
@@ -43490,12 +43480,12 @@ class PhetSimulation extends React.Component {
|
|
|
43490
43480
|
kind: this.state.banner.kind,
|
|
43491
43481
|
text: this.state.banner.message
|
|
43492
43482
|
})), /*#__PURE__*/React.createElement(View, {
|
|
43493
|
-
style: styles$
|
|
43483
|
+
style: styles$5.iframeContainer
|
|
43494
43484
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
43495
43485
|
ref: this.iframeRef,
|
|
43496
43486
|
title: this.props.description,
|
|
43497
43487
|
sandbox: sandboxProperties,
|
|
43498
|
-
className: css(styles$
|
|
43488
|
+
className: css(styles$5.iframeResponsive),
|
|
43499
43489
|
src: (_this$state$url = this.state.url) == null ? void 0 : _this$state$url.toString(),
|
|
43500
43490
|
allow: "fullscreen"
|
|
43501
43491
|
})), this.state.url !== null && /*#__PURE__*/React.createElement(IconButton, {
|
|
@@ -43528,7 +43518,7 @@ const makeSafeUrl = (urlString, locale) => {
|
|
|
43528
43518
|
url.searchParams.set("locale", locale);
|
|
43529
43519
|
return url;
|
|
43530
43520
|
};
|
|
43531
|
-
const styles$
|
|
43521
|
+
const styles$5 = StyleSheet.create({
|
|
43532
43522
|
widgetContainer: {
|
|
43533
43523
|
borderRadius: 6,
|
|
43534
43524
|
borderWidth: 1,
|
|
@@ -44446,7 +44436,7 @@ class PythonProgram extends React.Component {
|
|
|
44446
44436
|
// creator "went wild".
|
|
44447
44437
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
44448
44438
|
return /*#__PURE__*/React.createElement(View, {
|
|
44449
|
-
style: styles$
|
|
44439
|
+
style: styles$4.container
|
|
44450
44440
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
44451
44441
|
sandbox: sandboxOptions,
|
|
44452
44442
|
src: url,
|
|
@@ -44458,7 +44448,7 @@ class PythonProgram extends React.Component {
|
|
|
44458
44448
|
PythonProgram.defaultProps = {
|
|
44459
44449
|
height: 400
|
|
44460
44450
|
};
|
|
44461
|
-
const styles$
|
|
44451
|
+
const styles$4 = StyleSheet.create({
|
|
44462
44452
|
container: {
|
|
44463
44453
|
margin: "auto",
|
|
44464
44454
|
width: "100%"
|
|
@@ -44951,7 +44941,7 @@ const VideoTranscriptLink = props => {
|
|
|
44951
44941
|
var _result$data;
|
|
44952
44942
|
const video = (_result$data = result.data) == null ? void 0 : _result$data.video;
|
|
44953
44943
|
return /*#__PURE__*/React.createElement(View, {
|
|
44954
|
-
style: styles$
|
|
44944
|
+
style: styles$3.transcriptLink
|
|
44955
44945
|
}, /*#__PURE__*/React.createElement(Text$2, null, video == null ? void 0 : video.title), /*#__PURE__*/React.createElement(Strut, {
|
|
44956
44946
|
size: 10
|
|
44957
44947
|
}), /*#__PURE__*/React.createElement(Link, {
|
|
@@ -44968,7 +44958,7 @@ const VideoTranscriptLink = props => {
|
|
|
44968
44958
|
return /*#__PURE__*/React.createElement(View, null, strings.somethingWrong);
|
|
44969
44959
|
}
|
|
44970
44960
|
};
|
|
44971
|
-
const styles$
|
|
44961
|
+
const styles$3 = StyleSheet.create({
|
|
44972
44962
|
transcriptLink: {
|
|
44973
44963
|
flexDirection: "row",
|
|
44974
44964
|
width: "100%",
|
|
@@ -45086,7 +45076,7 @@ const init = function init() {
|
|
|
45086
45076
|
|
|
45087
45077
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45088
45078
|
const libName = "@khanacademy/perseus";
|
|
45089
|
-
const libVersion = "
|
|
45079
|
+
const libVersion = "47.0.0";
|
|
45090
45080
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45091
45081
|
|
|
45092
45082
|
const apiVersion = {
|
|
@@ -45298,7 +45288,7 @@ class HintRenderer extends React.Component {
|
|
|
45298
45288
|
const {
|
|
45299
45289
|
isMobile
|
|
45300
45290
|
} = apiOptions;
|
|
45301
|
-
const classNames = classNames$1("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$
|
|
45291
|
+
const classNames = classNames$1("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$2.newHint), isMobile && lastRendered && css(styles$2.lastRenderedNewHint), lastHint && "last-hint", lastRendered && "last-rendered", className);
|
|
45302
45292
|
|
|
45303
45293
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
45304
45294
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -45343,7 +45333,7 @@ HintRenderer.contextType = PerseusI18nContext;
|
|
|
45343
45333
|
HintRenderer.defaultProps = {
|
|
45344
45334
|
linterContext: PerseusLinter.linterContextDefault
|
|
45345
45335
|
};
|
|
45346
|
-
const styles$
|
|
45336
|
+
const styles$2 = StyleSheet.create({
|
|
45347
45337
|
newHint: {
|
|
45348
45338
|
marginBottom: 1.5 * baseUnitPx,
|
|
45349
45339
|
borderLeftColor: gray97,
|
|
@@ -45516,14 +45506,14 @@ class HintsRenderer extends React.Component {
|
|
|
45516
45506
|
} = apiOptions;
|
|
45517
45507
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
45518
45508
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
45519
|
-
const classNames = classNames$1(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$
|
|
45509
|
+
const classNames = classNames$1(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$1.mobileHintStylesHintsRenderer));
|
|
45520
45510
|
return /*#__PURE__*/React.createElement("div", {
|
|
45521
45511
|
className: classNames
|
|
45522
45512
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React.createElement("div", {
|
|
45523
|
-
className: css(styles$
|
|
45513
|
+
className: css(styles$1.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
45524
45514
|
}, this.context.strings.hints), hints, showGetAnotherHint && /*#__PURE__*/React.createElement("button", {
|
|
45525
45515
|
rel: "button",
|
|
45526
|
-
className: css(styles$
|
|
45516
|
+
className: css(styles$1.linkButton, styles$1.getAnotherHintButton, apiOptions.isMobile && styles$1.mobileHintStylesGetAnotherHintButton),
|
|
45527
45517
|
onClick: evt => {
|
|
45528
45518
|
evt.preventDefault();
|
|
45529
45519
|
evt.stopPropagation();
|
|
@@ -45532,9 +45522,9 @@ class HintsRenderer extends React.Component {
|
|
|
45532
45522
|
}
|
|
45533
45523
|
}
|
|
45534
45524
|
}, /*#__PURE__*/React.createElement("span", {
|
|
45535
|
-
className: css(styles$
|
|
45525
|
+
className: css(styles$1.plusText, apiOptions.isMobile && styles$1.mobileHintStylesPlusText)
|
|
45536
45526
|
}, "+"), /*#__PURE__*/React.createElement("span", {
|
|
45537
|
-
className: css(styles$
|
|
45527
|
+
className: css(styles$1.getAnotherHintText)
|
|
45538
45528
|
}, this.context.strings.getAnotherHint, " ", hintRatioCopy)));
|
|
45539
45529
|
}
|
|
45540
45530
|
}
|
|
@@ -45543,7 +45533,7 @@ HintsRenderer.defaultProps = {
|
|
|
45543
45533
|
linterContext: PerseusLinter.linterContextDefault
|
|
45544
45534
|
};
|
|
45545
45535
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
45546
|
-
const styles$
|
|
45536
|
+
const styles$1 = StyleSheet.create({
|
|
45547
45537
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
45548
45538
|
rendererMargins: {
|
|
45549
45539
|
marginTop: baseUnitPx
|
|
@@ -45952,7 +45942,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
45952
45942
|
// mobile hint styles, which are flush to the left.
|
|
45953
45943
|
// NOTE(charlie): We may still want to apply this
|
|
45954
45944
|
// padding for desktop exercises.
|
|
45955
|
-
apiOptions.isMobile ? undefined : css(styles
|
|
45945
|
+
apiOptions.isMobile ? undefined : css(styles.hintsContainer)
|
|
45956
45946
|
}, hintsRenderer)));
|
|
45957
45947
|
}
|
|
45958
45948
|
}
|
|
@@ -45963,7 +45953,7 @@ ServerItemRenderer.defaultProps = {
|
|
|
45963
45953
|
linterContext: PerseusLinter.linterContextDefault,
|
|
45964
45954
|
onRendered: isRendered => {}
|
|
45965
45955
|
};
|
|
45966
|
-
const styles
|
|
45956
|
+
const styles = StyleSheet.create({
|
|
45967
45957
|
hintsContainer: {
|
|
45968
45958
|
marginLeft: 50
|
|
45969
45959
|
}
|
|
@@ -46068,1144 +46058,6 @@ const traverse = function traverse(rendererOptions, contentCallback, widgetCallb
|
|
|
46068
46058
|
return traverseRenderer$1(rendererOptions, contentCallback, deepCallbackFor(contentCallback, widgetCallback, optionsCallback), optionsCallback);
|
|
46069
46059
|
};
|
|
46070
46060
|
|
|
46071
|
-
/**
|
|
46072
|
-
* Utility functions for constructing and inferring multi-item shapes.
|
|
46073
|
-
*
|
|
46074
|
-
* A shape is an object that serves as a runtime type declaration: it specifies
|
|
46075
|
-
* a tree structure for a particular class of multi-item. See shape-types.js
|
|
46076
|
-
* for further discussion.
|
|
46077
|
-
*
|
|
46078
|
-
* This module allows you to construct arbitrary Shape trees, by combining
|
|
46079
|
-
* leaf node shapes like `content` and `hint` into composite shapes like
|
|
46080
|
-
* `arrayOf(shape({foo: content, bar: hint}))`.
|
|
46081
|
-
*/
|
|
46082
|
-
|
|
46083
|
-
/**
|
|
46084
|
-
* These tools allow you to construct arbirtary shapes, by combining simple
|
|
46085
|
-
* leaf shapes like `content` and `hint` into composite shapes like
|
|
46086
|
-
* `arrayOf(shape({question: content, hints: arrayOf(hint)}))`.
|
|
46087
|
-
*/
|
|
46088
|
-
const contentShape = {
|
|
46089
|
-
type: "content"
|
|
46090
|
-
};
|
|
46091
|
-
const hintShape = {
|
|
46092
|
-
type: "hint"
|
|
46093
|
-
};
|
|
46094
|
-
const tagsShape = {
|
|
46095
|
-
type: "tags"
|
|
46096
|
-
};
|
|
46097
|
-
const buildArrayShape = elementShape => ({
|
|
46098
|
-
type: "array",
|
|
46099
|
-
elementShape
|
|
46100
|
-
});
|
|
46101
|
-
const buildObjectShape = shape => ({
|
|
46102
|
-
type: "object",
|
|
46103
|
-
shape
|
|
46104
|
-
});
|
|
46105
|
-
const hintsShape = buildArrayShape(hintShape);
|
|
46106
|
-
var shapes = {
|
|
46107
|
-
content: contentShape,
|
|
46108
|
-
hint: hintShape,
|
|
46109
|
-
hints: hintsShape,
|
|
46110
|
-
tags: tagsShape,
|
|
46111
|
-
arrayOf: buildArrayShape,
|
|
46112
|
-
shape: buildObjectShape
|
|
46113
|
-
};
|
|
46114
|
-
|
|
46115
|
-
/**
|
|
46116
|
-
* Utility functions for manipulating multi-item-shaped trees.
|
|
46117
|
-
*
|
|
46118
|
-
* Multi-items are trees! But we also often have other trees that are shaped
|
|
46119
|
-
* like multi-items - for example, if we map a multi-item tree into a tree of
|
|
46120
|
-
* renderer info and state, and then map that again into a tree of just the
|
|
46121
|
-
* renderer nodes, like we do in MultiRenderer. See tree-types.js for further
|
|
46122
|
-
* discussion.
|
|
46123
|
-
*
|
|
46124
|
-
* These functions enable us to manipulate generic multi-item-shaped trees,
|
|
46125
|
-
* regardless of what type of data they contain at their leaves. You can use
|
|
46126
|
-
* the mapper functions to transform a tree into another tree of the same
|
|
46127
|
-
* shape, or to discover all the nodes of a particular type.
|
|
46128
|
-
*
|
|
46129
|
-
* We expose two simple mapper functions (mapContentNodes and mapHintNodes),
|
|
46130
|
-
* and also a more complex interface for creating a mapping over all of a
|
|
46131
|
-
* tree's node types simultaneously:
|
|
46132
|
-
*
|
|
46133
|
-
* `buildMapper()` returns a TreeMapper object that allows you to build your
|
|
46134
|
-
* mapper object one node type at a time. Then, you can execute your mapping by
|
|
46135
|
-
* calling the `mapTree` method.
|
|
46136
|
-
*
|
|
46137
|
-
* For example:
|
|
46138
|
-
* const renderers = buildMapper()
|
|
46139
|
-
* .setContentMapper(this.renderContentNode)
|
|
46140
|
-
* .setHintMapper(this.renderHintNode)
|
|
46141
|
-
* .setTagsMapper(this.renderTagsNode)
|
|
46142
|
-
* .setArrayMapper(this.hideSkippedQuestions)
|
|
46143
|
-
* .mapTree(tree, shape);
|
|
46144
|
-
*
|
|
46145
|
-
* This will copy the given tree, apply the given transformations to the
|
|
46146
|
-
* content, hint, and array nodes respectively, and return the resulting tree.
|
|
46147
|
-
*
|
|
46148
|
-
* For node types whose mappers aren't specified, we default to the identity
|
|
46149
|
-
* function. (This builder interface enables us to implement that default
|
|
46150
|
-
* behavior in a provably type-safe way, while not requiring the call site to
|
|
46151
|
-
* be aware of all the node types. Hooray!)
|
|
46152
|
-
*
|
|
46153
|
-
* The call to `setArrayMapper` must come last, because the array mapper's
|
|
46154
|
-
* argument types depend on the other mappers' types. See ArrayMapper for more
|
|
46155
|
-
* details.
|
|
46156
|
-
*
|
|
46157
|
-
* WARNING: These functions trust that the provided tree conforms to the
|
|
46158
|
-
* provided shape. If not, behavior is undefined and may not respect the type
|
|
46159
|
-
* signatures specified here.
|
|
46160
|
-
*/
|
|
46161
|
-
|
|
46162
|
-
/**
|
|
46163
|
-
* The sequence of edges that lead to a particular node in a Tree.
|
|
46164
|
-
* Elements can be `string` to correspond to an ObjectNode key, or `number` to
|
|
46165
|
-
* correspond to an ArrayNode index.
|
|
46166
|
-
*/
|
|
46167
|
-
|
|
46168
|
-
/**
|
|
46169
|
-
* These are function interfaces for mapping over various types of tree nodes.
|
|
46170
|
-
*
|
|
46171
|
-
* ArrayMapper is a bit more complicated than the leaf node mappers. It's
|
|
46172
|
-
* executed in the context of a `mapTree` call, after we've finished mapping
|
|
46173
|
-
* its child nodes, so the function has access to both the resulting array
|
|
46174
|
-
* (with mapped elements) and the original array (with the original untouched
|
|
46175
|
-
* elements).
|
|
46176
|
-
*
|
|
46177
|
-
* The ArrayMapper then has the opportunity to apply a final transformation to
|
|
46178
|
-
* the resulting array, like filtering certain elements or (in the hacky
|
|
46179
|
-
* MultiRenderer case) attaching a `renderHints` method to arrays of hint
|
|
46180
|
-
* renderers :)
|
|
46181
|
-
*
|
|
46182
|
-
* This is why `TreeMapper#setArrayMapper` must be called last: ArrayMapper's
|
|
46183
|
-
* types depend on the ContentMapper and HintMapper's types. And, since you can
|
|
46184
|
-
* only specify one mapper at a time in this builder interface (which is
|
|
46185
|
-
* necessary to provide default mappers in a type-safe way), you need your
|
|
46186
|
-
* dependencies to already be in place by the time you call `setArrayMapper`.
|
|
46187
|
-
* Otherwise, we'd have to set the ArrayMapper and *hope* that you *eventually*
|
|
46188
|
-
* provide a compatible ContentMapper and HintMapper, which is difficult to
|
|
46189
|
-
* prove at compile time.
|
|
46190
|
-
*
|
|
46191
|
-
* There's no ObjectMapper here, but not for any particular reason. We just
|
|
46192
|
-
* don't have a use case for it yet, so we haven't built it yet.
|
|
46193
|
-
*/
|
|
46194
|
-
|
|
46195
|
-
/**
|
|
46196
|
-
* A TreeMapper is a collection of node mappers, which, together, compose the
|
|
46197
|
-
* behavior for mapping over an entire tree.
|
|
46198
|
-
*
|
|
46199
|
-
* This serves as the interface for the two TreeMapper classes, including both
|
|
46200
|
-
* the internal mapper properties that we care about, and the `mapTree`
|
|
46201
|
-
* function that the call site will use.
|
|
46202
|
-
*/
|
|
46203
|
-
|
|
46204
|
-
/**
|
|
46205
|
-
* This is a TreeMapper that only has mappers specified for its leaf nodes; its
|
|
46206
|
-
* array mapper is the identity function.
|
|
46207
|
-
*
|
|
46208
|
-
* This is the TreeMapper initially returned by `buildMapper`. It allows you to
|
|
46209
|
-
* change the types of your ContentMapper and HintMapper, which is safe because
|
|
46210
|
-
* none of the other mappers that depend on those types (aka ArrayMapper) have
|
|
46211
|
-
* been specified yet. (Or, more specifically, the ArrayMapper is currently
|
|
46212
|
-
* `identity`, which can trivially vary with the ContentMapper and HintMapper's
|
|
46213
|
-
* types.)
|
|
46214
|
-
*
|
|
46215
|
-
* Once you call `setArrayMapper`, however, we move to the other class:
|
|
46216
|
-
* TreeMapperForLeavesAndCollections.
|
|
46217
|
-
*/
|
|
46218
|
-
class TreeMapperJustForLeaves {
|
|
46219
|
-
constructor(content, hint, tags) {
|
|
46220
|
-
this.content = void 0;
|
|
46221
|
-
this.hint = void 0;
|
|
46222
|
-
this.tags = void 0;
|
|
46223
|
-
this.array = void 0;
|
|
46224
|
-
this.content = content;
|
|
46225
|
-
this.hint = hint;
|
|
46226
|
-
this.tags = tags;
|
|
46227
|
-
this.array = identity;
|
|
46228
|
-
}
|
|
46229
|
-
setContentMapper(newContentMapper) {
|
|
46230
|
-
return new TreeMapperJustForLeaves(newContentMapper, this.hint, this.tags);
|
|
46231
|
-
}
|
|
46232
|
-
setHintMapper(newHintMapper) {
|
|
46233
|
-
return new TreeMapperJustForLeaves(this.content, newHintMapper, this.tags);
|
|
46234
|
-
}
|
|
46235
|
-
setTagsMapper(newTagsMapper) {
|
|
46236
|
-
return new TreeMapperJustForLeaves(this.content, this.hint, newTagsMapper);
|
|
46237
|
-
}
|
|
46238
|
-
setArrayMapper(newArrayMapper) {
|
|
46239
|
-
return new TreeMapperForLeavesAndCollections(this.content, this.hint, this.tags, newArrayMapper);
|
|
46240
|
-
}
|
|
46241
|
-
|
|
46242
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic. | TS2315 - Type 'Tree' is not generic.
|
|
46243
|
-
mapTree(tree, shape) {
|
|
46244
|
-
return mapTree(tree, shape, [], this);
|
|
46245
|
-
}
|
|
46246
|
-
}
|
|
46247
|
-
|
|
46248
|
-
/**
|
|
46249
|
-
* This is a TreeMapper that already has an ArrayMapper specified, so its
|
|
46250
|
-
* ContentMapper and HintMapper are now locked in.
|
|
46251
|
-
*/
|
|
46252
|
-
class TreeMapperForLeavesAndCollections {
|
|
46253
|
-
constructor(content, hint, tags, array) {
|
|
46254
|
-
this.content = void 0;
|
|
46255
|
-
this.hint = void 0;
|
|
46256
|
-
this.tags = void 0;
|
|
46257
|
-
this.array = void 0;
|
|
46258
|
-
this.content = content;
|
|
46259
|
-
this.hint = hint;
|
|
46260
|
-
this.tags = tags;
|
|
46261
|
-
this.array = array;
|
|
46262
|
-
}
|
|
46263
|
-
setArrayMapper(newArrayMapper) {
|
|
46264
|
-
return new TreeMapperForLeavesAndCollections(this.content, this.hint, this.tags, newArrayMapper);
|
|
46265
|
-
}
|
|
46266
|
-
|
|
46267
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic. | TS2315 - Type 'Tree' is not generic.
|
|
46268
|
-
mapTree(tree, shape) {
|
|
46269
|
-
return mapTree(tree, shape, [], this);
|
|
46270
|
-
}
|
|
46271
|
-
}
|
|
46272
|
-
function identity(x) {
|
|
46273
|
-
return x;
|
|
46274
|
-
}
|
|
46275
|
-
|
|
46276
|
-
/**
|
|
46277
|
-
* Return a new TreeMapper that will perform a no-op transformation on an input
|
|
46278
|
-
* tree. To make it useful, chain any combination of `setContentMapper`,
|
|
46279
|
-
* `setHintMapper`, `setTagMapper`, and `setArrayMapper` to specify
|
|
46280
|
-
* transformations for the individual node types.
|
|
46281
|
-
*/
|
|
46282
|
-
// @ts-expect-error - TS2300 - Duplicate identifier 'C'. | TS2300 - Duplicate identifier 'H'. | TS2300 - Duplicate identifier 'T'.
|
|
46283
|
-
function buildMapper() {
|
|
46284
|
-
return new TreeMapperJustForLeaves(identity, identity, identity);
|
|
46285
|
-
}
|
|
46286
|
-
|
|
46287
|
-
/**
|
|
46288
|
-
* Copy the given tree, apply the corresponding transformation specified in the
|
|
46289
|
-
* TreeMapper to each node, and return the resulting tree.
|
|
46290
|
-
*/
|
|
46291
|
-
function mapTree(
|
|
46292
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46293
|
-
tree, shape, path, mappers
|
|
46294
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46295
|
-
) {
|
|
46296
|
-
// We trust the shape of the multi-item to match the shape provided at
|
|
46297
|
-
// runtime. Therefore, in each shape branch, we cast the node to `any` and
|
|
46298
|
-
// reinterpret it as the expected node type.
|
|
46299
|
-
if (shape.type === "content") {
|
|
46300
|
-
const content = tree;
|
|
46301
|
-
return mappers.content(content, shape, path);
|
|
46302
|
-
}
|
|
46303
|
-
if (shape.type === "hint") {
|
|
46304
|
-
const hint = tree;
|
|
46305
|
-
return mappers.hint(hint, shape, path);
|
|
46306
|
-
}
|
|
46307
|
-
if (shape.type === "tags") {
|
|
46308
|
-
const tags = tree;
|
|
46309
|
-
return mappers.tags(tags, shape, path);
|
|
46310
|
-
}
|
|
46311
|
-
if (shape.type === "array") {
|
|
46312
|
-
// @ts-expect-error - TS2315 - Type 'ArrayNode' is not generic.
|
|
46313
|
-
const array = tree;
|
|
46314
|
-
if (!Array.isArray(array)) {
|
|
46315
|
-
throw new PerseusError(`Invalid object of type "${typeof array}" found at path ` +
|
|
46316
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46317
|
-
`${["<root>"].concat(path).join(".")}. Expected array.`, Errors.Internal);
|
|
46318
|
-
}
|
|
46319
|
-
const elementShape = shape.elementShape;
|
|
46320
|
-
// @ts-expect-error - TS2315 - Type 'ArrayNode' is not generic.
|
|
46321
|
-
const mappedElements = array.map((inner, i) => mapTree(inner, elementShape, path.concat(i), mappers));
|
|
46322
|
-
return mappers.array(mappedElements, array, shape, path);
|
|
46323
|
-
}
|
|
46324
|
-
if (shape.type === "object") {
|
|
46325
|
-
const object = tree;
|
|
46326
|
-
if (object && typeof object !== "object") {
|
|
46327
|
-
throw new PerseusError(`Invalid object of type "${typeof object}" found at ` +
|
|
46328
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46329
|
-
`path ${["<root>"].concat(path).join(".")}. Expected ` + `"object" type.`, Errors.InvalidInput);
|
|
46330
|
-
}
|
|
46331
|
-
const valueShapes = shape.shape;
|
|
46332
|
-
if (!valueShapes) {
|
|
46333
|
-
throw new PerseusError(`Unexpected shape ${JSON.stringify(shape)} at path ` +
|
|
46334
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46335
|
-
`${["<root>"].concat(path).join(".")}.`, Errors.InvalidInput);
|
|
46336
|
-
}
|
|
46337
|
-
const newObject = {};
|
|
46338
|
-
Object.keys(valueShapes).forEach(key => {
|
|
46339
|
-
if (!(key in object)) {
|
|
46340
|
-
throw new PerseusError(`Key "${key}" is missing from shape at path ` +
|
|
46341
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
46342
|
-
`${["<root>"].concat(path).join(".")}.`, Errors.InvalidInput);
|
|
46343
|
-
}
|
|
46344
|
-
newObject[key] = mapTree(object[key], valueShapes[key], path.concat(key), mappers);
|
|
46345
|
-
});
|
|
46346
|
-
return newObject;
|
|
46347
|
-
}
|
|
46348
|
-
throw new PerseusError(
|
|
46349
|
-
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
46350
|
-
`unexpected shape type ${shape.type}`, Errors.InvalidInput);
|
|
46351
|
-
}
|
|
46352
|
-
|
|
46353
|
-
/**
|
|
46354
|
-
* Utility functions for constructing and manipulating multi-items.
|
|
46355
|
-
*
|
|
46356
|
-
* These functions apply *specifically* to Items and ItemTrees - things that
|
|
46357
|
-
* actually semantically *are* multi-items. For more general functions for
|
|
46358
|
-
* traversing and manipulating *anything* shaped like a multi-item (like a
|
|
46359
|
-
* renderer tree or a score tree or, well, a multi-item), see trees.js.
|
|
46360
|
-
*/
|
|
46361
|
-
/**
|
|
46362
|
-
* Return a semantically empty ItemTree that conforms to the given shape.
|
|
46363
|
-
*
|
|
46364
|
-
* - An empty content node has an empty content string and no widgets/images.
|
|
46365
|
-
* - An empty hint node has an empty content string and no widgets/images.
|
|
46366
|
-
* - An empty array node has no elements.
|
|
46367
|
-
* - An empty object node has a semantically empty node for each of its keys.
|
|
46368
|
-
* (That is, we recursively call buildEmptyItemTreeForShape for each key.)
|
|
46369
|
-
*/
|
|
46370
|
-
function buildEmptyItemTreeForShape(shape) {
|
|
46371
|
-
if (shape.type === "content") {
|
|
46372
|
-
return {
|
|
46373
|
-
__type: "content",
|
|
46374
|
-
content: "",
|
|
46375
|
-
images: {},
|
|
46376
|
-
widgets: {}
|
|
46377
|
-
};
|
|
46378
|
-
}
|
|
46379
|
-
if (shape.type === "hint") {
|
|
46380
|
-
return {
|
|
46381
|
-
__type: "hint",
|
|
46382
|
-
replace: false,
|
|
46383
|
-
content: "",
|
|
46384
|
-
images: {},
|
|
46385
|
-
widgets: {}
|
|
46386
|
-
};
|
|
46387
|
-
}
|
|
46388
|
-
if (shape.type === "tags") {
|
|
46389
|
-
return [];
|
|
46390
|
-
}
|
|
46391
|
-
if (shape.type === "array") {
|
|
46392
|
-
return [];
|
|
46393
|
-
}
|
|
46394
|
-
if (shape.type === "object") {
|
|
46395
|
-
const valueShapes = shape.shape;
|
|
46396
|
-
const object = {};
|
|
46397
|
-
Object.keys(valueShapes).forEach(key => {
|
|
46398
|
-
object[key] = buildEmptyItemTreeForShape(valueShapes[key]);
|
|
46399
|
-
});
|
|
46400
|
-
return object;
|
|
46401
|
-
}
|
|
46402
|
-
throw new PerseusError(
|
|
46403
|
-
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
46404
|
-
`unexpected shape type ${shape.type}`, Errors.InvalidInput);
|
|
46405
|
-
}
|
|
46406
|
-
|
|
46407
|
-
/**
|
|
46408
|
-
* Return a semantically empty Item that conforms to the given shape.
|
|
46409
|
-
*
|
|
46410
|
-
* - An empty content node has an empty content string and no widgets/images.
|
|
46411
|
-
* - An empty hint node has an empty content string and no widgets/images.
|
|
46412
|
-
* - An empty array node has no elements.
|
|
46413
|
-
* - An empty object node has a semantically empty node for each of its keys.
|
|
46414
|
-
* (That is, we recursively call buildEmptyItemTreeForShape for each key.)
|
|
46415
|
-
*/
|
|
46416
|
-
function buildEmptyItemForShape(shape) {
|
|
46417
|
-
return treeToItem(buildEmptyItemTreeForShape(shape));
|
|
46418
|
-
}
|
|
46419
|
-
|
|
46420
|
-
/**
|
|
46421
|
-
* Given an Item and its Shape, yield all of its content nodes to the callback.
|
|
46422
|
-
*/
|
|
46423
|
-
function findContentNodesInItem$2(item, shape, callback) {
|
|
46424
|
-
const itemTree = itemToTree(item);
|
|
46425
|
-
buildMapper().setContentMapper(callback).mapTree(itemTree, shape);
|
|
46426
|
-
}
|
|
46427
|
-
|
|
46428
|
-
/**
|
|
46429
|
-
* Given an Item and its Shape, yield all of its hint nodes to the callback.
|
|
46430
|
-
*/
|
|
46431
|
-
function findHintNodesInItem(item, shape, callback) {
|
|
46432
|
-
const itemTree = itemToTree(item);
|
|
46433
|
-
buildMapper().setHintMapper(callback).mapTree(itemTree, shape);
|
|
46434
|
-
}
|
|
46435
|
-
|
|
46436
|
-
/**
|
|
46437
|
-
* Given an ItemTree, return a Shape that it conforms to.
|
|
46438
|
-
*
|
|
46439
|
-
* The Shape might not be complete or correct Shape that this Item was designed
|
|
46440
|
-
* for. If you have access to the intended Shape, use that instead.
|
|
46441
|
-
*/
|
|
46442
|
-
function inferItemShape$2(item) {
|
|
46443
|
-
const itemTree = itemToTree(item);
|
|
46444
|
-
return inferItemTreeShape(itemTree);
|
|
46445
|
-
}
|
|
46446
|
-
function inferItemTreeShape(node) {
|
|
46447
|
-
if (Array.isArray(node)) {
|
|
46448
|
-
if (node.length) {
|
|
46449
|
-
if (typeof node[0] === "string") {
|
|
46450
|
-
// There's no ItemTree that can manifest as a string.
|
|
46451
|
-
// So, an array of strings must be a TagsNode, not ArrayNode.
|
|
46452
|
-
return shapes.tags;
|
|
46453
|
-
}
|
|
46454
|
-
// Otherwise, assume that this is a valid ArrayNode, and
|
|
46455
|
-
// therefore the shape of the first element applies to all
|
|
46456
|
-
// elements in the array.
|
|
46457
|
-
return shapes.arrayOf(inferItemTreeShape(node[0]));
|
|
46458
|
-
}
|
|
46459
|
-
// The array is empty, so we arbitrarily guess that it's a content
|
|
46460
|
-
// array. As discussed in the docstring, this might be incorrect,
|
|
46461
|
-
// and you shouldn't depend on it.
|
|
46462
|
-
return shapes.arrayOf(shapes.content);
|
|
46463
|
-
}
|
|
46464
|
-
if (
|
|
46465
|
-
// TODO(mdr): Remove #LegacyContentNode support.
|
|
46466
|
-
typeof node === "object" && (node.__type === "content" || node.__type === "item")) {
|
|
46467
|
-
return shapes.content;
|
|
46468
|
-
}
|
|
46469
|
-
if (typeof node === "object" && node.__type === "hint") {
|
|
46470
|
-
return shapes.hint;
|
|
46471
|
-
}
|
|
46472
|
-
if (typeof node === "object") {
|
|
46473
|
-
const valueShapes = {};
|
|
46474
|
-
Object.keys(node).forEach(key => {
|
|
46475
|
-
valueShapes[key] = inferItemTreeShape(node[key]);
|
|
46476
|
-
});
|
|
46477
|
-
return shapes.shape(valueShapes);
|
|
46478
|
-
}
|
|
46479
|
-
throw new PerseusError(`unexpected multi-item node ${JSON.stringify(node)}`, Errors.InvalidInput);
|
|
46480
|
-
}
|
|
46481
|
-
|
|
46482
|
-
/**
|
|
46483
|
-
* Convert the given Item to an ItemTree, by unwrapping the `_multi` key.
|
|
46484
|
-
*/
|
|
46485
|
-
function itemToTree(item) {
|
|
46486
|
-
return item._multi;
|
|
46487
|
-
}
|
|
46488
|
-
|
|
46489
|
-
/**
|
|
46490
|
-
* Convert the given ItemTree to an Item, by wrapping it in the `_multi` key.
|
|
46491
|
-
*/
|
|
46492
|
-
function treeToItem(node) {
|
|
46493
|
-
return {
|
|
46494
|
-
_multi: node
|
|
46495
|
-
};
|
|
46496
|
-
}
|
|
46497
|
-
|
|
46498
|
-
var isObject$1 = function isObject(obj) {
|
|
46499
|
-
return obj === Object(obj);
|
|
46500
|
-
};
|
|
46501
|
-
var merge = function merge() {
|
|
46502
|
-
var obj = {};
|
|
46503
|
-
for (var i = 0; i < arguments.length; i++) {
|
|
46504
|
-
var source = arguments[i];
|
|
46505
|
-
if (source) {
|
|
46506
|
-
for (var prop in source) {
|
|
46507
|
-
obj[prop] = source[prop];
|
|
46508
|
-
}
|
|
46509
|
-
}
|
|
46510
|
-
}
|
|
46511
|
-
return obj;
|
|
46512
|
-
};
|
|
46513
|
-
var clone = function clone(obj) {
|
|
46514
|
-
if (!isObject$1(obj)) {
|
|
46515
|
-
return obj;
|
|
46516
|
-
}
|
|
46517
|
-
return Array.isArray(obj) ? obj.slice() : merge(obj);
|
|
46518
|
-
};
|
|
46519
|
-
|
|
46520
|
-
/* TODO batch *all* mutations
|
|
46521
|
-
* idea: freeze / thaw implementations for all types
|
|
46522
|
-
* lens constructor thaws, freeze delegates to type's freeze
|
|
46523
|
-
*/
|
|
46524
|
-
|
|
46525
|
-
// equivalents, without requiring it
|
|
46526
|
-
// find the implementation to use for a given object
|
|
46527
|
-
var dispatch = function dispatch(x) {
|
|
46528
|
-
if (Array.isArray(x)) {
|
|
46529
|
-
return arr;
|
|
46530
|
-
} else if (isObject$1(x)) {
|
|
46531
|
-
return obj;
|
|
46532
|
-
} else if (typeof x === "string") {
|
|
46533
|
-
return str;
|
|
46534
|
-
}
|
|
46535
|
-
};
|
|
46536
|
-
|
|
46537
|
-
// This is underscore with a different name
|
|
46538
|
-
var lens = function lens(obj) {
|
|
46539
|
-
if (obj instanceof lens) {
|
|
46540
|
-
return obj;
|
|
46541
|
-
}
|
|
46542
|
-
if (!(this instanceof lens)) {
|
|
46543
|
-
return new lens(obj);
|
|
46544
|
-
}
|
|
46545
|
-
var ops = dispatch(obj);
|
|
46546
|
-
this._wrapped = ops.thaw ? ops.thaw(obj) : obj;
|
|
46547
|
-
};
|
|
46548
|
-
lens.prototype.freeze = function () {
|
|
46549
|
-
var obj = this._wrapped;
|
|
46550
|
-
var ops = dispatch(obj);
|
|
46551
|
-
return ops.freeze ? ops.freeze(obj) : obj;
|
|
46552
|
-
};
|
|
46553
|
-
lens.prototype.zoom = function (lensArr) {
|
|
46554
|
-
if (this._zoomStack === undefined) {
|
|
46555
|
-
this._zoomStack = [];
|
|
46556
|
-
}
|
|
46557
|
-
this._zoomStack.push({
|
|
46558
|
-
zoom: lensArr,
|
|
46559
|
-
wrapped: this._wrapped
|
|
46560
|
-
});
|
|
46561
|
-
this._wrapped = lens(this._wrapped).get(lensArr);
|
|
46562
|
-
return this;
|
|
46563
|
-
};
|
|
46564
|
-
lens.prototype.deZoom = function () {
|
|
46565
|
-
var frame = this._zoomStack.pop();
|
|
46566
|
-
this._wrapped = lens(frame.wrapped).set(frame.zoom, this._wrapped).freeze();
|
|
46567
|
-
return this;
|
|
46568
|
-
};
|
|
46569
|
-
lens.prototype.get = function (lensArr) {
|
|
46570
|
-
var obj = this._wrapped;
|
|
46571
|
-
for (var i = 0; i < lensArr.length; i++) {
|
|
46572
|
-
obj = dispatch(obj).get(obj, lensArr[i]);
|
|
46573
|
-
}
|
|
46574
|
-
return obj;
|
|
46575
|
-
};
|
|
46576
|
-
lens.prototype.mod = function (lensArr, f) {
|
|
46577
|
-
var obj = this._wrapped;
|
|
46578
|
-
var newObj = clone(obj);
|
|
46579
|
-
var ops = dispatch(obj);
|
|
46580
|
-
if (lensArr.length === 0) {
|
|
46581
|
-
this._wrapped = f(this._wrapped);
|
|
46582
|
-
} else if (lensArr.length === 1) {
|
|
46583
|
-
this._wrapped = ops.mod(newObj, lensArr[0], f);
|
|
46584
|
-
} else {
|
|
46585
|
-
var monocle = lensArr[0];
|
|
46586
|
-
var shortLens = lensArr.slice(1);
|
|
46587
|
-
|
|
46588
|
-
// newObj = ops.mod(obj[monocle], shortLens, f);
|
|
46589
|
-
|
|
46590
|
-
newObj[monocle] = lens(obj[monocle]).mod(shortLens, f).freeze();
|
|
46591
|
-
this._wrapped = newObj;
|
|
46592
|
-
}
|
|
46593
|
-
return this;
|
|
46594
|
-
};
|
|
46595
|
-
|
|
46596
|
-
// TODO - move to individual files
|
|
46597
|
-
lens.prototype.merge = function (lensArr, props) {
|
|
46598
|
-
this._wrapped = lens(this._wrapped).mod(lensArr, function (oldProps) {
|
|
46599
|
-
return merge(oldProps, props);
|
|
46600
|
-
}).freeze();
|
|
46601
|
-
return this;
|
|
46602
|
-
};
|
|
46603
|
-
|
|
46604
|
-
// Lens must have length >= 1 or there would be nothing to return
|
|
46605
|
-
lens.prototype.del = function (lensArr) {
|
|
46606
|
-
var obj = this._wrapped;
|
|
46607
|
-
var ops = dispatch(obj);
|
|
46608
|
-
if (lensArr.length === 1) {
|
|
46609
|
-
this._wrapped = ops.del(obj, lensArr[0]);
|
|
46610
|
-
} else {
|
|
46611
|
-
var monocle = lensArr[0];
|
|
46612
|
-
var shortLens = lensArr.slice(1);
|
|
46613
|
-
var newObj = clone(obj);
|
|
46614
|
-
newObj[monocle] = lens(obj[monocle]).del(shortLens).freeze();
|
|
46615
|
-
this._wrapped = newObj;
|
|
46616
|
-
}
|
|
46617
|
-
return this;
|
|
46618
|
-
};
|
|
46619
|
-
lens.prototype.set = function (lensArr, set) {
|
|
46620
|
-
return this.mod(lensArr, function () {
|
|
46621
|
-
return set;
|
|
46622
|
-
});
|
|
46623
|
-
};
|
|
46624
|
-
|
|
46625
|
-
// ARRAY FUNCTIONS
|
|
46626
|
-
|
|
46627
|
-
const arr = {
|
|
46628
|
-
get: function (arr, monocle) {
|
|
46629
|
-
return arr[monocle];
|
|
46630
|
-
},
|
|
46631
|
-
set: function (arr, monocle, val) {
|
|
46632
|
-
var newArr = arr.splice();
|
|
46633
|
-
newArr[monocle] = val;
|
|
46634
|
-
return newArr;
|
|
46635
|
-
},
|
|
46636
|
-
mod: function (arr, monocle, f) {
|
|
46637
|
-
var newArr = arr.slice();
|
|
46638
|
-
newArr[monocle] = f(arr[monocle]);
|
|
46639
|
-
return newArr;
|
|
46640
|
-
},
|
|
46641
|
-
del: function (arr, monocle) {
|
|
46642
|
-
var newArr = arr.slice();
|
|
46643
|
-
newArr.splice(monocle, 1);
|
|
46644
|
-
return newArr;
|
|
46645
|
-
}
|
|
46646
|
-
};
|
|
46647
|
-
|
|
46648
|
-
/*
|
|
46649
|
-
// Lens must point to a member of an array. We'll insert into that array.
|
|
46650
|
-
lens.prototype.insertAt = function(lensArr, toInsert) {
|
|
46651
|
-
var obj = this._wrapped;
|
|
46652
|
-
|
|
46653
|
-
var arrLens = lensArr.slice(0, -1);
|
|
46654
|
-
var arr = lens(obj).get(arrLens).slice(); // slice to copy
|
|
46655
|
-
|
|
46656
|
-
var arrIdx = lensArr[lensArr.length-1];
|
|
46657
|
-
arr.splice(arrIdx, 0, toInsert);
|
|
46658
|
-
return lens(obj).set(arrLens, arr);
|
|
46659
|
-
};
|
|
46660
|
-
|
|
46661
|
-
lens.prototype.insertBefore = lens.prototype.insertAt;
|
|
46662
|
-
lens.prototype.insertAfter = function(lensArr, toInsert) {
|
|
46663
|
-
var newLens = lensArr.slice();
|
|
46664
|
-
newLens[newLens.length-1] += 1;
|
|
46665
|
-
return lens(this._wrapped).insertAt(newLens, toInsert);
|
|
46666
|
-
};
|
|
46667
|
-
*/
|
|
46668
|
-
|
|
46669
|
-
// OBJECT FUNCTIONS
|
|
46670
|
-
|
|
46671
|
-
const obj = {
|
|
46672
|
-
get: function (obj, monocle) {
|
|
46673
|
-
return obj[monocle];
|
|
46674
|
-
},
|
|
46675
|
-
set: function (obj, monocle, val) {
|
|
46676
|
-
var newObj = clone(obj);
|
|
46677
|
-
newObj[monocle] = val;
|
|
46678
|
-
return newObj;
|
|
46679
|
-
},
|
|
46680
|
-
mod: function (obj, monocle, f) {
|
|
46681
|
-
var newObj = clone(obj);
|
|
46682
|
-
newObj[monocle] = f(obj[monocle]);
|
|
46683
|
-
return newObj;
|
|
46684
|
-
},
|
|
46685
|
-
del: function (obj, monocle) {
|
|
46686
|
-
var newObj = clone(obj);
|
|
46687
|
-
delete newObj[monocle];
|
|
46688
|
-
return newObj;
|
|
46689
|
-
}
|
|
46690
|
-
};
|
|
46691
|
-
|
|
46692
|
-
// STRING FUNCTIONS
|
|
46693
|
-
|
|
46694
|
-
const str = {
|
|
46695
|
-
get: function (arr, monocle) {
|
|
46696
|
-
return arr[monocle];
|
|
46697
|
-
},
|
|
46698
|
-
set: function (arr, monocle, val) {
|
|
46699
|
-
var newArr = arr.splice();
|
|
46700
|
-
newArr[monocle] = val;
|
|
46701
|
-
return newArr;
|
|
46702
|
-
},
|
|
46703
|
-
mod: function (arr, monocle, f) {
|
|
46704
|
-
var newArr = arr.splice();
|
|
46705
|
-
newArr[monocle] = f(arr[monocle]);
|
|
46706
|
-
return newArr;
|
|
46707
|
-
},
|
|
46708
|
-
del: function (arr, monocle) {
|
|
46709
|
-
var newArr = arr.slice();
|
|
46710
|
-
newArr.splice(monocle);
|
|
46711
|
-
return newArr;
|
|
46712
|
-
}
|
|
46713
|
-
};
|
|
46714
|
-
|
|
46715
|
-
const _excluded$1 = ["item", "children", "shape", "serializedState", "onSerializedStateUpdated"];
|
|
46716
|
-
|
|
46717
|
-
// TODO(mdr)
|
|
46718
|
-
// TODO(mdr)
|
|
46719
|
-
// TODO(mdr)
|
|
46720
|
-
|
|
46721
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46722
|
-
|
|
46723
|
-
/**
|
|
46724
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
46725
|
-
* Some usage of this type somewhere is causing TypeScript to believe that these
|
|
46726
|
-
* elements should be components. Don't know where that is, to fix it up
|
|
46727
|
-
* properly. In reality, these types are just too hard to use and aren't
|
|
46728
|
-
* really helping us out as I now have to suppress this rather than
|
|
46729
|
-
* get value from the type. :(
|
|
46730
|
-
*/ // @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46731
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46732
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46733
|
-
class MultiRenderer extends React.Component {
|
|
46734
|
-
constructor(props) {
|
|
46735
|
-
super(props);
|
|
46736
|
-
this.rendererDataTreeMapper = void 0;
|
|
46737
|
-
this.getRenderersMapper = void 0;
|
|
46738
|
-
this._handleSerializedStateUpdated = (path, newState) => {
|
|
46739
|
-
const {
|
|
46740
|
-
onSerializedStateUpdated
|
|
46741
|
-
} = this.props;
|
|
46742
|
-
if (onSerializedStateUpdated) {
|
|
46743
|
-
const oldState = this._getSerializedState(this.props.serializedState);
|
|
46744
|
-
onSerializedStateUpdated(lens(oldState).set(path, newState).freeze());
|
|
46745
|
-
}
|
|
46746
|
-
};
|
|
46747
|
-
this.rendererDataTreeMapper = buildMapper()
|
|
46748
|
-
// @ts-expect-error - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'ContentNode'.
|
|
46749
|
-
.setContentMapper((c, _, p) => this._makeContentRendererData(c, p))
|
|
46750
|
-
// @ts-expect-error - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'HintNode'.
|
|
46751
|
-
.setHintMapper(h => this._makeHintRendererData(h)).setTagsMapper(t => null);
|
|
46752
|
-
|
|
46753
|
-
// @ts-expect-error - TS2322 - Type 'TreeMapperForLeavesAndCollections<unknown, any, unknown, any, unknown, unknown>' is not assignable to type 'TreeMapper<ContentRendererData, ContentRendererElement, HintRendererData, HintRendererElement, null, null>'.
|
|
46754
|
-
this.getRenderersMapper = buildMapper()
|
|
46755
|
-
// @ts-expect-error - TS2571 - Object is of type 'unknown'.
|
|
46756
|
-
.setContentMapper(c => c.makeRenderer())
|
|
46757
|
-
// @ts-expect-error - TS2571 - Object is of type 'unknown'.
|
|
46758
|
-
.setHintMapper(h => h.makeRenderer()).setArrayMapper((renderers, data, shape) => this._annotateRendererArray(renderers, data, shape));
|
|
46759
|
-
|
|
46760
|
-
// Keep state in sync with props.
|
|
46761
|
-
this.state = this._tryMakeRendererState(this.props);
|
|
46762
|
-
}
|
|
46763
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
46764
|
-
// Keep state in sync with props.
|
|
46765
|
-
if (nextProps.item !== this.props.item) {
|
|
46766
|
-
this.setState(this._tryMakeRendererState(nextProps));
|
|
46767
|
-
}
|
|
46768
|
-
}
|
|
46769
|
-
|
|
46770
|
-
/**
|
|
46771
|
-
* Attempt to build a State that includes a renderer tree corresponding to
|
|
46772
|
-
* the item provided in props. On error, return a state with `renderError`
|
|
46773
|
-
* set instead.
|
|
46774
|
-
*/
|
|
46775
|
-
_tryMakeRendererState(props) {
|
|
46776
|
-
try {
|
|
46777
|
-
return {
|
|
46778
|
-
rendererDataTree: this._makeRendererDataTree(props.item, props.shape),
|
|
46779
|
-
renderError: null
|
|
46780
|
-
};
|
|
46781
|
-
} catch (e) {
|
|
46782
|
-
Log.error("Error building tree state", Errors.Internal, {
|
|
46783
|
-
cause: e
|
|
46784
|
-
});
|
|
46785
|
-
return {
|
|
46786
|
-
rendererDataTree: null,
|
|
46787
|
-
renderError: e
|
|
46788
|
-
};
|
|
46789
|
-
}
|
|
46790
|
-
}
|
|
46791
|
-
/**
|
|
46792
|
-
* Props that aren't directly used by the MultiRenderer are delegated to
|
|
46793
|
-
* the underlying Renderers.
|
|
46794
|
-
*/
|
|
46795
|
-
_getRendererProps() {
|
|
46796
|
-
// `item`, `children`, and others are unused. I'm
|
|
46797
|
-
// explicitly pulling them out of `this.props` so I don't pass them to
|
|
46798
|
-
// `<Renderer>`. I'm not sure how else to do this.
|
|
46799
|
-
const _this$props = this.props,
|
|
46800
|
-
otherProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
|
|
46801
|
-
return _extends({}, otherProps, {
|
|
46802
|
-
strings: this.context.strings
|
|
46803
|
-
});
|
|
46804
|
-
}
|
|
46805
|
-
|
|
46806
|
-
/**
|
|
46807
|
-
* Construct a Renderer and a ref placeholder for the given ContentNode.
|
|
46808
|
-
*/
|
|
46809
|
-
_makeContentRendererData(content, path) {
|
|
46810
|
-
// NOTE(emily): The `findExternalWidgets` function here is computed
|
|
46811
|
-
// inline and thus changes each time we run this function. If it
|
|
46812
|
-
// were to change every render, it would cause the Renderer to
|
|
46813
|
-
// re-render a lot more than is necessary. Don't re-compute this
|
|
46814
|
-
// element unless it is necessary!
|
|
46815
|
-
// HACK(mdr): TypeScript can't prove that this is a ContentRendererData,
|
|
46816
|
-
// because of how we awkwardly construct it in order to obtain a
|
|
46817
|
-
// circular reference. But it is, I promise.
|
|
46818
|
-
const data = {
|
|
46819
|
-
ref: null,
|
|
46820
|
-
makeRenderer: null
|
|
46821
|
-
};
|
|
46822
|
-
const refFunc = e => data.ref = e;
|
|
46823
|
-
const findExternalWidgets = criterion => this._findWidgets(data, criterion);
|
|
46824
|
-
const handleSerializedState = state => this._handleSerializedStateUpdated(path, state);
|
|
46825
|
-
data.makeRenderer = () =>
|
|
46826
|
-
/*#__PURE__*/
|
|
46827
|
-
/**
|
|
46828
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
46829
|
-
* `content` contains props that Renderer doesn't have. However,
|
|
46830
|
-
* since the type for `content` is not exact, it's hard to know
|
|
46831
|
-
* if this spread is including undocumented props so mapping
|
|
46832
|
-
* one to one could introduce a bug. Need to work out the exact
|
|
46833
|
-
* type for ContentNode and then fix this.
|
|
46834
|
-
*/
|
|
46835
|
-
// @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">>'.
|
|
46836
|
-
React.createElement(Renderer, _extends({}, this._getRendererProps(), content, {
|
|
46837
|
-
ref: refFunc,
|
|
46838
|
-
findExternalWidgets: findExternalWidgets,
|
|
46839
|
-
serializedState: this.props.serializedState ? lens(this.props.serializedState).get(path) : null,
|
|
46840
|
-
onSerializedStateUpdated: handleSerializedState
|
|
46841
|
-
}));
|
|
46842
|
-
return data;
|
|
46843
|
-
}
|
|
46844
|
-
|
|
46845
|
-
/**
|
|
46846
|
-
* Construct a Renderer for the given HintNode, and keep track of the hint
|
|
46847
|
-
* itself for future use, too.
|
|
46848
|
-
*/
|
|
46849
|
-
_makeHintRendererData(hint) {
|
|
46850
|
-
// TODO(mdr): Once HintsRenderer supports inter-widget communication,
|
|
46851
|
-
// give it a ref. Until then, leave the ref null forever, to avoid
|
|
46852
|
-
// confusing the findWidgets functions.
|
|
46853
|
-
//
|
|
46854
|
-
// NOTE(davidflanagan): As a partial step toward inter-widget
|
|
46855
|
-
// communication we're going to pass a findExternalWidgets function
|
|
46856
|
-
// (using a dummy data object). This allows passage-ref widgets in
|
|
46857
|
-
// hints to use findWidget() to find the passage widgets they reference.
|
|
46858
|
-
// Note that this is one-way only, however. It does not allow
|
|
46859
|
-
// widgets in the question to find widgets in the hints, for example.
|
|
46860
|
-
const findExternalWidgets = criterion => this._findWidgets({}, criterion);
|
|
46861
|
-
return {
|
|
46862
|
-
hint,
|
|
46863
|
-
findExternalWidgets,
|
|
46864
|
-
// _annotateRendererArray() needs this
|
|
46865
|
-
ref: null,
|
|
46866
|
-
makeRenderer: () => /*#__PURE__*/React.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
46867
|
-
findExternalWidgets: findExternalWidgets
|
|
46868
|
-
// Note(Jeremy): The MultiRenderer codebase types are
|
|
46869
|
-
// slightly different from the rest of the codebase.
|
|
46870
|
-
// Ideally `HintNode` would spread the `Hint` type into it,
|
|
46871
|
-
// but there is a difference in optionality of `widgets`
|
|
46872
|
-
// and `images` and that causes a huge cascade of type
|
|
46873
|
-
// errors (they are truly optional, but most of our code
|
|
46874
|
-
// assumes they're provided/set). Ignoring this for now.
|
|
46875
|
-
// @ts-expect-error - TS2769 - Type 'HintNode' is not assignable to type 'Hint'.
|
|
46876
|
-
,
|
|
46877
|
-
hints: [hint]
|
|
46878
|
-
}))
|
|
46879
|
-
};
|
|
46880
|
-
}
|
|
46881
|
-
|
|
46882
|
-
/**
|
|
46883
|
-
* Construct a tree of interconnected RendererDatas, corresponding to the
|
|
46884
|
-
* given item. Called in `_tryMakeRendererState`, in order to store this
|
|
46885
|
-
* tree in the component state.
|
|
46886
|
-
*/
|
|
46887
|
-
_makeRendererDataTree(item, shape) {
|
|
46888
|
-
const itemTree = itemToTree(item);
|
|
46889
|
-
return this.rendererDataTreeMapper.mapTree(itemTree, shape);
|
|
46890
|
-
}
|
|
46891
|
-
|
|
46892
|
-
/**
|
|
46893
|
-
* Return all widgets that meet the given criterion, from all Renderers
|
|
46894
|
-
* except the Renderer that triggered this call.
|
|
46895
|
-
*
|
|
46896
|
-
* This function is provided to each Renderer's `findExternalWidgets` prop,
|
|
46897
|
-
* which enables widgets in different Renderers to discover each other and
|
|
46898
|
-
* communicate.
|
|
46899
|
-
*/
|
|
46900
|
-
_findWidgets(callingData, filterCriterion) {
|
|
46901
|
-
const results = [];
|
|
46902
|
-
this._mapRenderers(data => {
|
|
46903
|
-
if (callingData !== data && data.ref) {
|
|
46904
|
-
results.push(...data.ref.findInternalWidgets(filterCriterion));
|
|
46905
|
-
}
|
|
46906
|
-
});
|
|
46907
|
-
return results;
|
|
46908
|
-
}
|
|
46909
|
-
|
|
46910
|
-
/**
|
|
46911
|
-
* Copy the renderer tree, apply the given transformation to the leaf nodes
|
|
46912
|
-
* and the optional given transformation to the array nodes, and return the
|
|
46913
|
-
* result.
|
|
46914
|
-
*
|
|
46915
|
-
* Used to provide structured data to the call site (the Renderer tree on
|
|
46916
|
-
* `render`, the Score tree on `getScores`, etc.), and to traverse the
|
|
46917
|
-
* renderer tree even when we disregard the output (like in
|
|
46918
|
-
* `_findWidgets`).
|
|
46919
|
-
*/
|
|
46920
|
-
_mapRenderers(
|
|
46921
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
46922
|
-
leafMapper
|
|
46923
|
-
// @ts-expect-error - TS2315 - Type 'Tree' is not generic.
|
|
46924
|
-
) {
|
|
46925
|
-
const {
|
|
46926
|
-
rendererDataTree
|
|
46927
|
-
} = this.state;
|
|
46928
|
-
if (!rendererDataTree) {
|
|
46929
|
-
return null;
|
|
46930
|
-
}
|
|
46931
|
-
const mapper = buildMapper().setContentMapper(leafMapper).setHintMapper(leafMapper);
|
|
46932
|
-
return mapper.mapTree(rendererDataTree, this.props.shape);
|
|
46933
|
-
}
|
|
46934
|
-
_scoreFromRef(ref) {
|
|
46935
|
-
if (!ref) {
|
|
46936
|
-
return null;
|
|
46937
|
-
}
|
|
46938
|
-
const [guess, score] = ref.guessAndScore();
|
|
46939
|
-
let state;
|
|
46940
|
-
if (ref.getSerializedState) {
|
|
46941
|
-
state = ref.getSerializedState();
|
|
46942
|
-
}
|
|
46943
|
-
return keScoreFromPerseusScore(score, guess, state);
|
|
46944
|
-
}
|
|
46945
|
-
|
|
46946
|
-
/**
|
|
46947
|
-
* Return a tree in the shape of the multi-item, with scores at each of
|
|
46948
|
-
* the content nodes and `null` at the other leaf nodes.
|
|
46949
|
-
*/
|
|
46950
|
-
getScores() {
|
|
46951
|
-
return this._mapRenderers(data => this._scoreFromRef(data.ref));
|
|
46952
|
-
}
|
|
46953
|
-
|
|
46954
|
-
/**
|
|
46955
|
-
* Return a single composite score for all rendered content nodes.
|
|
46956
|
-
* The `guess` is a tree in the shape of the multi-item, with an individual
|
|
46957
|
-
* guess at each content node and `null` at the other leaf nodes.
|
|
46958
|
-
*/
|
|
46959
|
-
score() {
|
|
46960
|
-
const scores = [];
|
|
46961
|
-
const state = [];
|
|
46962
|
-
const guess = this._mapRenderers(data => {
|
|
46963
|
-
var _data$ref;
|
|
46964
|
-
if (!data.ref) {
|
|
46965
|
-
return null;
|
|
46966
|
-
}
|
|
46967
|
-
if (data.ref.getSerializedState) {
|
|
46968
|
-
state.push(data.ref.getSerializedState());
|
|
46969
|
-
}
|
|
46970
|
-
scores.push(data.ref.score());
|
|
46971
|
-
return (_data$ref = data.ref) == null ? void 0 : _data$ref.getUserInput();
|
|
46972
|
-
});
|
|
46973
|
-
const combinedScore = scores.reduce(combineScores);
|
|
46974
|
-
return keScoreFromPerseusScore(combinedScore, guess, state);
|
|
46975
|
-
}
|
|
46976
|
-
|
|
46977
|
-
/**
|
|
46978
|
-
* Return a tree in the shape of the multi-item, with serialized state at
|
|
46979
|
-
* each of the content nodes and `null` at the other leaf nodes.
|
|
46980
|
-
*
|
|
46981
|
-
* If the lastSerializedState argument is supplied, this function will fill
|
|
46982
|
-
* in the state of not-currently-rendered content and hint nodes with the
|
|
46983
|
-
* values from the previous serialized state. If no lastSerializedState is
|
|
46984
|
-
* supplied, `null` will be returned for not-currently-rendered content and
|
|
46985
|
-
* hint nodes.
|
|
46986
|
-
*/
|
|
46987
|
-
_getSerializedState(lastSerializedState) {
|
|
46988
|
-
return this._mapRenderers((data, _, path) => {
|
|
46989
|
-
if (data.ref) {
|
|
46990
|
-
return data.ref.getSerializedState();
|
|
46991
|
-
}
|
|
46992
|
-
if (lastSerializedState) {
|
|
46993
|
-
return lens(lastSerializedState).get(path);
|
|
46994
|
-
}
|
|
46995
|
-
return null;
|
|
46996
|
-
});
|
|
46997
|
-
}
|
|
46998
|
-
|
|
46999
|
-
/**
|
|
47000
|
-
* Given a tree in the shape of the multi-item, with serialized state at
|
|
47001
|
-
* each of the content nodes, restore each state to the corresponding
|
|
47002
|
-
* renderer if currently mounted.
|
|
47003
|
-
*/
|
|
47004
|
-
restoreSerializedState(serializedState, callback) {
|
|
47005
|
-
// We want to call our async callback only once all of the childrens'
|
|
47006
|
-
// callbacks have run. We add one to this counter before we call out to
|
|
47007
|
-
// each renderer and decrement it when it runs our callback.
|
|
47008
|
-
let numCallbacks = 0;
|
|
47009
|
-
const countCallback = () => {
|
|
47010
|
-
numCallbacks--;
|
|
47011
|
-
if (callback && numCallbacks === 0) {
|
|
47012
|
-
callback();
|
|
47013
|
-
}
|
|
47014
|
-
};
|
|
47015
|
-
this._mapRenderers((data, _, path) => {
|
|
47016
|
-
var _data$ref2;
|
|
47017
|
-
if (!data.ref) {
|
|
47018
|
-
return;
|
|
47019
|
-
}
|
|
47020
|
-
const state = lens(serializedState).get(path);
|
|
47021
|
-
if (!state) {
|
|
47022
|
-
return;
|
|
47023
|
-
}
|
|
47024
|
-
numCallbacks++;
|
|
47025
|
-
(_data$ref2 = data.ref) == null || _data$ref2.restoreSerializedState(state, countCallback);
|
|
47026
|
-
});
|
|
47027
|
-
}
|
|
47028
|
-
|
|
47029
|
-
/**
|
|
47030
|
-
* Given an array of renderers, if it happens to be an array of *hint*
|
|
47031
|
-
* renderers, then attach a `firstN` method to the array, which allows the
|
|
47032
|
-
* layout to render the hints together in one HintsRenderer.
|
|
47033
|
-
*/
|
|
47034
|
-
_annotateRendererArray(renderers, rendererDatas, shape) {
|
|
47035
|
-
if (shape.elementShape.type === "hint") {
|
|
47036
|
-
// The shape says that these are HintRendererDatas, even though
|
|
47037
|
-
// it's not provable at compile time, so perform a cast.
|
|
47038
|
-
const hintRendererDatas = rendererDatas;
|
|
47039
|
-
renderers = [...renderers];
|
|
47040
|
-
renderers.firstN = n => /*#__PURE__*/React.createElement(HintsRenderer, _extends({}, this._getRendererProps(), {
|
|
47041
|
-
findExternalWidgets: hintRendererDatas[0] ? hintRendererDatas[0].findExternalWidgets : undefined,
|
|
47042
|
-
hints: hintRendererDatas.map(d => d.hint),
|
|
47043
|
-
hintsVisible: n
|
|
47044
|
-
}));
|
|
47045
|
-
}
|
|
47046
|
-
return renderers;
|
|
47047
|
-
}
|
|
47048
|
-
|
|
47049
|
-
/**
|
|
47050
|
-
* Return a tree in the shape of the multi-item, with a Renderer at each
|
|
47051
|
-
* content node and a HintRenderer at each hint node.
|
|
47052
|
-
*
|
|
47053
|
-
* This is generated by running each of the `makeRenderer` functions at the
|
|
47054
|
-
* leaf nodes.
|
|
47055
|
-
*/
|
|
47056
|
-
_getRenderers() {
|
|
47057
|
-
return this.getRenderersMapper.mapTree(this.state.rendererDataTree, this.props.shape);
|
|
47058
|
-
}
|
|
47059
|
-
render() {
|
|
47060
|
-
if (this.state.renderError) {
|
|
47061
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
47062
|
-
className: css(styles.error)
|
|
47063
|
-
}, this.context.strings.errorRendering({
|
|
47064
|
-
error: String(this.state.renderError)
|
|
47065
|
-
}));
|
|
47066
|
-
}
|
|
47067
|
-
|
|
47068
|
-
// Pass the renderer tree to the `children` function, which will
|
|
47069
|
-
// determine the actual content of this component.
|
|
47070
|
-
return /*#__PURE__*/React.createElement(DependenciesContext.Provider, {
|
|
47071
|
-
value: this.props.dependencies
|
|
47072
|
-
}, this.props.children({
|
|
47073
|
-
renderers: this._getRenderers()
|
|
47074
|
-
}));
|
|
47075
|
-
}
|
|
47076
|
-
}
|
|
47077
|
-
MultiRenderer.contextType = PerseusI18nContext;
|
|
47078
|
-
const styles = StyleSheet.create({
|
|
47079
|
-
error: {
|
|
47080
|
-
color: "red"
|
|
47081
|
-
}
|
|
47082
|
-
});
|
|
47083
|
-
|
|
47084
|
-
/**
|
|
47085
|
-
* Utility functions to build React PropTypes for multi-items and shapes.
|
|
47086
|
-
*
|
|
47087
|
-
* If you're writing new components, though, consider using the Item and Shape
|
|
47088
|
-
* types instead.
|
|
47089
|
-
*/
|
|
47090
|
-
/**
|
|
47091
|
-
* Return a PropType that accepts Items of the given shape, and rejects other
|
|
47092
|
-
* objects.
|
|
47093
|
-
*
|
|
47094
|
-
* Usage: `propTypes: {item: buildPropTypeForShape(myShape)}`
|
|
47095
|
-
*/
|
|
47096
|
-
function buildPropTypeForShape(shape) {
|
|
47097
|
-
return PropTypes.oneOfType([PropTypes.shape({
|
|
47098
|
-
_multi: buildTreePropTypeForShape(shape)
|
|
47099
|
-
}), PropTypes.oneOf([null, undefined])]);
|
|
47100
|
-
}
|
|
47101
|
-
|
|
47102
|
-
/**
|
|
47103
|
-
* Return a PropType that accepts ItemTrees of the given shape, and rejects
|
|
47104
|
-
* other objects.
|
|
47105
|
-
*/
|
|
47106
|
-
function buildTreePropTypeForShape(shape) {
|
|
47107
|
-
if (shape.type === "content") {
|
|
47108
|
-
return PropTypes.shape({
|
|
47109
|
-
// TODO(mdr): Remove #LegacyContentNode support.
|
|
47110
|
-
__type: PropTypes.oneOf(["content", "item"]).isRequired,
|
|
47111
|
-
content: PropTypes.string,
|
|
47112
|
-
images: PropTypes.objectOf(PropTypes.any),
|
|
47113
|
-
widgets: PropTypes.objectOf(PropTypes.any)
|
|
47114
|
-
});
|
|
47115
|
-
}
|
|
47116
|
-
if (shape.type === "hint") {
|
|
47117
|
-
return PropTypes.shape({
|
|
47118
|
-
__type: PropTypes.oneOf(["hint"]).isRequired,
|
|
47119
|
-
content: PropTypes.string,
|
|
47120
|
-
images: PropTypes.objectOf(PropTypes.any),
|
|
47121
|
-
widgets: PropTypes.objectOf(PropTypes.any),
|
|
47122
|
-
replace: PropTypes.bool
|
|
47123
|
-
});
|
|
47124
|
-
}
|
|
47125
|
-
if (shape.type === "tags") {
|
|
47126
|
-
return PropTypes.arrayOf(PropTypes.string.isRequired);
|
|
47127
|
-
}
|
|
47128
|
-
if (shape.type === "array") {
|
|
47129
|
-
const elementPropType = buildTreePropTypeForShape(shape.elementShape);
|
|
47130
|
-
return PropTypes.arrayOf(elementPropType.isRequired);
|
|
47131
|
-
}
|
|
47132
|
-
if (shape.type === "object") {
|
|
47133
|
-
const valueShapes = shape.shape;
|
|
47134
|
-
const propTypeShape = {};
|
|
47135
|
-
Object.keys(valueShapes).forEach(key => {
|
|
47136
|
-
propTypeShape[key] = buildTreePropTypeForShape(valueShapes[key]).isRequired;
|
|
47137
|
-
});
|
|
47138
|
-
return PropTypes.shape(propTypeShape);
|
|
47139
|
-
}
|
|
47140
|
-
throw new PerseusError(
|
|
47141
|
-
// @ts-expect-error - TS2339 - Property 'type' does not exist on type 'never'.
|
|
47142
|
-
`unexpected shape type ${shape.type}`, Errors.InvalidInput);
|
|
47143
|
-
}
|
|
47144
|
-
|
|
47145
|
-
/**
|
|
47146
|
-
* This library provides support for Perseus multi-items: structured Perseus
|
|
47147
|
-
* content that content creators can easily create, and that applications can
|
|
47148
|
-
* easily render into different parts of the layout.
|
|
47149
|
-
*
|
|
47150
|
-
* For more details about application and motivation, see:
|
|
47151
|
-
* https://sites.google.com/a/khanacademy.org/forge/for-developers/perseus-items-and-multi-items
|
|
47152
|
-
*
|
|
47153
|
-
* This file primarily exposes the `MultiRenderer` component, which performs
|
|
47154
|
-
* multi-rendering. To multi-render a question, pass in the content of the item
|
|
47155
|
-
* to the `MultiRenderer` component as a props. Then, pass in a function which
|
|
47156
|
-
* takes an object of renderers (in the same structure as the content), and
|
|
47157
|
-
* return a render tree. The `MultiRenderer` component will allow you to
|
|
47158
|
-
* combine scores, serialized state, etc. without having to manually call on
|
|
47159
|
-
* each of the functions. It also handles inter-widgets requests between the
|
|
47160
|
-
* different renderers.
|
|
47161
|
-
* For more details, see `multi-items/multi-renderer.jsx`.
|
|
47162
|
-
*
|
|
47163
|
-
* Example:
|
|
47164
|
-
*
|
|
47165
|
-
* item = {_multi: {
|
|
47166
|
-
* left: <content data>,
|
|
47167
|
-
* right: [<content data>, <content data>],
|
|
47168
|
-
* }}
|
|
47169
|
-
* shape = shapes.shape({
|
|
47170
|
-
* left: shapes.content,
|
|
47171
|
-
* right: shapes.arrayOf(shapes.content),
|
|
47172
|
-
* })
|
|
47173
|
-
*
|
|
47174
|
-
* <MultiRenderer item={item} shape={shape}>
|
|
47175
|
-
* {({renderers}) =>
|
|
47176
|
-
* <div>
|
|
47177
|
-
* <div id="left">{renderers.left}</div>
|
|
47178
|
-
* <ul id="right">
|
|
47179
|
-
* {renderers.right.map(r => <li>{r}</li>)}
|
|
47180
|
-
* </ul>
|
|
47181
|
-
* </div>
|
|
47182
|
-
* }
|
|
47183
|
-
* </MultiRenderer>
|
|
47184
|
-
*
|
|
47185
|
-
* This file also exposes `shapes`, which helps you construct a runtime type
|
|
47186
|
-
* declaration for your particular class of multi-item. This can then be used
|
|
47187
|
-
* to create a MultirendererEditor for your multi-item shape, and to validate
|
|
47188
|
-
* that a multi-item conforms to the shape via `buildPropTypeForShape`.
|
|
47189
|
-
* For more details, see `multi-items/shapes.js`.
|
|
47190
|
-
*
|
|
47191
|
-
* This file also exposes some utility functions for working with generic
|
|
47192
|
-
* multi-items, like `findContentNodesInItem`, `findHintNodesInItem`,
|
|
47193
|
-
* `inferItemShape`, and `buildEmptyItemForShape`.
|
|
47194
|
-
* For more details, see `multi-items/items.js`.
|
|
47195
|
-
*/
|
|
47196
|
-
var MultiItems = {
|
|
47197
|
-
// Tools for rendering your multi-items
|
|
47198
|
-
MultiRenderer,
|
|
47199
|
-
// Tools for declaring your multi-item shapes
|
|
47200
|
-
shapes,
|
|
47201
|
-
buildPropTypeForShape,
|
|
47202
|
-
// Tools for generically manipulating multi-items
|
|
47203
|
-
buildEmptyItemForShape,
|
|
47204
|
-
findContentNodesInItem: findContentNodesInItem$2,
|
|
47205
|
-
findHintNodesInItem,
|
|
47206
|
-
inferItemShape: inferItemShape$2
|
|
47207
|
-
};
|
|
47208
|
-
|
|
47209
46061
|
/**
|
|
47210
46062
|
* Calculates whether a perseus item is renderable by a specific
|
|
47211
46063
|
* perseus-item-data version.
|
|
@@ -47215,10 +46067,6 @@ var MultiItems = {
|
|
|
47215
46067
|
* This supports widgets that contain renderers, such as the
|
|
47216
46068
|
* group or sequence widgets.
|
|
47217
46069
|
*/
|
|
47218
|
-
const {
|
|
47219
|
-
findContentNodesInItem: findContentNodesInItem$1,
|
|
47220
|
-
inferItemShape: inferItemShape$1
|
|
47221
|
-
} = MultiItems;
|
|
47222
46070
|
const isUpgradedWidgetInfoRenderableBy = function isUpgradedWidgetInfoRenderableBy(widgetInfo, widgetRendererVersion) {
|
|
47223
46071
|
if (widgetRendererVersion == null) {
|
|
47224
46072
|
// If the widget does not exist in this version, this will
|
|
@@ -47264,17 +46112,6 @@ const isItemRenderableByVersion = function isItemRenderableByVersion(itemData, r
|
|
|
47264
46112
|
if (itemData == null || rendererContentVersion == null) {
|
|
47265
46113
|
throw new PerseusError("missing parameter to Perseus.isRenderable.item", Errors.InvalidInput);
|
|
47266
46114
|
}
|
|
47267
|
-
if (itemData._multi) {
|
|
47268
|
-
const shape = inferItemShape$1(itemData);
|
|
47269
|
-
let isRenderable = true;
|
|
47270
|
-
findContentNodesInItem$1(itemData, shape, node => {
|
|
47271
|
-
const nodeIsRenderable = isRendererContentRenderableBy(node, rendererContentVersion);
|
|
47272
|
-
if (!nodeIsRenderable) {
|
|
47273
|
-
isRenderable = false;
|
|
47274
|
-
}
|
|
47275
|
-
});
|
|
47276
|
-
return isRenderable;
|
|
47277
|
-
}
|
|
47278
46115
|
return isRendererContentRenderableBy(itemData.question, rendererContentVersion);
|
|
47279
46116
|
};
|
|
47280
46117
|
|
|
@@ -47282,10 +46119,6 @@ const isItemRenderableByVersion = function isItemRenderableByVersion(itemData, r
|
|
|
47282
46119
|
* Identifies whether or not a given perseus item requires the use of a mouse
|
|
47283
46120
|
* or screen, based on the widgets it contains.
|
|
47284
46121
|
*/
|
|
47285
|
-
const {
|
|
47286
|
-
findContentNodesInItem,
|
|
47287
|
-
inferItemShape
|
|
47288
|
-
} = MultiItems;
|
|
47289
46122
|
|
|
47290
46123
|
// Iterate over a single Perseus renderer, mutating `widgets` by appending
|
|
47291
46124
|
// violating widget types discovered in this item.
|
|
@@ -47306,12 +46139,7 @@ function traverseRenderer(itemData, widgets) {
|
|
|
47306
46139
|
function violatingWidgets(itemData) {
|
|
47307
46140
|
// TODO(jordan): Hints as well
|
|
47308
46141
|
const widgets = [];
|
|
47309
|
-
|
|
47310
|
-
const shape = inferItemShape(itemData);
|
|
47311
|
-
findContentNodesInItem(itemData, shape, content => traverseRenderer(content, widgets));
|
|
47312
|
-
} else {
|
|
47313
|
-
traverseRenderer(itemData.question, widgets);
|
|
47314
|
-
}
|
|
46142
|
+
traverseRenderer(itemData.question, widgets);
|
|
47315
46143
|
|
|
47316
46144
|
// Uniquify the list of widgets (by type)
|
|
47317
46145
|
return _.uniq(widgets);
|
|
@@ -49818,5 +48646,9 @@ const ScoringUtil = {
|
|
|
49818
48646
|
keScoreFromPerseusScore
|
|
49819
48647
|
};
|
|
49820
48648
|
|
|
49821
|
-
|
|
48649
|
+
/**
|
|
48650
|
+
* Types
|
|
48651
|
+
*/
|
|
48652
|
+
|
|
48653
|
+
export { ApiOptions, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, dependencies as Dependencies, EditorJsonify, Expression, GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ScoringUtil, ref as ServerItemRenderer, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, widgets$1 as Widgets, addWidget, apiVersion, bodyXsmallBold, components, containerSizeClass, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAngleCoords, getAnswerFromUserInput, getAnswersFromWidgets, getCircleCoords, getClockwiseAngle, getCorrectAnswerForWidgetId, getImagesWithoutAltData, getInteractiveBoxFromSizeClass, getLineCoords, getLinearSystemCoords, getPointCoords, getPolygonCoords, getQuadraticCoords, getSegmentCoords, getSinusoidCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, iconChevronDown, iconTrash, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, makeSafeUrl, mathOnlyParser, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, scorePerseusItem, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
49822
48654
|
//# sourceMappingURL=index.js.map
|