@khanacademy/perseus 19.6.3 → 19.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +171 -0
- package/dist/es/index.js +975 -745
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +171 -0
- package/dist/index.js +972 -740
- 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 +81 -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] = props.box;
|
|
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,25 @@ 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;
|
|
29387
30259
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
30260
|
+
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
30261
|
+
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
30262
|
+
|
|
30263
|
+
// Mafs shim
|
|
30264
|
+
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]) {
|
|
30265
|
+
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, this.props, {
|
|
30266
|
+
ref: this.mafsRef,
|
|
30267
|
+
gridStep: gridStep,
|
|
30268
|
+
snapStep: snapStep,
|
|
30269
|
+
box: box
|
|
30270
|
+
}));
|
|
30271
|
+
}
|
|
29388
30272
|
let instructions;
|
|
30273
|
+
// isClickToAddPoints() only applies to points and polygons
|
|
29389
30274
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
29390
30275
|
if (this.props.graph.type === "point") {
|
|
29391
30276
|
instructions = i18n._("Click to add points");
|
|
@@ -29399,8 +30284,6 @@ class InteractiveGraph extends React.Component {
|
|
|
29399
30284
|
if (this.isClickToAddPoints()) {
|
|
29400
30285
|
onMouseDown = this.handleAddPointsMouseDown;
|
|
29401
30286
|
}
|
|
29402
|
-
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
29403
|
-
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
29404
30287
|
const isMobile = this.props.apiOptions.isMobile;
|
|
29405
30288
|
return /*#__PURE__*/React.createElement("div", {
|
|
29406
30289
|
className: "perseus-widget " + "perseus-widget-interactive-graph",
|
|
@@ -30688,7 +31571,7 @@ var globalConstants = /*#__PURE__*/Object.freeze({
|
|
|
30688
31571
|
pureLgMax: pureLgMax
|
|
30689
31572
|
});
|
|
30690
31573
|
|
|
30691
|
-
const colors
|
|
31574
|
+
const colors = {
|
|
30692
31575
|
white: "#FFFFFF",
|
|
30693
31576
|
gray98: "#FAFAFA",
|
|
30694
31577
|
gray97: "#F6F7F7",
|
|
@@ -30748,7 +31631,7 @@ const colors$1 = {
|
|
|
30748
31631
|
};
|
|
30749
31632
|
const borderRadius = 4;
|
|
30750
31633
|
const breadcrumbStyles = {
|
|
30751
|
-
color: colors
|
|
31634
|
+
color: colors.breadcrumbs,
|
|
30752
31635
|
fontFamily: "inherit",
|
|
30753
31636
|
fontSize: 15,
|
|
30754
31637
|
fontWeight: "bold",
|
|
@@ -30818,14 +31701,14 @@ const typography = {
|
|
|
30818
31701
|
},
|
|
30819
31702
|
// For callouts
|
|
30820
31703
|
smallHeading: {
|
|
30821
|
-
color: colors
|
|
31704
|
+
color: colors.gray25,
|
|
30822
31705
|
fontFamily: "inherit",
|
|
30823
31706
|
fontSize: 17,
|
|
30824
31707
|
fontWeight: "bold",
|
|
30825
31708
|
lineHeight: "23px"
|
|
30826
31709
|
},
|
|
30827
31710
|
smallHeadingMobile: {
|
|
30828
|
-
color: colors
|
|
31711
|
+
color: colors.gray25,
|
|
30829
31712
|
fontFamily: "inherit",
|
|
30830
31713
|
fontSize: 15,
|
|
30831
31714
|
fontWeight: "bold",
|
|
@@ -30833,7 +31716,7 @@ const typography = {
|
|
|
30833
31716
|
},
|
|
30834
31717
|
// Accent headings
|
|
30835
31718
|
accentHeading: {
|
|
30836
|
-
color: colors
|
|
31719
|
+
color: colors.gray68,
|
|
30837
31720
|
fontFamily: "inherit",
|
|
30838
31721
|
fontSize: 15,
|
|
30839
31722
|
fontWeight: "bold",
|
|
@@ -30939,7 +31822,7 @@ const typography = {
|
|
|
30939
31822
|
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
30940
31823
|
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
30941
31824
|
wonderBlocksTitle: {
|
|
30942
|
-
color: colors
|
|
31825
|
+
color: colors.white,
|
|
30943
31826
|
fontWeight: 900,
|
|
30944
31827
|
// "Black" weight
|
|
30945
31828
|
fontSize: 28,
|
|
@@ -30961,7 +31844,7 @@ const typography = {
|
|
|
30961
31844
|
|
|
30962
31845
|
var globalStyles = /*#__PURE__*/Object.freeze({
|
|
30963
31846
|
__proto__: null,
|
|
30964
|
-
colors: colors
|
|
31847
|
+
colors: colors,
|
|
30965
31848
|
borderRadius: borderRadius,
|
|
30966
31849
|
fonts: fonts,
|
|
30967
31850
|
typography: typography
|
|
@@ -31023,7 +31906,7 @@ const HideAnswersToggle = props => {
|
|
|
31023
31906
|
const switchId = idFactory.get("hide-answers-toggle");
|
|
31024
31907
|
const labelId = idFactory.get("hide-answers-label");
|
|
31025
31908
|
return /*#__PURE__*/React.createElement(View, {
|
|
31026
|
-
style: styles$
|
|
31909
|
+
style: styles$g.switchWrapper
|
|
31027
31910
|
}, /*#__PURE__*/React.createElement(Switch, {
|
|
31028
31911
|
id: switchId,
|
|
31029
31912
|
checked: props.areAnswersHidden,
|
|
@@ -31035,7 +31918,7 @@ const HideAnswersToggle = props => {
|
|
|
31035
31918
|
tag: "label"
|
|
31036
31919
|
}, strings.hideAnswersToggleLabel));
|
|
31037
31920
|
};
|
|
31038
|
-
const styles$
|
|
31921
|
+
const styles$g = StyleSheet.create({
|
|
31039
31922
|
switchWrapper: {
|
|
31040
31923
|
display: "flex",
|
|
31041
31924
|
flexDirection: "row",
|
|
@@ -31088,13 +31971,13 @@ const AnswerPill = props => {
|
|
|
31088
31971
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31089
31972
|
onClick: correct ? undefined : onClick,
|
|
31090
31973
|
ref: ref,
|
|
31091
|
-
style: [style, popperStyle, styles$
|
|
31974
|
+
style: [style, popperStyle, styles$f.pill, correct && styles$f.correct, incorrect && styles$f.incorrect, (focused || hovered) && BringToFront]
|
|
31092
31975
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
31093
31976
|
content: answerString,
|
|
31094
31977
|
inline: true
|
|
31095
31978
|
})));
|
|
31096
31979
|
};
|
|
31097
|
-
const styles$
|
|
31980
|
+
const styles$f = StyleSheet.create({
|
|
31098
31981
|
correct: {
|
|
31099
31982
|
// WB green darkened by 18%
|
|
31100
31983
|
backgroundColor: "#00880b"
|
|
@@ -31147,23 +32030,23 @@ class Marker extends React.Component {
|
|
|
31147
32030
|
icon: iconNull
|
|
31148
32031
|
};
|
|
31149
32032
|
if (showCorrectness) {
|
|
31150
|
-
iconStyles = [styles$
|
|
32033
|
+
iconStyles = [styles$e.markerGraded, showCorrectness === "correct" ? styles$e.markerCorrect : styles$e.markerIncorrect, isOpen && styles$e.markerSelected];
|
|
31151
32034
|
args = _extends({}, args, {
|
|
31152
32035
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31153
32036
|
});
|
|
31154
32037
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31155
|
-
iconStyles = [styles$
|
|
32038
|
+
iconStyles = [styles$e.markerFilled, isOpen && styles$e.markerSelected];
|
|
31156
32039
|
} else if (isOpen) {
|
|
31157
|
-
iconStyles = [styles$
|
|
32040
|
+
iconStyles = [styles$e.markerSelected];
|
|
31158
32041
|
args = _extends({}, args, {
|
|
31159
32042
|
icon: iconChevronDown,
|
|
31160
32043
|
size: 8
|
|
31161
32044
|
});
|
|
31162
32045
|
} else if (showPulsate) {
|
|
31163
|
-
iconStyles = [styles$
|
|
32046
|
+
iconStyles = [styles$e.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$e.markerUnfilledPulsateOnce : showPulsate && styles$e.markerUnfilledPulsateInfinite];
|
|
31164
32047
|
}
|
|
31165
32048
|
return /*#__PURE__*/React.createElement(View, {
|
|
31166
|
-
style: [styles$
|
|
32049
|
+
style: [styles$e.markerIcon, iconStyles],
|
|
31167
32050
|
ref: node => this._icon = node
|
|
31168
32051
|
}, /*#__PURE__*/React.createElement(Icon, args));
|
|
31169
32052
|
}
|
|
@@ -31185,7 +32068,7 @@ class Marker extends React.Component {
|
|
|
31185
32068
|
const markerDisabled = showCorrectness === "correct";
|
|
31186
32069
|
const active = hovered || focused;
|
|
31187
32070
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
31188
|
-
style: [styles$
|
|
32071
|
+
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive]
|
|
31189
32072
|
// already translated in: /widgets/graded-group.tsx
|
|
31190
32073
|
,
|
|
31191
32074
|
"aria-label": markerDisabled ? i18n._("Correct!") : label
|
|
@@ -31203,7 +32086,7 @@ class Marker extends React.Component {
|
|
|
31203
32086
|
Marker.defaultProps = {
|
|
31204
32087
|
selected: []
|
|
31205
32088
|
};
|
|
31206
|
-
const styles$
|
|
32089
|
+
const styles$e = StyleSheet.create({
|
|
31207
32090
|
marker: {
|
|
31208
32091
|
position: "absolute",
|
|
31209
32092
|
backgroundColor: Color.white,
|
|
@@ -31773,13 +32656,13 @@ class LabelImage extends React.Component {
|
|
|
31773
32656
|
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
32657
|
const choicesString = i18n._("Choices:");
|
|
31775
32658
|
return /*#__PURE__*/React.createElement("div", {
|
|
31776
|
-
className: classNames("perseus-label-image-widget-instructions", css(styles$
|
|
32659
|
+
className: classNames("perseus-label-image-widget-instructions", css(styles$d.instructions))
|
|
31777
32660
|
}, /*#__PURE__*/React.createElement("div", {
|
|
31778
|
-
className: css(styles$
|
|
32661
|
+
className: css(styles$d.instructionsCaption)
|
|
31779
32662
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React.createElement("div", {
|
|
31780
|
-
className: css(styles$
|
|
32663
|
+
className: css(styles$d.instructionsChoices)
|
|
31781
32664
|
}, choices.map((choice, index) => /*#__PURE__*/React.createElement("div", {
|
|
31782
|
-
className: css(styles$
|
|
32665
|
+
className: css(styles$d.instructionsChoice),
|
|
31783
32666
|
key: index
|
|
31784
32667
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
31785
32668
|
content: choice
|
|
@@ -31796,20 +32679,20 @@ class LabelImage extends React.Component {
|
|
|
31796
32679
|
activeMarkerIndex
|
|
31797
32680
|
} = this.state;
|
|
31798
32681
|
return /*#__PURE__*/React.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React.createElement("div", {
|
|
31799
|
-
className: css(styles$
|
|
32682
|
+
className: css(styles$d.markersCanvas),
|
|
31800
32683
|
style: {
|
|
31801
32684
|
maxWidth: imageWidth,
|
|
31802
32685
|
maxHeight: imageHeight
|
|
31803
32686
|
}
|
|
31804
32687
|
}, /*#__PURE__*/React.createElement("div", {
|
|
31805
|
-
className: css(styles$
|
|
32688
|
+
className: css(styles$d.imageContainer,
|
|
31806
32689
|
// Ensure image interaction is disabled while answer
|
|
31807
32690
|
// choices popup is visible. This addresses specific
|
|
31808
32691
|
// case where user may click on question image to
|
|
31809
32692
|
// dismiss the popup. If the image is larger in size
|
|
31810
32693
|
// than its rendered in the widget, this would
|
|
31811
32694
|
// result in a zoom of the image.
|
|
31812
|
-
activeMarkerIndex !== -1 && styles$
|
|
32695
|
+
activeMarkerIndex !== -1 && styles$d.imageInteractionDisabled)
|
|
31813
32696
|
}, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
|
|
31814
32697
|
setAssetStatus
|
|
31815
32698
|
}) => /*#__PURE__*/React.createElement(SvgImage, {
|
|
@@ -31833,7 +32716,7 @@ class LabelImage extends React.Component {
|
|
|
31833
32716
|
}));
|
|
31834
32717
|
}
|
|
31835
32718
|
}
|
|
31836
|
-
const styles$
|
|
32719
|
+
const styles$d = StyleSheet.create({
|
|
31837
32720
|
instructions: {
|
|
31838
32721
|
paddingBottom: 16
|
|
31839
32722
|
},
|
|
@@ -32190,7 +33073,7 @@ class Placeholder extends React.Component {
|
|
|
32190
33073
|
const {
|
|
32191
33074
|
layout
|
|
32192
33075
|
} = this.props;
|
|
32193
|
-
const className = css(styles$
|
|
33076
|
+
const className = css(styles$c.card, styles$c.placeholder, layout === Layout.HORIZONTAL && styles$c.horizontalCard);
|
|
32194
33077
|
const style = {
|
|
32195
33078
|
width: this.props.width,
|
|
32196
33079
|
height: this.props.height
|
|
@@ -32373,7 +33256,7 @@ class Draggable extends React.Component {
|
|
|
32373
33256
|
// We need to keep backwards compatbility with rules specified directly
|
|
32374
33257
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
32375
33258
|
// See sortable.less for details.
|
|
32376
|
-
let className = css(styles$
|
|
33259
|
+
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
33260
|
if (!includePadding) {
|
|
32378
33261
|
className += " perseus-sortable-draggable-unpadded";
|
|
32379
33262
|
}
|
|
@@ -32580,7 +33463,7 @@ class Sortable extends React.Component {
|
|
|
32580
33463
|
} = this.props;
|
|
32581
33464
|
// We need to keep backwards compatbility with rules specified directly
|
|
32582
33465
|
// in CSS. See sortable.less for details.
|
|
32583
|
-
const className = css(styles$
|
|
33466
|
+
const className = css(styles$c.sortable) + " perseus-sortable";
|
|
32584
33467
|
const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === Layout.VERTICAL;
|
|
32585
33468
|
const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === Layout.HORIZONTAL;
|
|
32586
33469
|
_.each(this.state.items, function (item, i, items) {
|
|
@@ -32822,7 +33705,7 @@ Sortable.defaultProps = {
|
|
|
32822
33705
|
linterContext: PerseusLinter.linterContextDefault,
|
|
32823
33706
|
waitForTexRendererToLoad: true
|
|
32824
33707
|
};
|
|
32825
|
-
const styles$
|
|
33708
|
+
const styles$c = StyleSheet.create({
|
|
32826
33709
|
sortable: {
|
|
32827
33710
|
boxSizing: "border-box",
|
|
32828
33711
|
float: "left",
|
|
@@ -32984,23 +33867,23 @@ class Matcher extends React.Component {
|
|
|
32984
33867
|
};
|
|
32985
33868
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
32986
33869
|
return /*#__PURE__*/React.createElement("table", {
|
|
32987
|
-
className: css(styles$
|
|
33870
|
+
className: css(styles$b.widget) + " " + HACKY_CSS_CLASSNAME
|
|
32988
33871
|
}, /*#__PURE__*/React.createElement("tbody", null, showLabels && /*#__PURE__*/React.createElement("tr", {
|
|
32989
|
-
className: css(styles$
|
|
33872
|
+
className: css(styles$b.row)
|
|
32990
33873
|
}, /*#__PURE__*/React.createElement("th", {
|
|
32991
|
-
className: css(styles$
|
|
33874
|
+
className: css(styles$b.column, styles$b.columnLabel)
|
|
32992
33875
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
32993
33876
|
content: this.props.labels[0] || "...",
|
|
32994
33877
|
linterContext: this.props.linterContext
|
|
32995
33878
|
})), /*#__PURE__*/React.createElement("th", {
|
|
32996
|
-
className: css(styles$
|
|
33879
|
+
className: css(styles$b.column, styles$b.columnRight, styles$b.columnLabel)
|
|
32997
33880
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
32998
33881
|
content: this.props.labels[1] || "...",
|
|
32999
33882
|
linterContext: this.props.linterContext
|
|
33000
33883
|
}))), /*#__PURE__*/React.createElement("tr", {
|
|
33001
|
-
className: css(styles$
|
|
33884
|
+
className: css(styles$b.row)
|
|
33002
33885
|
}, /*#__PURE__*/React.createElement("td", {
|
|
33003
|
-
className: css(styles$
|
|
33886
|
+
className: css(styles$b.column)
|
|
33004
33887
|
}, /*#__PURE__*/React.createElement(Sortable, {
|
|
33005
33888
|
options: left,
|
|
33006
33889
|
layout: Layout.VERTICAL,
|
|
@@ -33015,7 +33898,7 @@ class Matcher extends React.Component {
|
|
|
33015
33898
|
,
|
|
33016
33899
|
ref: "left"
|
|
33017
33900
|
})), /*#__PURE__*/React.createElement("td", {
|
|
33018
|
-
className: css(styles$
|
|
33901
|
+
className: css(styles$b.column, styles$b.columnRight)
|
|
33019
33902
|
}, /*#__PURE__*/React.createElement(Sortable
|
|
33020
33903
|
// @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
|
|
33021
33904
|
, {
|
|
@@ -33068,7 +33951,7 @@ _.extend(Matcher, {
|
|
|
33068
33951
|
});
|
|
33069
33952
|
const padding = 5;
|
|
33070
33953
|
const border = "1px solid #444";
|
|
33071
|
-
const styles$
|
|
33954
|
+
const styles$b = StyleSheet.create({
|
|
33072
33955
|
widget: {
|
|
33073
33956
|
paddingTop: padding,
|
|
33074
33957
|
maxWidth: "100%",
|
|
@@ -33101,197 +33984,6 @@ var Matcher$1 = {
|
|
|
33101
33984
|
isLintable: true
|
|
33102
33985
|
};
|
|
33103
33986
|
|
|
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
33987
|
// Type imports
|
|
33296
33988
|
|
|
33297
33989
|
const {
|
|
@@ -33935,9 +34627,9 @@ function drawText(ctx, item) {
|
|
|
33935
34627
|
if (item.value === null) {
|
|
33936
34628
|
return;
|
|
33937
34629
|
}
|
|
33938
|
-
ctx.fillStyle = styles$
|
|
33939
|
-
ctx.font = styles$
|
|
33940
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
34630
|
+
ctx.fillStyle = styles$a.fgColor;
|
|
34631
|
+
ctx.font = styles$a.font;
|
|
34632
|
+
ctx.fillText(item.value, item.pos[0] - styles$a.fontSizePx / 2 + 1, item.pos[1] + styles$a.fontSizePx / 2);
|
|
33941
34633
|
}
|
|
33942
34634
|
|
|
33943
34635
|
/**
|
|
@@ -33958,16 +34650,16 @@ function drawText(ctx, item) {
|
|
|
33958
34650
|
function drawDoubleLine(ctx, item) {
|
|
33959
34651
|
// Outer line that forms both of the bond lines.
|
|
33960
34652
|
let path = new Path2D();
|
|
33961
|
-
ctx.lineWidth = 5 * styles$
|
|
33962
|
-
ctx.strokeStyle = styles$
|
|
34653
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34654
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
33963
34655
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33964
34656
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
33965
34657
|
ctx.stroke(path);
|
|
33966
34658
|
|
|
33967
34659
|
// Inner white line that separates the two bond lines.
|
|
33968
34660
|
path = new Path2D();
|
|
33969
|
-
ctx.lineWidth = 3 * styles$
|
|
33970
|
-
ctx.strokeStyle = styles$
|
|
34661
|
+
ctx.lineWidth = 3 * styles$a.lineWidth;
|
|
34662
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
33971
34663
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33972
34664
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
33973
34665
|
ctx.stroke(path);
|
|
@@ -33994,16 +34686,16 @@ function drawTripleLine(ctx, item) {
|
|
|
33994
34686
|
|
|
33995
34687
|
// Outer line that will form the two outer bond lines.
|
|
33996
34688
|
let path = new Path2D();
|
|
33997
|
-
ctx.lineWidth = 7 * styles$
|
|
33998
|
-
ctx.strokeStyle = styles$
|
|
34689
|
+
ctx.lineWidth = 7 * styles$a.lineWidth;
|
|
34690
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
33999
34691
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34000
34692
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34001
34693
|
ctx.stroke(path);
|
|
34002
34694
|
|
|
34003
34695
|
// Middle white line that separates the bonds
|
|
34004
34696
|
path = new Path2D();
|
|
34005
|
-
ctx.lineWidth = 5 * styles$
|
|
34006
|
-
ctx.strokeStyle = styles$
|
|
34697
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34698
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34007
34699
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34008
34700
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34009
34701
|
ctx.stroke(path);
|
|
@@ -34025,8 +34717,8 @@ function drawTripleLine(ctx, item) {
|
|
|
34025
34717
|
*/
|
|
34026
34718
|
function drawLine(ctx, item) {
|
|
34027
34719
|
const path = new Path2D();
|
|
34028
|
-
ctx.lineWidth = styles$
|
|
34029
|
-
ctx.strokeStyle = styles$
|
|
34720
|
+
ctx.lineWidth = styles$a.lineWidth;
|
|
34721
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34030
34722
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34031
34723
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34032
34724
|
ctx.stroke(path);
|
|
@@ -34078,7 +34770,7 @@ function compareElements(item0, item1) {
|
|
|
34078
34770
|
function draw(ctx, items) {
|
|
34079
34771
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
34080
34772
|
}
|
|
34081
|
-
const styles$
|
|
34773
|
+
const styles$a = {
|
|
34082
34774
|
bgColor: "rgb(255, 255, 255)",
|
|
34083
34775
|
fgColor: "rgb(0, 0, 0)",
|
|
34084
34776
|
fontSizePx: 12,
|
|
@@ -36640,7 +37332,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
36640
37332
|
const rects = this.state.cachedHighlightRects;
|
|
36641
37333
|
return /*#__PURE__*/React.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React.createElement("div", {
|
|
36642
37334
|
key: index,
|
|
36643
|
-
className: css(styles$
|
|
37335
|
+
className: css(styles$9.highlightRect),
|
|
36644
37336
|
style: {
|
|
36645
37337
|
// NOTE(mdr): We apply `position: absolute` here
|
|
36646
37338
|
// rather than in Aphrodite styles, because
|
|
@@ -36659,7 +37351,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
36659
37351
|
})));
|
|
36660
37352
|
}
|
|
36661
37353
|
}
|
|
36662
|
-
const styles$
|
|
37354
|
+
const styles$9 = StyleSheet.create({
|
|
36663
37355
|
highlightRect: {
|
|
36664
37356
|
background: "#fffabe" // highlighter yellow :)
|
|
36665
37357
|
}
|
|
@@ -36740,7 +37432,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
36740
37432
|
// TooltipContent wouldn't let me overwrite
|
|
36741
37433
|
// user-select and onClick
|
|
36742
37434
|
const content = /*#__PURE__*/React.createElement("div", {
|
|
36743
|
-
className: css(styles$
|
|
37435
|
+
className: css(styles$8.tooltipLabel),
|
|
36744
37436
|
onClick: this.props.onClick
|
|
36745
37437
|
}, this.props.label);
|
|
36746
37438
|
const style = {
|
|
@@ -36760,7 +37452,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
36760
37452
|
}, /*#__PURE__*/React.createElement("div", null)));
|
|
36761
37453
|
}
|
|
36762
37454
|
}
|
|
36763
|
-
const styles$
|
|
37455
|
+
const styles$8 = StyleSheet.create({
|
|
36764
37456
|
tooltipLabel: {
|
|
36765
37457
|
// Unlike most tooltip contents, we don't want this label to be
|
|
36766
37458
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -37312,7 +38004,7 @@ class HighlightableContent extends React.PureComponent {
|
|
|
37312
38004
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
37313
38005
|
const buildHighlight = r => this._buildHighlight(r);
|
|
37314
38006
|
return /*#__PURE__*/React.createElement("div", {
|
|
37315
|
-
className: css(styles$
|
|
38007
|
+
className: css(styles$7.container),
|
|
37316
38008
|
ref: container => this._container = container
|
|
37317
38009
|
}, /*#__PURE__*/React.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React.createElement(HighlightingUI, {
|
|
37318
38010
|
buildHighlight: buildHighlight,
|
|
@@ -37333,14 +38025,14 @@ class HighlightableContent extends React.PureComponent {
|
|
|
37333
38025
|
onAddHighlight: this._handleAddHighlight,
|
|
37334
38026
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
37335
38027
|
})), /*#__PURE__*/React.createElement("div", {
|
|
37336
|
-
className: css(styles$
|
|
38028
|
+
className: css(styles$7.content),
|
|
37337
38029
|
ref: content => this._content = content
|
|
37338
38030
|
}, /*#__PURE__*/React.createElement(WordIndexer, {
|
|
37339
38031
|
onWordsUpdate: this._handleWordsUpdate
|
|
37340
38032
|
}, this.props.children)));
|
|
37341
38033
|
}
|
|
37342
38034
|
}
|
|
37343
|
-
const styles$
|
|
38035
|
+
const styles$7 = StyleSheet.create({
|
|
37344
38036
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
37345
38037
|
// content will receive the browser's native pointer events. (Highlights
|
|
37346
38038
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -37740,7 +38432,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
37740
38432
|
}
|
|
37741
38433
|
render() {
|
|
37742
38434
|
return /*#__PURE__*/React.createElement("div", {
|
|
37743
|
-
className: css(styles$
|
|
38435
|
+
className: css(styles$6.measurer),
|
|
37744
38436
|
"aria-hidden": "true"
|
|
37745
38437
|
}, /*#__PURE__*/React.createElement("div", {
|
|
37746
38438
|
ref: ref => this._line = ref,
|
|
@@ -37748,7 +38440,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
37748
38440
|
}, "Line Height Measurement"));
|
|
37749
38441
|
}
|
|
37750
38442
|
}
|
|
37751
|
-
const styles$
|
|
38443
|
+
const styles$6 = StyleSheet.create({
|
|
37752
38444
|
measurer: {
|
|
37753
38445
|
position: "absolute",
|
|
37754
38446
|
top: 0,
|
|
@@ -39060,7 +39752,7 @@ class PythonProgram extends React.Component {
|
|
|
39060
39752
|
// creator "went wild".
|
|
39061
39753
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
39062
39754
|
return /*#__PURE__*/React.createElement(View, {
|
|
39063
|
-
style: styles$
|
|
39755
|
+
style: styles$5.container
|
|
39064
39756
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
39065
39757
|
sandbox: sandboxOptions,
|
|
39066
39758
|
src: url,
|
|
@@ -39072,7 +39764,7 @@ class PythonProgram extends React.Component {
|
|
|
39072
39764
|
PythonProgram.defaultProps = {
|
|
39073
39765
|
height: 400
|
|
39074
39766
|
};
|
|
39075
|
-
const styles$
|
|
39767
|
+
const styles$5 = StyleSheet.create({
|
|
39076
39768
|
container: {
|
|
39077
39769
|
margin: "auto",
|
|
39078
39770
|
width: "100%"
|
|
@@ -39312,129 +40004,6 @@ var Sequence$1 = {
|
|
|
39312
40004
|
isLintable: true
|
|
39313
40005
|
};
|
|
39314
40006
|
|
|
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
40007
|
const {
|
|
39439
40008
|
assert: assert$1
|
|
39440
40009
|
} = InteractiveUtil;
|
|
@@ -41389,7 +41958,7 @@ const VideoTranscriptLink = props => {
|
|
|
41389
41958
|
var _result$data;
|
|
41390
41959
|
const video = (_result$data = result.data) == null ? void 0 : _result$data.video;
|
|
41391
41960
|
return /*#__PURE__*/React.createElement(View, {
|
|
41392
|
-
style: styles$
|
|
41961
|
+
style: styles$4.transcriptLink
|
|
41393
41962
|
}, /*#__PURE__*/React.createElement(Text$1, null, video == null ? void 0 : video.title), /*#__PURE__*/React.createElement(Strut, {
|
|
41394
41963
|
size: 10
|
|
41395
41964
|
}), /*#__PURE__*/React.createElement(Link, {
|
|
@@ -41406,7 +41975,7 @@ const VideoTranscriptLink = props => {
|
|
|
41406
41975
|
return /*#__PURE__*/React.createElement(View, null, i18n._("Something went wrong."));
|
|
41407
41976
|
}
|
|
41408
41977
|
};
|
|
41409
|
-
const styles$
|
|
41978
|
+
const styles$4 = StyleSheet.create({
|
|
41410
41979
|
transcriptLink: {
|
|
41411
41980
|
flexDirection: "row",
|
|
41412
41981
|
width: "100%",
|
|
@@ -41559,7 +42128,7 @@ const init = function init(options) {
|
|
|
41559
42128
|
|
|
41560
42129
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41561
42130
|
const libName = "@khanacademy/perseus";
|
|
41562
|
-
const libVersion = "19.
|
|
42131
|
+
const libVersion = "19.7.1";
|
|
41563
42132
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41564
42133
|
|
|
41565
42134
|
const apiVersion = {
|
|
@@ -41769,7 +42338,7 @@ class HintRenderer extends React.Component {
|
|
|
41769
42338
|
const {
|
|
41770
42339
|
isMobile
|
|
41771
42340
|
} = apiOptions;
|
|
41772
|
-
const classNames$1 = classNames("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$
|
|
42341
|
+
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
42342
|
|
|
41774
42343
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
41775
42344
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -41812,7 +42381,7 @@ class HintRenderer extends React.Component {
|
|
|
41812
42381
|
HintRenderer.defaultProps = {
|
|
41813
42382
|
linterContext: PerseusLinter.linterContextDefault
|
|
41814
42383
|
};
|
|
41815
|
-
const styles$
|
|
42384
|
+
const styles$3 = StyleSheet.create({
|
|
41816
42385
|
newHint: {
|
|
41817
42386
|
marginBottom: 1.5 * baseUnitPx,
|
|
41818
42387
|
borderLeftColor: gray97,
|
|
@@ -41985,15 +42554,15 @@ class HintsRenderer extends React.Component {
|
|
|
41985
42554
|
} = apiOptions;
|
|
41986
42555
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
41987
42556
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
41988
|
-
const classNames$1 = classNames(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$
|
|
42557
|
+
const classNames$1 = classNames(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$2.mobileHintStylesHintsRenderer));
|
|
41989
42558
|
return /*#__PURE__*/React.createElement("div", {
|
|
41990
42559
|
className: classNames$1
|
|
41991
42560
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React.createElement("div", {
|
|
41992
|
-
className: css(styles$
|
|
42561
|
+
className: css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
41993
42562
|
}, i18n._("Hints")), hints, showGetAnotherHint && /*#__PURE__*/React.createElement("button", {
|
|
41994
42563
|
// @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
42564
|
rel: "button",
|
|
41996
|
-
className: css(styles$
|
|
42565
|
+
className: css(styles$2.linkButton, styles$2.getAnotherHintButton, apiOptions.isMobile && styles$2.mobileHintStylesGetAnotherHintButton),
|
|
41997
42566
|
onClick: evt => {
|
|
41998
42567
|
evt.preventDefault();
|
|
41999
42568
|
evt.stopPropagation();
|
|
@@ -42002,9 +42571,9 @@ class HintsRenderer extends React.Component {
|
|
|
42002
42571
|
}
|
|
42003
42572
|
}
|
|
42004
42573
|
}, /*#__PURE__*/React.createElement("span", {
|
|
42005
|
-
className: css(styles$
|
|
42574
|
+
className: css(styles$2.plusText, apiOptions.isMobile && styles$2.mobileHintStylesPlusText)
|
|
42006
42575
|
}, "+"), /*#__PURE__*/React.createElement("span", {
|
|
42007
|
-
className: css(styles$
|
|
42576
|
+
className: css(styles$2.getAnotherHintText)
|
|
42008
42577
|
}, i18n._("Get another hint"), " ", hintRatioCopy)));
|
|
42009
42578
|
}
|
|
42010
42579
|
}
|
|
@@ -42012,7 +42581,7 @@ HintsRenderer.defaultProps = {
|
|
|
42012
42581
|
linterContext: PerseusLinter.linterContextDefault
|
|
42013
42582
|
};
|
|
42014
42583
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
42015
|
-
const styles$
|
|
42584
|
+
const styles$2 = StyleSheet.create({
|
|
42016
42585
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
42017
42586
|
rendererMargins: {
|
|
42018
42587
|
marginTop: baseUnitPx
|
|
@@ -42419,7 +42988,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
42419
42988
|
// mobile hint styles, which are flush to the left.
|
|
42420
42989
|
// NOTE(charlie): We may still want to apply this
|
|
42421
42990
|
// padding for desktop exercises.
|
|
42422
|
-
apiOptions.isMobile ? undefined : css(styles$
|
|
42991
|
+
apiOptions.isMobile ? undefined : css(styles$1.hintsContainer)
|
|
42423
42992
|
}, hintsRenderer)));
|
|
42424
42993
|
}
|
|
42425
42994
|
}
|
|
@@ -42429,7 +42998,7 @@ ServerItemRenderer.defaultProps = {
|
|
|
42429
42998
|
linterContext: PerseusLinter.linterContextDefault,
|
|
42430
42999
|
onRendered: isRendered => {}
|
|
42431
43000
|
};
|
|
42432
|
-
const styles$
|
|
43001
|
+
const styles$1 = StyleSheet.create({
|
|
42433
43002
|
hintsContainer: {
|
|
42434
43003
|
marginLeft: 50
|
|
42435
43004
|
}
|
|
@@ -42563,345 +43132,6 @@ ElementContainer.defaultProps = {
|
|
|
42563
43132
|
title: "More"
|
|
42564
43133
|
};
|
|
42565
43134
|
|
|
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
43135
|
const devices = {
|
|
42906
43136
|
PHONE: "phone",
|
|
42907
43137
|
TABLET: "tablet",
|