@khanacademy/perseus 46.0.1 → 47.0.1
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.js +233 -1370
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +3 -13
- package/dist/index.js +218 -1364
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +33 -15
- 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,
|
|
@@ -27352,7 +27350,7 @@ class Dropdown extends React.Component {
|
|
|
27352
27350
|
key: "placeholder",
|
|
27353
27351
|
value: "0",
|
|
27354
27352
|
disabled: true,
|
|
27355
|
-
label: this.props.placeholder
|
|
27353
|
+
label: this.props.placeholder || " "
|
|
27356
27354
|
}), ...this.props.choices.map((choice, i) => /*#__PURE__*/React.createElement(OptionItem, {
|
|
27357
27355
|
key: String(i + 1),
|
|
27358
27356
|
value: String(i + 1),
|
|
@@ -27373,15 +27371,14 @@ class Dropdown extends React.Component {
|
|
|
27373
27371
|
}
|
|
27374
27372
|
}, this.props.visibleLabel && /*#__PURE__*/React.createElement(LabelLarge, {
|
|
27375
27373
|
tag: "label",
|
|
27376
|
-
|
|
27374
|
+
htmlFor: ids.get("dropdown")
|
|
27377
27375
|
}, this.props.visibleLabel), /*#__PURE__*/React.createElement(SingleSelect, {
|
|
27378
27376
|
id: ids.get("dropdown"),
|
|
27379
27377
|
placeholder: "",
|
|
27380
27378
|
onChange: value => this._handleChange(parseInt(value)),
|
|
27381
27379
|
selectedValue: String(this.props.selected),
|
|
27382
27380
|
disabled: this.props.apiOptions.readOnly,
|
|
27383
|
-
"aria-label": this.props.ariaLabel || this.context.strings.selectAnAnswer
|
|
27384
|
-
"aria-labelledby": ids.get("dropdown-label")
|
|
27381
|
+
"aria-label": this.props.ariaLabel || this.props.visibleLabel || this.context.strings.selectAnAnswer
|
|
27385
27382
|
// This is currently necessary for SRs to read the labels properly.
|
|
27386
27383
|
// However, WB is working on a change to add the "combobox" role to
|
|
27387
27384
|
// all dropdowns.
|
|
@@ -27490,7 +27487,7 @@ class Explanation extends React.Component {
|
|
|
27490
27487
|
marginRight: "-6px",
|
|
27491
27488
|
"white-space": "normal"
|
|
27492
27489
|
};
|
|
27493
|
-
const contentStyling = [styles$
|
|
27490
|
+
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
27491
|
return /*#__PURE__*/React.createElement(UniqueIDProvider, {
|
|
27495
27492
|
mockOnFirstRender: true,
|
|
27496
27493
|
scope: "explanation-widget"
|
|
@@ -27509,7 +27506,7 @@ class Explanation extends React.Component {
|
|
|
27509
27506
|
"aria-hidden": !this.state.expanded,
|
|
27510
27507
|
testId: "content-container"
|
|
27511
27508
|
}, /*#__PURE__*/React.createElement(View, {
|
|
27512
|
-
style: styles$
|
|
27509
|
+
style: styles$k.contentWrapper
|
|
27513
27510
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
27514
27511
|
apiOptions: this.props.apiOptions,
|
|
27515
27512
|
content: this.props.explanation,
|
|
@@ -27530,7 +27527,7 @@ Explanation.defaultProps = {
|
|
|
27530
27527
|
const leftBorderSpacing = 23;
|
|
27531
27528
|
const verticalContentPadding = 10;
|
|
27532
27529
|
const arrowHeight = 14;
|
|
27533
|
-
const styles$
|
|
27530
|
+
const styles$k = StyleSheet.create({
|
|
27534
27531
|
content: {
|
|
27535
27532
|
borderLeft: "0px solid #ccc",
|
|
27536
27533
|
display: "inline-grid",
|
|
@@ -27613,15 +27610,15 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
27613
27610
|
correctExcited,
|
|
27614
27611
|
nextQuestion
|
|
27615
27612
|
} = this.context.strings;
|
|
27616
|
-
const answerBarStyle = _extends({}, styles$
|
|
27613
|
+
const answerBarStyle = _extends({}, styles$j.answerBar, {
|
|
27617
27614
|
backgroundColor: answerBarState === "CORRECT" ? color.offWhite : "white",
|
|
27618
27615
|
// Center the "Correct!" message only when there's no next question
|
|
27619
27616
|
justifyContent: answerBarState === "CORRECT" && !onNextQuestion ? "center" : "space-between"
|
|
27620
27617
|
});
|
|
27621
27618
|
const message = answerBarState === "INCORRECT" ? /*#__PURE__*/React.createElement("span", {
|
|
27622
|
-
style: styles$
|
|
27619
|
+
style: styles$j.text
|
|
27623
27620
|
}, /*#__PURE__*/React.createElement("span", {
|
|
27624
|
-
style: styles$
|
|
27621
|
+
style: styles$j.tryAgainIcon
|
|
27625
27622
|
}, /*#__PURE__*/React.createElement(InlineIcon, iconTryAgain)), /*#__PURE__*/React.createElement("span", {
|
|
27626
27623
|
style: {
|
|
27627
27624
|
marginLeft: 8
|
|
@@ -27640,7 +27637,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
27640
27637
|
return /*#__PURE__*/React.createElement("div", {
|
|
27641
27638
|
style: answerBarStyle
|
|
27642
27639
|
}, /*#__PURE__*/React.createElement("span", {
|
|
27643
|
-
style: styles$
|
|
27640
|
+
style: styles$j.text
|
|
27644
27641
|
}, /*#__PURE__*/React.createElement("span", {
|
|
27645
27642
|
style: {
|
|
27646
27643
|
fontSize: 28,
|
|
@@ -27663,7 +27660,7 @@ class GradedGroupAnswerBar extends React.Component {
|
|
|
27663
27660
|
}
|
|
27664
27661
|
GradedGroupAnswerBar.contextType = PerseusI18nContext;
|
|
27665
27662
|
const fontSize = 17;
|
|
27666
|
-
const styles$
|
|
27663
|
+
const styles$j = {
|
|
27667
27664
|
answerBar: {
|
|
27668
27665
|
display: "flex",
|
|
27669
27666
|
alignItems: "center",
|
|
@@ -27848,7 +27845,7 @@ class GradedGroup extends React.Component {
|
|
|
27848
27845
|
}));
|
|
27849
27846
|
gradeStatus = this.context.strings.incorrect;
|
|
27850
27847
|
}
|
|
27851
|
-
const mobileClass = this.props.inGradedGroupSet ? css(styles$
|
|
27848
|
+
const mobileClass = this.props.inGradedGroupSet ? css(styles$i.gradedGroupInSet) : css(styles$i.gradedGroup);
|
|
27852
27849
|
const classes = classNames$1({
|
|
27853
27850
|
[mobileClass]: apiOptions.isMobile,
|
|
27854
27851
|
"perseus-graded-group": true,
|
|
@@ -27867,7 +27864,7 @@ class GradedGroup extends React.Component {
|
|
|
27867
27864
|
return /*#__PURE__*/React.createElement("div", {
|
|
27868
27865
|
className: classes
|
|
27869
27866
|
}, !!this.props.title && /*#__PURE__*/React.createElement("div", {
|
|
27870
|
-
className: css(styles$
|
|
27867
|
+
className: css(styles$i.title)
|
|
27871
27868
|
}, this.props.title), /*#__PURE__*/React.createElement(Renderer, _extends({}, this.props, {
|
|
27872
27869
|
ref: this.rendererRef,
|
|
27873
27870
|
apiOptions: _extends({}, apiOptions, {
|
|
@@ -27899,7 +27896,7 @@ class GradedGroup extends React.Component {
|
|
|
27899
27896
|
}, this.context.strings.nextQuestion), this.props.hint && this.props.hint.content && (this.state.showHint ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
|
27900
27897
|
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'number | undefined'.
|
|
27901
27898
|
tabIndex: "0",
|
|
27902
|
-
className: css(styles$
|
|
27899
|
+
className: css(styles$i.explanationTitle),
|
|
27903
27900
|
onClick: () => this.setState({
|
|
27904
27901
|
showHint: false
|
|
27905
27902
|
}),
|
|
@@ -27931,7 +27928,7 @@ class GradedGroup extends React.Component {
|
|
|
27931
27928
|
showHint: true
|
|
27932
27929
|
});
|
|
27933
27930
|
},
|
|
27934
|
-
className: css(styles$
|
|
27931
|
+
className: css(styles$i.showHintLink)
|
|
27935
27932
|
}, this.context.strings.explain)), apiOptions.isMobile && answerBarState !== "HIDDEN" && /*#__PURE__*/React.createElement(GradedGroupAnswerBar, {
|
|
27936
27933
|
apiOptions: apiOptions,
|
|
27937
27934
|
answerBarState: answerBarState,
|
|
@@ -27953,7 +27950,7 @@ GradedGroup.defaultProps = {
|
|
|
27953
27950
|
const traverseChildWidgets$2 = function traverseChildWidgets(props, traverseRenderer) {
|
|
27954
27951
|
return _.extend({}, props, traverseRenderer(props));
|
|
27955
27952
|
};
|
|
27956
|
-
const styles$
|
|
27953
|
+
const styles$i = StyleSheet.create({
|
|
27957
27954
|
gradedGroupInSet: {
|
|
27958
27955
|
// Reset a few desktop-only styles that come from graded-group.less
|
|
27959
27956
|
marginLeft: 0,
|
|
@@ -28036,18 +28033,18 @@ class Indicators extends React.Component {
|
|
|
28036
28033
|
return /*#__PURE__*/React.createElement("ul", {
|
|
28037
28034
|
// reduntantly add class name for use in .less files--
|
|
28038
28035
|
// the styles object key gets hashed
|
|
28039
|
-
className: classNames$1(css(styles$
|
|
28036
|
+
className: classNames$1(css(styles$h.indicatorContainer), "indicatorContainer")
|
|
28040
28037
|
}, this.props.gradedGroups.map(({
|
|
28041
28038
|
title
|
|
28042
28039
|
}, i) => /*#__PURE__*/React.createElement("li", {
|
|
28043
|
-
className: css(styles$
|
|
28040
|
+
className: css(styles$h.indicator),
|
|
28044
28041
|
key: title
|
|
28045
28042
|
}, /*#__PURE__*/React.createElement(Clickable, {
|
|
28046
28043
|
role: "button",
|
|
28047
28044
|
"aria-label": this.context.strings.skipToTitle({
|
|
28048
28045
|
title
|
|
28049
28046
|
}),
|
|
28050
|
-
style: styles$
|
|
28047
|
+
style: styles$h.indicatorButton,
|
|
28051
28048
|
onClick: () => this.props.onChangeCurrentGroup(i),
|
|
28052
28049
|
onKeyDown: e => this.handleKeyDown(e, i)
|
|
28053
28050
|
}, ({
|
|
@@ -28055,9 +28052,9 @@ class Indicators extends React.Component {
|
|
|
28055
28052
|
focused,
|
|
28056
28053
|
pressed
|
|
28057
28054
|
}) => /*#__PURE__*/React.createElement(View, {
|
|
28058
|
-
style: [styles$
|
|
28055
|
+
style: [styles$h.indicatorDot, (hovered || focused || pressed) && styles$h.indicatorDotFocused]
|
|
28059
28056
|
}, i === this.props.currentGroup && /*#__PURE__*/React.createElement(View, {
|
|
28060
|
-
style: styles$
|
|
28057
|
+
style: styles$h.indicatorDotActive
|
|
28061
28058
|
}, /*#__PURE__*/React.createElement("span", {
|
|
28062
28059
|
className: css(a11y.srOnly)
|
|
28063
28060
|
}, this.context.strings.current)))))));
|
|
@@ -28125,7 +28122,7 @@ class GradedGroupSet extends React.Component {
|
|
|
28125
28122
|
} = getDependencies();
|
|
28126
28123
|
if (JIPT.useJIPT && this.props.gradedGroups.length > 1) {
|
|
28127
28124
|
return /*#__PURE__*/React.createElement("div", {
|
|
28128
|
-
className: css(styles$
|
|
28125
|
+
className: css(styles$h.container)
|
|
28129
28126
|
}, this.props.gradedGroups.map((gradedGroup, i) => {
|
|
28130
28127
|
return (
|
|
28131
28128
|
/*#__PURE__*/
|
|
@@ -28148,13 +28145,13 @@ class GradedGroupSet extends React.Component {
|
|
|
28148
28145
|
const numGroups = this.props.gradedGroups.length;
|
|
28149
28146
|
const handleNextQuestion = this.state.currentGroup < numGroups - 1 ? this.handleNextQuestion : null;
|
|
28150
28147
|
return /*#__PURE__*/React.createElement("div", {
|
|
28151
|
-
className: css(styles$
|
|
28148
|
+
className: css(styles$h.container)
|
|
28152
28149
|
}, /*#__PURE__*/React.createElement("div", {
|
|
28153
|
-
className: css(styles$
|
|
28150
|
+
className: css(styles$h.top)
|
|
28154
28151
|
}, /*#__PURE__*/React.createElement("div", {
|
|
28155
|
-
className: css(styles$
|
|
28152
|
+
className: css(styles$h.title)
|
|
28156
28153
|
}, currentGroup.title), /*#__PURE__*/React.createElement("div", {
|
|
28157
|
-
className: css(styles$
|
|
28154
|
+
className: css(styles$h.spacer)
|
|
28158
28155
|
}), /*#__PURE__*/React.createElement(Indicators, {
|
|
28159
28156
|
currentGroup: this.state.currentGroup,
|
|
28160
28157
|
gradedGroups: this.props.gradedGroups,
|
|
@@ -28196,7 +28193,7 @@ var GradedGroupSet$1 = {
|
|
|
28196
28193
|
tracking: "all",
|
|
28197
28194
|
isLintable: true
|
|
28198
28195
|
};
|
|
28199
|
-
const styles$
|
|
28196
|
+
const styles$h = StyleSheet.create({
|
|
28200
28197
|
top: {
|
|
28201
28198
|
display: "flex",
|
|
28202
28199
|
flexDirection: "row"
|
|
@@ -28301,7 +28298,7 @@ class ButtonGroup extends React.Component {
|
|
|
28301
28298
|
id: "" + i,
|
|
28302
28299
|
ref: "button" + i,
|
|
28303
28300
|
key: "" + i,
|
|
28304
|
-
className: css(styles$
|
|
28301
|
+
className: css(styles$g.buttonStyle, button.value === value && styles$g.selectedStyle),
|
|
28305
28302
|
onClick: () => this.toggleSelect(button.value)
|
|
28306
28303
|
}, button.content || "" + button.value);
|
|
28307
28304
|
});
|
|
@@ -28318,7 +28315,7 @@ ButtonGroup.defaultProps = {
|
|
|
28318
28315
|
value: null,
|
|
28319
28316
|
allowEmpty: true
|
|
28320
28317
|
};
|
|
28321
|
-
const styles$
|
|
28318
|
+
const styles$g = StyleSheet.create({
|
|
28322
28319
|
buttonStyle: {
|
|
28323
28320
|
backgroundColor: "white",
|
|
28324
28321
|
border: "1px solid #ccc",
|
|
@@ -31659,7 +31656,7 @@ const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
31659
31656
|
width: "24",
|
|
31660
31657
|
height: "24",
|
|
31661
31658
|
viewBox: "0 0 24 24",
|
|
31662
|
-
className: css(styles$
|
|
31659
|
+
className: css(styles$f.icon)
|
|
31663
31660
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
31664
31661
|
id: "a",
|
|
31665
31662
|
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 +31687,7 @@ const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
|
31690
31687
|
width: "24",
|
|
31691
31688
|
height: "24",
|
|
31692
31689
|
viewBox: "0 0 24 24",
|
|
31693
|
-
className: css(styles$
|
|
31690
|
+
className: css(styles$f.icon)
|
|
31694
31691
|
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
31695
31692
|
id: "a",
|
|
31696
31693
|
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 +31725,20 @@ const HUD = ({
|
|
|
31728
31725
|
let state;
|
|
31729
31726
|
let icon;
|
|
31730
31727
|
if (enabled) {
|
|
31731
|
-
state = styles$
|
|
31728
|
+
state = styles$f.enabled;
|
|
31732
31729
|
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
31733
31730
|
} else {
|
|
31734
|
-
state = styles$
|
|
31731
|
+
state = styles$f.disabled;
|
|
31735
31732
|
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
31736
31733
|
}
|
|
31737
31734
|
return /*#__PURE__*/React.createElement("button", {
|
|
31738
|
-
className: css(styles$
|
|
31735
|
+
className: css(styles$f.hud, _fixedPosition && styles$f.hudFixedPosition, state),
|
|
31739
31736
|
onClick: e => {
|
|
31740
31737
|
onClick();
|
|
31741
31738
|
}
|
|
31742
31739
|
}, icon, message);
|
|
31743
31740
|
};
|
|
31744
|
-
const styles$
|
|
31741
|
+
const styles$f = StyleSheet.create({
|
|
31745
31742
|
hud: {
|
|
31746
31743
|
boxSizing: "border-box",
|
|
31747
31744
|
height: 36,
|
|
@@ -31794,16 +31791,16 @@ const styles$g = StyleSheet.create({
|
|
|
31794
31791
|
const InfoTipBase = props => {
|
|
31795
31792
|
return /*#__PURE__*/React.createElement(Tooltip$1, {
|
|
31796
31793
|
content: /*#__PURE__*/React.createElement(Body, {
|
|
31797
|
-
style: styles$
|
|
31794
|
+
style: styles$e.body
|
|
31798
31795
|
}, props.children),
|
|
31799
31796
|
placement: "right"
|
|
31800
31797
|
}, /*#__PURE__*/React.createElement(PhosphorIcon, {
|
|
31801
31798
|
size: "small",
|
|
31802
31799
|
icon: questionIcon,
|
|
31803
|
-
style: styles$
|
|
31800
|
+
style: styles$e.spacingLeft
|
|
31804
31801
|
}));
|
|
31805
31802
|
};
|
|
31806
|
-
const styles$
|
|
31803
|
+
const styles$e = StyleSheet.create({
|
|
31807
31804
|
spacingLeft: {
|
|
31808
31805
|
marginInlineStart: spacing.xxxSmall_4
|
|
31809
31806
|
},
|
|
@@ -31882,7 +31879,7 @@ class MultiButtonGroup extends React.Component {
|
|
|
31882
31879
|
id: "" + i,
|
|
31883
31880
|
key: "" + i,
|
|
31884
31881
|
ref: "button" + i,
|
|
31885
|
-
className: css(styles$
|
|
31882
|
+
className: css(styles$d.buttonStyle, selected && styles$d.selectedStyle),
|
|
31886
31883
|
onClick: () => this.toggleSelect(button.value)
|
|
31887
31884
|
}, button.content || "" + button.value);
|
|
31888
31885
|
});
|
|
@@ -31899,7 +31896,7 @@ MultiButtonGroup.defaultProps = {
|
|
|
31899
31896
|
values: [],
|
|
31900
31897
|
allowEmpty: true
|
|
31901
31898
|
};
|
|
31902
|
-
const styles$
|
|
31899
|
+
const styles$d = StyleSheet.create({
|
|
31903
31900
|
buttonStyle: {
|
|
31904
31901
|
backgroundColor: "white",
|
|
31905
31902
|
border: "1px solid #ccc",
|
|
@@ -31932,7 +31929,7 @@ const styles$e = StyleSheet.create({
|
|
|
31932
31929
|
}
|
|
31933
31930
|
});
|
|
31934
31931
|
|
|
31935
|
-
const _excluded$
|
|
31932
|
+
const _excluded$3 = ["onFormatChange", "checkValidity", "useArrowKeys"];
|
|
31936
31933
|
const {
|
|
31937
31934
|
firstNumericalParse,
|
|
31938
31935
|
captureScratchpadTouchStart
|
|
@@ -32086,7 +32083,7 @@ class NumberInput extends React.Component {
|
|
|
32086
32083
|
classes = classes + " " + this.props.className;
|
|
32087
32084
|
}
|
|
32088
32085
|
const _this$props = this.props,
|
|
32089
|
-
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$
|
|
32086
|
+
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
|
|
32090
32087
|
return /*#__PURE__*/React.createElement("input", _extends({}, restProps, {
|
|
32091
32088
|
className: classes,
|
|
32092
32089
|
type: "text",
|
|
@@ -32225,11 +32222,39 @@ const LegacyGrid = ({
|
|
|
32225
32222
|
return null;
|
|
32226
32223
|
};
|
|
32227
32224
|
|
|
32225
|
+
/**
|
|
32226
|
+
* The Perseus "data schema" file.
|
|
32227
|
+
*
|
|
32228
|
+
* This file, and the types in it, represents the "data schema" that Perseus
|
|
32229
|
+
* uses. The @khanacademy/perseus-editor package edits and produces objects
|
|
32230
|
+
* that conform to the types in this file. Similarly, the top-level renderers
|
|
32231
|
+
* in @khanacademy/perseus, consume objects that conform to these types.
|
|
32232
|
+
*
|
|
32233
|
+
* WARNING: This file should not import any types from elsewhere so that it is
|
|
32234
|
+
* easy to reason about changes that alter the Perseus schema. This helps
|
|
32235
|
+
* ensure that it is not changed accidentally when upgrading a dependant
|
|
32236
|
+
* package or other part of Perseus code. Note that TypeScript does type
|
|
32237
|
+
* checking via something called "structural typing". This means that as long
|
|
32238
|
+
* as the shape of a type matches, the name it goes by doesn't matter. As a
|
|
32239
|
+
* result, a `Coord` type that looks like this `[x: number, y: number]` is
|
|
32240
|
+
* _identical_, in TypeScript's eyes, to this `Vector2` type `[x: number, y:
|
|
32241
|
+
* number]`. Also, with tuples, the labels for each entry is ignored, so `[x:
|
|
32242
|
+
* number, y: number]` is compatible with `[min: number, max: number]`. The
|
|
32243
|
+
* labels are for humans, not TypeScript. :)
|
|
32244
|
+
*
|
|
32245
|
+
* If you make changes to types in this file, be very sure that:
|
|
32246
|
+
*
|
|
32247
|
+
* a) the changes are backwards compatible. If they are not, old data from
|
|
32248
|
+
* previous versions of the "schema" could become unrenderable, or worse,
|
|
32249
|
+
* introduce hard-to-diagnose bugs.
|
|
32250
|
+
* b) the parsing code (`util/parse-perseus-json/`) is updated to handle
|
|
32251
|
+
* the new format _as well as_ the old format.
|
|
32252
|
+
*/
|
|
32253
|
+
|
|
32228
32254
|
// TODO(FEI-4010): Remove `Perseus` prefix for all types here
|
|
32229
|
-
// TODO(FEI-4011): Use types generated by https://github.com/jaredly/generate-perseus-flowtypes
|
|
32230
32255
|
|
|
32231
|
-
//
|
|
32232
|
-
|
|
32256
|
+
// Same name as Mafs
|
|
32257
|
+
|
|
32233
32258
|
/**
|
|
32234
32259
|
* Our core set of Perseus widgets.
|
|
32235
32260
|
*
|
|
@@ -32273,6 +32298,7 @@ const LegacyGrid = ({
|
|
|
32273
32298
|
*
|
|
32274
32299
|
* @see {@link https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation}
|
|
32275
32300
|
*/
|
|
32301
|
+
|
|
32276
32302
|
/**
|
|
32277
32303
|
* A map of widget IDs to widget options. This is most often used as the type
|
|
32278
32304
|
* for a set of widgets defined in a `PerseusItem` but can also be useful to
|
|
@@ -32285,6 +32311,7 @@ const LegacyGrid = ({
|
|
|
32285
32311
|
* @see {@link PerseusWidgetTypes} additional widgets can be added to this map type
|
|
32286
32312
|
* by augmenting the PerseusWidgetTypes with new widget types!
|
|
32287
32313
|
*/
|
|
32314
|
+
|
|
32288
32315
|
/**
|
|
32289
32316
|
* A "PerseusItem" is a classic Perseus item. It is rendered by the
|
|
32290
32317
|
* `ServerItemRenderer` and the layout is pre-set.
|
|
@@ -32292,18 +32319,12 @@ const LegacyGrid = ({
|
|
|
32292
32319
|
* To render more complex Perseus items, see the `Item` type in the multi item
|
|
32293
32320
|
* area.
|
|
32294
32321
|
*/
|
|
32322
|
+
|
|
32295
32323
|
/**
|
|
32296
32324
|
* A "PerseusArticle" is an item that is meant to be rendered as an article.
|
|
32297
32325
|
* This item is never scored and is rendered by the `ArticleRenderer`.
|
|
32298
32326
|
*/
|
|
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
|
-
*/
|
|
32327
|
+
|
|
32307
32328
|
const ItemExtras = [
|
|
32308
32329
|
// The user might benefit from using a Scientific Calculator. Provided on Khan Academy when true
|
|
32309
32330
|
"calculator",
|
|
@@ -33076,12 +33097,12 @@ const MafsCssTransformWrapper = ({
|
|
|
33076
33097
|
}
|
|
33077
33098
|
}, children);
|
|
33078
33099
|
|
|
33079
|
-
const _excluded$
|
|
33100
|
+
const _excluded$2 = ["children"];
|
|
33080
33101
|
const TextLabel = _ref => {
|
|
33081
33102
|
let {
|
|
33082
33103
|
children
|
|
33083
33104
|
} = _ref,
|
|
33084
|
-
rest = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
33105
|
+
rest = _objectWithoutPropertiesLoose(_ref, _excluded$2);
|
|
33085
33106
|
return /*#__PURE__*/React__default.createElement(Text$1, _extends({
|
|
33086
33107
|
size: 16,
|
|
33087
33108
|
svgTextProps: {
|
|
@@ -38711,7 +38732,7 @@ const HideAnswersToggle = props => {
|
|
|
38711
38732
|
strings
|
|
38712
38733
|
} = usePerseusI18n();
|
|
38713
38734
|
return /*#__PURE__*/React.createElement(View, {
|
|
38714
|
-
style: styles$
|
|
38735
|
+
style: styles$c.switchWrapper
|
|
38715
38736
|
}, /*#__PURE__*/React.createElement(Switch, {
|
|
38716
38737
|
id: switchId,
|
|
38717
38738
|
checked: props.areAnswersHidden,
|
|
@@ -38723,7 +38744,7 @@ const HideAnswersToggle = props => {
|
|
|
38723
38744
|
tag: "label"
|
|
38724
38745
|
}, strings.hideAnswersToggleLabel));
|
|
38725
38746
|
};
|
|
38726
|
-
const styles$
|
|
38747
|
+
const styles$c = StyleSheet.create({
|
|
38727
38748
|
switchWrapper: {
|
|
38728
38749
|
display: "flex",
|
|
38729
38750
|
flexDirection: "row",
|
|
@@ -38779,14 +38800,14 @@ const AnswerPill = props => {
|
|
|
38779
38800
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
38780
38801
|
onClick: correct ? undefined : onClick,
|
|
38781
38802
|
ref: ref,
|
|
38782
|
-
style: [style, popperStyle, styles$
|
|
38803
|
+
style: [style, popperStyle, styles$b.pill, correct && styles$b.correct, incorrect && styles$b.incorrect, (focused || hovered) && BringToFront]
|
|
38783
38804
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
38784
38805
|
content: answerString,
|
|
38785
38806
|
strings: strings,
|
|
38786
38807
|
inline: true
|
|
38787
38808
|
})));
|
|
38788
38809
|
};
|
|
38789
|
-
const styles$
|
|
38810
|
+
const styles$b = StyleSheet.create({
|
|
38790
38811
|
correct: {
|
|
38791
38812
|
// WB green darkened by 18%
|
|
38792
38813
|
backgroundColor: "#00880b"
|
|
@@ -38850,23 +38871,23 @@ class Marker extends React.Component {
|
|
|
38850
38871
|
icon: iconNull
|
|
38851
38872
|
};
|
|
38852
38873
|
if (showCorrectness) {
|
|
38853
|
-
iconStyles = [styles$
|
|
38874
|
+
iconStyles = [styles$a.markerGraded, showCorrectness === "correct" ? styles$a.markerCorrect : styles$a.markerIncorrect, isOpen && styles$a.markerSelected];
|
|
38854
38875
|
args = _extends({}, args, {
|
|
38855
38876
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
38856
38877
|
});
|
|
38857
38878
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
38858
|
-
iconStyles = [styles$
|
|
38879
|
+
iconStyles = [styles$a.markerFilled, isOpen && styles$a.markerSelected];
|
|
38859
38880
|
} else if (isOpen) {
|
|
38860
|
-
iconStyles = [styles$
|
|
38881
|
+
iconStyles = [styles$a.markerSelected];
|
|
38861
38882
|
args = _extends({}, args, {
|
|
38862
38883
|
icon: iconChevronDown,
|
|
38863
38884
|
size: 8
|
|
38864
38885
|
});
|
|
38865
38886
|
} else if (showPulsate) {
|
|
38866
|
-
iconStyles = [styles$
|
|
38887
|
+
iconStyles = [styles$a.markerPulsateBase, this._mounted && shouldReduceMotion() ? showPulsate && styles$a.markerUnfilledPulsateOnce : showPulsate && styles$a.markerUnfilledPulsateInfinite];
|
|
38867
38888
|
}
|
|
38868
38889
|
return /*#__PURE__*/React.createElement(View, {
|
|
38869
|
-
style: [styles$
|
|
38890
|
+
style: [styles$a.markerIcon, iconStyles],
|
|
38870
38891
|
ref: node => this._icon = node
|
|
38871
38892
|
}, /*#__PURE__*/React.createElement(Icon, args));
|
|
38872
38893
|
}
|
|
@@ -38888,7 +38909,7 @@ class Marker extends React.Component {
|
|
|
38888
38909
|
const markerDisabled = showCorrectness === "correct";
|
|
38889
38910
|
const active = hovered || focused;
|
|
38890
38911
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
38891
|
-
style: [styles$
|
|
38912
|
+
style: [styles$a.marker, active && !markerDisabled && styles$a.markerActive],
|
|
38892
38913
|
"aria-label": markerDisabled ? this.context.strings.correctExcited : label
|
|
38893
38914
|
}, this.renderIcon()), !!selected && showAnswer && /*#__PURE__*/React.createElement(AnswerPill, {
|
|
38894
38915
|
selectedAnswers: selected,
|
|
@@ -38905,7 +38926,7 @@ Marker.contextType = PerseusI18nContext;
|
|
|
38905
38926
|
Marker.defaultProps = {
|
|
38906
38927
|
selected: []
|
|
38907
38928
|
};
|
|
38908
|
-
const styles$
|
|
38929
|
+
const styles$a = StyleSheet.create({
|
|
38909
38930
|
marker: {
|
|
38910
38931
|
position: "absolute",
|
|
38911
38932
|
backgroundColor: color.white,
|
|
@@ -39490,13 +39511,13 @@ class LabelImage extends React.Component {
|
|
|
39490
39511
|
const promptString = isMobile ? multipleAnswers ? strings.tapMultiple : strings.tapSingle : multipleAnswers ? strings.clickMultiple : strings.clickSingle;
|
|
39491
39512
|
const choicesString = strings.choices;
|
|
39492
39513
|
return /*#__PURE__*/React.createElement("div", {
|
|
39493
|
-
className: classNames$1("perseus-label-image-widget-instructions", css(styles$
|
|
39514
|
+
className: classNames$1("perseus-label-image-widget-instructions", css(styles$9.instructions))
|
|
39494
39515
|
}, /*#__PURE__*/React.createElement("div", {
|
|
39495
|
-
className: css(styles$
|
|
39516
|
+
className: css(styles$9.instructionsCaption)
|
|
39496
39517
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React.createElement("div", {
|
|
39497
|
-
className: css(styles$
|
|
39518
|
+
className: css(styles$9.instructionsChoices)
|
|
39498
39519
|
}, choices.map((choice, index) => /*#__PURE__*/React.createElement("div", {
|
|
39499
|
-
className: css(styles$
|
|
39520
|
+
className: css(styles$9.instructionsChoice),
|
|
39500
39521
|
key: index
|
|
39501
39522
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
39502
39523
|
content: choice,
|
|
@@ -39514,20 +39535,20 @@ class LabelImage extends React.Component {
|
|
|
39514
39535
|
activeMarkerIndex
|
|
39515
39536
|
} = this.state;
|
|
39516
39537
|
return /*#__PURE__*/React.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React.createElement("div", {
|
|
39517
|
-
className: css(styles$
|
|
39538
|
+
className: css(styles$9.markersCanvas),
|
|
39518
39539
|
style: {
|
|
39519
39540
|
maxWidth: imageWidth,
|
|
39520
39541
|
maxHeight: imageHeight
|
|
39521
39542
|
}
|
|
39522
39543
|
}, /*#__PURE__*/React.createElement("div", {
|
|
39523
|
-
className: css(styles$
|
|
39544
|
+
className: css(styles$9.imageContainer,
|
|
39524
39545
|
// Ensure image interaction is disabled while answer
|
|
39525
39546
|
// choices popup is visible. This addresses specific
|
|
39526
39547
|
// case where user may click on question image to
|
|
39527
39548
|
// dismiss the popup. If the image is larger in size
|
|
39528
39549
|
// than its rendered in the widget, this would
|
|
39529
39550
|
// result in a zoom of the image.
|
|
39530
|
-
activeMarkerIndex !== -1 && styles$
|
|
39551
|
+
activeMarkerIndex !== -1 && styles$9.imageInteractionDisabled)
|
|
39531
39552
|
}, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
|
|
39532
39553
|
setAssetStatus
|
|
39533
39554
|
}) => /*#__PURE__*/React.createElement(SvgImage, {
|
|
@@ -39552,7 +39573,7 @@ class LabelImage extends React.Component {
|
|
|
39552
39573
|
}
|
|
39553
39574
|
}
|
|
39554
39575
|
LabelImage.contextType = PerseusI18nContext;
|
|
39555
|
-
const styles$
|
|
39576
|
+
const styles$9 = StyleSheet.create({
|
|
39556
39577
|
instructions: {
|
|
39557
39578
|
paddingBottom: 16
|
|
39558
39579
|
},
|
|
@@ -39638,7 +39659,7 @@ class Placeholder extends React.Component {
|
|
|
39638
39659
|
const {
|
|
39639
39660
|
layout
|
|
39640
39661
|
} = this.props;
|
|
39641
|
-
const className = css(styles$
|
|
39662
|
+
const className = css(styles$8.card, styles$8.placeholder, layout === "horizontal" && styles$8.horizontalCard);
|
|
39642
39663
|
const style = {
|
|
39643
39664
|
width: this.props.width,
|
|
39644
39665
|
height: this.props.height
|
|
@@ -39842,7 +39863,7 @@ class Draggable extends React.Component {
|
|
|
39842
39863
|
// We need to keep backwards compatbility with rules specified directly
|
|
39843
39864
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
39844
39865
|
// See sortable.less for details.
|
|
39845
|
-
let className = css(styles$
|
|
39866
|
+
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
39867
|
if (!includePadding) {
|
|
39847
39868
|
className += " perseus-sortable-draggable-unpadded";
|
|
39848
39869
|
}
|
|
@@ -40175,7 +40196,7 @@ class Sortable extends React.Component {
|
|
|
40175
40196
|
} = this.props;
|
|
40176
40197
|
// We need to keep backwards compatbility with rules specified directly
|
|
40177
40198
|
// in CSS. See sortable.less for details.
|
|
40178
|
-
const className = css(styles$
|
|
40199
|
+
const className = css(styles$8.sortable) + " perseus-sortable";
|
|
40179
40200
|
const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === "vertical";
|
|
40180
40201
|
const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === "horizontal";
|
|
40181
40202
|
_.each(this.state.items, function (item, i, items) {
|
|
@@ -40272,7 +40293,7 @@ Sortable.defaultProps = {
|
|
|
40272
40293
|
linterContext: PerseusLinter.linterContextDefault,
|
|
40273
40294
|
waitForTexRendererToLoad: true
|
|
40274
40295
|
};
|
|
40275
|
-
const styles$
|
|
40296
|
+
const styles$8 = StyleSheet.create({
|
|
40276
40297
|
sortable: {
|
|
40277
40298
|
boxSizing: "border-box",
|
|
40278
40299
|
float: "left",
|
|
@@ -40458,25 +40479,25 @@ class Matcher extends React.Component {
|
|
|
40458
40479
|
};
|
|
40459
40480
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
40460
40481
|
return /*#__PURE__*/React.createElement("table", {
|
|
40461
|
-
className: css(styles$
|
|
40482
|
+
className: css(styles$7.widget) + " " + HACKY_CSS_CLASSNAME
|
|
40462
40483
|
}, /*#__PURE__*/React.createElement("tbody", null, showLabels && /*#__PURE__*/React.createElement("tr", {
|
|
40463
|
-
className: css(styles$
|
|
40484
|
+
className: css(styles$7.row)
|
|
40464
40485
|
}, /*#__PURE__*/React.createElement("th", {
|
|
40465
|
-
className: css(styles$
|
|
40486
|
+
className: css(styles$7.column, styles$7.columnLabel)
|
|
40466
40487
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
40467
40488
|
content: this.props.labels[0] || "...",
|
|
40468
40489
|
linterContext: this.props.linterContext,
|
|
40469
40490
|
strings: this.context.strings
|
|
40470
40491
|
})), /*#__PURE__*/React.createElement("th", {
|
|
40471
|
-
className: css(styles$
|
|
40492
|
+
className: css(styles$7.column, styles$7.columnRight, styles$7.columnLabel)
|
|
40472
40493
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
40473
40494
|
content: this.props.labels[1] || "...",
|
|
40474
40495
|
linterContext: this.props.linterContext,
|
|
40475
40496
|
strings: this.context.strings
|
|
40476
40497
|
}))), /*#__PURE__*/React.createElement("tr", {
|
|
40477
|
-
className: css(styles$
|
|
40498
|
+
className: css(styles$7.row)
|
|
40478
40499
|
}, /*#__PURE__*/React.createElement("td", {
|
|
40479
|
-
className: css(styles$
|
|
40500
|
+
className: css(styles$7.column)
|
|
40480
40501
|
}, /*#__PURE__*/React.createElement(Sortable, {
|
|
40481
40502
|
options: left,
|
|
40482
40503
|
layout: "vertical",
|
|
@@ -40491,7 +40512,7 @@ class Matcher extends React.Component {
|
|
|
40491
40512
|
,
|
|
40492
40513
|
ref: "left"
|
|
40493
40514
|
})), /*#__PURE__*/React.createElement("td", {
|
|
40494
|
-
className: css(styles$
|
|
40515
|
+
className: css(styles$7.column, styles$7.columnRight)
|
|
40495
40516
|
}, /*#__PURE__*/React.createElement(Sortable, {
|
|
40496
40517
|
options: right,
|
|
40497
40518
|
layout: "vertical",
|
|
@@ -40520,7 +40541,7 @@ Matcher.defaultProps = {
|
|
|
40520
40541
|
};
|
|
40521
40542
|
const padding = 5;
|
|
40522
40543
|
const border = "1px solid #444";
|
|
40523
|
-
const styles$
|
|
40544
|
+
const styles$7 = StyleSheet.create({
|
|
40524
40545
|
widget: {
|
|
40525
40546
|
paddingTop: padding,
|
|
40526
40547
|
maxWidth: "100%",
|
|
@@ -41062,7 +41083,7 @@ const getPromptJSON$7 = () => {
|
|
|
41062
41083
|
return getUnsupportedPromptJSON("measurer");
|
|
41063
41084
|
};
|
|
41064
41085
|
|
|
41065
|
-
const _excluded$
|
|
41086
|
+
const _excluded$1 = ["imageUrl", "imageTop", "imageLeft"];
|
|
41066
41087
|
const defaultImage = {
|
|
41067
41088
|
url: null,
|
|
41068
41089
|
top: 0,
|
|
@@ -41174,7 +41195,7 @@ const propUpgrades = {
|
|
|
41174
41195
|
imageTop,
|
|
41175
41196
|
imageLeft
|
|
41176
41197
|
} = v0props,
|
|
41177
|
-
rest = _objectWithoutPropertiesLoose(v0props, _excluded$
|
|
41198
|
+
rest = _objectWithoutPropertiesLoose(v0props, _excluded$1);
|
|
41178
41199
|
return _extends({}, rest, {
|
|
41179
41200
|
image: {
|
|
41180
41201
|
url: imageUrl,
|
|
@@ -41214,9 +41235,9 @@ function drawText(ctx, item) {
|
|
|
41214
41235
|
if (item.value === null) {
|
|
41215
41236
|
return;
|
|
41216
41237
|
}
|
|
41217
|
-
ctx.fillStyle = styles$
|
|
41218
|
-
ctx.font = styles$
|
|
41219
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
41238
|
+
ctx.fillStyle = styles$6.fgColor;
|
|
41239
|
+
ctx.font = styles$6.font;
|
|
41240
|
+
ctx.fillText(item.value, item.pos[0] - styles$6.fontSizePx / 2 + 1, item.pos[1] + styles$6.fontSizePx / 2);
|
|
41220
41241
|
}
|
|
41221
41242
|
|
|
41222
41243
|
/**
|
|
@@ -41237,16 +41258,16 @@ function drawText(ctx, item) {
|
|
|
41237
41258
|
function drawDoubleLine(ctx, item) {
|
|
41238
41259
|
// Outer line that forms both of the bond lines.
|
|
41239
41260
|
let path = new Path2D();
|
|
41240
|
-
ctx.lineWidth = 5 * styles$
|
|
41241
|
-
ctx.strokeStyle = styles$
|
|
41261
|
+
ctx.lineWidth = 5 * styles$6.lineWidth;
|
|
41262
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41242
41263
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41243
41264
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41244
41265
|
ctx.stroke(path);
|
|
41245
41266
|
|
|
41246
41267
|
// Inner white line that separates the two bond lines.
|
|
41247
41268
|
path = new Path2D();
|
|
41248
|
-
ctx.lineWidth = 3 * styles$
|
|
41249
|
-
ctx.strokeStyle = styles$
|
|
41269
|
+
ctx.lineWidth = 3 * styles$6.lineWidth;
|
|
41270
|
+
ctx.strokeStyle = styles$6.bgColor;
|
|
41250
41271
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41251
41272
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41252
41273
|
ctx.stroke(path);
|
|
@@ -41273,16 +41294,16 @@ function drawTripleLine(ctx, item) {
|
|
|
41273
41294
|
|
|
41274
41295
|
// Outer line that will form the two outer bond lines.
|
|
41275
41296
|
let path = new Path2D();
|
|
41276
|
-
ctx.lineWidth = 7 * styles$
|
|
41277
|
-
ctx.strokeStyle = styles$
|
|
41297
|
+
ctx.lineWidth = 7 * styles$6.lineWidth;
|
|
41298
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41278
41299
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41279
41300
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41280
41301
|
ctx.stroke(path);
|
|
41281
41302
|
|
|
41282
41303
|
// Middle white line that separates the bonds
|
|
41283
41304
|
path = new Path2D();
|
|
41284
|
-
ctx.lineWidth = 5 * styles$
|
|
41285
|
-
ctx.strokeStyle = styles$
|
|
41305
|
+
ctx.lineWidth = 5 * styles$6.lineWidth;
|
|
41306
|
+
ctx.strokeStyle = styles$6.bgColor;
|
|
41286
41307
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41287
41308
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41288
41309
|
ctx.stroke(path);
|
|
@@ -41304,8 +41325,8 @@ function drawTripleLine(ctx, item) {
|
|
|
41304
41325
|
*/
|
|
41305
41326
|
function drawLine(ctx, item) {
|
|
41306
41327
|
const path = new Path2D();
|
|
41307
|
-
ctx.lineWidth = styles$
|
|
41308
|
-
ctx.strokeStyle = styles$
|
|
41328
|
+
ctx.lineWidth = styles$6.lineWidth;
|
|
41329
|
+
ctx.strokeStyle = styles$6.fgColor;
|
|
41309
41330
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
41310
41331
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
41311
41332
|
ctx.stroke(path);
|
|
@@ -41357,7 +41378,7 @@ function compareElements(item0, item1) {
|
|
|
41357
41378
|
function draw(ctx, items) {
|
|
41358
41379
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
41359
41380
|
}
|
|
41360
|
-
const styles$
|
|
41381
|
+
const styles$6 = {
|
|
41361
41382
|
bgColor: "rgb(255, 255, 255)",
|
|
41362
41383
|
fgColor: "rgb(0, 0, 0)",
|
|
41363
41384
|
fontSizePx: 12,
|
|
@@ -43477,7 +43498,7 @@ class PhetSimulation extends React.Component {
|
|
|
43477
43498
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
43478
43499
|
const sandboxProperties = "allow-same-origin allow-scripts";
|
|
43479
43500
|
return /*#__PURE__*/React.createElement(View, {
|
|
43480
|
-
style: styles$
|
|
43501
|
+
style: styles$5.widgetContainer
|
|
43481
43502
|
}, this.state.banner !== null &&
|
|
43482
43503
|
/*#__PURE__*/
|
|
43483
43504
|
// TODO(anna): Make this banner focusable
|
|
@@ -43490,12 +43511,12 @@ class PhetSimulation extends React.Component {
|
|
|
43490
43511
|
kind: this.state.banner.kind,
|
|
43491
43512
|
text: this.state.banner.message
|
|
43492
43513
|
})), /*#__PURE__*/React.createElement(View, {
|
|
43493
|
-
style: styles$
|
|
43514
|
+
style: styles$5.iframeContainer
|
|
43494
43515
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
43495
43516
|
ref: this.iframeRef,
|
|
43496
43517
|
title: this.props.description,
|
|
43497
43518
|
sandbox: sandboxProperties,
|
|
43498
|
-
className: css(styles$
|
|
43519
|
+
className: css(styles$5.iframeResponsive),
|
|
43499
43520
|
src: (_this$state$url = this.state.url) == null ? void 0 : _this$state$url.toString(),
|
|
43500
43521
|
allow: "fullscreen"
|
|
43501
43522
|
})), this.state.url !== null && /*#__PURE__*/React.createElement(IconButton, {
|
|
@@ -43528,7 +43549,7 @@ const makeSafeUrl = (urlString, locale) => {
|
|
|
43528
43549
|
url.searchParams.set("locale", locale);
|
|
43529
43550
|
return url;
|
|
43530
43551
|
};
|
|
43531
|
-
const styles$
|
|
43552
|
+
const styles$5 = StyleSheet.create({
|
|
43532
43553
|
widgetContainer: {
|
|
43533
43554
|
borderRadius: 6,
|
|
43534
43555
|
borderWidth: 1,
|
|
@@ -44446,7 +44467,7 @@ class PythonProgram extends React.Component {
|
|
|
44446
44467
|
// creator "went wild".
|
|
44447
44468
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
44448
44469
|
return /*#__PURE__*/React.createElement(View, {
|
|
44449
|
-
style: styles$
|
|
44470
|
+
style: styles$4.container
|
|
44450
44471
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
44451
44472
|
sandbox: sandboxOptions,
|
|
44452
44473
|
src: url,
|
|
@@ -44458,7 +44479,7 @@ class PythonProgram extends React.Component {
|
|
|
44458
44479
|
PythonProgram.defaultProps = {
|
|
44459
44480
|
height: 400
|
|
44460
44481
|
};
|
|
44461
|
-
const styles$
|
|
44482
|
+
const styles$4 = StyleSheet.create({
|
|
44462
44483
|
container: {
|
|
44463
44484
|
margin: "auto",
|
|
44464
44485
|
width: "100%"
|
|
@@ -44951,7 +44972,7 @@ const VideoTranscriptLink = props => {
|
|
|
44951
44972
|
var _result$data;
|
|
44952
44973
|
const video = (_result$data = result.data) == null ? void 0 : _result$data.video;
|
|
44953
44974
|
return /*#__PURE__*/React.createElement(View, {
|
|
44954
|
-
style: styles$
|
|
44975
|
+
style: styles$3.transcriptLink
|
|
44955
44976
|
}, /*#__PURE__*/React.createElement(Text$2, null, video == null ? void 0 : video.title), /*#__PURE__*/React.createElement(Strut, {
|
|
44956
44977
|
size: 10
|
|
44957
44978
|
}), /*#__PURE__*/React.createElement(Link, {
|
|
@@ -44968,7 +44989,7 @@ const VideoTranscriptLink = props => {
|
|
|
44968
44989
|
return /*#__PURE__*/React.createElement(View, null, strings.somethingWrong);
|
|
44969
44990
|
}
|
|
44970
44991
|
};
|
|
44971
|
-
const styles$
|
|
44992
|
+
const styles$3 = StyleSheet.create({
|
|
44972
44993
|
transcriptLink: {
|
|
44973
44994
|
flexDirection: "row",
|
|
44974
44995
|
width: "100%",
|
|
@@ -45086,7 +45107,7 @@ const init = function init() {
|
|
|
45086
45107
|
|
|
45087
45108
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45088
45109
|
const libName = "@khanacademy/perseus";
|
|
45089
|
-
const libVersion = "
|
|
45110
|
+
const libVersion = "47.0.1";
|
|
45090
45111
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45091
45112
|
|
|
45092
45113
|
const apiVersion = {
|
|
@@ -45298,7 +45319,7 @@ class HintRenderer extends React.Component {
|
|
|
45298
45319
|
const {
|
|
45299
45320
|
isMobile
|
|
45300
45321
|
} = apiOptions;
|
|
45301
|
-
const classNames = classNames$1("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$
|
|
45322
|
+
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
45323
|
|
|
45303
45324
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
45304
45325
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -45343,7 +45364,7 @@ HintRenderer.contextType = PerseusI18nContext;
|
|
|
45343
45364
|
HintRenderer.defaultProps = {
|
|
45344
45365
|
linterContext: PerseusLinter.linterContextDefault
|
|
45345
45366
|
};
|
|
45346
|
-
const styles$
|
|
45367
|
+
const styles$2 = StyleSheet.create({
|
|
45347
45368
|
newHint: {
|
|
45348
45369
|
marginBottom: 1.5 * baseUnitPx,
|
|
45349
45370
|
borderLeftColor: gray97,
|
|
@@ -45516,14 +45537,14 @@ class HintsRenderer extends React.Component {
|
|
|
45516
45537
|
} = apiOptions;
|
|
45517
45538
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
45518
45539
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
45519
|
-
const classNames = classNames$1(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$
|
|
45540
|
+
const classNames = classNames$1(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$1.mobileHintStylesHintsRenderer));
|
|
45520
45541
|
return /*#__PURE__*/React.createElement("div", {
|
|
45521
45542
|
className: classNames
|
|
45522
45543
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React.createElement("div", {
|
|
45523
|
-
className: css(styles$
|
|
45544
|
+
className: css(styles$1.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
45524
45545
|
}, this.context.strings.hints), hints, showGetAnotherHint && /*#__PURE__*/React.createElement("button", {
|
|
45525
45546
|
rel: "button",
|
|
45526
|
-
className: css(styles$
|
|
45547
|
+
className: css(styles$1.linkButton, styles$1.getAnotherHintButton, apiOptions.isMobile && styles$1.mobileHintStylesGetAnotherHintButton),
|
|
45527
45548
|
onClick: evt => {
|
|
45528
45549
|
evt.preventDefault();
|
|
45529
45550
|
evt.stopPropagation();
|
|
@@ -45532,9 +45553,9 @@ class HintsRenderer extends React.Component {
|
|
|
45532
45553
|
}
|
|
45533
45554
|
}
|
|
45534
45555
|
}, /*#__PURE__*/React.createElement("span", {
|
|
45535
|
-
className: css(styles$
|
|
45556
|
+
className: css(styles$1.plusText, apiOptions.isMobile && styles$1.mobileHintStylesPlusText)
|
|
45536
45557
|
}, "+"), /*#__PURE__*/React.createElement("span", {
|
|
45537
|
-
className: css(styles$
|
|
45558
|
+
className: css(styles$1.getAnotherHintText)
|
|
45538
45559
|
}, this.context.strings.getAnotherHint, " ", hintRatioCopy)));
|
|
45539
45560
|
}
|
|
45540
45561
|
}
|
|
@@ -45543,7 +45564,7 @@ HintsRenderer.defaultProps = {
|
|
|
45543
45564
|
linterContext: PerseusLinter.linterContextDefault
|
|
45544
45565
|
};
|
|
45545
45566
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
45546
|
-
const styles$
|
|
45567
|
+
const styles$1 = StyleSheet.create({
|
|
45547
45568
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
45548
45569
|
rendererMargins: {
|
|
45549
45570
|
marginTop: baseUnitPx
|
|
@@ -45952,7 +45973,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
45952
45973
|
// mobile hint styles, which are flush to the left.
|
|
45953
45974
|
// NOTE(charlie): We may still want to apply this
|
|
45954
45975
|
// padding for desktop exercises.
|
|
45955
|
-
apiOptions.isMobile ? undefined : css(styles
|
|
45976
|
+
apiOptions.isMobile ? undefined : css(styles.hintsContainer)
|
|
45956
45977
|
}, hintsRenderer)));
|
|
45957
45978
|
}
|
|
45958
45979
|
}
|
|
@@ -45963,7 +45984,7 @@ ServerItemRenderer.defaultProps = {
|
|
|
45963
45984
|
linterContext: PerseusLinter.linterContextDefault,
|
|
45964
45985
|
onRendered: isRendered => {}
|
|
45965
45986
|
};
|
|
45966
|
-
const styles
|
|
45987
|
+
const styles = StyleSheet.create({
|
|
45967
45988
|
hintsContainer: {
|
|
45968
45989
|
marginLeft: 50
|
|
45969
45990
|
}
|
|
@@ -46068,1144 +46089,6 @@ const traverse = function traverse(rendererOptions, contentCallback, widgetCallb
|
|
|
46068
46089
|
return traverseRenderer$1(rendererOptions, contentCallback, deepCallbackFor(contentCallback, widgetCallback, optionsCallback), optionsCallback);
|
|
46069
46090
|
};
|
|
46070
46091
|
|
|
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
46092
|
/**
|
|
47210
46093
|
* Calculates whether a perseus item is renderable by a specific
|
|
47211
46094
|
* perseus-item-data version.
|
|
@@ -47215,10 +46098,6 @@ var MultiItems = {
|
|
|
47215
46098
|
* This supports widgets that contain renderers, such as the
|
|
47216
46099
|
* group or sequence widgets.
|
|
47217
46100
|
*/
|
|
47218
|
-
const {
|
|
47219
|
-
findContentNodesInItem: findContentNodesInItem$1,
|
|
47220
|
-
inferItemShape: inferItemShape$1
|
|
47221
|
-
} = MultiItems;
|
|
47222
46101
|
const isUpgradedWidgetInfoRenderableBy = function isUpgradedWidgetInfoRenderableBy(widgetInfo, widgetRendererVersion) {
|
|
47223
46102
|
if (widgetRendererVersion == null) {
|
|
47224
46103
|
// If the widget does not exist in this version, this will
|
|
@@ -47264,17 +46143,6 @@ const isItemRenderableByVersion = function isItemRenderableByVersion(itemData, r
|
|
|
47264
46143
|
if (itemData == null || rendererContentVersion == null) {
|
|
47265
46144
|
throw new PerseusError("missing parameter to Perseus.isRenderable.item", Errors.InvalidInput);
|
|
47266
46145
|
}
|
|
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
46146
|
return isRendererContentRenderableBy(itemData.question, rendererContentVersion);
|
|
47279
46147
|
};
|
|
47280
46148
|
|
|
@@ -47282,10 +46150,6 @@ const isItemRenderableByVersion = function isItemRenderableByVersion(itemData, r
|
|
|
47282
46150
|
* Identifies whether or not a given perseus item requires the use of a mouse
|
|
47283
46151
|
* or screen, based on the widgets it contains.
|
|
47284
46152
|
*/
|
|
47285
|
-
const {
|
|
47286
|
-
findContentNodesInItem,
|
|
47287
|
-
inferItemShape
|
|
47288
|
-
} = MultiItems;
|
|
47289
46153
|
|
|
47290
46154
|
// Iterate over a single Perseus renderer, mutating `widgets` by appending
|
|
47291
46155
|
// violating widget types discovered in this item.
|
|
@@ -47306,12 +46170,7 @@ function traverseRenderer(itemData, widgets) {
|
|
|
47306
46170
|
function violatingWidgets(itemData) {
|
|
47307
46171
|
// TODO(jordan): Hints as well
|
|
47308
46172
|
const widgets = [];
|
|
47309
|
-
|
|
47310
|
-
const shape = inferItemShape(itemData);
|
|
47311
|
-
findContentNodesInItem(itemData, shape, content => traverseRenderer(content, widgets));
|
|
47312
|
-
} else {
|
|
47313
|
-
traverseRenderer(itemData.question, widgets);
|
|
47314
|
-
}
|
|
46173
|
+
traverseRenderer(itemData.question, widgets);
|
|
47315
46174
|
|
|
47316
46175
|
// Uniquify the list of widgets (by type)
|
|
47317
46176
|
return _.uniq(widgets);
|
|
@@ -49818,5 +48677,9 @@ const ScoringUtil = {
|
|
|
49818
48677
|
keScoreFromPerseusScore
|
|
49819
48678
|
};
|
|
49820
48679
|
|
|
49821
|
-
|
|
48680
|
+
/**
|
|
48681
|
+
* Types
|
|
48682
|
+
*/
|
|
48683
|
+
|
|
48684
|
+
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
48685
|
//# sourceMappingURL=index.js.map
|