@khanacademy/perseus 19.6.3 → 19.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +168 -0
- package/dist/es/index.js +969 -743
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +168 -0
- package/dist/index.js +966 -738
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +1 -0
- package/dist/perseus-types.d.ts +14 -2
- package/dist/server-item-renderer.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/widgets/expression.d.ts +6 -0
- package/dist/widgets/interactive-graph.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/segment.d.ts +5 -0
- package/dist/widgets/interactive-graphs/grid.d.ts +11 -0
- package/dist/widgets/interactive-graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/legacy-grid.d.ts +7 -0
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +79 -0
- package/dist/widgets/interactive-graphs/types.d.ts +9 -0
- package/dist/widgets/interactive-graphs/utils.d.ts +15 -0
- package/dist/widgets/label-image.d.ts +2 -0
- package/package.json +3 -2
package/dist/es/index.js
CHANGED
|
@@ -29,11 +29,12 @@ import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
|
29
29
|
import Banner from '@khanacademy/wonder-blocks-banner';
|
|
30
30
|
import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-blocks-dropdown';
|
|
31
31
|
import debounce$1 from 'lodash.debounce';
|
|
32
|
+
import { useMovablePoint, Line as Line$4, Coordinates, Mafs } from 'mafs';
|
|
33
|
+
import createReactClass from 'create-react-class';
|
|
32
34
|
import Switch from '@khanacademy/wonder-blocks-switch';
|
|
33
35
|
import { LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
34
36
|
import Pill from '@khanacademy/wonder-blocks-pill';
|
|
35
37
|
import { Popper } from 'react-popper';
|
|
36
|
-
import createReactClass from 'create-react-class';
|
|
37
38
|
import Link from '@khanacademy/wonder-blocks-link';
|
|
38
39
|
import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-core';
|
|
39
40
|
|
|
@@ -1901,7 +1902,7 @@ const KhanAnswerTypes = {
|
|
|
1901
1902
|
}
|
|
1902
1903
|
};
|
|
1903
1904
|
|
|
1904
|
-
const _excluded$
|
|
1905
|
+
const _excluded$5 = ["scoring"];
|
|
1905
1906
|
const ERROR_TITLE = i18n._("Oops!");
|
|
1906
1907
|
const ERROR_MESSAGE = i18n._("Sorry, I don't understand that!");
|
|
1907
1908
|
|
|
@@ -1989,7 +1990,7 @@ class Expression extends React.Component {
|
|
|
1989
1990
|
let {
|
|
1990
1991
|
scoring
|
|
1991
1992
|
} = _ref,
|
|
1992
|
-
rubric = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
1993
|
+
rubric = _objectWithoutPropertiesLoose(_ref, _excluded$5);
|
|
1993
1994
|
const score = Expression.validate(this.getUserInput(), rubric, onInputError || function () {});
|
|
1994
1995
|
|
|
1995
1996
|
// "scoring" is a flag that indicates when we are checking answers.
|
|
@@ -21392,7 +21393,7 @@ InputWithExamples.defaultProps = {
|
|
|
21392
21393
|
className: ""
|
|
21393
21394
|
};
|
|
21394
21395
|
|
|
21395
|
-
const _excluded$
|
|
21396
|
+
const _excluded$4 = ["keypadElement", "onFocus", "value"];
|
|
21396
21397
|
class SimpleKeypadInput extends React.Component {
|
|
21397
21398
|
constructor(...args) {
|
|
21398
21399
|
super(...args);
|
|
@@ -21431,7 +21432,7 @@ class SimpleKeypadInput extends React.Component {
|
|
|
21431
21432
|
onFocus,
|
|
21432
21433
|
value
|
|
21433
21434
|
} = _this$props,
|
|
21434
|
-
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$
|
|
21435
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$4);
|
|
21435
21436
|
return (
|
|
21436
21437
|
/*#__PURE__*/
|
|
21437
21438
|
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
@@ -23262,14 +23263,14 @@ var Choice$1 = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.
|
|
|
23262
23263
|
forwardedRef: ref
|
|
23263
23264
|
})));
|
|
23264
23265
|
|
|
23265
|
-
const _excluded$
|
|
23266
|
+
const _excluded$3 = ["showContent", "content", "forwardedRef"];
|
|
23266
23267
|
const ChoiceNoneAbove = function ChoiceNoneAbove(props) {
|
|
23267
23268
|
const {
|
|
23268
23269
|
showContent,
|
|
23269
23270
|
content,
|
|
23270
23271
|
forwardedRef
|
|
23271
23272
|
} = props,
|
|
23272
|
-
rest = _objectWithoutPropertiesLoose(props, _excluded$
|
|
23273
|
+
rest = _objectWithoutPropertiesLoose(props, _excluded$3);
|
|
23273
23274
|
const choiceProps = _extends({}, rest, {
|
|
23274
23275
|
content: showContent ? content :
|
|
23275
23276
|
/*#__PURE__*/
|
|
@@ -28173,6 +28174,872 @@ Graph.defaultProps = {
|
|
|
28173
28174
|
isMobile: false
|
|
28174
28175
|
};
|
|
28175
28176
|
|
|
28177
|
+
const useInteractivePoint = (coords, snaps, range) => useMovablePoint(coords, {
|
|
28178
|
+
constrain: coord => constrain(coord, snaps, range),
|
|
28179
|
+
color: Color.blue
|
|
28180
|
+
});
|
|
28181
|
+
|
|
28182
|
+
/**
|
|
28183
|
+
* We do not want to call `onGraphChange` until the user
|
|
28184
|
+
* has interacted with the graph. See the test,
|
|
28185
|
+
* "should reject no interaction"
|
|
28186
|
+
*/
|
|
28187
|
+
const useEffectAfterFirstRender = (fn, deps) => {
|
|
28188
|
+
const firstRender = useRef(true);
|
|
28189
|
+
useEffect(() => {
|
|
28190
|
+
if (firstRender.current) {
|
|
28191
|
+
firstRender.current = false;
|
|
28192
|
+
return;
|
|
28193
|
+
}
|
|
28194
|
+
fn();
|
|
28195
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28196
|
+
}, [fn, ...deps]);
|
|
28197
|
+
};
|
|
28198
|
+
const snap = (val, step) => {
|
|
28199
|
+
const inverse = 1 / step;
|
|
28200
|
+
return Math.round(val * inverse) / inverse;
|
|
28201
|
+
};
|
|
28202
|
+
const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
28203
|
+
const constrain = (coord, snapStep, range) => {
|
|
28204
|
+
const [x, y] = coord;
|
|
28205
|
+
const [xSnap, ySnap] = snapStep;
|
|
28206
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
28207
|
+
return [clamp(snap(x, xSnap), xMin, xMax), clamp(snap(y, ySnap), yMin, yMax)];
|
|
28208
|
+
};
|
|
28209
|
+
|
|
28210
|
+
// same as pointsFromNormalized in interactive-graph.tsx
|
|
28211
|
+
const normalizePoints = (range, step, coordsList, noSnap) => coordsList.map(coords =>
|
|
28212
|
+
// maps over [x, y]
|
|
28213
|
+
coords.map((coord, i) => {
|
|
28214
|
+
const axisRange = range[i];
|
|
28215
|
+
if (noSnap) {
|
|
28216
|
+
return axisRange[0] + (axisRange[1] - axisRange[0]) * coord;
|
|
28217
|
+
}
|
|
28218
|
+
const axisStep = step[i];
|
|
28219
|
+
const nSteps = Math.floor((axisRange[1] - axisRange[0]) / axisStep);
|
|
28220
|
+
const tick = Math.round(coord * nSteps);
|
|
28221
|
+
return axisRange[0] + axisStep * tick;
|
|
28222
|
+
}));
|
|
28223
|
+
|
|
28224
|
+
// same as normalizeCoords in interactive-graph.tsx
|
|
28225
|
+
const normalizeCoords = (coordsList, ranges) => coordsList.map(coords => coords.map((coord, i) => {
|
|
28226
|
+
const extent = ranges[i][1] - ranges[i][0];
|
|
28227
|
+
return (coord + ranges[i][1]) / extent;
|
|
28228
|
+
}));
|
|
28229
|
+
|
|
28230
|
+
const getSegmentCoords = props => {
|
|
28231
|
+
const coords = props.graph.coords;
|
|
28232
|
+
if (coords) {
|
|
28233
|
+
return coords;
|
|
28234
|
+
}
|
|
28235
|
+
const ys = n => {
|
|
28236
|
+
switch (n) {
|
|
28237
|
+
case 2:
|
|
28238
|
+
return [5, -5];
|
|
28239
|
+
case 3:
|
|
28240
|
+
return [5, 0, -5];
|
|
28241
|
+
case 4:
|
|
28242
|
+
return [6, 2, -2, -6];
|
|
28243
|
+
case 5:
|
|
28244
|
+
return [6, 3, 0, -3, -6];
|
|
28245
|
+
case 6:
|
|
28246
|
+
return [5, 3, 1, -1, -3, -5];
|
|
28247
|
+
default:
|
|
28248
|
+
return [5];
|
|
28249
|
+
}
|
|
28250
|
+
};
|
|
28251
|
+
return ys(props.graph.numSegments).map(y => {
|
|
28252
|
+
let segment = [[-5, y], [5, y]];
|
|
28253
|
+
segment = normalizeCoords(segment, props.range);
|
|
28254
|
+
segment = normalizePoints(props.range, props.step, segment);
|
|
28255
|
+
return segment;
|
|
28256
|
+
});
|
|
28257
|
+
};
|
|
28258
|
+
const updateSegmentsArray = (segments, index, segment) => segments.map((seg, i) => index === i ? segment : seg);
|
|
28259
|
+
const SegmentGraph = props => {
|
|
28260
|
+
const segments = getSegmentCoords(props);
|
|
28261
|
+
const handleChange = (i, segment) => props.onGraphChange(current => _extends({}, current, {
|
|
28262
|
+
coords: current.coords ? updateSegmentsArray(current.coords, i, segment) : updateSegmentsArray(segments, i, segment)
|
|
28263
|
+
}));
|
|
28264
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, segments.map((segment, i) => /*#__PURE__*/React.createElement(Segment, {
|
|
28265
|
+
key: i,
|
|
28266
|
+
i: i,
|
|
28267
|
+
segment: segment,
|
|
28268
|
+
snaps: props.snapStep,
|
|
28269
|
+
range: props.range,
|
|
28270
|
+
onChange: handleChange,
|
|
28271
|
+
"data-testid": "segment" + i
|
|
28272
|
+
})));
|
|
28273
|
+
};
|
|
28274
|
+
const Segment = props => {
|
|
28275
|
+
const [start, end] = props.segment;
|
|
28276
|
+
const {
|
|
28277
|
+
point: pt1,
|
|
28278
|
+
element: el1
|
|
28279
|
+
} = useInteractivePoint(start, props.snaps, props.range);
|
|
28280
|
+
const {
|
|
28281
|
+
point: pt2,
|
|
28282
|
+
element: el2
|
|
28283
|
+
} = useInteractivePoint(end, props.snaps, props.range);
|
|
28284
|
+
useEffectAfterFirstRender(() => props.onChange(props.i, [pt1, pt2]), [pt1, pt2]);
|
|
28285
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Line$4.Segment, {
|
|
28286
|
+
point1: pt1,
|
|
28287
|
+
point2: pt2
|
|
28288
|
+
}), el1, el2);
|
|
28289
|
+
};
|
|
28290
|
+
|
|
28291
|
+
const renderLineLabel = (n, [min, max]) => n !== -1 && n !== min && n !== max;
|
|
28292
|
+
const axisOptions = (props, index) => ({
|
|
28293
|
+
axis: props.markings === "graph",
|
|
28294
|
+
lines: props.step[index],
|
|
28295
|
+
subdivisions: props.step[index] / props.gridStep[index],
|
|
28296
|
+
labels: n => renderLineLabel(n, props.range[index]) ? n : ""
|
|
28297
|
+
});
|
|
28298
|
+
const Grid = props => props.markings === "none" ? null : /*#__PURE__*/React.createElement(Coordinates.Cartesian, {
|
|
28299
|
+
xAxis: axisOptions(props, 0),
|
|
28300
|
+
yAxis: axisOptions(props, 1)
|
|
28301
|
+
});
|
|
28302
|
+
|
|
28303
|
+
// Displays a stylized open eye: lint warnings are visible
|
|
28304
|
+
const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
28305
|
+
width: "24",
|
|
28306
|
+
height: "24",
|
|
28307
|
+
viewBox: "0 0 24 24",
|
|
28308
|
+
className: css(styles$j.icon)
|
|
28309
|
+
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
28310
|
+
id: "a",
|
|
28311
|
+
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"
|
|
28312
|
+
})), /*#__PURE__*/React.createElement("g", {
|
|
28313
|
+
fill: "none",
|
|
28314
|
+
fillRule: "evenodd"
|
|
28315
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28316
|
+
fill: "none",
|
|
28317
|
+
d: "M0 0h24v24H0z"
|
|
28318
|
+
}), /*#__PURE__*/React.createElement("mask", {
|
|
28319
|
+
id: "b",
|
|
28320
|
+
fill: "#fff"
|
|
28321
|
+
}, /*#__PURE__*/React.createElement("use", {
|
|
28322
|
+
href: "#a"
|
|
28323
|
+
})), /*#__PURE__*/React.createElement("use", {
|
|
28324
|
+
fill: "#fff",
|
|
28325
|
+
fillRule: "nonzero",
|
|
28326
|
+
href: "#a"
|
|
28327
|
+
}), /*#__PURE__*/React.createElement("g", {
|
|
28328
|
+
fill: "#fff",
|
|
28329
|
+
mask: "url(#b)"
|
|
28330
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28331
|
+
d: "M0 0h24v24H0z"
|
|
28332
|
+
}))));
|
|
28333
|
+
|
|
28334
|
+
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
28335
|
+
const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
28336
|
+
width: "24",
|
|
28337
|
+
height: "24",
|
|
28338
|
+
viewBox: "0 0 24 24",
|
|
28339
|
+
className: css(styles$j.icon)
|
|
28340
|
+
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
28341
|
+
id: "a",
|
|
28342
|
+
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"
|
|
28343
|
+
})), /*#__PURE__*/React.createElement("g", {
|
|
28344
|
+
fill: "none",
|
|
28345
|
+
fillRule: "evenodd"
|
|
28346
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28347
|
+
fill: "none",
|
|
28348
|
+
d: "M0 0h24v24H0z"
|
|
28349
|
+
}), /*#__PURE__*/React.createElement("mask", {
|
|
28350
|
+
id: "b",
|
|
28351
|
+
fill: "#fff"
|
|
28352
|
+
}, /*#__PURE__*/React.createElement("use", {
|
|
28353
|
+
href: "#a"
|
|
28354
|
+
})), /*#__PURE__*/React.createElement("use", {
|
|
28355
|
+
fill: "#fff",
|
|
28356
|
+
fillRule: "nonzero",
|
|
28357
|
+
href: "#a"
|
|
28358
|
+
}), /*#__PURE__*/React.createElement("g", {
|
|
28359
|
+
fill: "#fff",
|
|
28360
|
+
mask: "url(#b)"
|
|
28361
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28362
|
+
d: "M0 0h24v24H0z"
|
|
28363
|
+
}))));
|
|
28364
|
+
const HUD = ({
|
|
28365
|
+
message,
|
|
28366
|
+
enabled,
|
|
28367
|
+
onClick,
|
|
28368
|
+
fixedPosition: _fixedPosition = true
|
|
28369
|
+
}) => {
|
|
28370
|
+
let state;
|
|
28371
|
+
let icon;
|
|
28372
|
+
if (enabled) {
|
|
28373
|
+
state = styles$j.enabled;
|
|
28374
|
+
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
28375
|
+
} else {
|
|
28376
|
+
state = styles$j.disabled;
|
|
28377
|
+
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
28378
|
+
}
|
|
28379
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
28380
|
+
className: css(styles$j.hud, _fixedPosition && styles$j.hudFixedPosition, state),
|
|
28381
|
+
onClick: e => {
|
|
28382
|
+
onClick();
|
|
28383
|
+
}
|
|
28384
|
+
}, icon, message);
|
|
28385
|
+
};
|
|
28386
|
+
const styles$j = StyleSheet.create({
|
|
28387
|
+
hud: {
|
|
28388
|
+
boxSizing: "border-box",
|
|
28389
|
+
height: 36,
|
|
28390
|
+
padding: "9px 16px",
|
|
28391
|
+
borderRadius: 18,
|
|
28392
|
+
fontFamily: boldFontFamily,
|
|
28393
|
+
fontSize: "15px",
|
|
28394
|
+
lineHeight: "18px",
|
|
28395
|
+
color: white$1,
|
|
28396
|
+
userSelect: "none",
|
|
28397
|
+
borderWidth: 0 // <button> gives us a border by default
|
|
28398
|
+
},
|
|
28399
|
+
|
|
28400
|
+
// We want to render the element in-place in our fixtures, so allow us to
|
|
28401
|
+
// render in the bottom corner in production and in-place in testing.
|
|
28402
|
+
hudFixedPosition: {
|
|
28403
|
+
bottom: 20,
|
|
28404
|
+
position: "fixed",
|
|
28405
|
+
right: 20,
|
|
28406
|
+
zIndex: 1
|
|
28407
|
+
},
|
|
28408
|
+
icon: {
|
|
28409
|
+
width: 24,
|
|
28410
|
+
height: 24,
|
|
28411
|
+
marginRight: 8,
|
|
28412
|
+
marginTop: -3,
|
|
28413
|
+
verticalAlign: "middle"
|
|
28414
|
+
},
|
|
28415
|
+
enabled: {
|
|
28416
|
+
backgroundColor: warningColor,
|
|
28417
|
+
":hover": {
|
|
28418
|
+
backgroundColor: warningColorHover
|
|
28419
|
+
},
|
|
28420
|
+
":active": {
|
|
28421
|
+
backgroundColor: warningColorActive
|
|
28422
|
+
}
|
|
28423
|
+
},
|
|
28424
|
+
disabled: {
|
|
28425
|
+
backgroundColor: gray76,
|
|
28426
|
+
":hover": {
|
|
28427
|
+
backgroundColor: "#a1a5a9" // in between those two grays
|
|
28428
|
+
},
|
|
28429
|
+
|
|
28430
|
+
":active": {
|
|
28431
|
+
backgroundColor: gray68
|
|
28432
|
+
}
|
|
28433
|
+
}
|
|
28434
|
+
});
|
|
28435
|
+
|
|
28436
|
+
const colors$1 = {
|
|
28437
|
+
grayLight: "#aaa",
|
|
28438
|
+
basicBorderColor: "#ccc",
|
|
28439
|
+
white: "#fff"
|
|
28440
|
+
};
|
|
28441
|
+
const triangleBeforeAfter = {
|
|
28442
|
+
borderBottom: "9px solid transparent",
|
|
28443
|
+
borderTop: "9px solid transparent",
|
|
28444
|
+
content: '" "',
|
|
28445
|
+
height: "0",
|
|
28446
|
+
position: "absolute",
|
|
28447
|
+
top: "0",
|
|
28448
|
+
width: "0"
|
|
28449
|
+
};
|
|
28450
|
+
const styles$i = StyleSheet.create({
|
|
28451
|
+
infoTip: {
|
|
28452
|
+
display: "inline-block",
|
|
28453
|
+
marginLeft: "5px",
|
|
28454
|
+
position: "relative"
|
|
28455
|
+
},
|
|
28456
|
+
infoTipContainer: {
|
|
28457
|
+
position: "absolute",
|
|
28458
|
+
top: "-12px",
|
|
28459
|
+
left: "22px",
|
|
28460
|
+
zIndex: 1000
|
|
28461
|
+
},
|
|
28462
|
+
infoTipTriangle: {
|
|
28463
|
+
height: "10px",
|
|
28464
|
+
left: "0",
|
|
28465
|
+
position: "absolute",
|
|
28466
|
+
top: "8px",
|
|
28467
|
+
width: "0",
|
|
28468
|
+
zIndex: 1,
|
|
28469
|
+
":before": _extends({}, triangleBeforeAfter, {
|
|
28470
|
+
borderRight: "9px solid #bbb",
|
|
28471
|
+
right: "0"
|
|
28472
|
+
}),
|
|
28473
|
+
":after": _extends({}, triangleBeforeAfter, {
|
|
28474
|
+
borderRight: `9px solid ${colors$1.white}`,
|
|
28475
|
+
right: "-1px"
|
|
28476
|
+
})
|
|
28477
|
+
},
|
|
28478
|
+
verticalShadow: {
|
|
28479
|
+
border: `1px solid ${colors$1.basicBorderColor}`,
|
|
28480
|
+
boxShadow: `0 1px 3px ${colors$1.basicBorderColor}`,
|
|
28481
|
+
borderBottom: `1px solid ${colors$1.grayLight}`
|
|
28482
|
+
},
|
|
28483
|
+
infoTipContentContainer: {
|
|
28484
|
+
background: colors$1.white,
|
|
28485
|
+
padding: "5px 10px",
|
|
28486
|
+
width: "240px"
|
|
28487
|
+
}
|
|
28488
|
+
});
|
|
28489
|
+
const questionMark = "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBB" + "ZG9iZSBJbWFnZVJlYWR5ccllPAAAA3NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/" + "eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+" + "IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2Jl" + "IFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAg" + "ICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5" + "LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9" + "IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHht" + "bG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3Vy" + "Y2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHht" + "cE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo2N2M3NTAxYS04YmVlLTQ0M2Mt" + "YmRiNS04OGM2N2IxN2NhYzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUJCRTk4" + "Qjc4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5p" + "aWQ6OUJCRTk4QjY4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcDpDcmVhdG9yVG9v" + "bD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRG" + "cm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NGE5ZDI0OTMtODk1NC00OGFkLTlh" + "MTgtZDAwM2MwYWNjNDJlIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY3Yzc1MDFh" + "LThiZWUtNDQzYy1iZGI1LTg4YzY3YjE3Y2FjMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4g" + "PC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pqm89uYAAADM" + "SURBVHjaXJA9DoJAEIUH1M4TUHIFsCMGen9OwCGw1YRGW2ntKel0exsojHIBC0ouQAyU" + "viFDstmXfNmZeS+zm7XSNCXRFiRgJf0bXIHixpbhGdxBBJYC1w/xaA424MhNEATkui71" + "fU9KqfEU78UbD9PdbJRlOdae55GmhIP+1NV1TcMwkOM41DSNHvRtMhTHMRVFQW3b6mOL" + "gx99kue5GRp/gIOZuZGvNpTNwjD8oliANU+qqqKu6/TQBdymN57AHjzBT+B6Jx79BRgA" + "vc49kQA4yxgAAAAASUVORK5CYII=";
|
|
28490
|
+
class InfoTip$1 extends React.Component {
|
|
28491
|
+
constructor(...args) {
|
|
28492
|
+
super(...args);
|
|
28493
|
+
this.state = {
|
|
28494
|
+
hover: false
|
|
28495
|
+
};
|
|
28496
|
+
this.handleMouseEnter = () => {
|
|
28497
|
+
this.setState({
|
|
28498
|
+
hover: true
|
|
28499
|
+
});
|
|
28500
|
+
};
|
|
28501
|
+
this.handleMouseLeave = () => {
|
|
28502
|
+
this.setState({
|
|
28503
|
+
hover: false
|
|
28504
|
+
});
|
|
28505
|
+
};
|
|
28506
|
+
}
|
|
28507
|
+
render() {
|
|
28508
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
28509
|
+
className: css(styles$i.infoTip)
|
|
28510
|
+
}, /*#__PURE__*/React.createElement("img", {
|
|
28511
|
+
alt: "",
|
|
28512
|
+
width: 10,
|
|
28513
|
+
height: 10,
|
|
28514
|
+
src: questionMark,
|
|
28515
|
+
onMouseEnter: this.handleMouseEnter,
|
|
28516
|
+
onMouseLeave: this.handleMouseLeave
|
|
28517
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
28518
|
+
className: css(styles$i.infoTipContainer),
|
|
28519
|
+
style: {
|
|
28520
|
+
display: this.state.hover ? "block" : "none"
|
|
28521
|
+
}
|
|
28522
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
28523
|
+
className: css(styles$i.infoTipTriangle)
|
|
28524
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
28525
|
+
className: css(styles$i.verticalShadow, styles$i.infoTipContentContainer)
|
|
28526
|
+
}, this.props.children)));
|
|
28527
|
+
}
|
|
28528
|
+
}
|
|
28529
|
+
|
|
28530
|
+
/**
|
|
28531
|
+
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
28532
|
+
* server without causing a checksum mismatch on the client.
|
|
28533
|
+
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
28534
|
+
* two sets of generated classnames will not match.)
|
|
28535
|
+
*/
|
|
28536
|
+
class InfoTip extends React.Component {
|
|
28537
|
+
constructor(...args) {
|
|
28538
|
+
super(...args);
|
|
28539
|
+
this.state = {
|
|
28540
|
+
didMount: false
|
|
28541
|
+
};
|
|
28542
|
+
}
|
|
28543
|
+
componentDidMount() {
|
|
28544
|
+
/* eslint-disable react/no-did-mount-set-state */
|
|
28545
|
+
this.setState({
|
|
28546
|
+
didMount: true
|
|
28547
|
+
});
|
|
28548
|
+
/* eslint-enable react/no-did-mount-set-state */
|
|
28549
|
+
}
|
|
28550
|
+
|
|
28551
|
+
render() {
|
|
28552
|
+
if (this.state.didMount) {
|
|
28553
|
+
return /*#__PURE__*/React.createElement(InfoTip$1, this.props);
|
|
28554
|
+
}
|
|
28555
|
+
return /*#__PURE__*/React.createElement("div", null);
|
|
28556
|
+
}
|
|
28557
|
+
}
|
|
28558
|
+
|
|
28559
|
+
/**
|
|
28560
|
+
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
28561
|
+
* which allows multiple buttons to be selected at the same time.
|
|
28562
|
+
*
|
|
28563
|
+
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
28564
|
+
* this component allows multiple selection!
|
|
28565
|
+
*/
|
|
28566
|
+
class MultiButtonGroup extends React.Component {
|
|
28567
|
+
constructor(...args) {
|
|
28568
|
+
super(...args);
|
|
28569
|
+
this.toggleSelect = newValue => {
|
|
28570
|
+
const values = (this.props.values || []).slice(0);
|
|
28571
|
+
const allowEmpty = this.props.allowEmpty;
|
|
28572
|
+
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
28573
|
+
// If the value is already selected, unselect it
|
|
28574
|
+
values.splice(values.indexOf(newValue), 1);
|
|
28575
|
+
} else {
|
|
28576
|
+
// Otherwise merge with other values and return
|
|
28577
|
+
if (values.indexOf(newValue) < 0) {
|
|
28578
|
+
values.push(newValue);
|
|
28579
|
+
}
|
|
28580
|
+
}
|
|
28581
|
+
this.props.onChange(values);
|
|
28582
|
+
};
|
|
28583
|
+
}
|
|
28584
|
+
focus() {
|
|
28585
|
+
var _ReactDOM$findDOMNode;
|
|
28586
|
+
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28587
|
+
(_ReactDOM$findDOMNode = ReactDOM.findDOMNode(this)) == null || _ReactDOM$findDOMNode.focus();
|
|
28588
|
+
return true;
|
|
28589
|
+
}
|
|
28590
|
+
render() {
|
|
28591
|
+
const values = this.props.values || [];
|
|
28592
|
+
const buttons = this.props.buttons.map((button, i) => {
|
|
28593
|
+
const selected = values.indexOf(button.value) >= 0;
|
|
28594
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
28595
|
+
title: button.title,
|
|
28596
|
+
type: "button",
|
|
28597
|
+
id: "" + i,
|
|
28598
|
+
key: "" + i,
|
|
28599
|
+
ref: "button" + i,
|
|
28600
|
+
className: css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
28601
|
+
onClick: () => this.toggleSelect(button.value)
|
|
28602
|
+
}, button.content || "" + button.value);
|
|
28603
|
+
});
|
|
28604
|
+
const outerStyle = {
|
|
28605
|
+
display: "inline-block"
|
|
28606
|
+
};
|
|
28607
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
28608
|
+
style: outerStyle
|
|
28609
|
+
}, buttons);
|
|
28610
|
+
}
|
|
28611
|
+
}
|
|
28612
|
+
MultiButtonGroup.defaultProps = {
|
|
28613
|
+
values: [],
|
|
28614
|
+
allowEmpty: true
|
|
28615
|
+
};
|
|
28616
|
+
const styles$h = StyleSheet.create({
|
|
28617
|
+
buttonStyle: {
|
|
28618
|
+
backgroundColor: "white",
|
|
28619
|
+
border: "1px solid #ccc",
|
|
28620
|
+
borderLeft: "0",
|
|
28621
|
+
cursor: "pointer",
|
|
28622
|
+
margin: "0",
|
|
28623
|
+
padding: "5px 10px",
|
|
28624
|
+
position: "relative",
|
|
28625
|
+
// for hover
|
|
28626
|
+
|
|
28627
|
+
":first-child": {
|
|
28628
|
+
borderLeft: "1px solid #ccc",
|
|
28629
|
+
borderTopLeftRadius: "3px",
|
|
28630
|
+
borderBottomLeftRadius: "3px"
|
|
28631
|
+
},
|
|
28632
|
+
":last-child": {
|
|
28633
|
+
borderRight: "1px solid #ccc",
|
|
28634
|
+
borderTopRightRadius: "3px",
|
|
28635
|
+
borderBottomRightRadius: "3px"
|
|
28636
|
+
},
|
|
28637
|
+
":hover": {
|
|
28638
|
+
backgroundColor: "#ccc"
|
|
28639
|
+
},
|
|
28640
|
+
":focus": {
|
|
28641
|
+
zIndex: 2
|
|
28642
|
+
}
|
|
28643
|
+
},
|
|
28644
|
+
selectedStyle: {
|
|
28645
|
+
backgroundColor: "#ddd"
|
|
28646
|
+
}
|
|
28647
|
+
});
|
|
28648
|
+
|
|
28649
|
+
const _excluded$2 = ["onFormatChange", "checkValidity", "useArrowKeys"];
|
|
28650
|
+
const {
|
|
28651
|
+
firstNumericalParse,
|
|
28652
|
+
captureScratchpadTouchStart
|
|
28653
|
+
} = Util;
|
|
28654
|
+
const toNumericString = KhanMath.toNumericString;
|
|
28655
|
+
const getNumericFormat = KhanMath.getNumericFormat;
|
|
28656
|
+
|
|
28657
|
+
/* An input box that accepts only numeric strings
|
|
28658
|
+
*
|
|
28659
|
+
* Calls onChange(value, format) for valid numbers.
|
|
28660
|
+
* Reverts to the current value onBlur or on [ENTER],
|
|
28661
|
+
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
28662
|
+
* Accepts empty input and sends it to onChange as null
|
|
28663
|
+
* if no numeric placeholder is set.
|
|
28664
|
+
* If given a checkValidity function, will turn
|
|
28665
|
+
* the background/outline red when invalid
|
|
28666
|
+
* If useArrowKeys is set to true, up/down arrows will
|
|
28667
|
+
* increment/decrement integers
|
|
28668
|
+
* Optionally takes a size ("mini", "small", "normal")
|
|
28669
|
+
*/
|
|
28670
|
+
class NumberInput extends React.Component {
|
|
28671
|
+
constructor(...args) {
|
|
28672
|
+
super(...args);
|
|
28673
|
+
this.state = {
|
|
28674
|
+
format: this.props.format
|
|
28675
|
+
};
|
|
28676
|
+
/* Return the current "value" of this input
|
|
28677
|
+
* If empty, it returns the placeholder (if it is a number) or null
|
|
28678
|
+
*/
|
|
28679
|
+
this.getValue = () => {
|
|
28680
|
+
return this.parseInputValue(
|
|
28681
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28682
|
+
ReactDOM__default.findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
28683
|
+
);
|
|
28684
|
+
};
|
|
28685
|
+
/* Return the current string value of this input */
|
|
28686
|
+
this.getStringValue = () => {
|
|
28687
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28688
|
+
return ReactDOM__default.findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
28689
|
+
};
|
|
28690
|
+
this.parseInputValue = value => {
|
|
28691
|
+
if (value === "") {
|
|
28692
|
+
const placeholder = this.props.placeholder;
|
|
28693
|
+
return _.isFinite(placeholder) ? +placeholder : null;
|
|
28694
|
+
}
|
|
28695
|
+
const result = firstNumericalParse(value);
|
|
28696
|
+
return _.isFinite(result) ? result : this.props.value;
|
|
28697
|
+
};
|
|
28698
|
+
/* Set text input focus to this input */
|
|
28699
|
+
this.focus = () => {
|
|
28700
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28701
|
+
ReactDOM__default.findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
28702
|
+
this._handleFocus();
|
|
28703
|
+
};
|
|
28704
|
+
this.blur = () => {
|
|
28705
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
28706
|
+
ReactDOM__default.findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
28707
|
+
this._handleBlur();
|
|
28708
|
+
};
|
|
28709
|
+
this.setSelectionRange = (selectionStart, selectionEnd) => {
|
|
28710
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
28711
|
+
ReactDOM__default.findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
28712
|
+
};
|
|
28713
|
+
this.getSelectionStart = () => {
|
|
28714
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
28715
|
+
return ReactDOM__default.findDOMNode(this).selectionStart;
|
|
28716
|
+
};
|
|
28717
|
+
this.getSelectionEnd = () => {
|
|
28718
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
28719
|
+
return ReactDOM__default.findDOMNode(this).selectionEnd;
|
|
28720
|
+
};
|
|
28721
|
+
this._checkValidity = value => {
|
|
28722
|
+
if (value == null) {
|
|
28723
|
+
return true;
|
|
28724
|
+
}
|
|
28725
|
+
const val = firstNumericalParse(value);
|
|
28726
|
+
const checkValidity = this.props.checkValidity;
|
|
28727
|
+
return _.isFinite(val) && checkValidity(val);
|
|
28728
|
+
};
|
|
28729
|
+
this._handleChange = e => {
|
|
28730
|
+
const text = e.target.value;
|
|
28731
|
+
const value = this.parseInputValue(text);
|
|
28732
|
+
const format = getNumericFormat(text);
|
|
28733
|
+
this.props.onChange(value);
|
|
28734
|
+
if (format) {
|
|
28735
|
+
this.props.onFormatChange(value, format);
|
|
28736
|
+
this.setState({
|
|
28737
|
+
format: format
|
|
28738
|
+
});
|
|
28739
|
+
}
|
|
28740
|
+
};
|
|
28741
|
+
this._handleFocus = () => {
|
|
28742
|
+
if (this.props.onFocus) {
|
|
28743
|
+
this.props.onFocus();
|
|
28744
|
+
}
|
|
28745
|
+
};
|
|
28746
|
+
this._handleBlur = e => {
|
|
28747
|
+
// Only continue on blur or "enter"
|
|
28748
|
+
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
28749
|
+
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
28750
|
+
return;
|
|
28751
|
+
}
|
|
28752
|
+
this._setValue(this.props.value, this.state.format);
|
|
28753
|
+
if (this.props.onBlur) {
|
|
28754
|
+
this.props.onBlur();
|
|
28755
|
+
}
|
|
28756
|
+
};
|
|
28757
|
+
this._onKeyDown = e => {
|
|
28758
|
+
if (this.props.onKeyDown) {
|
|
28759
|
+
this.props.onKeyDown(e);
|
|
28760
|
+
}
|
|
28761
|
+
if (!this.props.useArrowKeys || !_.contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
28762
|
+
return;
|
|
28763
|
+
}
|
|
28764
|
+
let val = this.getValue();
|
|
28765
|
+
if (val !== Math.floor(val)) {
|
|
28766
|
+
return; // bail if not an integer
|
|
28767
|
+
}
|
|
28768
|
+
|
|
28769
|
+
if (e.key === "ArrowUp") {
|
|
28770
|
+
val = val + 1;
|
|
28771
|
+
} else if (e.key === "ArrowDown") {
|
|
28772
|
+
val = val - 1;
|
|
28773
|
+
}
|
|
28774
|
+
if (this._checkValidity(val)) {
|
|
28775
|
+
this.props.onChange(val);
|
|
28776
|
+
}
|
|
28777
|
+
};
|
|
28778
|
+
this._setValue = (val, format) => {
|
|
28779
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28780
|
+
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
28781
|
+
$(ReactDOM__default.findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
28782
|
+
};
|
|
28783
|
+
}
|
|
28784
|
+
render() {
|
|
28785
|
+
let classes = classNames({
|
|
28786
|
+
"number-input": true,
|
|
28787
|
+
"invalid-input": !this._checkValidity(this.props.value),
|
|
28788
|
+
mini: this.props.size === "mini",
|
|
28789
|
+
small: this.props.size === "small",
|
|
28790
|
+
normal: this.props.size === "normal"
|
|
28791
|
+
});
|
|
28792
|
+
if (this.props.className != null) {
|
|
28793
|
+
classes = classes + " " + this.props.className;
|
|
28794
|
+
}
|
|
28795
|
+
const _this$props = this.props,
|
|
28796
|
+
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$2);
|
|
28797
|
+
return /*#__PURE__*/React.createElement("input", _extends({}, restProps, {
|
|
28798
|
+
className: classes,
|
|
28799
|
+
type: "text"
|
|
28800
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28801
|
+
,
|
|
28802
|
+
ref: "input",
|
|
28803
|
+
onChange: this._handleChange,
|
|
28804
|
+
onFocus: this._handleFocus,
|
|
28805
|
+
onBlur: this._handleBlur,
|
|
28806
|
+
onKeyPress: this._handleBlur,
|
|
28807
|
+
onKeyDown: this._onKeyDown
|
|
28808
|
+
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
28809
|
+
,
|
|
28810
|
+
onTouchStart: captureScratchpadTouchStart,
|
|
28811
|
+
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
28812
|
+
value: undefined
|
|
28813
|
+
}));
|
|
28814
|
+
}
|
|
28815
|
+
componentDidUpdate(prevProps) {
|
|
28816
|
+
if (!number.equal(this.getValue(), this.props.value)) {
|
|
28817
|
+
this._setValue(this.props.value, this.state.format);
|
|
28818
|
+
}
|
|
28819
|
+
}
|
|
28820
|
+
}
|
|
28821
|
+
NumberInput.propTypes = {
|
|
28822
|
+
value: PropTypes.number,
|
|
28823
|
+
format: PropTypes.string,
|
|
28824
|
+
placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
28825
|
+
onChange: PropTypes.func.isRequired,
|
|
28826
|
+
onFormatChange: PropTypes.func,
|
|
28827
|
+
checkValidity: PropTypes.func,
|
|
28828
|
+
size: PropTypes.string,
|
|
28829
|
+
label: PropTypes.oneOf(["put your labels outside your inputs!"])
|
|
28830
|
+
};
|
|
28831
|
+
NumberInput.defaultProps = {
|
|
28832
|
+
value: null,
|
|
28833
|
+
placeholder: null,
|
|
28834
|
+
format: null,
|
|
28835
|
+
onFormatChange: () => null,
|
|
28836
|
+
checkValidity: () => true,
|
|
28837
|
+
useArrowKeys: false
|
|
28838
|
+
};
|
|
28839
|
+
|
|
28840
|
+
/* eslint-disable @babel/no-invalid-this */
|
|
28841
|
+
|
|
28842
|
+
/* A checkbox that syncs its value to props using the
|
|
28843
|
+
* renderer's onChange method, and gets the prop name
|
|
28844
|
+
* dynamically from its props list
|
|
28845
|
+
*/
|
|
28846
|
+
const PropCheckBox = createReactClass({
|
|
28847
|
+
displayName: "PropCheckBox",
|
|
28848
|
+
propTypes: {
|
|
28849
|
+
labelAlignment: PropTypes.oneOf(["left", "right"])
|
|
28850
|
+
},
|
|
28851
|
+
DEFAULT_PROPS: {
|
|
28852
|
+
label: null,
|
|
28853
|
+
onChange: null,
|
|
28854
|
+
labelAlignment: "left"
|
|
28855
|
+
},
|
|
28856
|
+
getDefaultProps: function () {
|
|
28857
|
+
return this.DEFAULT_PROPS;
|
|
28858
|
+
},
|
|
28859
|
+
propName: function () {
|
|
28860
|
+
const propName = _.find(_.keys(this.props), function (localPropName) {
|
|
28861
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
28862
|
+
return !_.has(this.DEFAULT_PROPS, localPropName);
|
|
28863
|
+
}, this);
|
|
28864
|
+
if (!propName) {
|
|
28865
|
+
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
28866
|
+
}
|
|
28867
|
+
return propName;
|
|
28868
|
+
},
|
|
28869
|
+
_labelAlignLeft: function () {
|
|
28870
|
+
return this.props.labelAlignment === "left";
|
|
28871
|
+
},
|
|
28872
|
+
render: function () {
|
|
28873
|
+
const propName = this.propName();
|
|
28874
|
+
return /*#__PURE__*/React.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React.createElement("input", {
|
|
28875
|
+
type: "checkbox",
|
|
28876
|
+
checked: this.props[propName],
|
|
28877
|
+
onChange: this.toggle
|
|
28878
|
+
}), !this._labelAlignLeft() && this.props.label);
|
|
28879
|
+
},
|
|
28880
|
+
toggle: function () {
|
|
28881
|
+
const propName = this.propName();
|
|
28882
|
+
const changes = {};
|
|
28883
|
+
changes[propName] = !this.props[propName];
|
|
28884
|
+
this.props.onChange(changes);
|
|
28885
|
+
}
|
|
28886
|
+
});
|
|
28887
|
+
|
|
28888
|
+
const truth = () => true;
|
|
28889
|
+
|
|
28890
|
+
/* A minor abstraction on top of NumberInput for ranges
|
|
28891
|
+
*
|
|
28892
|
+
*/
|
|
28893
|
+
class RangeInput extends React.Component {
|
|
28894
|
+
constructor(...args) {
|
|
28895
|
+
super(...args);
|
|
28896
|
+
this.onChange = (i, newVal) => {
|
|
28897
|
+
const value = this.props.value;
|
|
28898
|
+
if (i === 0) {
|
|
28899
|
+
this.props.onChange([newVal, value[1]]);
|
|
28900
|
+
} else {
|
|
28901
|
+
this.props.onChange([value[0], newVal]);
|
|
28902
|
+
}
|
|
28903
|
+
};
|
|
28904
|
+
}
|
|
28905
|
+
render() {
|
|
28906
|
+
const value = this.props.value;
|
|
28907
|
+
const checkValidity = this.props.checkValidity || truth;
|
|
28908
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
28909
|
+
className: "range-input"
|
|
28910
|
+
}, /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
28911
|
+
value: value[0],
|
|
28912
|
+
checkValidity: val => checkValidity([val, value[1]])
|
|
28913
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
28914
|
+
,
|
|
28915
|
+
onChange: this.onChange.bind(this, 0),
|
|
28916
|
+
placeholder: this.props.placeholder[0]
|
|
28917
|
+
})), /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
28918
|
+
value: value[1],
|
|
28919
|
+
checkValidity: val => checkValidity([value[0], val])
|
|
28920
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
28921
|
+
,
|
|
28922
|
+
onChange: this.onChange.bind(this, 1),
|
|
28923
|
+
placeholder: this.props.placeholder[1]
|
|
28924
|
+
})));
|
|
28925
|
+
}
|
|
28926
|
+
}
|
|
28927
|
+
RangeInput.propTypes = {
|
|
28928
|
+
value: PropTypes.array.isRequired,
|
|
28929
|
+
onChange: PropTypes.func.isRequired,
|
|
28930
|
+
placeholder: PropTypes.array,
|
|
28931
|
+
checkValidity: PropTypes.func
|
|
28932
|
+
};
|
|
28933
|
+
RangeInput.defaultProps = {
|
|
28934
|
+
placeholder: [null, null]
|
|
28935
|
+
};
|
|
28936
|
+
|
|
28937
|
+
var components = /*#__PURE__*/Object.freeze({
|
|
28938
|
+
__proto__: null,
|
|
28939
|
+
ButtonGroup: ButtonGroup,
|
|
28940
|
+
Graph: Graph,
|
|
28941
|
+
Graphie: Graphie,
|
|
28942
|
+
HUD: HUD,
|
|
28943
|
+
Icon: Icon,
|
|
28944
|
+
InfoTip: InfoTip,
|
|
28945
|
+
InlineIcon: InlineIcon,
|
|
28946
|
+
MathInput: MathInput,
|
|
28947
|
+
MultiButtonGroup: MultiButtonGroup,
|
|
28948
|
+
NumberInput: NumberInput,
|
|
28949
|
+
PropCheckBox: PropCheckBox,
|
|
28950
|
+
RangeInput: RangeInput,
|
|
28951
|
+
SvgImage: SvgImage,
|
|
28952
|
+
TextInput: TextInput,
|
|
28953
|
+
TextListEditor: TextListEditor
|
|
28954
|
+
});
|
|
28955
|
+
|
|
28956
|
+
/**
|
|
28957
|
+
* If a graphie URL is provided in `backgroundImage`, will return the rendered graphie background.
|
|
28958
|
+
* Otherwise, returns `null`.
|
|
28959
|
+
*/
|
|
28960
|
+
const getLegacyGrid = (box, backgroundImage) => {
|
|
28961
|
+
const {
|
|
28962
|
+
url,
|
|
28963
|
+
width,
|
|
28964
|
+
height
|
|
28965
|
+
} = backgroundImage != null ? backgroundImage : {};
|
|
28966
|
+
if (url && typeof url === "string") {
|
|
28967
|
+
const scale = box[0] / interactiveSizes$1.defaultBoxSize;
|
|
28968
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
28969
|
+
style: {
|
|
28970
|
+
position: "absolute",
|
|
28971
|
+
bottom: 0,
|
|
28972
|
+
left: 0
|
|
28973
|
+
}
|
|
28974
|
+
}, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
|
|
28975
|
+
setAssetStatus
|
|
28976
|
+
}) => /*#__PURE__*/React.createElement(SvgImage, {
|
|
28977
|
+
src: url,
|
|
28978
|
+
width: width,
|
|
28979
|
+
height: height,
|
|
28980
|
+
scale: scale,
|
|
28981
|
+
responsive: false,
|
|
28982
|
+
setAssetStatus: setAssetStatus,
|
|
28983
|
+
alt: ""
|
|
28984
|
+
})));
|
|
28985
|
+
}
|
|
28986
|
+
return null;
|
|
28987
|
+
};
|
|
28988
|
+
|
|
28989
|
+
const _excluded$1 = ["graph"];
|
|
28990
|
+
const renderGraph = props => {
|
|
28991
|
+
const {
|
|
28992
|
+
graph
|
|
28993
|
+
} = props,
|
|
28994
|
+
rest = _objectWithoutPropertiesLoose(props, _excluded$1);
|
|
28995
|
+
switch (graph.type) {
|
|
28996
|
+
case "segment":
|
|
28997
|
+
return /*#__PURE__*/React.createElement(SegmentGraph, _extends({}, rest, {
|
|
28998
|
+
graph: graph,
|
|
28999
|
+
onGraphChange: props.onGraphChange
|
|
29000
|
+
}));
|
|
29001
|
+
}
|
|
29002
|
+
};
|
|
29003
|
+
const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
29004
|
+
var _props$backgroundImag, _props$backgroundImag2, _props$backgroundImag3, _props$backgroundImag4;
|
|
29005
|
+
// Storing the gradable state in a ref so that it can be updated without
|
|
29006
|
+
// causing a re-render.
|
|
29007
|
+
const graphRef = React.useRef(props.graph);
|
|
29008
|
+
const handleGraphUpdate = callback => {
|
|
29009
|
+
graphRef.current = callback(graphRef.current);
|
|
29010
|
+
};
|
|
29011
|
+
React.useImperativeHandle(ref, () => ({
|
|
29012
|
+
getUserInput: () => graphRef.current
|
|
29013
|
+
}));
|
|
29014
|
+
const [width, height] = getInteractiveBoxFromSizeClass(props.containerSizeClass);
|
|
29015
|
+
const legacyGrid = getLegacyGrid([width, height], props.backgroundImage);
|
|
29016
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
29017
|
+
style: {
|
|
29018
|
+
width: (_props$backgroundImag = (_props$backgroundImag2 = props.backgroundImage) == null ? void 0 : _props$backgroundImag2.width) != null ? _props$backgroundImag : width,
|
|
29019
|
+
height: (_props$backgroundImag3 = (_props$backgroundImag4 = props.backgroundImage) == null ? void 0 : _props$backgroundImag4.height) != null ? _props$backgroundImag3 : height,
|
|
29020
|
+
position: "relative"
|
|
29021
|
+
}
|
|
29022
|
+
}, legacyGrid, /*#__PURE__*/React.createElement(View, {
|
|
29023
|
+
style: {
|
|
29024
|
+
position: "absolute",
|
|
29025
|
+
bottom: 0,
|
|
29026
|
+
left: 0
|
|
29027
|
+
}
|
|
29028
|
+
}, /*#__PURE__*/React.createElement(Mafs, {
|
|
29029
|
+
viewBox: {
|
|
29030
|
+
x: props.range[0],
|
|
29031
|
+
y: props.range[1],
|
|
29032
|
+
padding: 0
|
|
29033
|
+
},
|
|
29034
|
+
pan: false,
|
|
29035
|
+
zoom: false,
|
|
29036
|
+
width: width,
|
|
29037
|
+
height: height
|
|
29038
|
+
}, !!legacyGrid && /*#__PURE__*/React.createElement(Grid, props), renderGraph(_extends({}, props, {
|
|
29039
|
+
onGraphChange: handleGraphUpdate
|
|
29040
|
+
})))));
|
|
29041
|
+
});
|
|
29042
|
+
|
|
28176
29043
|
const {
|
|
28177
29044
|
DeprecationMixin
|
|
28178
29045
|
} = Util;
|
|
@@ -28250,6 +29117,7 @@ class InteractiveGraph extends React.Component {
|
|
|
28250
29117
|
this.sinusoid = void 0;
|
|
28251
29118
|
this.trashCan = void 0;
|
|
28252
29119
|
this.vertHairline = void 0;
|
|
29120
|
+
this.mafsRef = /*#__PURE__*/React.createRef();
|
|
28253
29121
|
this.state = {
|
|
28254
29122
|
shouldShowInstructions: _getShouldShowInstructions(this.props)
|
|
28255
29123
|
};
|
|
@@ -29329,11 +30197,10 @@ class InteractiveGraph extends React.Component {
|
|
|
29329
30197
|
});
|
|
29330
30198
|
};
|
|
29331
30199
|
this.getUserInput = () => {
|
|
29332
|
-
|
|
29333
|
-
|
|
29334
|
-
this.simpleValidate = rubric => {
|
|
29335
|
-
return InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
30200
|
+
var _this$mafsRef$current, _this$mafsRef$current2;
|
|
30201
|
+
return (_this$mafsRef$current = (_this$mafsRef$current2 = this.mafsRef.current) == null || _this$mafsRef$current2.getUserInput == null ? void 0 : _this$mafsRef$current2.getUserInput()) != null ? _this$mafsRef$current : InteractiveGraph.getUserInputFromProps(this.props);
|
|
29336
30202
|
};
|
|
30203
|
+
this.simpleValidate = rubric => InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
29337
30204
|
this.focus = $.noop;
|
|
29338
30205
|
}
|
|
29339
30206
|
// TODO(jangmi, CP-3288): Remove usage of `UNSAFE_componentWillMount`
|
|
@@ -29341,9 +30208,11 @@ class InteractiveGraph extends React.Component {
|
|
|
29341
30208
|
DeprecationMixin.UNSAFE_componentWillMount.call(this);
|
|
29342
30209
|
}
|
|
29343
30210
|
componentDidMount() {
|
|
29344
|
-
|
|
29345
|
-
|
|
29346
|
-
|
|
30211
|
+
if (this.refs.graph) {
|
|
30212
|
+
// eslint-disable-next-line react/no-string-refs
|
|
30213
|
+
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
|
|
30214
|
+
this.setGraphie(this.refs.graph.graphie());
|
|
30215
|
+
}
|
|
29347
30216
|
}
|
|
29348
30217
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
29349
30218
|
var _this$props$backgroun, _nextProps$background;
|
|
@@ -29383,9 +30252,19 @@ class InteractiveGraph extends React.Component {
|
|
|
29383
30252
|
areSegmentGraphsEqual(prevGraph, currentGraph) {
|
|
29384
30253
|
return prevGraph.numSegments !== currentGraph.numSegments;
|
|
29385
30254
|
}
|
|
30255
|
+
// const segment: boolean = useFeatureIsOn("mafs-segment-graph");
|
|
30256
|
+
// <Renderer apiOptions={{flags: {mafs: {segment}}}}
|
|
29386
30257
|
render() {
|
|
30258
|
+
var _this$props$apiOption;
|
|
30259
|
+
// Mafs shim
|
|
30260
|
+
if ((_this$props$apiOption = this.props.apiOptions) != null && (_this$props$apiOption = _this$props$apiOption.flags) != null && (_this$props$apiOption = _this$props$apiOption["mafs"]) != null && _this$props$apiOption[this.props.graph.type]) {
|
|
30261
|
+
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, this.props, {
|
|
30262
|
+
ref: this.mafsRef
|
|
30263
|
+
}));
|
|
30264
|
+
}
|
|
29387
30265
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
29388
30266
|
let instructions;
|
|
30267
|
+
// isClickToAddPoints() only applies to points and polygons
|
|
29389
30268
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
29390
30269
|
if (this.props.graph.type === "point") {
|
|
29391
30270
|
instructions = i18n._("Click to add points");
|
|
@@ -30688,7 +31567,7 @@ var globalConstants = /*#__PURE__*/Object.freeze({
|
|
|
30688
31567
|
pureLgMax: pureLgMax
|
|
30689
31568
|
});
|
|
30690
31569
|
|
|
30691
|
-
const colors
|
|
31570
|
+
const colors = {
|
|
30692
31571
|
white: "#FFFFFF",
|
|
30693
31572
|
gray98: "#FAFAFA",
|
|
30694
31573
|
gray97: "#F6F7F7",
|
|
@@ -30748,7 +31627,7 @@ const colors$1 = {
|
|
|
30748
31627
|
};
|
|
30749
31628
|
const borderRadius = 4;
|
|
30750
31629
|
const breadcrumbStyles = {
|
|
30751
|
-
color: colors
|
|
31630
|
+
color: colors.breadcrumbs,
|
|
30752
31631
|
fontFamily: "inherit",
|
|
30753
31632
|
fontSize: 15,
|
|
30754
31633
|
fontWeight: "bold",
|
|
@@ -30818,14 +31697,14 @@ const typography = {
|
|
|
30818
31697
|
},
|
|
30819
31698
|
// For callouts
|
|
30820
31699
|
smallHeading: {
|
|
30821
|
-
color: colors
|
|
31700
|
+
color: colors.gray25,
|
|
30822
31701
|
fontFamily: "inherit",
|
|
30823
31702
|
fontSize: 17,
|
|
30824
31703
|
fontWeight: "bold",
|
|
30825
31704
|
lineHeight: "23px"
|
|
30826
31705
|
},
|
|
30827
31706
|
smallHeadingMobile: {
|
|
30828
|
-
color: colors
|
|
31707
|
+
color: colors.gray25,
|
|
30829
31708
|
fontFamily: "inherit",
|
|
30830
31709
|
fontSize: 15,
|
|
30831
31710
|
fontWeight: "bold",
|
|
@@ -30833,7 +31712,7 @@ const typography = {
|
|
|
30833
31712
|
},
|
|
30834
31713
|
// Accent headings
|
|
30835
31714
|
accentHeading: {
|
|
30836
|
-
color: colors
|
|
31715
|
+
color: colors.gray68,
|
|
30837
31716
|
fontFamily: "inherit",
|
|
30838
31717
|
fontSize: 15,
|
|
30839
31718
|
fontWeight: "bold",
|
|
@@ -30939,7 +31818,7 @@ const typography = {
|
|
|
30939
31818
|
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
30940
31819
|
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
30941
31820
|
wonderBlocksTitle: {
|
|
30942
|
-
color: colors
|
|
31821
|
+
color: colors.white,
|
|
30943
31822
|
fontWeight: 900,
|
|
30944
31823
|
// "Black" weight
|
|
30945
31824
|
fontSize: 28,
|
|
@@ -30961,7 +31840,7 @@ const typography = {
|
|
|
30961
31840
|
|
|
30962
31841
|
var globalStyles = /*#__PURE__*/Object.freeze({
|
|
30963
31842
|
__proto__: null,
|
|
30964
|
-
colors: colors
|
|
31843
|
+
colors: colors,
|
|
30965
31844
|
borderRadius: borderRadius,
|
|
30966
31845
|
fonts: fonts,
|
|
30967
31846
|
typography: typography
|
|
@@ -31023,7 +31902,7 @@ const HideAnswersToggle = props => {
|
|
|
31023
31902
|
const switchId = idFactory.get("hide-answers-toggle");
|
|
31024
31903
|
const labelId = idFactory.get("hide-answers-label");
|
|
31025
31904
|
return /*#__PURE__*/React.createElement(View, {
|
|
31026
|
-
style: styles$
|
|
31905
|
+
style: styles$g.switchWrapper
|
|
31027
31906
|
}, /*#__PURE__*/React.createElement(Switch, {
|
|
31028
31907
|
id: switchId,
|
|
31029
31908
|
checked: props.areAnswersHidden,
|
|
@@ -31035,7 +31914,7 @@ const HideAnswersToggle = props => {
|
|
|
31035
31914
|
tag: "label"
|
|
31036
31915
|
}, strings.hideAnswersToggleLabel));
|
|
31037
31916
|
};
|
|
31038
|
-
const styles$
|
|
31917
|
+
const styles$g = StyleSheet.create({
|
|
31039
31918
|
switchWrapper: {
|
|
31040
31919
|
display: "flex",
|
|
31041
31920
|
flexDirection: "row",
|
|
@@ -31088,13 +31967,13 @@ const AnswerPill = props => {
|
|
|
31088
31967
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31089
31968
|
onClick: correct ? undefined : onClick,
|
|
31090
31969
|
ref: ref,
|
|
31091
|
-
style: [style, popperStyle, styles$
|
|
31970
|
+
style: [style, popperStyle, styles$f.pill, correct && styles$f.correct, incorrect && styles$f.incorrect, (focused || hovered) && BringToFront]
|
|
31092
31971
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
31093
31972
|
content: answerString,
|
|
31094
31973
|
inline: true
|
|
31095
31974
|
})));
|
|
31096
31975
|
};
|
|
31097
|
-
const styles$
|
|
31976
|
+
const styles$f = StyleSheet.create({
|
|
31098
31977
|
correct: {
|
|
31099
31978
|
// WB green darkened by 18%
|
|
31100
31979
|
backgroundColor: "#00880b"
|
|
@@ -31147,23 +32026,23 @@ class Marker extends React.Component {
|
|
|
31147
32026
|
icon: iconNull
|
|
31148
32027
|
};
|
|
31149
32028
|
if (showCorrectness) {
|
|
31150
|
-
iconStyles = [styles$
|
|
32029
|
+
iconStyles = [styles$e.markerGraded, showCorrectness === "correct" ? styles$e.markerCorrect : styles$e.markerIncorrect, isOpen && styles$e.markerSelected];
|
|
31151
32030
|
args = _extends({}, args, {
|
|
31152
32031
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31153
32032
|
});
|
|
31154
32033
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31155
|
-
iconStyles = [styles$
|
|
32034
|
+
iconStyles = [styles$e.markerFilled, isOpen && styles$e.markerSelected];
|
|
31156
32035
|
} else if (isOpen) {
|
|
31157
|
-
iconStyles = [styles$
|
|
32036
|
+
iconStyles = [styles$e.markerSelected];
|
|
31158
32037
|
args = _extends({}, args, {
|
|
31159
32038
|
icon: iconChevronDown,
|
|
31160
32039
|
size: 8
|
|
31161
32040
|
});
|
|
31162
32041
|
} else if (showPulsate) {
|
|
31163
|
-
iconStyles = [styles$
|
|
32042
|
+
iconStyles = [styles$e.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$e.markerUnfilledPulsateOnce : showPulsate && styles$e.markerUnfilledPulsateInfinite];
|
|
31164
32043
|
}
|
|
31165
32044
|
return /*#__PURE__*/React.createElement(View, {
|
|
31166
|
-
style: [styles$
|
|
32045
|
+
style: [styles$e.markerIcon, iconStyles],
|
|
31167
32046
|
ref: node => this._icon = node
|
|
31168
32047
|
}, /*#__PURE__*/React.createElement(Icon, args));
|
|
31169
32048
|
}
|
|
@@ -31185,7 +32064,7 @@ class Marker extends React.Component {
|
|
|
31185
32064
|
const markerDisabled = showCorrectness === "correct";
|
|
31186
32065
|
const active = hovered || focused;
|
|
31187
32066
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
31188
|
-
style: [styles$
|
|
32067
|
+
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive]
|
|
31189
32068
|
// already translated in: /widgets/graded-group.tsx
|
|
31190
32069
|
,
|
|
31191
32070
|
"aria-label": markerDisabled ? i18n._("Correct!") : label
|
|
@@ -31203,7 +32082,7 @@ class Marker extends React.Component {
|
|
|
31203
32082
|
Marker.defaultProps = {
|
|
31204
32083
|
selected: []
|
|
31205
32084
|
};
|
|
31206
|
-
const styles$
|
|
32085
|
+
const styles$e = StyleSheet.create({
|
|
31207
32086
|
marker: {
|
|
31208
32087
|
position: "absolute",
|
|
31209
32088
|
backgroundColor: Color.white,
|
|
@@ -31773,13 +32652,13 @@ class LabelImage extends React.Component {
|
|
|
31773
32652
|
const promptString = isMobile ? multipleAnswers ? i18n._("Tap each dot on the image to select all answers that apply.") : i18n._("Tap each dot on the image to select an answer.") : multipleAnswers ? i18n._("Click each dot on the image to select all answers that apply.") : i18n._("Click each dot on the image to select an answer.");
|
|
31774
32653
|
const choicesString = i18n._("Choices:");
|
|
31775
32654
|
return /*#__PURE__*/React.createElement("div", {
|
|
31776
|
-
className: classNames("perseus-label-image-widget-instructions", css(styles$
|
|
32655
|
+
className: classNames("perseus-label-image-widget-instructions", css(styles$d.instructions))
|
|
31777
32656
|
}, /*#__PURE__*/React.createElement("div", {
|
|
31778
|
-
className: css(styles$
|
|
32657
|
+
className: css(styles$d.instructionsCaption)
|
|
31779
32658
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React.createElement("div", {
|
|
31780
|
-
className: css(styles$
|
|
32659
|
+
className: css(styles$d.instructionsChoices)
|
|
31781
32660
|
}, choices.map((choice, index) => /*#__PURE__*/React.createElement("div", {
|
|
31782
|
-
className: css(styles$
|
|
32661
|
+
className: css(styles$d.instructionsChoice),
|
|
31783
32662
|
key: index
|
|
31784
32663
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
31785
32664
|
content: choice
|
|
@@ -31796,20 +32675,20 @@ class LabelImage extends React.Component {
|
|
|
31796
32675
|
activeMarkerIndex
|
|
31797
32676
|
} = this.state;
|
|
31798
32677
|
return /*#__PURE__*/React.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React.createElement("div", {
|
|
31799
|
-
className: css(styles$
|
|
32678
|
+
className: css(styles$d.markersCanvas),
|
|
31800
32679
|
style: {
|
|
31801
32680
|
maxWidth: imageWidth,
|
|
31802
32681
|
maxHeight: imageHeight
|
|
31803
32682
|
}
|
|
31804
32683
|
}, /*#__PURE__*/React.createElement("div", {
|
|
31805
|
-
className: css(styles$
|
|
32684
|
+
className: css(styles$d.imageContainer,
|
|
31806
32685
|
// Ensure image interaction is disabled while answer
|
|
31807
32686
|
// choices popup is visible. This addresses specific
|
|
31808
32687
|
// case where user may click on question image to
|
|
31809
32688
|
// dismiss the popup. If the image is larger in size
|
|
31810
32689
|
// than its rendered in the widget, this would
|
|
31811
32690
|
// result in a zoom of the image.
|
|
31812
|
-
activeMarkerIndex !== -1 && styles$
|
|
32691
|
+
activeMarkerIndex !== -1 && styles$d.imageInteractionDisabled)
|
|
31813
32692
|
}, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
|
|
31814
32693
|
setAssetStatus
|
|
31815
32694
|
}) => /*#__PURE__*/React.createElement(SvgImage, {
|
|
@@ -31833,7 +32712,7 @@ class LabelImage extends React.Component {
|
|
|
31833
32712
|
}));
|
|
31834
32713
|
}
|
|
31835
32714
|
}
|
|
31836
|
-
const styles$
|
|
32715
|
+
const styles$d = StyleSheet.create({
|
|
31837
32716
|
instructions: {
|
|
31838
32717
|
paddingBottom: 16
|
|
31839
32718
|
},
|
|
@@ -32190,7 +33069,7 @@ class Placeholder extends React.Component {
|
|
|
32190
33069
|
const {
|
|
32191
33070
|
layout
|
|
32192
33071
|
} = this.props;
|
|
32193
|
-
const className = css(styles$
|
|
33072
|
+
const className = css(styles$c.card, styles$c.placeholder, layout === Layout.HORIZONTAL && styles$c.horizontalCard);
|
|
32194
33073
|
const style = {
|
|
32195
33074
|
width: this.props.width,
|
|
32196
33075
|
height: this.props.height
|
|
@@ -32373,7 +33252,7 @@ class Draggable extends React.Component {
|
|
|
32373
33252
|
// We need to keep backwards compatbility with rules specified directly
|
|
32374
33253
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
32375
33254
|
// See sortable.less for details.
|
|
32376
|
-
let className = css(styles$
|
|
33255
|
+
let className = css(styles$c.card, styles$c.draggable, layout === Layout.HORIZONTAL && styles$c.horizontalCard, layout === Layout.VERTICAL && styles$c.verticalCard, type === ItemState.DRAGGING && styles$c.dragging, type === ItemState.DISABLED && styles$c.disabled, !includePadding && styles$c.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
|
|
32377
33256
|
if (!includePadding) {
|
|
32378
33257
|
className += " perseus-sortable-draggable-unpadded";
|
|
32379
33258
|
}
|
|
@@ -32580,7 +33459,7 @@ class Sortable extends React.Component {
|
|
|
32580
33459
|
} = this.props;
|
|
32581
33460
|
// We need to keep backwards compatbility with rules specified directly
|
|
32582
33461
|
// in CSS. See sortable.less for details.
|
|
32583
|
-
const className = css(styles$
|
|
33462
|
+
const className = css(styles$c.sortable) + " perseus-sortable";
|
|
32584
33463
|
const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === Layout.VERTICAL;
|
|
32585
33464
|
const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === Layout.HORIZONTAL;
|
|
32586
33465
|
_.each(this.state.items, function (item, i, items) {
|
|
@@ -32822,7 +33701,7 @@ Sortable.defaultProps = {
|
|
|
32822
33701
|
linterContext: PerseusLinter.linterContextDefault,
|
|
32823
33702
|
waitForTexRendererToLoad: true
|
|
32824
33703
|
};
|
|
32825
|
-
const styles$
|
|
33704
|
+
const styles$c = StyleSheet.create({
|
|
32826
33705
|
sortable: {
|
|
32827
33706
|
boxSizing: "border-box",
|
|
32828
33707
|
float: "left",
|
|
@@ -32984,23 +33863,23 @@ class Matcher extends React.Component {
|
|
|
32984
33863
|
};
|
|
32985
33864
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
32986
33865
|
return /*#__PURE__*/React.createElement("table", {
|
|
32987
|
-
className: css(styles$
|
|
33866
|
+
className: css(styles$b.widget) + " " + HACKY_CSS_CLASSNAME
|
|
32988
33867
|
}, /*#__PURE__*/React.createElement("tbody", null, showLabels && /*#__PURE__*/React.createElement("tr", {
|
|
32989
|
-
className: css(styles$
|
|
33868
|
+
className: css(styles$b.row)
|
|
32990
33869
|
}, /*#__PURE__*/React.createElement("th", {
|
|
32991
|
-
className: css(styles$
|
|
33870
|
+
className: css(styles$b.column, styles$b.columnLabel)
|
|
32992
33871
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
32993
33872
|
content: this.props.labels[0] || "...",
|
|
32994
33873
|
linterContext: this.props.linterContext
|
|
32995
33874
|
})), /*#__PURE__*/React.createElement("th", {
|
|
32996
|
-
className: css(styles$
|
|
33875
|
+
className: css(styles$b.column, styles$b.columnRight, styles$b.columnLabel)
|
|
32997
33876
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
32998
33877
|
content: this.props.labels[1] || "...",
|
|
32999
33878
|
linterContext: this.props.linterContext
|
|
33000
33879
|
}))), /*#__PURE__*/React.createElement("tr", {
|
|
33001
|
-
className: css(styles$
|
|
33880
|
+
className: css(styles$b.row)
|
|
33002
33881
|
}, /*#__PURE__*/React.createElement("td", {
|
|
33003
|
-
className: css(styles$
|
|
33882
|
+
className: css(styles$b.column)
|
|
33004
33883
|
}, /*#__PURE__*/React.createElement(Sortable, {
|
|
33005
33884
|
options: left,
|
|
33006
33885
|
layout: Layout.VERTICAL,
|
|
@@ -33015,7 +33894,7 @@ class Matcher extends React.Component {
|
|
|
33015
33894
|
,
|
|
33016
33895
|
ref: "left"
|
|
33017
33896
|
})), /*#__PURE__*/React.createElement("td", {
|
|
33018
|
-
className: css(styles$
|
|
33897
|
+
className: css(styles$b.column, styles$b.columnRight)
|
|
33019
33898
|
}, /*#__PURE__*/React.createElement(Sortable
|
|
33020
33899
|
// @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
|
|
33021
33900
|
, {
|
|
@@ -33068,7 +33947,7 @@ _.extend(Matcher, {
|
|
|
33068
33947
|
});
|
|
33069
33948
|
const padding = 5;
|
|
33070
33949
|
const border = "1px solid #444";
|
|
33071
|
-
const styles$
|
|
33950
|
+
const styles$b = StyleSheet.create({
|
|
33072
33951
|
widget: {
|
|
33073
33952
|
paddingTop: padding,
|
|
33074
33953
|
maxWidth: "100%",
|
|
@@ -33101,197 +33980,6 @@ var Matcher$1 = {
|
|
|
33101
33980
|
isLintable: true
|
|
33102
33981
|
};
|
|
33103
33982
|
|
|
33104
|
-
const _excluded$1 = ["onFormatChange", "checkValidity", "useArrowKeys"];
|
|
33105
|
-
const {
|
|
33106
|
-
firstNumericalParse,
|
|
33107
|
-
captureScratchpadTouchStart
|
|
33108
|
-
} = Util;
|
|
33109
|
-
const toNumericString = KhanMath.toNumericString;
|
|
33110
|
-
const getNumericFormat = KhanMath.getNumericFormat;
|
|
33111
|
-
|
|
33112
|
-
/* An input box that accepts only numeric strings
|
|
33113
|
-
*
|
|
33114
|
-
* Calls onChange(value, format) for valid numbers.
|
|
33115
|
-
* Reverts to the current value onBlur or on [ENTER],
|
|
33116
|
-
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
33117
|
-
* Accepts empty input and sends it to onChange as null
|
|
33118
|
-
* if no numeric placeholder is set.
|
|
33119
|
-
* If given a checkValidity function, will turn
|
|
33120
|
-
* the background/outline red when invalid
|
|
33121
|
-
* If useArrowKeys is set to true, up/down arrows will
|
|
33122
|
-
* increment/decrement integers
|
|
33123
|
-
* Optionally takes a size ("mini", "small", "normal")
|
|
33124
|
-
*/
|
|
33125
|
-
class NumberInput extends React.Component {
|
|
33126
|
-
constructor(...args) {
|
|
33127
|
-
super(...args);
|
|
33128
|
-
this.state = {
|
|
33129
|
-
format: this.props.format
|
|
33130
|
-
};
|
|
33131
|
-
/* Return the current "value" of this input
|
|
33132
|
-
* If empty, it returns the placeholder (if it is a number) or null
|
|
33133
|
-
*/
|
|
33134
|
-
this.getValue = () => {
|
|
33135
|
-
return this.parseInputValue(
|
|
33136
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33137
|
-
ReactDOM__default.findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
33138
|
-
);
|
|
33139
|
-
};
|
|
33140
|
-
/* Return the current string value of this input */
|
|
33141
|
-
this.getStringValue = () => {
|
|
33142
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33143
|
-
return ReactDOM__default.findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
33144
|
-
};
|
|
33145
|
-
this.parseInputValue = value => {
|
|
33146
|
-
if (value === "") {
|
|
33147
|
-
const placeholder = this.props.placeholder;
|
|
33148
|
-
return _.isFinite(placeholder) ? +placeholder : null;
|
|
33149
|
-
}
|
|
33150
|
-
const result = firstNumericalParse(value);
|
|
33151
|
-
return _.isFinite(result) ? result : this.props.value;
|
|
33152
|
-
};
|
|
33153
|
-
/* Set text input focus to this input */
|
|
33154
|
-
this.focus = () => {
|
|
33155
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
33156
|
-
ReactDOM__default.findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
33157
|
-
this._handleFocus();
|
|
33158
|
-
};
|
|
33159
|
-
this.blur = () => {
|
|
33160
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
33161
|
-
ReactDOM__default.findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
33162
|
-
this._handleBlur();
|
|
33163
|
-
};
|
|
33164
|
-
this.setSelectionRange = (selectionStart, selectionEnd) => {
|
|
33165
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
33166
|
-
ReactDOM__default.findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
33167
|
-
};
|
|
33168
|
-
this.getSelectionStart = () => {
|
|
33169
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
33170
|
-
return ReactDOM__default.findDOMNode(this).selectionStart;
|
|
33171
|
-
};
|
|
33172
|
-
this.getSelectionEnd = () => {
|
|
33173
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
33174
|
-
return ReactDOM__default.findDOMNode(this).selectionEnd;
|
|
33175
|
-
};
|
|
33176
|
-
this._checkValidity = value => {
|
|
33177
|
-
if (value == null) {
|
|
33178
|
-
return true;
|
|
33179
|
-
}
|
|
33180
|
-
const val = firstNumericalParse(value);
|
|
33181
|
-
const checkValidity = this.props.checkValidity;
|
|
33182
|
-
return _.isFinite(val) && checkValidity(val);
|
|
33183
|
-
};
|
|
33184
|
-
this._handleChange = e => {
|
|
33185
|
-
const text = e.target.value;
|
|
33186
|
-
const value = this.parseInputValue(text);
|
|
33187
|
-
const format = getNumericFormat(text);
|
|
33188
|
-
this.props.onChange(value);
|
|
33189
|
-
if (format) {
|
|
33190
|
-
this.props.onFormatChange(value, format);
|
|
33191
|
-
this.setState({
|
|
33192
|
-
format: format
|
|
33193
|
-
});
|
|
33194
|
-
}
|
|
33195
|
-
};
|
|
33196
|
-
this._handleFocus = () => {
|
|
33197
|
-
if (this.props.onFocus) {
|
|
33198
|
-
this.props.onFocus();
|
|
33199
|
-
}
|
|
33200
|
-
};
|
|
33201
|
-
this._handleBlur = e => {
|
|
33202
|
-
// Only continue on blur or "enter"
|
|
33203
|
-
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
33204
|
-
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
33205
|
-
return;
|
|
33206
|
-
}
|
|
33207
|
-
this._setValue(this.props.value, this.state.format);
|
|
33208
|
-
if (this.props.onBlur) {
|
|
33209
|
-
this.props.onBlur();
|
|
33210
|
-
}
|
|
33211
|
-
};
|
|
33212
|
-
this._onKeyDown = e => {
|
|
33213
|
-
if (this.props.onKeyDown) {
|
|
33214
|
-
this.props.onKeyDown(e);
|
|
33215
|
-
}
|
|
33216
|
-
if (!this.props.useArrowKeys || !_.contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
33217
|
-
return;
|
|
33218
|
-
}
|
|
33219
|
-
let val = this.getValue();
|
|
33220
|
-
if (val !== Math.floor(val)) {
|
|
33221
|
-
return; // bail if not an integer
|
|
33222
|
-
}
|
|
33223
|
-
|
|
33224
|
-
if (e.key === "ArrowUp") {
|
|
33225
|
-
val = val + 1;
|
|
33226
|
-
} else if (e.key === "ArrowDown") {
|
|
33227
|
-
val = val - 1;
|
|
33228
|
-
}
|
|
33229
|
-
if (this._checkValidity(val)) {
|
|
33230
|
-
this.props.onChange(val);
|
|
33231
|
-
}
|
|
33232
|
-
};
|
|
33233
|
-
this._setValue = (val, format) => {
|
|
33234
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33235
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
33236
|
-
$(ReactDOM__default.findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
33237
|
-
};
|
|
33238
|
-
}
|
|
33239
|
-
render() {
|
|
33240
|
-
let classes = classNames({
|
|
33241
|
-
"number-input": true,
|
|
33242
|
-
"invalid-input": !this._checkValidity(this.props.value),
|
|
33243
|
-
mini: this.props.size === "mini",
|
|
33244
|
-
small: this.props.size === "small",
|
|
33245
|
-
normal: this.props.size === "normal"
|
|
33246
|
-
});
|
|
33247
|
-
if (this.props.className != null) {
|
|
33248
|
-
classes = classes + " " + this.props.className;
|
|
33249
|
-
}
|
|
33250
|
-
const _this$props = this.props,
|
|
33251
|
-
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
|
|
33252
|
-
return /*#__PURE__*/React.createElement("input", _extends({}, restProps, {
|
|
33253
|
-
className: classes,
|
|
33254
|
-
type: "text"
|
|
33255
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33256
|
-
,
|
|
33257
|
-
ref: "input",
|
|
33258
|
-
onChange: this._handleChange,
|
|
33259
|
-
onFocus: this._handleFocus,
|
|
33260
|
-
onBlur: this._handleBlur,
|
|
33261
|
-
onKeyPress: this._handleBlur,
|
|
33262
|
-
onKeyDown: this._onKeyDown
|
|
33263
|
-
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
33264
|
-
,
|
|
33265
|
-
onTouchStart: captureScratchpadTouchStart,
|
|
33266
|
-
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
33267
|
-
value: undefined
|
|
33268
|
-
}));
|
|
33269
|
-
}
|
|
33270
|
-
componentDidUpdate(prevProps) {
|
|
33271
|
-
if (!number.equal(this.getValue(), this.props.value)) {
|
|
33272
|
-
this._setValue(this.props.value, this.state.format);
|
|
33273
|
-
}
|
|
33274
|
-
}
|
|
33275
|
-
}
|
|
33276
|
-
NumberInput.propTypes = {
|
|
33277
|
-
value: PropTypes.number,
|
|
33278
|
-
format: PropTypes.string,
|
|
33279
|
-
placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
33280
|
-
onChange: PropTypes.func.isRequired,
|
|
33281
|
-
onFormatChange: PropTypes.func,
|
|
33282
|
-
checkValidity: PropTypes.func,
|
|
33283
|
-
size: PropTypes.string,
|
|
33284
|
-
label: PropTypes.oneOf(["put your labels outside your inputs!"])
|
|
33285
|
-
};
|
|
33286
|
-
NumberInput.defaultProps = {
|
|
33287
|
-
value: null,
|
|
33288
|
-
placeholder: null,
|
|
33289
|
-
format: null,
|
|
33290
|
-
onFormatChange: () => null,
|
|
33291
|
-
checkValidity: () => true,
|
|
33292
|
-
useArrowKeys: false
|
|
33293
|
-
};
|
|
33294
|
-
|
|
33295
33983
|
// Type imports
|
|
33296
33984
|
|
|
33297
33985
|
const {
|
|
@@ -33935,9 +34623,9 @@ function drawText(ctx, item) {
|
|
|
33935
34623
|
if (item.value === null) {
|
|
33936
34624
|
return;
|
|
33937
34625
|
}
|
|
33938
|
-
ctx.fillStyle = styles$
|
|
33939
|
-
ctx.font = styles$
|
|
33940
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
34626
|
+
ctx.fillStyle = styles$a.fgColor;
|
|
34627
|
+
ctx.font = styles$a.font;
|
|
34628
|
+
ctx.fillText(item.value, item.pos[0] - styles$a.fontSizePx / 2 + 1, item.pos[1] + styles$a.fontSizePx / 2);
|
|
33941
34629
|
}
|
|
33942
34630
|
|
|
33943
34631
|
/**
|
|
@@ -33958,16 +34646,16 @@ function drawText(ctx, item) {
|
|
|
33958
34646
|
function drawDoubleLine(ctx, item) {
|
|
33959
34647
|
// Outer line that forms both of the bond lines.
|
|
33960
34648
|
let path = new Path2D();
|
|
33961
|
-
ctx.lineWidth = 5 * styles$
|
|
33962
|
-
ctx.strokeStyle = styles$
|
|
34649
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34650
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
33963
34651
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33964
34652
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
33965
34653
|
ctx.stroke(path);
|
|
33966
34654
|
|
|
33967
34655
|
// Inner white line that separates the two bond lines.
|
|
33968
34656
|
path = new Path2D();
|
|
33969
|
-
ctx.lineWidth = 3 * styles$
|
|
33970
|
-
ctx.strokeStyle = styles$
|
|
34657
|
+
ctx.lineWidth = 3 * styles$a.lineWidth;
|
|
34658
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
33971
34659
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33972
34660
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
33973
34661
|
ctx.stroke(path);
|
|
@@ -33994,16 +34682,16 @@ function drawTripleLine(ctx, item) {
|
|
|
33994
34682
|
|
|
33995
34683
|
// Outer line that will form the two outer bond lines.
|
|
33996
34684
|
let path = new Path2D();
|
|
33997
|
-
ctx.lineWidth = 7 * styles$
|
|
33998
|
-
ctx.strokeStyle = styles$
|
|
34685
|
+
ctx.lineWidth = 7 * styles$a.lineWidth;
|
|
34686
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
33999
34687
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34000
34688
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34001
34689
|
ctx.stroke(path);
|
|
34002
34690
|
|
|
34003
34691
|
// Middle white line that separates the bonds
|
|
34004
34692
|
path = new Path2D();
|
|
34005
|
-
ctx.lineWidth = 5 * styles$
|
|
34006
|
-
ctx.strokeStyle = styles$
|
|
34693
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34694
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34007
34695
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34008
34696
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34009
34697
|
ctx.stroke(path);
|
|
@@ -34025,8 +34713,8 @@ function drawTripleLine(ctx, item) {
|
|
|
34025
34713
|
*/
|
|
34026
34714
|
function drawLine(ctx, item) {
|
|
34027
34715
|
const path = new Path2D();
|
|
34028
|
-
ctx.lineWidth = styles$
|
|
34029
|
-
ctx.strokeStyle = styles$
|
|
34716
|
+
ctx.lineWidth = styles$a.lineWidth;
|
|
34717
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34030
34718
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34031
34719
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34032
34720
|
ctx.stroke(path);
|
|
@@ -34078,7 +34766,7 @@ function compareElements(item0, item1) {
|
|
|
34078
34766
|
function draw(ctx, items) {
|
|
34079
34767
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
34080
34768
|
}
|
|
34081
|
-
const styles$
|
|
34769
|
+
const styles$a = {
|
|
34082
34770
|
bgColor: "rgb(255, 255, 255)",
|
|
34083
34771
|
fgColor: "rgb(0, 0, 0)",
|
|
34084
34772
|
fontSizePx: 12,
|
|
@@ -36640,7 +37328,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
36640
37328
|
const rects = this.state.cachedHighlightRects;
|
|
36641
37329
|
return /*#__PURE__*/React.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React.createElement("div", {
|
|
36642
37330
|
key: index,
|
|
36643
|
-
className: css(styles$
|
|
37331
|
+
className: css(styles$9.highlightRect),
|
|
36644
37332
|
style: {
|
|
36645
37333
|
// NOTE(mdr): We apply `position: absolute` here
|
|
36646
37334
|
// rather than in Aphrodite styles, because
|
|
@@ -36659,7 +37347,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
36659
37347
|
})));
|
|
36660
37348
|
}
|
|
36661
37349
|
}
|
|
36662
|
-
const styles$
|
|
37350
|
+
const styles$9 = StyleSheet.create({
|
|
36663
37351
|
highlightRect: {
|
|
36664
37352
|
background: "#fffabe" // highlighter yellow :)
|
|
36665
37353
|
}
|
|
@@ -36740,7 +37428,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
36740
37428
|
// TooltipContent wouldn't let me overwrite
|
|
36741
37429
|
// user-select and onClick
|
|
36742
37430
|
const content = /*#__PURE__*/React.createElement("div", {
|
|
36743
|
-
className: css(styles$
|
|
37431
|
+
className: css(styles$8.tooltipLabel),
|
|
36744
37432
|
onClick: this.props.onClick
|
|
36745
37433
|
}, this.props.label);
|
|
36746
37434
|
const style = {
|
|
@@ -36760,7 +37448,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
36760
37448
|
}, /*#__PURE__*/React.createElement("div", null)));
|
|
36761
37449
|
}
|
|
36762
37450
|
}
|
|
36763
|
-
const styles$
|
|
37451
|
+
const styles$8 = StyleSheet.create({
|
|
36764
37452
|
tooltipLabel: {
|
|
36765
37453
|
// Unlike most tooltip contents, we don't want this label to be
|
|
36766
37454
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -37312,7 +38000,7 @@ class HighlightableContent extends React.PureComponent {
|
|
|
37312
38000
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
37313
38001
|
const buildHighlight = r => this._buildHighlight(r);
|
|
37314
38002
|
return /*#__PURE__*/React.createElement("div", {
|
|
37315
|
-
className: css(styles$
|
|
38003
|
+
className: css(styles$7.container),
|
|
37316
38004
|
ref: container => this._container = container
|
|
37317
38005
|
}, /*#__PURE__*/React.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React.createElement(HighlightingUI, {
|
|
37318
38006
|
buildHighlight: buildHighlight,
|
|
@@ -37333,14 +38021,14 @@ class HighlightableContent extends React.PureComponent {
|
|
|
37333
38021
|
onAddHighlight: this._handleAddHighlight,
|
|
37334
38022
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
37335
38023
|
})), /*#__PURE__*/React.createElement("div", {
|
|
37336
|
-
className: css(styles$
|
|
38024
|
+
className: css(styles$7.content),
|
|
37337
38025
|
ref: content => this._content = content
|
|
37338
38026
|
}, /*#__PURE__*/React.createElement(WordIndexer, {
|
|
37339
38027
|
onWordsUpdate: this._handleWordsUpdate
|
|
37340
38028
|
}, this.props.children)));
|
|
37341
38029
|
}
|
|
37342
38030
|
}
|
|
37343
|
-
const styles$
|
|
38031
|
+
const styles$7 = StyleSheet.create({
|
|
37344
38032
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
37345
38033
|
// content will receive the browser's native pointer events. (Highlights
|
|
37346
38034
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -37740,7 +38428,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
37740
38428
|
}
|
|
37741
38429
|
render() {
|
|
37742
38430
|
return /*#__PURE__*/React.createElement("div", {
|
|
37743
|
-
className: css(styles$
|
|
38431
|
+
className: css(styles$6.measurer),
|
|
37744
38432
|
"aria-hidden": "true"
|
|
37745
38433
|
}, /*#__PURE__*/React.createElement("div", {
|
|
37746
38434
|
ref: ref => this._line = ref,
|
|
@@ -37748,7 +38436,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
37748
38436
|
}, "Line Height Measurement"));
|
|
37749
38437
|
}
|
|
37750
38438
|
}
|
|
37751
|
-
const styles$
|
|
38439
|
+
const styles$6 = StyleSheet.create({
|
|
37752
38440
|
measurer: {
|
|
37753
38441
|
position: "absolute",
|
|
37754
38442
|
top: 0,
|
|
@@ -39060,7 +39748,7 @@ class PythonProgram extends React.Component {
|
|
|
39060
39748
|
// creator "went wild".
|
|
39061
39749
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
39062
39750
|
return /*#__PURE__*/React.createElement(View, {
|
|
39063
|
-
style: styles$
|
|
39751
|
+
style: styles$5.container
|
|
39064
39752
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
39065
39753
|
sandbox: sandboxOptions,
|
|
39066
39754
|
src: url,
|
|
@@ -39072,7 +39760,7 @@ class PythonProgram extends React.Component {
|
|
|
39072
39760
|
PythonProgram.defaultProps = {
|
|
39073
39761
|
height: 400
|
|
39074
39762
|
};
|
|
39075
|
-
const styles$
|
|
39763
|
+
const styles$5 = StyleSheet.create({
|
|
39076
39764
|
container: {
|
|
39077
39765
|
margin: "auto",
|
|
39078
39766
|
width: "100%"
|
|
@@ -39312,129 +40000,6 @@ var Sequence$1 = {
|
|
|
39312
40000
|
isLintable: true
|
|
39313
40001
|
};
|
|
39314
40002
|
|
|
39315
|
-
const colors = {
|
|
39316
|
-
grayLight: "#aaa",
|
|
39317
|
-
basicBorderColor: "#ccc",
|
|
39318
|
-
white: "#fff"
|
|
39319
|
-
};
|
|
39320
|
-
const triangleBeforeAfter = {
|
|
39321
|
-
borderBottom: "9px solid transparent",
|
|
39322
|
-
borderTop: "9px solid transparent",
|
|
39323
|
-
content: '" "',
|
|
39324
|
-
height: "0",
|
|
39325
|
-
position: "absolute",
|
|
39326
|
-
top: "0",
|
|
39327
|
-
width: "0"
|
|
39328
|
-
};
|
|
39329
|
-
const styles$7 = StyleSheet.create({
|
|
39330
|
-
infoTip: {
|
|
39331
|
-
display: "inline-block",
|
|
39332
|
-
marginLeft: "5px",
|
|
39333
|
-
position: "relative"
|
|
39334
|
-
},
|
|
39335
|
-
infoTipContainer: {
|
|
39336
|
-
position: "absolute",
|
|
39337
|
-
top: "-12px",
|
|
39338
|
-
left: "22px",
|
|
39339
|
-
zIndex: 1000
|
|
39340
|
-
},
|
|
39341
|
-
infoTipTriangle: {
|
|
39342
|
-
height: "10px",
|
|
39343
|
-
left: "0",
|
|
39344
|
-
position: "absolute",
|
|
39345
|
-
top: "8px",
|
|
39346
|
-
width: "0",
|
|
39347
|
-
zIndex: 1,
|
|
39348
|
-
":before": _extends({}, triangleBeforeAfter, {
|
|
39349
|
-
borderRight: "9px solid #bbb",
|
|
39350
|
-
right: "0"
|
|
39351
|
-
}),
|
|
39352
|
-
":after": _extends({}, triangleBeforeAfter, {
|
|
39353
|
-
borderRight: `9px solid ${colors.white}`,
|
|
39354
|
-
right: "-1px"
|
|
39355
|
-
})
|
|
39356
|
-
},
|
|
39357
|
-
verticalShadow: {
|
|
39358
|
-
border: `1px solid ${colors.basicBorderColor}`,
|
|
39359
|
-
boxShadow: `0 1px 3px ${colors.basicBorderColor}`,
|
|
39360
|
-
borderBottom: `1px solid ${colors.grayLight}`
|
|
39361
|
-
},
|
|
39362
|
-
infoTipContentContainer: {
|
|
39363
|
-
background: colors.white,
|
|
39364
|
-
padding: "5px 10px",
|
|
39365
|
-
width: "240px"
|
|
39366
|
-
}
|
|
39367
|
-
});
|
|
39368
|
-
const questionMark = "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBB" + "ZG9iZSBJbWFnZVJlYWR5ccllPAAAA3NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/" + "eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+" + "IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2Jl" + "IFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAg" + "ICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5" + "LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9" + "IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHht" + "bG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3Vy" + "Y2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHht" + "cE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo2N2M3NTAxYS04YmVlLTQ0M2Mt" + "YmRiNS04OGM2N2IxN2NhYzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUJCRTk4" + "Qjc4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5p" + "aWQ6OUJCRTk4QjY4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcDpDcmVhdG9yVG9v" + "bD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRG" + "cm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NGE5ZDI0OTMtODk1NC00OGFkLTlh" + "MTgtZDAwM2MwYWNjNDJlIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY3Yzc1MDFh" + "LThiZWUtNDQzYy1iZGI1LTg4YzY3YjE3Y2FjMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4g" + "PC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pqm89uYAAADM" + "SURBVHjaXJA9DoJAEIUH1M4TUHIFsCMGen9OwCGw1YRGW2ntKel0exsojHIBC0ouQAyU" + "viFDstmXfNmZeS+zm7XSNCXRFiRgJf0bXIHixpbhGdxBBJYC1w/xaA424MhNEATkui71" + "fU9KqfEU78UbD9PdbJRlOdae55GmhIP+1NV1TcMwkOM41DSNHvRtMhTHMRVFQW3b6mOL" + "gx99kue5GRp/gIOZuZGvNpTNwjD8oliANU+qqqKu6/TQBdymN57AHjzBT+B6Jx79BRgA" + "vc49kQA4yxgAAAAASUVORK5CYII=";
|
|
39369
|
-
class InfoTip$1 extends React.Component {
|
|
39370
|
-
constructor(...args) {
|
|
39371
|
-
super(...args);
|
|
39372
|
-
this.state = {
|
|
39373
|
-
hover: false
|
|
39374
|
-
};
|
|
39375
|
-
this.handleMouseEnter = () => {
|
|
39376
|
-
this.setState({
|
|
39377
|
-
hover: true
|
|
39378
|
-
});
|
|
39379
|
-
};
|
|
39380
|
-
this.handleMouseLeave = () => {
|
|
39381
|
-
this.setState({
|
|
39382
|
-
hover: false
|
|
39383
|
-
});
|
|
39384
|
-
};
|
|
39385
|
-
}
|
|
39386
|
-
render() {
|
|
39387
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
39388
|
-
className: css(styles$7.infoTip)
|
|
39389
|
-
}, /*#__PURE__*/React.createElement("img", {
|
|
39390
|
-
alt: "",
|
|
39391
|
-
width: 10,
|
|
39392
|
-
height: 10,
|
|
39393
|
-
src: questionMark,
|
|
39394
|
-
onMouseEnter: this.handleMouseEnter,
|
|
39395
|
-
onMouseLeave: this.handleMouseLeave
|
|
39396
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
39397
|
-
className: css(styles$7.infoTipContainer),
|
|
39398
|
-
style: {
|
|
39399
|
-
display: this.state.hover ? "block" : "none"
|
|
39400
|
-
}
|
|
39401
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
39402
|
-
className: css(styles$7.infoTipTriangle)
|
|
39403
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
39404
|
-
className: css(styles$7.verticalShadow, styles$7.infoTipContentContainer)
|
|
39405
|
-
}, this.props.children)));
|
|
39406
|
-
}
|
|
39407
|
-
}
|
|
39408
|
-
|
|
39409
|
-
/**
|
|
39410
|
-
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
39411
|
-
* server without causing a checksum mismatch on the client.
|
|
39412
|
-
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
39413
|
-
* two sets of generated classnames will not match.)
|
|
39414
|
-
*/
|
|
39415
|
-
class InfoTip extends React.Component {
|
|
39416
|
-
constructor(...args) {
|
|
39417
|
-
super(...args);
|
|
39418
|
-
this.state = {
|
|
39419
|
-
didMount: false
|
|
39420
|
-
};
|
|
39421
|
-
}
|
|
39422
|
-
componentDidMount() {
|
|
39423
|
-
/* eslint-disable react/no-did-mount-set-state */
|
|
39424
|
-
this.setState({
|
|
39425
|
-
didMount: true
|
|
39426
|
-
});
|
|
39427
|
-
/* eslint-enable react/no-did-mount-set-state */
|
|
39428
|
-
}
|
|
39429
|
-
|
|
39430
|
-
render() {
|
|
39431
|
-
if (this.state.didMount) {
|
|
39432
|
-
return /*#__PURE__*/React.createElement(InfoTip$1, this.props);
|
|
39433
|
-
}
|
|
39434
|
-
return /*#__PURE__*/React.createElement("div", null);
|
|
39435
|
-
}
|
|
39436
|
-
}
|
|
39437
|
-
|
|
39438
40003
|
const {
|
|
39439
40004
|
assert: assert$1
|
|
39440
40005
|
} = InteractiveUtil;
|
|
@@ -41389,7 +41954,7 @@ const VideoTranscriptLink = props => {
|
|
|
41389
41954
|
var _result$data;
|
|
41390
41955
|
const video = (_result$data = result.data) == null ? void 0 : _result$data.video;
|
|
41391
41956
|
return /*#__PURE__*/React.createElement(View, {
|
|
41392
|
-
style: styles$
|
|
41957
|
+
style: styles$4.transcriptLink
|
|
41393
41958
|
}, /*#__PURE__*/React.createElement(Text$1, null, video == null ? void 0 : video.title), /*#__PURE__*/React.createElement(Strut, {
|
|
41394
41959
|
size: 10
|
|
41395
41960
|
}), /*#__PURE__*/React.createElement(Link, {
|
|
@@ -41406,7 +41971,7 @@ const VideoTranscriptLink = props => {
|
|
|
41406
41971
|
return /*#__PURE__*/React.createElement(View, null, i18n._("Something went wrong."));
|
|
41407
41972
|
}
|
|
41408
41973
|
};
|
|
41409
|
-
const styles$
|
|
41974
|
+
const styles$4 = StyleSheet.create({
|
|
41410
41975
|
transcriptLink: {
|
|
41411
41976
|
flexDirection: "row",
|
|
41412
41977
|
width: "100%",
|
|
@@ -41559,7 +42124,7 @@ const init = function init(options) {
|
|
|
41559
42124
|
|
|
41560
42125
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41561
42126
|
const libName = "@khanacademy/perseus";
|
|
41562
|
-
const libVersion = "19.
|
|
42127
|
+
const libVersion = "19.7.0";
|
|
41563
42128
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41564
42129
|
|
|
41565
42130
|
const apiVersion = {
|
|
@@ -41769,7 +42334,7 @@ class HintRenderer extends React.Component {
|
|
|
41769
42334
|
const {
|
|
41770
42335
|
isMobile
|
|
41771
42336
|
} = apiOptions;
|
|
41772
|
-
const classNames$1 = classNames("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$
|
|
42337
|
+
const classNames$1 = classNames("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$3.newHint), isMobile && lastRendered && css(styles$3.lastRenderedNewHint), lastHint && "last-hint", lastRendered && "last-rendered", className);
|
|
41773
42338
|
|
|
41774
42339
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
41775
42340
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -41812,7 +42377,7 @@ class HintRenderer extends React.Component {
|
|
|
41812
42377
|
HintRenderer.defaultProps = {
|
|
41813
42378
|
linterContext: PerseusLinter.linterContextDefault
|
|
41814
42379
|
};
|
|
41815
|
-
const styles$
|
|
42380
|
+
const styles$3 = StyleSheet.create({
|
|
41816
42381
|
newHint: {
|
|
41817
42382
|
marginBottom: 1.5 * baseUnitPx,
|
|
41818
42383
|
borderLeftColor: gray97,
|
|
@@ -41985,15 +42550,15 @@ class HintsRenderer extends React.Component {
|
|
|
41985
42550
|
} = apiOptions;
|
|
41986
42551
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
41987
42552
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
41988
|
-
const classNames$1 = classNames(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$
|
|
42553
|
+
const classNames$1 = classNames(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$2.mobileHintStylesHintsRenderer));
|
|
41989
42554
|
return /*#__PURE__*/React.createElement("div", {
|
|
41990
42555
|
className: classNames$1
|
|
41991
42556
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React.createElement("div", {
|
|
41992
|
-
className: css(styles$
|
|
42557
|
+
className: css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
41993
42558
|
}, i18n._("Hints")), hints, showGetAnotherHint && /*#__PURE__*/React.createElement("button", {
|
|
41994
42559
|
// @ts-expect-error - TS2322 - Type '{ children: Element[]; rel: string; className: string; onClick: (evt: MouseEvent<HTMLButtonElement, MouseEvent>) => void; }' is not assignable to type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'.
|
|
41995
42560
|
rel: "button",
|
|
41996
|
-
className: css(styles$
|
|
42561
|
+
className: css(styles$2.linkButton, styles$2.getAnotherHintButton, apiOptions.isMobile && styles$2.mobileHintStylesGetAnotherHintButton),
|
|
41997
42562
|
onClick: evt => {
|
|
41998
42563
|
evt.preventDefault();
|
|
41999
42564
|
evt.stopPropagation();
|
|
@@ -42002,9 +42567,9 @@ class HintsRenderer extends React.Component {
|
|
|
42002
42567
|
}
|
|
42003
42568
|
}
|
|
42004
42569
|
}, /*#__PURE__*/React.createElement("span", {
|
|
42005
|
-
className: css(styles$
|
|
42570
|
+
className: css(styles$2.plusText, apiOptions.isMobile && styles$2.mobileHintStylesPlusText)
|
|
42006
42571
|
}, "+"), /*#__PURE__*/React.createElement("span", {
|
|
42007
|
-
className: css(styles$
|
|
42572
|
+
className: css(styles$2.getAnotherHintText)
|
|
42008
42573
|
}, i18n._("Get another hint"), " ", hintRatioCopy)));
|
|
42009
42574
|
}
|
|
42010
42575
|
}
|
|
@@ -42012,7 +42577,7 @@ HintsRenderer.defaultProps = {
|
|
|
42012
42577
|
linterContext: PerseusLinter.linterContextDefault
|
|
42013
42578
|
};
|
|
42014
42579
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
42015
|
-
const styles$
|
|
42580
|
+
const styles$2 = StyleSheet.create({
|
|
42016
42581
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
42017
42582
|
rendererMargins: {
|
|
42018
42583
|
marginTop: baseUnitPx
|
|
@@ -42419,7 +42984,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
42419
42984
|
// mobile hint styles, which are flush to the left.
|
|
42420
42985
|
// NOTE(charlie): We may still want to apply this
|
|
42421
42986
|
// padding for desktop exercises.
|
|
42422
|
-
apiOptions.isMobile ? undefined : css(styles$
|
|
42987
|
+
apiOptions.isMobile ? undefined : css(styles$1.hintsContainer)
|
|
42423
42988
|
}, hintsRenderer)));
|
|
42424
42989
|
}
|
|
42425
42990
|
}
|
|
@@ -42429,7 +42994,7 @@ ServerItemRenderer.defaultProps = {
|
|
|
42429
42994
|
linterContext: PerseusLinter.linterContextDefault,
|
|
42430
42995
|
onRendered: isRendered => {}
|
|
42431
42996
|
};
|
|
42432
|
-
const styles$
|
|
42997
|
+
const styles$1 = StyleSheet.create({
|
|
42433
42998
|
hintsContainer: {
|
|
42434
42999
|
marginLeft: 50
|
|
42435
43000
|
}
|
|
@@ -42563,345 +43128,6 @@ ElementContainer.defaultProps = {
|
|
|
42563
43128
|
title: "More"
|
|
42564
43129
|
};
|
|
42565
43130
|
|
|
42566
|
-
// Displays a stylized open eye: lint warnings are visible
|
|
42567
|
-
const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
42568
|
-
width: "24",
|
|
42569
|
-
height: "24",
|
|
42570
|
-
viewBox: "0 0 24 24",
|
|
42571
|
-
className: css(styles$2.icon)
|
|
42572
|
-
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
42573
|
-
id: "a",
|
|
42574
|
-
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"
|
|
42575
|
-
})), /*#__PURE__*/React.createElement("g", {
|
|
42576
|
-
fill: "none",
|
|
42577
|
-
fillRule: "evenodd"
|
|
42578
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42579
|
-
fill: "none",
|
|
42580
|
-
d: "M0 0h24v24H0z"
|
|
42581
|
-
}), /*#__PURE__*/React.createElement("mask", {
|
|
42582
|
-
id: "b",
|
|
42583
|
-
fill: "#fff"
|
|
42584
|
-
}, /*#__PURE__*/React.createElement("use", {
|
|
42585
|
-
href: "#a"
|
|
42586
|
-
})), /*#__PURE__*/React.createElement("use", {
|
|
42587
|
-
fill: "#fff",
|
|
42588
|
-
fillRule: "nonzero",
|
|
42589
|
-
href: "#a"
|
|
42590
|
-
}), /*#__PURE__*/React.createElement("g", {
|
|
42591
|
-
fill: "#fff",
|
|
42592
|
-
mask: "url(#b)"
|
|
42593
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42594
|
-
d: "M0 0h24v24H0z"
|
|
42595
|
-
}))));
|
|
42596
|
-
|
|
42597
|
-
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
42598
|
-
const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
42599
|
-
width: "24",
|
|
42600
|
-
height: "24",
|
|
42601
|
-
viewBox: "0 0 24 24",
|
|
42602
|
-
className: css(styles$2.icon)
|
|
42603
|
-
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
42604
|
-
id: "a",
|
|
42605
|
-
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"
|
|
42606
|
-
})), /*#__PURE__*/React.createElement("g", {
|
|
42607
|
-
fill: "none",
|
|
42608
|
-
fillRule: "evenodd"
|
|
42609
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42610
|
-
fill: "none",
|
|
42611
|
-
d: "M0 0h24v24H0z"
|
|
42612
|
-
}), /*#__PURE__*/React.createElement("mask", {
|
|
42613
|
-
id: "b",
|
|
42614
|
-
fill: "#fff"
|
|
42615
|
-
}, /*#__PURE__*/React.createElement("use", {
|
|
42616
|
-
href: "#a"
|
|
42617
|
-
})), /*#__PURE__*/React.createElement("use", {
|
|
42618
|
-
fill: "#fff",
|
|
42619
|
-
fillRule: "nonzero",
|
|
42620
|
-
href: "#a"
|
|
42621
|
-
}), /*#__PURE__*/React.createElement("g", {
|
|
42622
|
-
fill: "#fff",
|
|
42623
|
-
mask: "url(#b)"
|
|
42624
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42625
|
-
d: "M0 0h24v24H0z"
|
|
42626
|
-
}))));
|
|
42627
|
-
const HUD = ({
|
|
42628
|
-
message,
|
|
42629
|
-
enabled,
|
|
42630
|
-
onClick,
|
|
42631
|
-
fixedPosition: _fixedPosition = true
|
|
42632
|
-
}) => {
|
|
42633
|
-
let state;
|
|
42634
|
-
let icon;
|
|
42635
|
-
if (enabled) {
|
|
42636
|
-
state = styles$2.enabled;
|
|
42637
|
-
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
42638
|
-
} else {
|
|
42639
|
-
state = styles$2.disabled;
|
|
42640
|
-
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
42641
|
-
}
|
|
42642
|
-
return /*#__PURE__*/React.createElement("button", {
|
|
42643
|
-
className: css(styles$2.hud, _fixedPosition && styles$2.hudFixedPosition, state),
|
|
42644
|
-
onClick: e => {
|
|
42645
|
-
onClick();
|
|
42646
|
-
}
|
|
42647
|
-
}, icon, message);
|
|
42648
|
-
};
|
|
42649
|
-
const styles$2 = StyleSheet.create({
|
|
42650
|
-
hud: {
|
|
42651
|
-
boxSizing: "border-box",
|
|
42652
|
-
height: 36,
|
|
42653
|
-
padding: "9px 16px",
|
|
42654
|
-
borderRadius: 18,
|
|
42655
|
-
fontFamily: boldFontFamily,
|
|
42656
|
-
fontSize: "15px",
|
|
42657
|
-
lineHeight: "18px",
|
|
42658
|
-
color: white$1,
|
|
42659
|
-
userSelect: "none",
|
|
42660
|
-
borderWidth: 0 // <button> gives us a border by default
|
|
42661
|
-
},
|
|
42662
|
-
|
|
42663
|
-
// We want to render the element in-place in our fixtures, so allow us to
|
|
42664
|
-
// render in the bottom corner in production and in-place in testing.
|
|
42665
|
-
hudFixedPosition: {
|
|
42666
|
-
bottom: 20,
|
|
42667
|
-
position: "fixed",
|
|
42668
|
-
right: 20,
|
|
42669
|
-
zIndex: 1
|
|
42670
|
-
},
|
|
42671
|
-
icon: {
|
|
42672
|
-
width: 24,
|
|
42673
|
-
height: 24,
|
|
42674
|
-
marginRight: 8,
|
|
42675
|
-
marginTop: -3,
|
|
42676
|
-
verticalAlign: "middle"
|
|
42677
|
-
},
|
|
42678
|
-
enabled: {
|
|
42679
|
-
backgroundColor: warningColor,
|
|
42680
|
-
":hover": {
|
|
42681
|
-
backgroundColor: warningColorHover
|
|
42682
|
-
},
|
|
42683
|
-
":active": {
|
|
42684
|
-
backgroundColor: warningColorActive
|
|
42685
|
-
}
|
|
42686
|
-
},
|
|
42687
|
-
disabled: {
|
|
42688
|
-
backgroundColor: gray76,
|
|
42689
|
-
":hover": {
|
|
42690
|
-
backgroundColor: "#a1a5a9" // in between those two grays
|
|
42691
|
-
},
|
|
42692
|
-
|
|
42693
|
-
":active": {
|
|
42694
|
-
backgroundColor: gray68
|
|
42695
|
-
}
|
|
42696
|
-
}
|
|
42697
|
-
});
|
|
42698
|
-
|
|
42699
|
-
/**
|
|
42700
|
-
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
42701
|
-
* which allows multiple buttons to be selected at the same time.
|
|
42702
|
-
*
|
|
42703
|
-
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
42704
|
-
* this component allows multiple selection!
|
|
42705
|
-
*/
|
|
42706
|
-
class MultiButtonGroup extends React.Component {
|
|
42707
|
-
constructor(...args) {
|
|
42708
|
-
super(...args);
|
|
42709
|
-
this.toggleSelect = newValue => {
|
|
42710
|
-
const values = (this.props.values || []).slice(0);
|
|
42711
|
-
const allowEmpty = this.props.allowEmpty;
|
|
42712
|
-
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
42713
|
-
// If the value is already selected, unselect it
|
|
42714
|
-
values.splice(values.indexOf(newValue), 1);
|
|
42715
|
-
} else {
|
|
42716
|
-
// Otherwise merge with other values and return
|
|
42717
|
-
if (values.indexOf(newValue) < 0) {
|
|
42718
|
-
values.push(newValue);
|
|
42719
|
-
}
|
|
42720
|
-
}
|
|
42721
|
-
this.props.onChange(values);
|
|
42722
|
-
};
|
|
42723
|
-
}
|
|
42724
|
-
focus() {
|
|
42725
|
-
var _ReactDOM$findDOMNode;
|
|
42726
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
42727
|
-
(_ReactDOM$findDOMNode = ReactDOM.findDOMNode(this)) == null || _ReactDOM$findDOMNode.focus();
|
|
42728
|
-
return true;
|
|
42729
|
-
}
|
|
42730
|
-
render() {
|
|
42731
|
-
const values = this.props.values || [];
|
|
42732
|
-
const buttons = this.props.buttons.map((button, i) => {
|
|
42733
|
-
const selected = values.indexOf(button.value) >= 0;
|
|
42734
|
-
return /*#__PURE__*/React.createElement("button", {
|
|
42735
|
-
title: button.title,
|
|
42736
|
-
type: "button",
|
|
42737
|
-
id: "" + i,
|
|
42738
|
-
key: "" + i,
|
|
42739
|
-
ref: "button" + i,
|
|
42740
|
-
className: css(styles$1.buttonStyle, selected && styles$1.selectedStyle),
|
|
42741
|
-
onClick: () => this.toggleSelect(button.value)
|
|
42742
|
-
}, button.content || "" + button.value);
|
|
42743
|
-
});
|
|
42744
|
-
const outerStyle = {
|
|
42745
|
-
display: "inline-block"
|
|
42746
|
-
};
|
|
42747
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
42748
|
-
style: outerStyle
|
|
42749
|
-
}, buttons);
|
|
42750
|
-
}
|
|
42751
|
-
}
|
|
42752
|
-
MultiButtonGroup.defaultProps = {
|
|
42753
|
-
values: [],
|
|
42754
|
-
allowEmpty: true
|
|
42755
|
-
};
|
|
42756
|
-
const styles$1 = StyleSheet.create({
|
|
42757
|
-
buttonStyle: {
|
|
42758
|
-
backgroundColor: "white",
|
|
42759
|
-
border: "1px solid #ccc",
|
|
42760
|
-
borderLeft: "0",
|
|
42761
|
-
cursor: "pointer",
|
|
42762
|
-
margin: "0",
|
|
42763
|
-
padding: "5px 10px",
|
|
42764
|
-
position: "relative",
|
|
42765
|
-
// for hover
|
|
42766
|
-
|
|
42767
|
-
":first-child": {
|
|
42768
|
-
borderLeft: "1px solid #ccc",
|
|
42769
|
-
borderTopLeftRadius: "3px",
|
|
42770
|
-
borderBottomLeftRadius: "3px"
|
|
42771
|
-
},
|
|
42772
|
-
":last-child": {
|
|
42773
|
-
borderRight: "1px solid #ccc",
|
|
42774
|
-
borderTopRightRadius: "3px",
|
|
42775
|
-
borderBottomRightRadius: "3px"
|
|
42776
|
-
},
|
|
42777
|
-
":hover": {
|
|
42778
|
-
backgroundColor: "#ccc"
|
|
42779
|
-
},
|
|
42780
|
-
":focus": {
|
|
42781
|
-
zIndex: 2
|
|
42782
|
-
}
|
|
42783
|
-
},
|
|
42784
|
-
selectedStyle: {
|
|
42785
|
-
backgroundColor: "#ddd"
|
|
42786
|
-
}
|
|
42787
|
-
});
|
|
42788
|
-
|
|
42789
|
-
/* eslint-disable @babel/no-invalid-this */
|
|
42790
|
-
|
|
42791
|
-
/* A checkbox that syncs its value to props using the
|
|
42792
|
-
* renderer's onChange method, and gets the prop name
|
|
42793
|
-
* dynamically from its props list
|
|
42794
|
-
*/
|
|
42795
|
-
const PropCheckBox = createReactClass({
|
|
42796
|
-
displayName: "PropCheckBox",
|
|
42797
|
-
propTypes: {
|
|
42798
|
-
labelAlignment: PropTypes.oneOf(["left", "right"])
|
|
42799
|
-
},
|
|
42800
|
-
DEFAULT_PROPS: {
|
|
42801
|
-
label: null,
|
|
42802
|
-
onChange: null,
|
|
42803
|
-
labelAlignment: "left"
|
|
42804
|
-
},
|
|
42805
|
-
getDefaultProps: function () {
|
|
42806
|
-
return this.DEFAULT_PROPS;
|
|
42807
|
-
},
|
|
42808
|
-
propName: function () {
|
|
42809
|
-
const propName = _.find(_.keys(this.props), function (localPropName) {
|
|
42810
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
42811
|
-
return !_.has(this.DEFAULT_PROPS, localPropName);
|
|
42812
|
-
}, this);
|
|
42813
|
-
if (!propName) {
|
|
42814
|
-
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
42815
|
-
}
|
|
42816
|
-
return propName;
|
|
42817
|
-
},
|
|
42818
|
-
_labelAlignLeft: function () {
|
|
42819
|
-
return this.props.labelAlignment === "left";
|
|
42820
|
-
},
|
|
42821
|
-
render: function () {
|
|
42822
|
-
const propName = this.propName();
|
|
42823
|
-
return /*#__PURE__*/React.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React.createElement("input", {
|
|
42824
|
-
type: "checkbox",
|
|
42825
|
-
checked: this.props[propName],
|
|
42826
|
-
onChange: this.toggle
|
|
42827
|
-
}), !this._labelAlignLeft() && this.props.label);
|
|
42828
|
-
},
|
|
42829
|
-
toggle: function () {
|
|
42830
|
-
const propName = this.propName();
|
|
42831
|
-
const changes = {};
|
|
42832
|
-
changes[propName] = !this.props[propName];
|
|
42833
|
-
this.props.onChange(changes);
|
|
42834
|
-
}
|
|
42835
|
-
});
|
|
42836
|
-
|
|
42837
|
-
const truth = () => true;
|
|
42838
|
-
|
|
42839
|
-
/* A minor abstraction on top of NumberInput for ranges
|
|
42840
|
-
*
|
|
42841
|
-
*/
|
|
42842
|
-
class RangeInput extends React.Component {
|
|
42843
|
-
constructor(...args) {
|
|
42844
|
-
super(...args);
|
|
42845
|
-
this.onChange = (i, newVal) => {
|
|
42846
|
-
const value = this.props.value;
|
|
42847
|
-
if (i === 0) {
|
|
42848
|
-
this.props.onChange([newVal, value[1]]);
|
|
42849
|
-
} else {
|
|
42850
|
-
this.props.onChange([value[0], newVal]);
|
|
42851
|
-
}
|
|
42852
|
-
};
|
|
42853
|
-
}
|
|
42854
|
-
render() {
|
|
42855
|
-
const value = this.props.value;
|
|
42856
|
-
const checkValidity = this.props.checkValidity || truth;
|
|
42857
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
42858
|
-
className: "range-input"
|
|
42859
|
-
}, /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
42860
|
-
value: value[0],
|
|
42861
|
-
checkValidity: val => checkValidity([val, value[1]])
|
|
42862
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
42863
|
-
,
|
|
42864
|
-
onChange: this.onChange.bind(this, 0),
|
|
42865
|
-
placeholder: this.props.placeholder[0]
|
|
42866
|
-
})), /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
42867
|
-
value: value[1],
|
|
42868
|
-
checkValidity: val => checkValidity([value[0], val])
|
|
42869
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
42870
|
-
,
|
|
42871
|
-
onChange: this.onChange.bind(this, 1),
|
|
42872
|
-
placeholder: this.props.placeholder[1]
|
|
42873
|
-
})));
|
|
42874
|
-
}
|
|
42875
|
-
}
|
|
42876
|
-
RangeInput.propTypes = {
|
|
42877
|
-
value: PropTypes.array.isRequired,
|
|
42878
|
-
onChange: PropTypes.func.isRequired,
|
|
42879
|
-
placeholder: PropTypes.array,
|
|
42880
|
-
checkValidity: PropTypes.func
|
|
42881
|
-
};
|
|
42882
|
-
RangeInput.defaultProps = {
|
|
42883
|
-
placeholder: [null, null]
|
|
42884
|
-
};
|
|
42885
|
-
|
|
42886
|
-
var components = /*#__PURE__*/Object.freeze({
|
|
42887
|
-
__proto__: null,
|
|
42888
|
-
ButtonGroup: ButtonGroup,
|
|
42889
|
-
Graph: Graph,
|
|
42890
|
-
Graphie: Graphie,
|
|
42891
|
-
HUD: HUD,
|
|
42892
|
-
Icon: Icon,
|
|
42893
|
-
InfoTip: InfoTip,
|
|
42894
|
-
InlineIcon: InlineIcon,
|
|
42895
|
-
MathInput: MathInput,
|
|
42896
|
-
MultiButtonGroup: MultiButtonGroup,
|
|
42897
|
-
NumberInput: NumberInput,
|
|
42898
|
-
PropCheckBox: PropCheckBox,
|
|
42899
|
-
RangeInput: RangeInput,
|
|
42900
|
-
SvgImage: SvgImage,
|
|
42901
|
-
TextInput: TextInput,
|
|
42902
|
-
TextListEditor: TextListEditor
|
|
42903
|
-
});
|
|
42904
|
-
|
|
42905
43131
|
const devices = {
|
|
42906
43132
|
PHONE: "phone",
|
|
42907
43133
|
TABLET: "tablet",
|