@khanacademy/perseus 19.6.2 → 19.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +168 -0
- package/dist/es/index.js +978 -743
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +168 -0
- package/dist/index.js +975 -738
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +1 -0
- package/dist/perseus-types.d.ts +14 -2
- package/dist/renderer.d.ts +9 -0
- package/dist/server-item-renderer.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/widgets/expression.d.ts +6 -0
- package/dist/widgets/interactive-graph.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/segment.d.ts +5 -0
- package/dist/widgets/interactive-graphs/grid.d.ts +11 -0
- package/dist/widgets/interactive-graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/legacy-grid.d.ts +7 -0
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +79 -0
- package/dist/widgets/interactive-graphs/types.d.ts +9 -0
- package/dist/widgets/interactive-graphs/utils.d.ts +15 -0
- package/dist/widgets/label-image.d.ts +2 -0
- package/package.json +3 -2
package/dist/es/index.js
CHANGED
|
@@ -29,11 +29,12 @@ import { Strut } from '@khanacademy/wonder-blocks-layout';
|
|
|
29
29
|
import Banner from '@khanacademy/wonder-blocks-banner';
|
|
30
30
|
import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-blocks-dropdown';
|
|
31
31
|
import debounce$1 from 'lodash.debounce';
|
|
32
|
+
import { useMovablePoint, Line as Line$4, Coordinates, Mafs } from 'mafs';
|
|
33
|
+
import createReactClass from 'create-react-class';
|
|
32
34
|
import Switch from '@khanacademy/wonder-blocks-switch';
|
|
33
35
|
import { LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
34
36
|
import Pill from '@khanacademy/wonder-blocks-pill';
|
|
35
37
|
import { Popper } from 'react-popper';
|
|
36
|
-
import createReactClass from 'create-react-class';
|
|
37
38
|
import Link from '@khanacademy/wonder-blocks-link';
|
|
38
39
|
import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-core';
|
|
39
40
|
|
|
@@ -1901,7 +1902,7 @@ const KhanAnswerTypes = {
|
|
|
1901
1902
|
}
|
|
1902
1903
|
};
|
|
1903
1904
|
|
|
1904
|
-
const _excluded$
|
|
1905
|
+
const _excluded$5 = ["scoring"];
|
|
1905
1906
|
const ERROR_TITLE = i18n._("Oops!");
|
|
1906
1907
|
const ERROR_MESSAGE = i18n._("Sorry, I don't understand that!");
|
|
1907
1908
|
|
|
@@ -1989,7 +1990,7 @@ class Expression extends React.Component {
|
|
|
1989
1990
|
let {
|
|
1990
1991
|
scoring
|
|
1991
1992
|
} = _ref,
|
|
1992
|
-
rubric = _objectWithoutPropertiesLoose(_ref, _excluded$
|
|
1993
|
+
rubric = _objectWithoutPropertiesLoose(_ref, _excluded$5);
|
|
1993
1994
|
const score = Expression.validate(this.getUserInput(), rubric, onInputError || function () {});
|
|
1994
1995
|
|
|
1995
1996
|
// "scoring" is a flag that indicates when we are checking answers.
|
|
@@ -19252,6 +19253,15 @@ const isIdPathPrefix = function isIdPathPrefix(prefixArray, wholeArray) {
|
|
|
19252
19253
|
// some return a custom-built object, some delegate to
|
|
19253
19254
|
// `WidgetJsonifyDeprecated` which returns an object containing widget props
|
|
19254
19255
|
// (filtered by deprecated keys)).
|
|
19256
|
+
/**
|
|
19257
|
+
* The Widget type represents the common API that the Renderer uses to interact
|
|
19258
|
+
* with all widgets. All widgets must implement the methods in this API, unless
|
|
19259
|
+
* they are marked as optional (?: ...).
|
|
19260
|
+
*
|
|
19261
|
+
* These methods are called on the widget ref and allow the renderer to
|
|
19262
|
+
* communicate with the individual widgets to coordinate actions such as
|
|
19263
|
+
* scoring, state serialization/deserialization, and focus management.
|
|
19264
|
+
*/
|
|
19255
19265
|
class Renderer extends React.Component {
|
|
19256
19266
|
constructor(_props) {
|
|
19257
19267
|
super(_props);
|
|
@@ -21383,7 +21393,7 @@ InputWithExamples.defaultProps = {
|
|
|
21383
21393
|
className: ""
|
|
21384
21394
|
};
|
|
21385
21395
|
|
|
21386
|
-
const _excluded$
|
|
21396
|
+
const _excluded$4 = ["keypadElement", "onFocus", "value"];
|
|
21387
21397
|
class SimpleKeypadInput extends React.Component {
|
|
21388
21398
|
constructor(...args) {
|
|
21389
21399
|
super(...args);
|
|
@@ -21422,7 +21432,7 @@ class SimpleKeypadInput extends React.Component {
|
|
|
21422
21432
|
onFocus,
|
|
21423
21433
|
value
|
|
21424
21434
|
} = _this$props,
|
|
21425
|
-
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$
|
|
21435
|
+
rest = _objectWithoutPropertiesLoose(_this$props, _excluded$4);
|
|
21426
21436
|
return (
|
|
21427
21437
|
/*#__PURE__*/
|
|
21428
21438
|
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
@@ -23253,14 +23263,14 @@ var Choice$1 = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.
|
|
|
23253
23263
|
forwardedRef: ref
|
|
23254
23264
|
})));
|
|
23255
23265
|
|
|
23256
|
-
const _excluded$
|
|
23266
|
+
const _excluded$3 = ["showContent", "content", "forwardedRef"];
|
|
23257
23267
|
const ChoiceNoneAbove = function ChoiceNoneAbove(props) {
|
|
23258
23268
|
const {
|
|
23259
23269
|
showContent,
|
|
23260
23270
|
content,
|
|
23261
23271
|
forwardedRef
|
|
23262
23272
|
} = props,
|
|
23263
|
-
rest = _objectWithoutPropertiesLoose(props, _excluded$
|
|
23273
|
+
rest = _objectWithoutPropertiesLoose(props, _excluded$3);
|
|
23264
23274
|
const choiceProps = _extends({}, rest, {
|
|
23265
23275
|
content: showContent ? content :
|
|
23266
23276
|
/*#__PURE__*/
|
|
@@ -28164,6 +28174,872 @@ Graph.defaultProps = {
|
|
|
28164
28174
|
isMobile: false
|
|
28165
28175
|
};
|
|
28166
28176
|
|
|
28177
|
+
const useInteractivePoint = (coords, snaps, range) => useMovablePoint(coords, {
|
|
28178
|
+
constrain: coord => constrain(coord, snaps, range),
|
|
28179
|
+
color: Color.blue
|
|
28180
|
+
});
|
|
28181
|
+
|
|
28182
|
+
/**
|
|
28183
|
+
* We do not want to call `onGraphChange` until the user
|
|
28184
|
+
* has interacted with the graph. See the test,
|
|
28185
|
+
* "should reject no interaction"
|
|
28186
|
+
*/
|
|
28187
|
+
const useEffectAfterFirstRender = (fn, deps) => {
|
|
28188
|
+
const firstRender = useRef(true);
|
|
28189
|
+
useEffect(() => {
|
|
28190
|
+
if (firstRender.current) {
|
|
28191
|
+
firstRender.current = false;
|
|
28192
|
+
return;
|
|
28193
|
+
}
|
|
28194
|
+
fn();
|
|
28195
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28196
|
+
}, [fn, ...deps]);
|
|
28197
|
+
};
|
|
28198
|
+
const snap = (val, step) => {
|
|
28199
|
+
const inverse = 1 / step;
|
|
28200
|
+
return Math.round(val * inverse) / inverse;
|
|
28201
|
+
};
|
|
28202
|
+
const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
28203
|
+
const constrain = (coord, snapStep, range) => {
|
|
28204
|
+
const [x, y] = coord;
|
|
28205
|
+
const [xSnap, ySnap] = snapStep;
|
|
28206
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
28207
|
+
return [clamp(snap(x, xSnap), xMin, xMax), clamp(snap(y, ySnap), yMin, yMax)];
|
|
28208
|
+
};
|
|
28209
|
+
|
|
28210
|
+
// same as pointsFromNormalized in interactive-graph.tsx
|
|
28211
|
+
const normalizePoints = (range, step, coordsList, noSnap) => coordsList.map(coords =>
|
|
28212
|
+
// maps over [x, y]
|
|
28213
|
+
coords.map((coord, i) => {
|
|
28214
|
+
const axisRange = range[i];
|
|
28215
|
+
if (noSnap) {
|
|
28216
|
+
return axisRange[0] + (axisRange[1] - axisRange[0]) * coord;
|
|
28217
|
+
}
|
|
28218
|
+
const axisStep = step[i];
|
|
28219
|
+
const nSteps = Math.floor((axisRange[1] - axisRange[0]) / axisStep);
|
|
28220
|
+
const tick = Math.round(coord * nSteps);
|
|
28221
|
+
return axisRange[0] + axisStep * tick;
|
|
28222
|
+
}));
|
|
28223
|
+
|
|
28224
|
+
// same as normalizeCoords in interactive-graph.tsx
|
|
28225
|
+
const normalizeCoords = (coordsList, ranges) => coordsList.map(coords => coords.map((coord, i) => {
|
|
28226
|
+
const extent = ranges[i][1] - ranges[i][0];
|
|
28227
|
+
return (coord + ranges[i][1]) / extent;
|
|
28228
|
+
}));
|
|
28229
|
+
|
|
28230
|
+
const getSegmentCoords = props => {
|
|
28231
|
+
const coords = props.graph.coords;
|
|
28232
|
+
if (coords) {
|
|
28233
|
+
return coords;
|
|
28234
|
+
}
|
|
28235
|
+
const ys = n => {
|
|
28236
|
+
switch (n) {
|
|
28237
|
+
case 2:
|
|
28238
|
+
return [5, -5];
|
|
28239
|
+
case 3:
|
|
28240
|
+
return [5, 0, -5];
|
|
28241
|
+
case 4:
|
|
28242
|
+
return [6, 2, -2, -6];
|
|
28243
|
+
case 5:
|
|
28244
|
+
return [6, 3, 0, -3, -6];
|
|
28245
|
+
case 6:
|
|
28246
|
+
return [5, 3, 1, -1, -3, -5];
|
|
28247
|
+
default:
|
|
28248
|
+
return [5];
|
|
28249
|
+
}
|
|
28250
|
+
};
|
|
28251
|
+
return ys(props.graph.numSegments).map(y => {
|
|
28252
|
+
let segment = [[-5, y], [5, y]];
|
|
28253
|
+
segment = normalizeCoords(segment, props.range);
|
|
28254
|
+
segment = normalizePoints(props.range, props.step, segment);
|
|
28255
|
+
return segment;
|
|
28256
|
+
});
|
|
28257
|
+
};
|
|
28258
|
+
const updateSegmentsArray = (segments, index, segment) => segments.map((seg, i) => index === i ? segment : seg);
|
|
28259
|
+
const SegmentGraph = props => {
|
|
28260
|
+
const segments = getSegmentCoords(props);
|
|
28261
|
+
const handleChange = (i, segment) => props.onGraphChange(current => _extends({}, current, {
|
|
28262
|
+
coords: current.coords ? updateSegmentsArray(current.coords, i, segment) : updateSegmentsArray(segments, i, segment)
|
|
28263
|
+
}));
|
|
28264
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, segments.map((segment, i) => /*#__PURE__*/React.createElement(Segment, {
|
|
28265
|
+
key: i,
|
|
28266
|
+
i: i,
|
|
28267
|
+
segment: segment,
|
|
28268
|
+
snaps: props.snapStep,
|
|
28269
|
+
range: props.range,
|
|
28270
|
+
onChange: handleChange,
|
|
28271
|
+
"data-testid": "segment" + i
|
|
28272
|
+
})));
|
|
28273
|
+
};
|
|
28274
|
+
const Segment = props => {
|
|
28275
|
+
const [start, end] = props.segment;
|
|
28276
|
+
const {
|
|
28277
|
+
point: pt1,
|
|
28278
|
+
element: el1
|
|
28279
|
+
} = useInteractivePoint(start, props.snaps, props.range);
|
|
28280
|
+
const {
|
|
28281
|
+
point: pt2,
|
|
28282
|
+
element: el2
|
|
28283
|
+
} = useInteractivePoint(end, props.snaps, props.range);
|
|
28284
|
+
useEffectAfterFirstRender(() => props.onChange(props.i, [pt1, pt2]), [pt1, pt2]);
|
|
28285
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Line$4.Segment, {
|
|
28286
|
+
point1: pt1,
|
|
28287
|
+
point2: pt2
|
|
28288
|
+
}), el1, el2);
|
|
28289
|
+
};
|
|
28290
|
+
|
|
28291
|
+
const renderLineLabel = (n, [min, max]) => n !== -1 && n !== min && n !== max;
|
|
28292
|
+
const axisOptions = (props, index) => ({
|
|
28293
|
+
axis: props.markings === "graph",
|
|
28294
|
+
lines: props.step[index],
|
|
28295
|
+
subdivisions: props.step[index] / props.gridStep[index],
|
|
28296
|
+
labels: n => renderLineLabel(n, props.range[index]) ? n : ""
|
|
28297
|
+
});
|
|
28298
|
+
const Grid = props => props.markings === "none" ? null : /*#__PURE__*/React.createElement(Coordinates.Cartesian, {
|
|
28299
|
+
xAxis: axisOptions(props, 0),
|
|
28300
|
+
yAxis: axisOptions(props, 1)
|
|
28301
|
+
});
|
|
28302
|
+
|
|
28303
|
+
// Displays a stylized open eye: lint warnings are visible
|
|
28304
|
+
const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
28305
|
+
width: "24",
|
|
28306
|
+
height: "24",
|
|
28307
|
+
viewBox: "0 0 24 24",
|
|
28308
|
+
className: css(styles$j.icon)
|
|
28309
|
+
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
28310
|
+
id: "a",
|
|
28311
|
+
d: "M7.401 10.035c-1.424.748-2.599 1.905-3.544 " + "3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 " + "12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 " + "1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-" + "3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 " + "0 0 0 0 6z"
|
|
28312
|
+
})), /*#__PURE__*/React.createElement("g", {
|
|
28313
|
+
fill: "none",
|
|
28314
|
+
fillRule: "evenodd"
|
|
28315
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28316
|
+
fill: "none",
|
|
28317
|
+
d: "M0 0h24v24H0z"
|
|
28318
|
+
}), /*#__PURE__*/React.createElement("mask", {
|
|
28319
|
+
id: "b",
|
|
28320
|
+
fill: "#fff"
|
|
28321
|
+
}, /*#__PURE__*/React.createElement("use", {
|
|
28322
|
+
href: "#a"
|
|
28323
|
+
})), /*#__PURE__*/React.createElement("use", {
|
|
28324
|
+
fill: "#fff",
|
|
28325
|
+
fillRule: "nonzero",
|
|
28326
|
+
href: "#a"
|
|
28327
|
+
}), /*#__PURE__*/React.createElement("g", {
|
|
28328
|
+
fill: "#fff",
|
|
28329
|
+
mask: "url(#b)"
|
|
28330
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28331
|
+
d: "M0 0h24v24H0z"
|
|
28332
|
+
}))));
|
|
28333
|
+
|
|
28334
|
+
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
28335
|
+
const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
28336
|
+
width: "24",
|
|
28337
|
+
height: "24",
|
|
28338
|
+
viewBox: "0 0 24 24",
|
|
28339
|
+
className: css(styles$j.icon)
|
|
28340
|
+
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
28341
|
+
id: "a",
|
|
28342
|
+
d: "M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 " + "7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 " + "1.028c-.945-1.574-2.12-2.73-3.544-3.48.258." + "604.401 1.268.401 1.966 0 1.02-.305 " + "1.967-.828 2.757l2.535 2.536a1 1 0 0 " + "1-1.414 1.414l-12-12a1 1 0 0 1 " + "1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 " + "0-4.001-4.001l4 4.001zM6.072 8.486l2.976 " + "2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 " + "0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 " + "3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 " + "2.363-3.085 3.929-4z"
|
|
28343
|
+
})), /*#__PURE__*/React.createElement("g", {
|
|
28344
|
+
fill: "none",
|
|
28345
|
+
fillRule: "evenodd"
|
|
28346
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28347
|
+
fill: "none",
|
|
28348
|
+
d: "M0 0h24v24H0z"
|
|
28349
|
+
}), /*#__PURE__*/React.createElement("mask", {
|
|
28350
|
+
id: "b",
|
|
28351
|
+
fill: "#fff"
|
|
28352
|
+
}, /*#__PURE__*/React.createElement("use", {
|
|
28353
|
+
href: "#a"
|
|
28354
|
+
})), /*#__PURE__*/React.createElement("use", {
|
|
28355
|
+
fill: "#fff",
|
|
28356
|
+
fillRule: "nonzero",
|
|
28357
|
+
href: "#a"
|
|
28358
|
+
}), /*#__PURE__*/React.createElement("g", {
|
|
28359
|
+
fill: "#fff",
|
|
28360
|
+
mask: "url(#b)"
|
|
28361
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
28362
|
+
d: "M0 0h24v24H0z"
|
|
28363
|
+
}))));
|
|
28364
|
+
const HUD = ({
|
|
28365
|
+
message,
|
|
28366
|
+
enabled,
|
|
28367
|
+
onClick,
|
|
28368
|
+
fixedPosition: _fixedPosition = true
|
|
28369
|
+
}) => {
|
|
28370
|
+
let state;
|
|
28371
|
+
let icon;
|
|
28372
|
+
if (enabled) {
|
|
28373
|
+
state = styles$j.enabled;
|
|
28374
|
+
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
28375
|
+
} else {
|
|
28376
|
+
state = styles$j.disabled;
|
|
28377
|
+
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
28378
|
+
}
|
|
28379
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
28380
|
+
className: css(styles$j.hud, _fixedPosition && styles$j.hudFixedPosition, state),
|
|
28381
|
+
onClick: e => {
|
|
28382
|
+
onClick();
|
|
28383
|
+
}
|
|
28384
|
+
}, icon, message);
|
|
28385
|
+
};
|
|
28386
|
+
const styles$j = StyleSheet.create({
|
|
28387
|
+
hud: {
|
|
28388
|
+
boxSizing: "border-box",
|
|
28389
|
+
height: 36,
|
|
28390
|
+
padding: "9px 16px",
|
|
28391
|
+
borderRadius: 18,
|
|
28392
|
+
fontFamily: boldFontFamily,
|
|
28393
|
+
fontSize: "15px",
|
|
28394
|
+
lineHeight: "18px",
|
|
28395
|
+
color: white$1,
|
|
28396
|
+
userSelect: "none",
|
|
28397
|
+
borderWidth: 0 // <button> gives us a border by default
|
|
28398
|
+
},
|
|
28399
|
+
|
|
28400
|
+
// We want to render the element in-place in our fixtures, so allow us to
|
|
28401
|
+
// render in the bottom corner in production and in-place in testing.
|
|
28402
|
+
hudFixedPosition: {
|
|
28403
|
+
bottom: 20,
|
|
28404
|
+
position: "fixed",
|
|
28405
|
+
right: 20,
|
|
28406
|
+
zIndex: 1
|
|
28407
|
+
},
|
|
28408
|
+
icon: {
|
|
28409
|
+
width: 24,
|
|
28410
|
+
height: 24,
|
|
28411
|
+
marginRight: 8,
|
|
28412
|
+
marginTop: -3,
|
|
28413
|
+
verticalAlign: "middle"
|
|
28414
|
+
},
|
|
28415
|
+
enabled: {
|
|
28416
|
+
backgroundColor: warningColor,
|
|
28417
|
+
":hover": {
|
|
28418
|
+
backgroundColor: warningColorHover
|
|
28419
|
+
},
|
|
28420
|
+
":active": {
|
|
28421
|
+
backgroundColor: warningColorActive
|
|
28422
|
+
}
|
|
28423
|
+
},
|
|
28424
|
+
disabled: {
|
|
28425
|
+
backgroundColor: gray76,
|
|
28426
|
+
":hover": {
|
|
28427
|
+
backgroundColor: "#a1a5a9" // in between those two grays
|
|
28428
|
+
},
|
|
28429
|
+
|
|
28430
|
+
":active": {
|
|
28431
|
+
backgroundColor: gray68
|
|
28432
|
+
}
|
|
28433
|
+
}
|
|
28434
|
+
});
|
|
28435
|
+
|
|
28436
|
+
const colors$1 = {
|
|
28437
|
+
grayLight: "#aaa",
|
|
28438
|
+
basicBorderColor: "#ccc",
|
|
28439
|
+
white: "#fff"
|
|
28440
|
+
};
|
|
28441
|
+
const triangleBeforeAfter = {
|
|
28442
|
+
borderBottom: "9px solid transparent",
|
|
28443
|
+
borderTop: "9px solid transparent",
|
|
28444
|
+
content: '" "',
|
|
28445
|
+
height: "0",
|
|
28446
|
+
position: "absolute",
|
|
28447
|
+
top: "0",
|
|
28448
|
+
width: "0"
|
|
28449
|
+
};
|
|
28450
|
+
const styles$i = StyleSheet.create({
|
|
28451
|
+
infoTip: {
|
|
28452
|
+
display: "inline-block",
|
|
28453
|
+
marginLeft: "5px",
|
|
28454
|
+
position: "relative"
|
|
28455
|
+
},
|
|
28456
|
+
infoTipContainer: {
|
|
28457
|
+
position: "absolute",
|
|
28458
|
+
top: "-12px",
|
|
28459
|
+
left: "22px",
|
|
28460
|
+
zIndex: 1000
|
|
28461
|
+
},
|
|
28462
|
+
infoTipTriangle: {
|
|
28463
|
+
height: "10px",
|
|
28464
|
+
left: "0",
|
|
28465
|
+
position: "absolute",
|
|
28466
|
+
top: "8px",
|
|
28467
|
+
width: "0",
|
|
28468
|
+
zIndex: 1,
|
|
28469
|
+
":before": _extends({}, triangleBeforeAfter, {
|
|
28470
|
+
borderRight: "9px solid #bbb",
|
|
28471
|
+
right: "0"
|
|
28472
|
+
}),
|
|
28473
|
+
":after": _extends({}, triangleBeforeAfter, {
|
|
28474
|
+
borderRight: `9px solid ${colors$1.white}`,
|
|
28475
|
+
right: "-1px"
|
|
28476
|
+
})
|
|
28477
|
+
},
|
|
28478
|
+
verticalShadow: {
|
|
28479
|
+
border: `1px solid ${colors$1.basicBorderColor}`,
|
|
28480
|
+
boxShadow: `0 1px 3px ${colors$1.basicBorderColor}`,
|
|
28481
|
+
borderBottom: `1px solid ${colors$1.grayLight}`
|
|
28482
|
+
},
|
|
28483
|
+
infoTipContentContainer: {
|
|
28484
|
+
background: colors$1.white,
|
|
28485
|
+
padding: "5px 10px",
|
|
28486
|
+
width: "240px"
|
|
28487
|
+
}
|
|
28488
|
+
});
|
|
28489
|
+
const questionMark = "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBB" + "ZG9iZSBJbWFnZVJlYWR5ccllPAAAA3NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/" + "eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+" + "IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2Jl" + "IFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAg" + "ICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5" + "LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9" + "IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHht" + "bG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3Vy" + "Y2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHht" + "cE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo2N2M3NTAxYS04YmVlLTQ0M2Mt" + "YmRiNS04OGM2N2IxN2NhYzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUJCRTk4" + "Qjc4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5p" + "aWQ6OUJCRTk4QjY4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcDpDcmVhdG9yVG9v" + "bD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRG" + "cm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NGE5ZDI0OTMtODk1NC00OGFkLTlh" + "MTgtZDAwM2MwYWNjNDJlIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY3Yzc1MDFh" + "LThiZWUtNDQzYy1iZGI1LTg4YzY3YjE3Y2FjMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4g" + "PC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pqm89uYAAADM" + "SURBVHjaXJA9DoJAEIUH1M4TUHIFsCMGen9OwCGw1YRGW2ntKel0exsojHIBC0ouQAyU" + "viFDstmXfNmZeS+zm7XSNCXRFiRgJf0bXIHixpbhGdxBBJYC1w/xaA424MhNEATkui71" + "fU9KqfEU78UbD9PdbJRlOdae55GmhIP+1NV1TcMwkOM41DSNHvRtMhTHMRVFQW3b6mOL" + "gx99kue5GRp/gIOZuZGvNpTNwjD8oliANU+qqqKu6/TQBdymN57AHjzBT+B6Jx79BRgA" + "vc49kQA4yxgAAAAASUVORK5CYII=";
|
|
28490
|
+
class InfoTip$1 extends React.Component {
|
|
28491
|
+
constructor(...args) {
|
|
28492
|
+
super(...args);
|
|
28493
|
+
this.state = {
|
|
28494
|
+
hover: false
|
|
28495
|
+
};
|
|
28496
|
+
this.handleMouseEnter = () => {
|
|
28497
|
+
this.setState({
|
|
28498
|
+
hover: true
|
|
28499
|
+
});
|
|
28500
|
+
};
|
|
28501
|
+
this.handleMouseLeave = () => {
|
|
28502
|
+
this.setState({
|
|
28503
|
+
hover: false
|
|
28504
|
+
});
|
|
28505
|
+
};
|
|
28506
|
+
}
|
|
28507
|
+
render() {
|
|
28508
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
28509
|
+
className: css(styles$i.infoTip)
|
|
28510
|
+
}, /*#__PURE__*/React.createElement("img", {
|
|
28511
|
+
alt: "",
|
|
28512
|
+
width: 10,
|
|
28513
|
+
height: 10,
|
|
28514
|
+
src: questionMark,
|
|
28515
|
+
onMouseEnter: this.handleMouseEnter,
|
|
28516
|
+
onMouseLeave: this.handleMouseLeave
|
|
28517
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
28518
|
+
className: css(styles$i.infoTipContainer),
|
|
28519
|
+
style: {
|
|
28520
|
+
display: this.state.hover ? "block" : "none"
|
|
28521
|
+
}
|
|
28522
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
28523
|
+
className: css(styles$i.infoTipTriangle)
|
|
28524
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
28525
|
+
className: css(styles$i.verticalShadow, styles$i.infoTipContentContainer)
|
|
28526
|
+
}, this.props.children)));
|
|
28527
|
+
}
|
|
28528
|
+
}
|
|
28529
|
+
|
|
28530
|
+
/**
|
|
28531
|
+
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
28532
|
+
* server without causing a checksum mismatch on the client.
|
|
28533
|
+
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
28534
|
+
* two sets of generated classnames will not match.)
|
|
28535
|
+
*/
|
|
28536
|
+
class InfoTip extends React.Component {
|
|
28537
|
+
constructor(...args) {
|
|
28538
|
+
super(...args);
|
|
28539
|
+
this.state = {
|
|
28540
|
+
didMount: false
|
|
28541
|
+
};
|
|
28542
|
+
}
|
|
28543
|
+
componentDidMount() {
|
|
28544
|
+
/* eslint-disable react/no-did-mount-set-state */
|
|
28545
|
+
this.setState({
|
|
28546
|
+
didMount: true
|
|
28547
|
+
});
|
|
28548
|
+
/* eslint-enable react/no-did-mount-set-state */
|
|
28549
|
+
}
|
|
28550
|
+
|
|
28551
|
+
render() {
|
|
28552
|
+
if (this.state.didMount) {
|
|
28553
|
+
return /*#__PURE__*/React.createElement(InfoTip$1, this.props);
|
|
28554
|
+
}
|
|
28555
|
+
return /*#__PURE__*/React.createElement("div", null);
|
|
28556
|
+
}
|
|
28557
|
+
}
|
|
28558
|
+
|
|
28559
|
+
/**
|
|
28560
|
+
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
28561
|
+
* which allows multiple buttons to be selected at the same time.
|
|
28562
|
+
*
|
|
28563
|
+
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
28564
|
+
* this component allows multiple selection!
|
|
28565
|
+
*/
|
|
28566
|
+
class MultiButtonGroup extends React.Component {
|
|
28567
|
+
constructor(...args) {
|
|
28568
|
+
super(...args);
|
|
28569
|
+
this.toggleSelect = newValue => {
|
|
28570
|
+
const values = (this.props.values || []).slice(0);
|
|
28571
|
+
const allowEmpty = this.props.allowEmpty;
|
|
28572
|
+
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
28573
|
+
// If the value is already selected, unselect it
|
|
28574
|
+
values.splice(values.indexOf(newValue), 1);
|
|
28575
|
+
} else {
|
|
28576
|
+
// Otherwise merge with other values and return
|
|
28577
|
+
if (values.indexOf(newValue) < 0) {
|
|
28578
|
+
values.push(newValue);
|
|
28579
|
+
}
|
|
28580
|
+
}
|
|
28581
|
+
this.props.onChange(values);
|
|
28582
|
+
};
|
|
28583
|
+
}
|
|
28584
|
+
focus() {
|
|
28585
|
+
var _ReactDOM$findDOMNode;
|
|
28586
|
+
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28587
|
+
(_ReactDOM$findDOMNode = ReactDOM.findDOMNode(this)) == null || _ReactDOM$findDOMNode.focus();
|
|
28588
|
+
return true;
|
|
28589
|
+
}
|
|
28590
|
+
render() {
|
|
28591
|
+
const values = this.props.values || [];
|
|
28592
|
+
const buttons = this.props.buttons.map((button, i) => {
|
|
28593
|
+
const selected = values.indexOf(button.value) >= 0;
|
|
28594
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
28595
|
+
title: button.title,
|
|
28596
|
+
type: "button",
|
|
28597
|
+
id: "" + i,
|
|
28598
|
+
key: "" + i,
|
|
28599
|
+
ref: "button" + i,
|
|
28600
|
+
className: css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
28601
|
+
onClick: () => this.toggleSelect(button.value)
|
|
28602
|
+
}, button.content || "" + button.value);
|
|
28603
|
+
});
|
|
28604
|
+
const outerStyle = {
|
|
28605
|
+
display: "inline-block"
|
|
28606
|
+
};
|
|
28607
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
28608
|
+
style: outerStyle
|
|
28609
|
+
}, buttons);
|
|
28610
|
+
}
|
|
28611
|
+
}
|
|
28612
|
+
MultiButtonGroup.defaultProps = {
|
|
28613
|
+
values: [],
|
|
28614
|
+
allowEmpty: true
|
|
28615
|
+
};
|
|
28616
|
+
const styles$h = StyleSheet.create({
|
|
28617
|
+
buttonStyle: {
|
|
28618
|
+
backgroundColor: "white",
|
|
28619
|
+
border: "1px solid #ccc",
|
|
28620
|
+
borderLeft: "0",
|
|
28621
|
+
cursor: "pointer",
|
|
28622
|
+
margin: "0",
|
|
28623
|
+
padding: "5px 10px",
|
|
28624
|
+
position: "relative",
|
|
28625
|
+
// for hover
|
|
28626
|
+
|
|
28627
|
+
":first-child": {
|
|
28628
|
+
borderLeft: "1px solid #ccc",
|
|
28629
|
+
borderTopLeftRadius: "3px",
|
|
28630
|
+
borderBottomLeftRadius: "3px"
|
|
28631
|
+
},
|
|
28632
|
+
":last-child": {
|
|
28633
|
+
borderRight: "1px solid #ccc",
|
|
28634
|
+
borderTopRightRadius: "3px",
|
|
28635
|
+
borderBottomRightRadius: "3px"
|
|
28636
|
+
},
|
|
28637
|
+
":hover": {
|
|
28638
|
+
backgroundColor: "#ccc"
|
|
28639
|
+
},
|
|
28640
|
+
":focus": {
|
|
28641
|
+
zIndex: 2
|
|
28642
|
+
}
|
|
28643
|
+
},
|
|
28644
|
+
selectedStyle: {
|
|
28645
|
+
backgroundColor: "#ddd"
|
|
28646
|
+
}
|
|
28647
|
+
});
|
|
28648
|
+
|
|
28649
|
+
const _excluded$2 = ["onFormatChange", "checkValidity", "useArrowKeys"];
|
|
28650
|
+
const {
|
|
28651
|
+
firstNumericalParse,
|
|
28652
|
+
captureScratchpadTouchStart
|
|
28653
|
+
} = Util;
|
|
28654
|
+
const toNumericString = KhanMath.toNumericString;
|
|
28655
|
+
const getNumericFormat = KhanMath.getNumericFormat;
|
|
28656
|
+
|
|
28657
|
+
/* An input box that accepts only numeric strings
|
|
28658
|
+
*
|
|
28659
|
+
* Calls onChange(value, format) for valid numbers.
|
|
28660
|
+
* Reverts to the current value onBlur or on [ENTER],
|
|
28661
|
+
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
28662
|
+
* Accepts empty input and sends it to onChange as null
|
|
28663
|
+
* if no numeric placeholder is set.
|
|
28664
|
+
* If given a checkValidity function, will turn
|
|
28665
|
+
* the background/outline red when invalid
|
|
28666
|
+
* If useArrowKeys is set to true, up/down arrows will
|
|
28667
|
+
* increment/decrement integers
|
|
28668
|
+
* Optionally takes a size ("mini", "small", "normal")
|
|
28669
|
+
*/
|
|
28670
|
+
class NumberInput extends React.Component {
|
|
28671
|
+
constructor(...args) {
|
|
28672
|
+
super(...args);
|
|
28673
|
+
this.state = {
|
|
28674
|
+
format: this.props.format
|
|
28675
|
+
};
|
|
28676
|
+
/* Return the current "value" of this input
|
|
28677
|
+
* If empty, it returns the placeholder (if it is a number) or null
|
|
28678
|
+
*/
|
|
28679
|
+
this.getValue = () => {
|
|
28680
|
+
return this.parseInputValue(
|
|
28681
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28682
|
+
ReactDOM__default.findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
28683
|
+
);
|
|
28684
|
+
};
|
|
28685
|
+
/* Return the current string value of this input */
|
|
28686
|
+
this.getStringValue = () => {
|
|
28687
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28688
|
+
return ReactDOM__default.findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
28689
|
+
};
|
|
28690
|
+
this.parseInputValue = value => {
|
|
28691
|
+
if (value === "") {
|
|
28692
|
+
const placeholder = this.props.placeholder;
|
|
28693
|
+
return _.isFinite(placeholder) ? +placeholder : null;
|
|
28694
|
+
}
|
|
28695
|
+
const result = firstNumericalParse(value);
|
|
28696
|
+
return _.isFinite(result) ? result : this.props.value;
|
|
28697
|
+
};
|
|
28698
|
+
/* Set text input focus to this input */
|
|
28699
|
+
this.focus = () => {
|
|
28700
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28701
|
+
ReactDOM__default.findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
28702
|
+
this._handleFocus();
|
|
28703
|
+
};
|
|
28704
|
+
this.blur = () => {
|
|
28705
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
28706
|
+
ReactDOM__default.findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
28707
|
+
this._handleBlur();
|
|
28708
|
+
};
|
|
28709
|
+
this.setSelectionRange = (selectionStart, selectionEnd) => {
|
|
28710
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
28711
|
+
ReactDOM__default.findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
28712
|
+
};
|
|
28713
|
+
this.getSelectionStart = () => {
|
|
28714
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
28715
|
+
return ReactDOM__default.findDOMNode(this).selectionStart;
|
|
28716
|
+
};
|
|
28717
|
+
this.getSelectionEnd = () => {
|
|
28718
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
28719
|
+
return ReactDOM__default.findDOMNode(this).selectionEnd;
|
|
28720
|
+
};
|
|
28721
|
+
this._checkValidity = value => {
|
|
28722
|
+
if (value == null) {
|
|
28723
|
+
return true;
|
|
28724
|
+
}
|
|
28725
|
+
const val = firstNumericalParse(value);
|
|
28726
|
+
const checkValidity = this.props.checkValidity;
|
|
28727
|
+
return _.isFinite(val) && checkValidity(val);
|
|
28728
|
+
};
|
|
28729
|
+
this._handleChange = e => {
|
|
28730
|
+
const text = e.target.value;
|
|
28731
|
+
const value = this.parseInputValue(text);
|
|
28732
|
+
const format = getNumericFormat(text);
|
|
28733
|
+
this.props.onChange(value);
|
|
28734
|
+
if (format) {
|
|
28735
|
+
this.props.onFormatChange(value, format);
|
|
28736
|
+
this.setState({
|
|
28737
|
+
format: format
|
|
28738
|
+
});
|
|
28739
|
+
}
|
|
28740
|
+
};
|
|
28741
|
+
this._handleFocus = () => {
|
|
28742
|
+
if (this.props.onFocus) {
|
|
28743
|
+
this.props.onFocus();
|
|
28744
|
+
}
|
|
28745
|
+
};
|
|
28746
|
+
this._handleBlur = e => {
|
|
28747
|
+
// Only continue on blur or "enter"
|
|
28748
|
+
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
28749
|
+
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
28750
|
+
return;
|
|
28751
|
+
}
|
|
28752
|
+
this._setValue(this.props.value, this.state.format);
|
|
28753
|
+
if (this.props.onBlur) {
|
|
28754
|
+
this.props.onBlur();
|
|
28755
|
+
}
|
|
28756
|
+
};
|
|
28757
|
+
this._onKeyDown = e => {
|
|
28758
|
+
if (this.props.onKeyDown) {
|
|
28759
|
+
this.props.onKeyDown(e);
|
|
28760
|
+
}
|
|
28761
|
+
if (!this.props.useArrowKeys || !_.contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
28762
|
+
return;
|
|
28763
|
+
}
|
|
28764
|
+
let val = this.getValue();
|
|
28765
|
+
if (val !== Math.floor(val)) {
|
|
28766
|
+
return; // bail if not an integer
|
|
28767
|
+
}
|
|
28768
|
+
|
|
28769
|
+
if (e.key === "ArrowUp") {
|
|
28770
|
+
val = val + 1;
|
|
28771
|
+
} else if (e.key === "ArrowDown") {
|
|
28772
|
+
val = val - 1;
|
|
28773
|
+
}
|
|
28774
|
+
if (this._checkValidity(val)) {
|
|
28775
|
+
this.props.onChange(val);
|
|
28776
|
+
}
|
|
28777
|
+
};
|
|
28778
|
+
this._setValue = (val, format) => {
|
|
28779
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28780
|
+
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
28781
|
+
$(ReactDOM__default.findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
28782
|
+
};
|
|
28783
|
+
}
|
|
28784
|
+
render() {
|
|
28785
|
+
let classes = classNames({
|
|
28786
|
+
"number-input": true,
|
|
28787
|
+
"invalid-input": !this._checkValidity(this.props.value),
|
|
28788
|
+
mini: this.props.size === "mini",
|
|
28789
|
+
small: this.props.size === "small",
|
|
28790
|
+
normal: this.props.size === "normal"
|
|
28791
|
+
});
|
|
28792
|
+
if (this.props.className != null) {
|
|
28793
|
+
classes = classes + " " + this.props.className;
|
|
28794
|
+
}
|
|
28795
|
+
const _this$props = this.props,
|
|
28796
|
+
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$2);
|
|
28797
|
+
return /*#__PURE__*/React.createElement("input", _extends({}, restProps, {
|
|
28798
|
+
className: classes,
|
|
28799
|
+
type: "text"
|
|
28800
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28801
|
+
,
|
|
28802
|
+
ref: "input",
|
|
28803
|
+
onChange: this._handleChange,
|
|
28804
|
+
onFocus: this._handleFocus,
|
|
28805
|
+
onBlur: this._handleBlur,
|
|
28806
|
+
onKeyPress: this._handleBlur,
|
|
28807
|
+
onKeyDown: this._onKeyDown
|
|
28808
|
+
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
28809
|
+
,
|
|
28810
|
+
onTouchStart: captureScratchpadTouchStart,
|
|
28811
|
+
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
28812
|
+
value: undefined
|
|
28813
|
+
}));
|
|
28814
|
+
}
|
|
28815
|
+
componentDidUpdate(prevProps) {
|
|
28816
|
+
if (!number.equal(this.getValue(), this.props.value)) {
|
|
28817
|
+
this._setValue(this.props.value, this.state.format);
|
|
28818
|
+
}
|
|
28819
|
+
}
|
|
28820
|
+
}
|
|
28821
|
+
NumberInput.propTypes = {
|
|
28822
|
+
value: PropTypes.number,
|
|
28823
|
+
format: PropTypes.string,
|
|
28824
|
+
placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
28825
|
+
onChange: PropTypes.func.isRequired,
|
|
28826
|
+
onFormatChange: PropTypes.func,
|
|
28827
|
+
checkValidity: PropTypes.func,
|
|
28828
|
+
size: PropTypes.string,
|
|
28829
|
+
label: PropTypes.oneOf(["put your labels outside your inputs!"])
|
|
28830
|
+
};
|
|
28831
|
+
NumberInput.defaultProps = {
|
|
28832
|
+
value: null,
|
|
28833
|
+
placeholder: null,
|
|
28834
|
+
format: null,
|
|
28835
|
+
onFormatChange: () => null,
|
|
28836
|
+
checkValidity: () => true,
|
|
28837
|
+
useArrowKeys: false
|
|
28838
|
+
};
|
|
28839
|
+
|
|
28840
|
+
/* eslint-disable @babel/no-invalid-this */
|
|
28841
|
+
|
|
28842
|
+
/* A checkbox that syncs its value to props using the
|
|
28843
|
+
* renderer's onChange method, and gets the prop name
|
|
28844
|
+
* dynamically from its props list
|
|
28845
|
+
*/
|
|
28846
|
+
const PropCheckBox = createReactClass({
|
|
28847
|
+
displayName: "PropCheckBox",
|
|
28848
|
+
propTypes: {
|
|
28849
|
+
labelAlignment: PropTypes.oneOf(["left", "right"])
|
|
28850
|
+
},
|
|
28851
|
+
DEFAULT_PROPS: {
|
|
28852
|
+
label: null,
|
|
28853
|
+
onChange: null,
|
|
28854
|
+
labelAlignment: "left"
|
|
28855
|
+
},
|
|
28856
|
+
getDefaultProps: function () {
|
|
28857
|
+
return this.DEFAULT_PROPS;
|
|
28858
|
+
},
|
|
28859
|
+
propName: function () {
|
|
28860
|
+
const propName = _.find(_.keys(this.props), function (localPropName) {
|
|
28861
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
28862
|
+
return !_.has(this.DEFAULT_PROPS, localPropName);
|
|
28863
|
+
}, this);
|
|
28864
|
+
if (!propName) {
|
|
28865
|
+
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
28866
|
+
}
|
|
28867
|
+
return propName;
|
|
28868
|
+
},
|
|
28869
|
+
_labelAlignLeft: function () {
|
|
28870
|
+
return this.props.labelAlignment === "left";
|
|
28871
|
+
},
|
|
28872
|
+
render: function () {
|
|
28873
|
+
const propName = this.propName();
|
|
28874
|
+
return /*#__PURE__*/React.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React.createElement("input", {
|
|
28875
|
+
type: "checkbox",
|
|
28876
|
+
checked: this.props[propName],
|
|
28877
|
+
onChange: this.toggle
|
|
28878
|
+
}), !this._labelAlignLeft() && this.props.label);
|
|
28879
|
+
},
|
|
28880
|
+
toggle: function () {
|
|
28881
|
+
const propName = this.propName();
|
|
28882
|
+
const changes = {};
|
|
28883
|
+
changes[propName] = !this.props[propName];
|
|
28884
|
+
this.props.onChange(changes);
|
|
28885
|
+
}
|
|
28886
|
+
});
|
|
28887
|
+
|
|
28888
|
+
const truth = () => true;
|
|
28889
|
+
|
|
28890
|
+
/* A minor abstraction on top of NumberInput for ranges
|
|
28891
|
+
*
|
|
28892
|
+
*/
|
|
28893
|
+
class RangeInput extends React.Component {
|
|
28894
|
+
constructor(...args) {
|
|
28895
|
+
super(...args);
|
|
28896
|
+
this.onChange = (i, newVal) => {
|
|
28897
|
+
const value = this.props.value;
|
|
28898
|
+
if (i === 0) {
|
|
28899
|
+
this.props.onChange([newVal, value[1]]);
|
|
28900
|
+
} else {
|
|
28901
|
+
this.props.onChange([value[0], newVal]);
|
|
28902
|
+
}
|
|
28903
|
+
};
|
|
28904
|
+
}
|
|
28905
|
+
render() {
|
|
28906
|
+
const value = this.props.value;
|
|
28907
|
+
const checkValidity = this.props.checkValidity || truth;
|
|
28908
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
28909
|
+
className: "range-input"
|
|
28910
|
+
}, /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
28911
|
+
value: value[0],
|
|
28912
|
+
checkValidity: val => checkValidity([val, value[1]])
|
|
28913
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
28914
|
+
,
|
|
28915
|
+
onChange: this.onChange.bind(this, 0),
|
|
28916
|
+
placeholder: this.props.placeholder[0]
|
|
28917
|
+
})), /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
28918
|
+
value: value[1],
|
|
28919
|
+
checkValidity: val => checkValidity([value[0], val])
|
|
28920
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
28921
|
+
,
|
|
28922
|
+
onChange: this.onChange.bind(this, 1),
|
|
28923
|
+
placeholder: this.props.placeholder[1]
|
|
28924
|
+
})));
|
|
28925
|
+
}
|
|
28926
|
+
}
|
|
28927
|
+
RangeInput.propTypes = {
|
|
28928
|
+
value: PropTypes.array.isRequired,
|
|
28929
|
+
onChange: PropTypes.func.isRequired,
|
|
28930
|
+
placeholder: PropTypes.array,
|
|
28931
|
+
checkValidity: PropTypes.func
|
|
28932
|
+
};
|
|
28933
|
+
RangeInput.defaultProps = {
|
|
28934
|
+
placeholder: [null, null]
|
|
28935
|
+
};
|
|
28936
|
+
|
|
28937
|
+
var components = /*#__PURE__*/Object.freeze({
|
|
28938
|
+
__proto__: null,
|
|
28939
|
+
ButtonGroup: ButtonGroup,
|
|
28940
|
+
Graph: Graph,
|
|
28941
|
+
Graphie: Graphie,
|
|
28942
|
+
HUD: HUD,
|
|
28943
|
+
Icon: Icon,
|
|
28944
|
+
InfoTip: InfoTip,
|
|
28945
|
+
InlineIcon: InlineIcon,
|
|
28946
|
+
MathInput: MathInput,
|
|
28947
|
+
MultiButtonGroup: MultiButtonGroup,
|
|
28948
|
+
NumberInput: NumberInput,
|
|
28949
|
+
PropCheckBox: PropCheckBox,
|
|
28950
|
+
RangeInput: RangeInput,
|
|
28951
|
+
SvgImage: SvgImage,
|
|
28952
|
+
TextInput: TextInput,
|
|
28953
|
+
TextListEditor: TextListEditor
|
|
28954
|
+
});
|
|
28955
|
+
|
|
28956
|
+
/**
|
|
28957
|
+
* If a graphie URL is provided in `backgroundImage`, will return the rendered graphie background.
|
|
28958
|
+
* Otherwise, returns `null`.
|
|
28959
|
+
*/
|
|
28960
|
+
const getLegacyGrid = (box, backgroundImage) => {
|
|
28961
|
+
const {
|
|
28962
|
+
url,
|
|
28963
|
+
width,
|
|
28964
|
+
height
|
|
28965
|
+
} = backgroundImage != null ? backgroundImage : {};
|
|
28966
|
+
if (url && typeof url === "string") {
|
|
28967
|
+
const scale = box[0] / interactiveSizes$1.defaultBoxSize;
|
|
28968
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
28969
|
+
style: {
|
|
28970
|
+
position: "absolute",
|
|
28971
|
+
bottom: 0,
|
|
28972
|
+
left: 0
|
|
28973
|
+
}
|
|
28974
|
+
}, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
|
|
28975
|
+
setAssetStatus
|
|
28976
|
+
}) => /*#__PURE__*/React.createElement(SvgImage, {
|
|
28977
|
+
src: url,
|
|
28978
|
+
width: width,
|
|
28979
|
+
height: height,
|
|
28980
|
+
scale: scale,
|
|
28981
|
+
responsive: false,
|
|
28982
|
+
setAssetStatus: setAssetStatus,
|
|
28983
|
+
alt: ""
|
|
28984
|
+
})));
|
|
28985
|
+
}
|
|
28986
|
+
return null;
|
|
28987
|
+
};
|
|
28988
|
+
|
|
28989
|
+
const _excluded$1 = ["graph"];
|
|
28990
|
+
const renderGraph = props => {
|
|
28991
|
+
const {
|
|
28992
|
+
graph
|
|
28993
|
+
} = props,
|
|
28994
|
+
rest = _objectWithoutPropertiesLoose(props, _excluded$1);
|
|
28995
|
+
switch (graph.type) {
|
|
28996
|
+
case "segment":
|
|
28997
|
+
return /*#__PURE__*/React.createElement(SegmentGraph, _extends({}, rest, {
|
|
28998
|
+
graph: graph,
|
|
28999
|
+
onGraphChange: props.onGraphChange
|
|
29000
|
+
}));
|
|
29001
|
+
}
|
|
29002
|
+
};
|
|
29003
|
+
const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
29004
|
+
var _props$backgroundImag, _props$backgroundImag2, _props$backgroundImag3, _props$backgroundImag4;
|
|
29005
|
+
// Storing the gradable state in a ref so that it can be updated without
|
|
29006
|
+
// causing a re-render.
|
|
29007
|
+
const graphRef = React.useRef(props.graph);
|
|
29008
|
+
const handleGraphUpdate = callback => {
|
|
29009
|
+
graphRef.current = callback(graphRef.current);
|
|
29010
|
+
};
|
|
29011
|
+
React.useImperativeHandle(ref, () => ({
|
|
29012
|
+
getUserInput: () => graphRef.current
|
|
29013
|
+
}));
|
|
29014
|
+
const [width, height] = getInteractiveBoxFromSizeClass(props.containerSizeClass);
|
|
29015
|
+
const legacyGrid = getLegacyGrid([width, height], props.backgroundImage);
|
|
29016
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
29017
|
+
style: {
|
|
29018
|
+
width: (_props$backgroundImag = (_props$backgroundImag2 = props.backgroundImage) == null ? void 0 : _props$backgroundImag2.width) != null ? _props$backgroundImag : width,
|
|
29019
|
+
height: (_props$backgroundImag3 = (_props$backgroundImag4 = props.backgroundImage) == null ? void 0 : _props$backgroundImag4.height) != null ? _props$backgroundImag3 : height,
|
|
29020
|
+
position: "relative"
|
|
29021
|
+
}
|
|
29022
|
+
}, legacyGrid, /*#__PURE__*/React.createElement(View, {
|
|
29023
|
+
style: {
|
|
29024
|
+
position: "absolute",
|
|
29025
|
+
bottom: 0,
|
|
29026
|
+
left: 0
|
|
29027
|
+
}
|
|
29028
|
+
}, /*#__PURE__*/React.createElement(Mafs, {
|
|
29029
|
+
viewBox: {
|
|
29030
|
+
x: props.range[0],
|
|
29031
|
+
y: props.range[1],
|
|
29032
|
+
padding: 0
|
|
29033
|
+
},
|
|
29034
|
+
pan: false,
|
|
29035
|
+
zoom: false,
|
|
29036
|
+
width: width,
|
|
29037
|
+
height: height
|
|
29038
|
+
}, !!legacyGrid && /*#__PURE__*/React.createElement(Grid, props), renderGraph(_extends({}, props, {
|
|
29039
|
+
onGraphChange: handleGraphUpdate
|
|
29040
|
+
})))));
|
|
29041
|
+
});
|
|
29042
|
+
|
|
28167
29043
|
const {
|
|
28168
29044
|
DeprecationMixin
|
|
28169
29045
|
} = Util;
|
|
@@ -28241,6 +29117,7 @@ class InteractiveGraph extends React.Component {
|
|
|
28241
29117
|
this.sinusoid = void 0;
|
|
28242
29118
|
this.trashCan = void 0;
|
|
28243
29119
|
this.vertHairline = void 0;
|
|
29120
|
+
this.mafsRef = /*#__PURE__*/React.createRef();
|
|
28244
29121
|
this.state = {
|
|
28245
29122
|
shouldShowInstructions: _getShouldShowInstructions(this.props)
|
|
28246
29123
|
};
|
|
@@ -29320,11 +30197,10 @@ class InteractiveGraph extends React.Component {
|
|
|
29320
30197
|
});
|
|
29321
30198
|
};
|
|
29322
30199
|
this.getUserInput = () => {
|
|
29323
|
-
|
|
29324
|
-
|
|
29325
|
-
this.simpleValidate = rubric => {
|
|
29326
|
-
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);
|
|
29327
30202
|
};
|
|
30203
|
+
this.simpleValidate = rubric => InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
29328
30204
|
this.focus = $.noop;
|
|
29329
30205
|
}
|
|
29330
30206
|
// TODO(jangmi, CP-3288): Remove usage of `UNSAFE_componentWillMount`
|
|
@@ -29332,9 +30208,11 @@ class InteractiveGraph extends React.Component {
|
|
|
29332
30208
|
DeprecationMixin.UNSAFE_componentWillMount.call(this);
|
|
29333
30209
|
}
|
|
29334
30210
|
componentDidMount() {
|
|
29335
|
-
|
|
29336
|
-
|
|
29337
|
-
|
|
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
|
+
}
|
|
29338
30216
|
}
|
|
29339
30217
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
29340
30218
|
var _this$props$backgroun, _nextProps$background;
|
|
@@ -29374,9 +30252,19 @@ class InteractiveGraph extends React.Component {
|
|
|
29374
30252
|
areSegmentGraphsEqual(prevGraph, currentGraph) {
|
|
29375
30253
|
return prevGraph.numSegments !== currentGraph.numSegments;
|
|
29376
30254
|
}
|
|
30255
|
+
// const segment: boolean = useFeatureIsOn("mafs-segment-graph");
|
|
30256
|
+
// <Renderer apiOptions={{flags: {mafs: {segment}}}}
|
|
29377
30257
|
render() {
|
|
30258
|
+
var _this$props$apiOption;
|
|
30259
|
+
// Mafs shim
|
|
30260
|
+
if ((_this$props$apiOption = this.props.apiOptions) != null && (_this$props$apiOption = _this$props$apiOption.flags) != null && (_this$props$apiOption = _this$props$apiOption["mafs"]) != null && _this$props$apiOption[this.props.graph.type]) {
|
|
30261
|
+
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, this.props, {
|
|
30262
|
+
ref: this.mafsRef
|
|
30263
|
+
}));
|
|
30264
|
+
}
|
|
29378
30265
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
29379
30266
|
let instructions;
|
|
30267
|
+
// isClickToAddPoints() only applies to points and polygons
|
|
29380
30268
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
29381
30269
|
if (this.props.graph.type === "point") {
|
|
29382
30270
|
instructions = i18n._("Click to add points");
|
|
@@ -30679,7 +31567,7 @@ var globalConstants = /*#__PURE__*/Object.freeze({
|
|
|
30679
31567
|
pureLgMax: pureLgMax
|
|
30680
31568
|
});
|
|
30681
31569
|
|
|
30682
|
-
const colors
|
|
31570
|
+
const colors = {
|
|
30683
31571
|
white: "#FFFFFF",
|
|
30684
31572
|
gray98: "#FAFAFA",
|
|
30685
31573
|
gray97: "#F6F7F7",
|
|
@@ -30739,7 +31627,7 @@ const colors$1 = {
|
|
|
30739
31627
|
};
|
|
30740
31628
|
const borderRadius = 4;
|
|
30741
31629
|
const breadcrumbStyles = {
|
|
30742
|
-
color: colors
|
|
31630
|
+
color: colors.breadcrumbs,
|
|
30743
31631
|
fontFamily: "inherit",
|
|
30744
31632
|
fontSize: 15,
|
|
30745
31633
|
fontWeight: "bold",
|
|
@@ -30809,14 +31697,14 @@ const typography = {
|
|
|
30809
31697
|
},
|
|
30810
31698
|
// For callouts
|
|
30811
31699
|
smallHeading: {
|
|
30812
|
-
color: colors
|
|
31700
|
+
color: colors.gray25,
|
|
30813
31701
|
fontFamily: "inherit",
|
|
30814
31702
|
fontSize: 17,
|
|
30815
31703
|
fontWeight: "bold",
|
|
30816
31704
|
lineHeight: "23px"
|
|
30817
31705
|
},
|
|
30818
31706
|
smallHeadingMobile: {
|
|
30819
|
-
color: colors
|
|
31707
|
+
color: colors.gray25,
|
|
30820
31708
|
fontFamily: "inherit",
|
|
30821
31709
|
fontSize: 15,
|
|
30822
31710
|
fontWeight: "bold",
|
|
@@ -30824,7 +31712,7 @@ const typography = {
|
|
|
30824
31712
|
},
|
|
30825
31713
|
// Accent headings
|
|
30826
31714
|
accentHeading: {
|
|
30827
|
-
color: colors
|
|
31715
|
+
color: colors.gray68,
|
|
30828
31716
|
fontFamily: "inherit",
|
|
30829
31717
|
fontSize: 15,
|
|
30830
31718
|
fontWeight: "bold",
|
|
@@ -30930,7 +31818,7 @@ const typography = {
|
|
|
30930
31818
|
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
30931
31819
|
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
30932
31820
|
wonderBlocksTitle: {
|
|
30933
|
-
color: colors
|
|
31821
|
+
color: colors.white,
|
|
30934
31822
|
fontWeight: 900,
|
|
30935
31823
|
// "Black" weight
|
|
30936
31824
|
fontSize: 28,
|
|
@@ -30952,7 +31840,7 @@ const typography = {
|
|
|
30952
31840
|
|
|
30953
31841
|
var globalStyles = /*#__PURE__*/Object.freeze({
|
|
30954
31842
|
__proto__: null,
|
|
30955
|
-
colors: colors
|
|
31843
|
+
colors: colors,
|
|
30956
31844
|
borderRadius: borderRadius,
|
|
30957
31845
|
fonts: fonts,
|
|
30958
31846
|
typography: typography
|
|
@@ -31014,7 +31902,7 @@ const HideAnswersToggle = props => {
|
|
|
31014
31902
|
const switchId = idFactory.get("hide-answers-toggle");
|
|
31015
31903
|
const labelId = idFactory.get("hide-answers-label");
|
|
31016
31904
|
return /*#__PURE__*/React.createElement(View, {
|
|
31017
|
-
style: styles$
|
|
31905
|
+
style: styles$g.switchWrapper
|
|
31018
31906
|
}, /*#__PURE__*/React.createElement(Switch, {
|
|
31019
31907
|
id: switchId,
|
|
31020
31908
|
checked: props.areAnswersHidden,
|
|
@@ -31026,7 +31914,7 @@ const HideAnswersToggle = props => {
|
|
|
31026
31914
|
tag: "label"
|
|
31027
31915
|
}, strings.hideAnswersToggleLabel));
|
|
31028
31916
|
};
|
|
31029
|
-
const styles$
|
|
31917
|
+
const styles$g = StyleSheet.create({
|
|
31030
31918
|
switchWrapper: {
|
|
31031
31919
|
display: "flex",
|
|
31032
31920
|
flexDirection: "row",
|
|
@@ -31079,13 +31967,13 @@ const AnswerPill = props => {
|
|
|
31079
31967
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31080
31968
|
onClick: correct ? undefined : onClick,
|
|
31081
31969
|
ref: ref,
|
|
31082
|
-
style: [style, popperStyle, styles$
|
|
31970
|
+
style: [style, popperStyle, styles$f.pill, correct && styles$f.correct, incorrect && styles$f.incorrect, (focused || hovered) && BringToFront]
|
|
31083
31971
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
31084
31972
|
content: answerString,
|
|
31085
31973
|
inline: true
|
|
31086
31974
|
})));
|
|
31087
31975
|
};
|
|
31088
|
-
const styles$
|
|
31976
|
+
const styles$f = StyleSheet.create({
|
|
31089
31977
|
correct: {
|
|
31090
31978
|
// WB green darkened by 18%
|
|
31091
31979
|
backgroundColor: "#00880b"
|
|
@@ -31138,23 +32026,23 @@ class Marker extends React.Component {
|
|
|
31138
32026
|
icon: iconNull
|
|
31139
32027
|
};
|
|
31140
32028
|
if (showCorrectness) {
|
|
31141
|
-
iconStyles = [styles$
|
|
32029
|
+
iconStyles = [styles$e.markerGraded, showCorrectness === "correct" ? styles$e.markerCorrect : styles$e.markerIncorrect, isOpen && styles$e.markerSelected];
|
|
31142
32030
|
args = _extends({}, args, {
|
|
31143
32031
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31144
32032
|
});
|
|
31145
32033
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31146
|
-
iconStyles = [styles$
|
|
32034
|
+
iconStyles = [styles$e.markerFilled, isOpen && styles$e.markerSelected];
|
|
31147
32035
|
} else if (isOpen) {
|
|
31148
|
-
iconStyles = [styles$
|
|
32036
|
+
iconStyles = [styles$e.markerSelected];
|
|
31149
32037
|
args = _extends({}, args, {
|
|
31150
32038
|
icon: iconChevronDown,
|
|
31151
32039
|
size: 8
|
|
31152
32040
|
});
|
|
31153
32041
|
} else if (showPulsate) {
|
|
31154
|
-
iconStyles = [styles$
|
|
32042
|
+
iconStyles = [styles$e.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$e.markerUnfilledPulsateOnce : showPulsate && styles$e.markerUnfilledPulsateInfinite];
|
|
31155
32043
|
}
|
|
31156
32044
|
return /*#__PURE__*/React.createElement(View, {
|
|
31157
|
-
style: [styles$
|
|
32045
|
+
style: [styles$e.markerIcon, iconStyles],
|
|
31158
32046
|
ref: node => this._icon = node
|
|
31159
32047
|
}, /*#__PURE__*/React.createElement(Icon, args));
|
|
31160
32048
|
}
|
|
@@ -31176,7 +32064,7 @@ class Marker extends React.Component {
|
|
|
31176
32064
|
const markerDisabled = showCorrectness === "correct";
|
|
31177
32065
|
const active = hovered || focused;
|
|
31178
32066
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
|
|
31179
|
-
style: [styles$
|
|
32067
|
+
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive]
|
|
31180
32068
|
// already translated in: /widgets/graded-group.tsx
|
|
31181
32069
|
,
|
|
31182
32070
|
"aria-label": markerDisabled ? i18n._("Correct!") : label
|
|
@@ -31194,7 +32082,7 @@ class Marker extends React.Component {
|
|
|
31194
32082
|
Marker.defaultProps = {
|
|
31195
32083
|
selected: []
|
|
31196
32084
|
};
|
|
31197
|
-
const styles$
|
|
32085
|
+
const styles$e = StyleSheet.create({
|
|
31198
32086
|
marker: {
|
|
31199
32087
|
position: "absolute",
|
|
31200
32088
|
backgroundColor: Color.white,
|
|
@@ -31764,13 +32652,13 @@ class LabelImage extends React.Component {
|
|
|
31764
32652
|
const promptString = isMobile ? multipleAnswers ? i18n._("Tap each dot on the image to select all answers that apply.") : i18n._("Tap each dot on the image to select an answer.") : multipleAnswers ? i18n._("Click each dot on the image to select all answers that apply.") : i18n._("Click each dot on the image to select an answer.");
|
|
31765
32653
|
const choicesString = i18n._("Choices:");
|
|
31766
32654
|
return /*#__PURE__*/React.createElement("div", {
|
|
31767
|
-
className: classNames("perseus-label-image-widget-instructions", css(styles$
|
|
32655
|
+
className: classNames("perseus-label-image-widget-instructions", css(styles$d.instructions))
|
|
31768
32656
|
}, /*#__PURE__*/React.createElement("div", {
|
|
31769
|
-
className: css(styles$
|
|
32657
|
+
className: css(styles$d.instructionsCaption)
|
|
31770
32658
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React.createElement("div", {
|
|
31771
|
-
className: css(styles$
|
|
32659
|
+
className: css(styles$d.instructionsChoices)
|
|
31772
32660
|
}, choices.map((choice, index) => /*#__PURE__*/React.createElement("div", {
|
|
31773
|
-
className: css(styles$
|
|
32661
|
+
className: css(styles$d.instructionsChoice),
|
|
31774
32662
|
key: index
|
|
31775
32663
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
31776
32664
|
content: choice
|
|
@@ -31787,20 +32675,20 @@ class LabelImage extends React.Component {
|
|
|
31787
32675
|
activeMarkerIndex
|
|
31788
32676
|
} = this.state;
|
|
31789
32677
|
return /*#__PURE__*/React.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React.createElement("div", {
|
|
31790
|
-
className: css(styles$
|
|
32678
|
+
className: css(styles$d.markersCanvas),
|
|
31791
32679
|
style: {
|
|
31792
32680
|
maxWidth: imageWidth,
|
|
31793
32681
|
maxHeight: imageHeight
|
|
31794
32682
|
}
|
|
31795
32683
|
}, /*#__PURE__*/React.createElement("div", {
|
|
31796
|
-
className: css(styles$
|
|
32684
|
+
className: css(styles$d.imageContainer,
|
|
31797
32685
|
// Ensure image interaction is disabled while answer
|
|
31798
32686
|
// choices popup is visible. This addresses specific
|
|
31799
32687
|
// case where user may click on question image to
|
|
31800
32688
|
// dismiss the popup. If the image is larger in size
|
|
31801
32689
|
// than its rendered in the widget, this would
|
|
31802
32690
|
// result in a zoom of the image.
|
|
31803
|
-
activeMarkerIndex !== -1 && styles$
|
|
32691
|
+
activeMarkerIndex !== -1 && styles$d.imageInteractionDisabled)
|
|
31804
32692
|
}, /*#__PURE__*/React.createElement(context$1.Consumer, null, ({
|
|
31805
32693
|
setAssetStatus
|
|
31806
32694
|
}) => /*#__PURE__*/React.createElement(SvgImage, {
|
|
@@ -31824,7 +32712,7 @@ class LabelImage extends React.Component {
|
|
|
31824
32712
|
}));
|
|
31825
32713
|
}
|
|
31826
32714
|
}
|
|
31827
|
-
const styles$
|
|
32715
|
+
const styles$d = StyleSheet.create({
|
|
31828
32716
|
instructions: {
|
|
31829
32717
|
paddingBottom: 16
|
|
31830
32718
|
},
|
|
@@ -32181,7 +33069,7 @@ class Placeholder extends React.Component {
|
|
|
32181
33069
|
const {
|
|
32182
33070
|
layout
|
|
32183
33071
|
} = this.props;
|
|
32184
|
-
const className = css(styles$
|
|
33072
|
+
const className = css(styles$c.card, styles$c.placeholder, layout === Layout.HORIZONTAL && styles$c.horizontalCard);
|
|
32185
33073
|
const style = {
|
|
32186
33074
|
width: this.props.width,
|
|
32187
33075
|
height: this.props.height
|
|
@@ -32364,7 +33252,7 @@ class Draggable extends React.Component {
|
|
|
32364
33252
|
// We need to keep backwards compatbility with rules specified directly
|
|
32365
33253
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
32366
33254
|
// See sortable.less for details.
|
|
32367
|
-
let className = css(styles$
|
|
33255
|
+
let className = css(styles$c.card, styles$c.draggable, layout === Layout.HORIZONTAL && styles$c.horizontalCard, layout === Layout.VERTICAL && styles$c.verticalCard, type === ItemState.DRAGGING && styles$c.dragging, type === ItemState.DISABLED && styles$c.disabled, !includePadding && styles$c.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
|
|
32368
33256
|
if (!includePadding) {
|
|
32369
33257
|
className += " perseus-sortable-draggable-unpadded";
|
|
32370
33258
|
}
|
|
@@ -32571,7 +33459,7 @@ class Sortable extends React.Component {
|
|
|
32571
33459
|
} = this.props;
|
|
32572
33460
|
// We need to keep backwards compatbility with rules specified directly
|
|
32573
33461
|
// in CSS. See sortable.less for details.
|
|
32574
|
-
const className = css(styles$
|
|
33462
|
+
const className = css(styles$c.sortable) + " perseus-sortable";
|
|
32575
33463
|
const syncWidth = ((_this$props$constrain = this.props.constraints) == null ? void 0 : _this$props$constrain.width) || layout === Layout.VERTICAL;
|
|
32576
33464
|
const syncHeight = ((_this$props$constrain2 = this.props.constraints) == null ? void 0 : _this$props$constrain2.height) || layout === Layout.HORIZONTAL;
|
|
32577
33465
|
_.each(this.state.items, function (item, i, items) {
|
|
@@ -32813,7 +33701,7 @@ Sortable.defaultProps = {
|
|
|
32813
33701
|
linterContext: PerseusLinter.linterContextDefault,
|
|
32814
33702
|
waitForTexRendererToLoad: true
|
|
32815
33703
|
};
|
|
32816
|
-
const styles$
|
|
33704
|
+
const styles$c = StyleSheet.create({
|
|
32817
33705
|
sortable: {
|
|
32818
33706
|
boxSizing: "border-box",
|
|
32819
33707
|
float: "left",
|
|
@@ -32975,23 +33863,23 @@ class Matcher extends React.Component {
|
|
|
32975
33863
|
};
|
|
32976
33864
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
32977
33865
|
return /*#__PURE__*/React.createElement("table", {
|
|
32978
|
-
className: css(styles$
|
|
33866
|
+
className: css(styles$b.widget) + " " + HACKY_CSS_CLASSNAME
|
|
32979
33867
|
}, /*#__PURE__*/React.createElement("tbody", null, showLabels && /*#__PURE__*/React.createElement("tr", {
|
|
32980
|
-
className: css(styles$
|
|
33868
|
+
className: css(styles$b.row)
|
|
32981
33869
|
}, /*#__PURE__*/React.createElement("th", {
|
|
32982
|
-
className: css(styles$
|
|
33870
|
+
className: css(styles$b.column, styles$b.columnLabel)
|
|
32983
33871
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
32984
33872
|
content: this.props.labels[0] || "...",
|
|
32985
33873
|
linterContext: this.props.linterContext
|
|
32986
33874
|
})), /*#__PURE__*/React.createElement("th", {
|
|
32987
|
-
className: css(styles$
|
|
33875
|
+
className: css(styles$b.column, styles$b.columnRight, styles$b.columnLabel)
|
|
32988
33876
|
}, /*#__PURE__*/React.createElement(Renderer, {
|
|
32989
33877
|
content: this.props.labels[1] || "...",
|
|
32990
33878
|
linterContext: this.props.linterContext
|
|
32991
33879
|
}))), /*#__PURE__*/React.createElement("tr", {
|
|
32992
|
-
className: css(styles$
|
|
33880
|
+
className: css(styles$b.row)
|
|
32993
33881
|
}, /*#__PURE__*/React.createElement("td", {
|
|
32994
|
-
className: css(styles$
|
|
33882
|
+
className: css(styles$b.column)
|
|
32995
33883
|
}, /*#__PURE__*/React.createElement(Sortable, {
|
|
32996
33884
|
options: left,
|
|
32997
33885
|
layout: Layout.VERTICAL,
|
|
@@ -33006,7 +33894,7 @@ class Matcher extends React.Component {
|
|
|
33006
33894
|
,
|
|
33007
33895
|
ref: "left"
|
|
33008
33896
|
})), /*#__PURE__*/React.createElement("td", {
|
|
33009
|
-
className: css(styles$
|
|
33897
|
+
className: css(styles$b.column, styles$b.columnRight)
|
|
33010
33898
|
}, /*#__PURE__*/React.createElement(Sortable
|
|
33011
33899
|
// @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
|
|
33012
33900
|
, {
|
|
@@ -33059,7 +33947,7 @@ _.extend(Matcher, {
|
|
|
33059
33947
|
});
|
|
33060
33948
|
const padding = 5;
|
|
33061
33949
|
const border = "1px solid #444";
|
|
33062
|
-
const styles$
|
|
33950
|
+
const styles$b = StyleSheet.create({
|
|
33063
33951
|
widget: {
|
|
33064
33952
|
paddingTop: padding,
|
|
33065
33953
|
maxWidth: "100%",
|
|
@@ -33092,197 +33980,6 @@ var Matcher$1 = {
|
|
|
33092
33980
|
isLintable: true
|
|
33093
33981
|
};
|
|
33094
33982
|
|
|
33095
|
-
const _excluded$1 = ["onFormatChange", "checkValidity", "useArrowKeys"];
|
|
33096
|
-
const {
|
|
33097
|
-
firstNumericalParse,
|
|
33098
|
-
captureScratchpadTouchStart
|
|
33099
|
-
} = Util;
|
|
33100
|
-
const toNumericString = KhanMath.toNumericString;
|
|
33101
|
-
const getNumericFormat = KhanMath.getNumericFormat;
|
|
33102
|
-
|
|
33103
|
-
/* An input box that accepts only numeric strings
|
|
33104
|
-
*
|
|
33105
|
-
* Calls onChange(value, format) for valid numbers.
|
|
33106
|
-
* Reverts to the current value onBlur or on [ENTER],
|
|
33107
|
-
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
33108
|
-
* Accepts empty input and sends it to onChange as null
|
|
33109
|
-
* if no numeric placeholder is set.
|
|
33110
|
-
* If given a checkValidity function, will turn
|
|
33111
|
-
* the background/outline red when invalid
|
|
33112
|
-
* If useArrowKeys is set to true, up/down arrows will
|
|
33113
|
-
* increment/decrement integers
|
|
33114
|
-
* Optionally takes a size ("mini", "small", "normal")
|
|
33115
|
-
*/
|
|
33116
|
-
class NumberInput extends React.Component {
|
|
33117
|
-
constructor(...args) {
|
|
33118
|
-
super(...args);
|
|
33119
|
-
this.state = {
|
|
33120
|
-
format: this.props.format
|
|
33121
|
-
};
|
|
33122
|
-
/* Return the current "value" of this input
|
|
33123
|
-
* If empty, it returns the placeholder (if it is a number) or null
|
|
33124
|
-
*/
|
|
33125
|
-
this.getValue = () => {
|
|
33126
|
-
return this.parseInputValue(
|
|
33127
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33128
|
-
ReactDOM__default.findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
33129
|
-
);
|
|
33130
|
-
};
|
|
33131
|
-
/* Return the current string value of this input */
|
|
33132
|
-
this.getStringValue = () => {
|
|
33133
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33134
|
-
return ReactDOM__default.findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
33135
|
-
};
|
|
33136
|
-
this.parseInputValue = value => {
|
|
33137
|
-
if (value === "") {
|
|
33138
|
-
const placeholder = this.props.placeholder;
|
|
33139
|
-
return _.isFinite(placeholder) ? +placeholder : null;
|
|
33140
|
-
}
|
|
33141
|
-
const result = firstNumericalParse(value);
|
|
33142
|
-
return _.isFinite(result) ? result : this.props.value;
|
|
33143
|
-
};
|
|
33144
|
-
/* Set text input focus to this input */
|
|
33145
|
-
this.focus = () => {
|
|
33146
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
33147
|
-
ReactDOM__default.findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
33148
|
-
this._handleFocus();
|
|
33149
|
-
};
|
|
33150
|
-
this.blur = () => {
|
|
33151
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
33152
|
-
ReactDOM__default.findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
33153
|
-
this._handleBlur();
|
|
33154
|
-
};
|
|
33155
|
-
this.setSelectionRange = (selectionStart, selectionEnd) => {
|
|
33156
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
33157
|
-
ReactDOM__default.findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
33158
|
-
};
|
|
33159
|
-
this.getSelectionStart = () => {
|
|
33160
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
33161
|
-
return ReactDOM__default.findDOMNode(this).selectionStart;
|
|
33162
|
-
};
|
|
33163
|
-
this.getSelectionEnd = () => {
|
|
33164
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
33165
|
-
return ReactDOM__default.findDOMNode(this).selectionEnd;
|
|
33166
|
-
};
|
|
33167
|
-
this._checkValidity = value => {
|
|
33168
|
-
if (value == null) {
|
|
33169
|
-
return true;
|
|
33170
|
-
}
|
|
33171
|
-
const val = firstNumericalParse(value);
|
|
33172
|
-
const checkValidity = this.props.checkValidity;
|
|
33173
|
-
return _.isFinite(val) && checkValidity(val);
|
|
33174
|
-
};
|
|
33175
|
-
this._handleChange = e => {
|
|
33176
|
-
const text = e.target.value;
|
|
33177
|
-
const value = this.parseInputValue(text);
|
|
33178
|
-
const format = getNumericFormat(text);
|
|
33179
|
-
this.props.onChange(value);
|
|
33180
|
-
if (format) {
|
|
33181
|
-
this.props.onFormatChange(value, format);
|
|
33182
|
-
this.setState({
|
|
33183
|
-
format: format
|
|
33184
|
-
});
|
|
33185
|
-
}
|
|
33186
|
-
};
|
|
33187
|
-
this._handleFocus = () => {
|
|
33188
|
-
if (this.props.onFocus) {
|
|
33189
|
-
this.props.onFocus();
|
|
33190
|
-
}
|
|
33191
|
-
};
|
|
33192
|
-
this._handleBlur = e => {
|
|
33193
|
-
// Only continue on blur or "enter"
|
|
33194
|
-
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
33195
|
-
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
33196
|
-
return;
|
|
33197
|
-
}
|
|
33198
|
-
this._setValue(this.props.value, this.state.format);
|
|
33199
|
-
if (this.props.onBlur) {
|
|
33200
|
-
this.props.onBlur();
|
|
33201
|
-
}
|
|
33202
|
-
};
|
|
33203
|
-
this._onKeyDown = e => {
|
|
33204
|
-
if (this.props.onKeyDown) {
|
|
33205
|
-
this.props.onKeyDown(e);
|
|
33206
|
-
}
|
|
33207
|
-
if (!this.props.useArrowKeys || !_.contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
33208
|
-
return;
|
|
33209
|
-
}
|
|
33210
|
-
let val = this.getValue();
|
|
33211
|
-
if (val !== Math.floor(val)) {
|
|
33212
|
-
return; // bail if not an integer
|
|
33213
|
-
}
|
|
33214
|
-
|
|
33215
|
-
if (e.key === "ArrowUp") {
|
|
33216
|
-
val = val + 1;
|
|
33217
|
-
} else if (e.key === "ArrowDown") {
|
|
33218
|
-
val = val - 1;
|
|
33219
|
-
}
|
|
33220
|
-
if (this._checkValidity(val)) {
|
|
33221
|
-
this.props.onChange(val);
|
|
33222
|
-
}
|
|
33223
|
-
};
|
|
33224
|
-
this._setValue = (val, format) => {
|
|
33225
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33226
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
33227
|
-
$(ReactDOM__default.findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
33228
|
-
};
|
|
33229
|
-
}
|
|
33230
|
-
render() {
|
|
33231
|
-
let classes = classNames({
|
|
33232
|
-
"number-input": true,
|
|
33233
|
-
"invalid-input": !this._checkValidity(this.props.value),
|
|
33234
|
-
mini: this.props.size === "mini",
|
|
33235
|
-
small: this.props.size === "small",
|
|
33236
|
-
normal: this.props.size === "normal"
|
|
33237
|
-
});
|
|
33238
|
-
if (this.props.className != null) {
|
|
33239
|
-
classes = classes + " " + this.props.className;
|
|
33240
|
-
}
|
|
33241
|
-
const _this$props = this.props,
|
|
33242
|
-
restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
|
|
33243
|
-
return /*#__PURE__*/React.createElement("input", _extends({}, restProps, {
|
|
33244
|
-
className: classes,
|
|
33245
|
-
type: "text"
|
|
33246
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33247
|
-
,
|
|
33248
|
-
ref: "input",
|
|
33249
|
-
onChange: this._handleChange,
|
|
33250
|
-
onFocus: this._handleFocus,
|
|
33251
|
-
onBlur: this._handleBlur,
|
|
33252
|
-
onKeyPress: this._handleBlur,
|
|
33253
|
-
onKeyDown: this._onKeyDown
|
|
33254
|
-
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
33255
|
-
,
|
|
33256
|
-
onTouchStart: captureScratchpadTouchStart,
|
|
33257
|
-
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
33258
|
-
value: undefined
|
|
33259
|
-
}));
|
|
33260
|
-
}
|
|
33261
|
-
componentDidUpdate(prevProps) {
|
|
33262
|
-
if (!number.equal(this.getValue(), this.props.value)) {
|
|
33263
|
-
this._setValue(this.props.value, this.state.format);
|
|
33264
|
-
}
|
|
33265
|
-
}
|
|
33266
|
-
}
|
|
33267
|
-
NumberInput.propTypes = {
|
|
33268
|
-
value: PropTypes.number,
|
|
33269
|
-
format: PropTypes.string,
|
|
33270
|
-
placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
33271
|
-
onChange: PropTypes.func.isRequired,
|
|
33272
|
-
onFormatChange: PropTypes.func,
|
|
33273
|
-
checkValidity: PropTypes.func,
|
|
33274
|
-
size: PropTypes.string,
|
|
33275
|
-
label: PropTypes.oneOf(["put your labels outside your inputs!"])
|
|
33276
|
-
};
|
|
33277
|
-
NumberInput.defaultProps = {
|
|
33278
|
-
value: null,
|
|
33279
|
-
placeholder: null,
|
|
33280
|
-
format: null,
|
|
33281
|
-
onFormatChange: () => null,
|
|
33282
|
-
checkValidity: () => true,
|
|
33283
|
-
useArrowKeys: false
|
|
33284
|
-
};
|
|
33285
|
-
|
|
33286
33983
|
// Type imports
|
|
33287
33984
|
|
|
33288
33985
|
const {
|
|
@@ -33926,9 +34623,9 @@ function drawText(ctx, item) {
|
|
|
33926
34623
|
if (item.value === null) {
|
|
33927
34624
|
return;
|
|
33928
34625
|
}
|
|
33929
|
-
ctx.fillStyle = styles$
|
|
33930
|
-
ctx.font = styles$
|
|
33931
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
34626
|
+
ctx.fillStyle = styles$a.fgColor;
|
|
34627
|
+
ctx.font = styles$a.font;
|
|
34628
|
+
ctx.fillText(item.value, item.pos[0] - styles$a.fontSizePx / 2 + 1, item.pos[1] + styles$a.fontSizePx / 2);
|
|
33932
34629
|
}
|
|
33933
34630
|
|
|
33934
34631
|
/**
|
|
@@ -33949,16 +34646,16 @@ function drawText(ctx, item) {
|
|
|
33949
34646
|
function drawDoubleLine(ctx, item) {
|
|
33950
34647
|
// Outer line that forms both of the bond lines.
|
|
33951
34648
|
let path = new Path2D();
|
|
33952
|
-
ctx.lineWidth = 5 * styles$
|
|
33953
|
-
ctx.strokeStyle = styles$
|
|
34649
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34650
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
33954
34651
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33955
34652
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
33956
34653
|
ctx.stroke(path);
|
|
33957
34654
|
|
|
33958
34655
|
// Inner white line that separates the two bond lines.
|
|
33959
34656
|
path = new Path2D();
|
|
33960
|
-
ctx.lineWidth = 3 * styles$
|
|
33961
|
-
ctx.strokeStyle = styles$
|
|
34657
|
+
ctx.lineWidth = 3 * styles$a.lineWidth;
|
|
34658
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
33962
34659
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33963
34660
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
33964
34661
|
ctx.stroke(path);
|
|
@@ -33985,16 +34682,16 @@ function drawTripleLine(ctx, item) {
|
|
|
33985
34682
|
|
|
33986
34683
|
// Outer line that will form the two outer bond lines.
|
|
33987
34684
|
let path = new Path2D();
|
|
33988
|
-
ctx.lineWidth = 7 * styles$
|
|
33989
|
-
ctx.strokeStyle = styles$
|
|
34685
|
+
ctx.lineWidth = 7 * styles$a.lineWidth;
|
|
34686
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
33990
34687
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33991
34688
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
33992
34689
|
ctx.stroke(path);
|
|
33993
34690
|
|
|
33994
34691
|
// Middle white line that separates the bonds
|
|
33995
34692
|
path = new Path2D();
|
|
33996
|
-
ctx.lineWidth = 5 * styles$
|
|
33997
|
-
ctx.strokeStyle = styles$
|
|
34693
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34694
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
33998
34695
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
33999
34696
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34000
34697
|
ctx.stroke(path);
|
|
@@ -34016,8 +34713,8 @@ function drawTripleLine(ctx, item) {
|
|
|
34016
34713
|
*/
|
|
34017
34714
|
function drawLine(ctx, item) {
|
|
34018
34715
|
const path = new Path2D();
|
|
34019
|
-
ctx.lineWidth = styles$
|
|
34020
|
-
ctx.strokeStyle = styles$
|
|
34716
|
+
ctx.lineWidth = styles$a.lineWidth;
|
|
34717
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34021
34718
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34022
34719
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34023
34720
|
ctx.stroke(path);
|
|
@@ -34069,7 +34766,7 @@ function compareElements(item0, item1) {
|
|
|
34069
34766
|
function draw(ctx, items) {
|
|
34070
34767
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
34071
34768
|
}
|
|
34072
|
-
const styles$
|
|
34769
|
+
const styles$a = {
|
|
34073
34770
|
bgColor: "rgb(255, 255, 255)",
|
|
34074
34771
|
fgColor: "rgb(0, 0, 0)",
|
|
34075
34772
|
fontSizePx: 12,
|
|
@@ -36631,7 +37328,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
36631
37328
|
const rects = this.state.cachedHighlightRects;
|
|
36632
37329
|
return /*#__PURE__*/React.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React.createElement("div", {
|
|
36633
37330
|
key: index,
|
|
36634
|
-
className: css(styles$
|
|
37331
|
+
className: css(styles$9.highlightRect),
|
|
36635
37332
|
style: {
|
|
36636
37333
|
// NOTE(mdr): We apply `position: absolute` here
|
|
36637
37334
|
// rather than in Aphrodite styles, because
|
|
@@ -36650,7 +37347,7 @@ class HighlightRenderer extends React.PureComponent {
|
|
|
36650
37347
|
})));
|
|
36651
37348
|
}
|
|
36652
37349
|
}
|
|
36653
|
-
const styles$
|
|
37350
|
+
const styles$9 = StyleSheet.create({
|
|
36654
37351
|
highlightRect: {
|
|
36655
37352
|
background: "#fffabe" // highlighter yellow :)
|
|
36656
37353
|
}
|
|
@@ -36731,7 +37428,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
36731
37428
|
// TooltipContent wouldn't let me overwrite
|
|
36732
37429
|
// user-select and onClick
|
|
36733
37430
|
const content = /*#__PURE__*/React.createElement("div", {
|
|
36734
|
-
className: css(styles$
|
|
37431
|
+
className: css(styles$8.tooltipLabel),
|
|
36735
37432
|
onClick: this.props.onClick
|
|
36736
37433
|
}, this.props.label);
|
|
36737
37434
|
const style = {
|
|
@@ -36751,7 +37448,7 @@ class HighlightTooltip extends React.PureComponent {
|
|
|
36751
37448
|
}, /*#__PURE__*/React.createElement("div", null)));
|
|
36752
37449
|
}
|
|
36753
37450
|
}
|
|
36754
|
-
const styles$
|
|
37451
|
+
const styles$8 = StyleSheet.create({
|
|
36755
37452
|
tooltipLabel: {
|
|
36756
37453
|
// Unlike most tooltip contents, we don't want this label to be
|
|
36757
37454
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -37303,7 +38000,7 @@ class HighlightableContent extends React.PureComponent {
|
|
|
37303
38000
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
37304
38001
|
const buildHighlight = r => this._buildHighlight(r);
|
|
37305
38002
|
return /*#__PURE__*/React.createElement("div", {
|
|
37306
|
-
className: css(styles$
|
|
38003
|
+
className: css(styles$7.container),
|
|
37307
38004
|
ref: container => this._container = container
|
|
37308
38005
|
}, /*#__PURE__*/React.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React.createElement(HighlightingUI, {
|
|
37309
38006
|
buildHighlight: buildHighlight,
|
|
@@ -37324,14 +38021,14 @@ class HighlightableContent extends React.PureComponent {
|
|
|
37324
38021
|
onAddHighlight: this._handleAddHighlight,
|
|
37325
38022
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
37326
38023
|
})), /*#__PURE__*/React.createElement("div", {
|
|
37327
|
-
className: css(styles$
|
|
38024
|
+
className: css(styles$7.content),
|
|
37328
38025
|
ref: content => this._content = content
|
|
37329
38026
|
}, /*#__PURE__*/React.createElement(WordIndexer, {
|
|
37330
38027
|
onWordsUpdate: this._handleWordsUpdate
|
|
37331
38028
|
}, this.props.children)));
|
|
37332
38029
|
}
|
|
37333
38030
|
}
|
|
37334
|
-
const styles$
|
|
38031
|
+
const styles$7 = StyleSheet.create({
|
|
37335
38032
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
37336
38033
|
// content will receive the browser's native pointer events. (Highlights
|
|
37337
38034
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -37731,7 +38428,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
37731
38428
|
}
|
|
37732
38429
|
render() {
|
|
37733
38430
|
return /*#__PURE__*/React.createElement("div", {
|
|
37734
|
-
className: css(styles$
|
|
38431
|
+
className: css(styles$6.measurer),
|
|
37735
38432
|
"aria-hidden": "true"
|
|
37736
38433
|
}, /*#__PURE__*/React.createElement("div", {
|
|
37737
38434
|
ref: ref => this._line = ref,
|
|
@@ -37739,7 +38436,7 @@ class LineHeightMeasurer extends React.Component {
|
|
|
37739
38436
|
}, "Line Height Measurement"));
|
|
37740
38437
|
}
|
|
37741
38438
|
}
|
|
37742
|
-
const styles$
|
|
38439
|
+
const styles$6 = StyleSheet.create({
|
|
37743
38440
|
measurer: {
|
|
37744
38441
|
position: "absolute",
|
|
37745
38442
|
top: 0,
|
|
@@ -39051,7 +39748,7 @@ class PythonProgram extends React.Component {
|
|
|
39051
39748
|
// creator "went wild".
|
|
39052
39749
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
39053
39750
|
return /*#__PURE__*/React.createElement(View, {
|
|
39054
|
-
style: styles$
|
|
39751
|
+
style: styles$5.container
|
|
39055
39752
|
}, /*#__PURE__*/React.createElement("iframe", {
|
|
39056
39753
|
sandbox: sandboxOptions,
|
|
39057
39754
|
src: url,
|
|
@@ -39063,7 +39760,7 @@ class PythonProgram extends React.Component {
|
|
|
39063
39760
|
PythonProgram.defaultProps = {
|
|
39064
39761
|
height: 400
|
|
39065
39762
|
};
|
|
39066
|
-
const styles$
|
|
39763
|
+
const styles$5 = StyleSheet.create({
|
|
39067
39764
|
container: {
|
|
39068
39765
|
margin: "auto",
|
|
39069
39766
|
width: "100%"
|
|
@@ -39303,129 +40000,6 @@ var Sequence$1 = {
|
|
|
39303
40000
|
isLintable: true
|
|
39304
40001
|
};
|
|
39305
40002
|
|
|
39306
|
-
const colors = {
|
|
39307
|
-
grayLight: "#aaa",
|
|
39308
|
-
basicBorderColor: "#ccc",
|
|
39309
|
-
white: "#fff"
|
|
39310
|
-
};
|
|
39311
|
-
const triangleBeforeAfter = {
|
|
39312
|
-
borderBottom: "9px solid transparent",
|
|
39313
|
-
borderTop: "9px solid transparent",
|
|
39314
|
-
content: '" "',
|
|
39315
|
-
height: "0",
|
|
39316
|
-
position: "absolute",
|
|
39317
|
-
top: "0",
|
|
39318
|
-
width: "0"
|
|
39319
|
-
};
|
|
39320
|
-
const styles$7 = StyleSheet.create({
|
|
39321
|
-
infoTip: {
|
|
39322
|
-
display: "inline-block",
|
|
39323
|
-
marginLeft: "5px",
|
|
39324
|
-
position: "relative"
|
|
39325
|
-
},
|
|
39326
|
-
infoTipContainer: {
|
|
39327
|
-
position: "absolute",
|
|
39328
|
-
top: "-12px",
|
|
39329
|
-
left: "22px",
|
|
39330
|
-
zIndex: 1000
|
|
39331
|
-
},
|
|
39332
|
-
infoTipTriangle: {
|
|
39333
|
-
height: "10px",
|
|
39334
|
-
left: "0",
|
|
39335
|
-
position: "absolute",
|
|
39336
|
-
top: "8px",
|
|
39337
|
-
width: "0",
|
|
39338
|
-
zIndex: 1,
|
|
39339
|
-
":before": _extends({}, triangleBeforeAfter, {
|
|
39340
|
-
borderRight: "9px solid #bbb",
|
|
39341
|
-
right: "0"
|
|
39342
|
-
}),
|
|
39343
|
-
":after": _extends({}, triangleBeforeAfter, {
|
|
39344
|
-
borderRight: `9px solid ${colors.white}`,
|
|
39345
|
-
right: "-1px"
|
|
39346
|
-
})
|
|
39347
|
-
},
|
|
39348
|
-
verticalShadow: {
|
|
39349
|
-
border: `1px solid ${colors.basicBorderColor}`,
|
|
39350
|
-
boxShadow: `0 1px 3px ${colors.basicBorderColor}`,
|
|
39351
|
-
borderBottom: `1px solid ${colors.grayLight}`
|
|
39352
|
-
},
|
|
39353
|
-
infoTipContentContainer: {
|
|
39354
|
-
background: colors.white,
|
|
39355
|
-
padding: "5px 10px",
|
|
39356
|
-
width: "240px"
|
|
39357
|
-
}
|
|
39358
|
-
});
|
|
39359
|
-
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=";
|
|
39360
|
-
class InfoTip$1 extends React.Component {
|
|
39361
|
-
constructor(...args) {
|
|
39362
|
-
super(...args);
|
|
39363
|
-
this.state = {
|
|
39364
|
-
hover: false
|
|
39365
|
-
};
|
|
39366
|
-
this.handleMouseEnter = () => {
|
|
39367
|
-
this.setState({
|
|
39368
|
-
hover: true
|
|
39369
|
-
});
|
|
39370
|
-
};
|
|
39371
|
-
this.handleMouseLeave = () => {
|
|
39372
|
-
this.setState({
|
|
39373
|
-
hover: false
|
|
39374
|
-
});
|
|
39375
|
-
};
|
|
39376
|
-
}
|
|
39377
|
-
render() {
|
|
39378
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
39379
|
-
className: css(styles$7.infoTip)
|
|
39380
|
-
}, /*#__PURE__*/React.createElement("img", {
|
|
39381
|
-
alt: "",
|
|
39382
|
-
width: 10,
|
|
39383
|
-
height: 10,
|
|
39384
|
-
src: questionMark,
|
|
39385
|
-
onMouseEnter: this.handleMouseEnter,
|
|
39386
|
-
onMouseLeave: this.handleMouseLeave
|
|
39387
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
39388
|
-
className: css(styles$7.infoTipContainer),
|
|
39389
|
-
style: {
|
|
39390
|
-
display: this.state.hover ? "block" : "none"
|
|
39391
|
-
}
|
|
39392
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
39393
|
-
className: css(styles$7.infoTipTriangle)
|
|
39394
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
39395
|
-
className: css(styles$7.verticalShadow, styles$7.infoTipContentContainer)
|
|
39396
|
-
}, this.props.children)));
|
|
39397
|
-
}
|
|
39398
|
-
}
|
|
39399
|
-
|
|
39400
|
-
/**
|
|
39401
|
-
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
39402
|
-
* server without causing a checksum mismatch on the client.
|
|
39403
|
-
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
39404
|
-
* two sets of generated classnames will not match.)
|
|
39405
|
-
*/
|
|
39406
|
-
class InfoTip extends React.Component {
|
|
39407
|
-
constructor(...args) {
|
|
39408
|
-
super(...args);
|
|
39409
|
-
this.state = {
|
|
39410
|
-
didMount: false
|
|
39411
|
-
};
|
|
39412
|
-
}
|
|
39413
|
-
componentDidMount() {
|
|
39414
|
-
/* eslint-disable react/no-did-mount-set-state */
|
|
39415
|
-
this.setState({
|
|
39416
|
-
didMount: true
|
|
39417
|
-
});
|
|
39418
|
-
/* eslint-enable react/no-did-mount-set-state */
|
|
39419
|
-
}
|
|
39420
|
-
|
|
39421
|
-
render() {
|
|
39422
|
-
if (this.state.didMount) {
|
|
39423
|
-
return /*#__PURE__*/React.createElement(InfoTip$1, this.props);
|
|
39424
|
-
}
|
|
39425
|
-
return /*#__PURE__*/React.createElement("div", null);
|
|
39426
|
-
}
|
|
39427
|
-
}
|
|
39428
|
-
|
|
39429
40003
|
const {
|
|
39430
40004
|
assert: assert$1
|
|
39431
40005
|
} = InteractiveUtil;
|
|
@@ -41380,7 +41954,7 @@ const VideoTranscriptLink = props => {
|
|
|
41380
41954
|
var _result$data;
|
|
41381
41955
|
const video = (_result$data = result.data) == null ? void 0 : _result$data.video;
|
|
41382
41956
|
return /*#__PURE__*/React.createElement(View, {
|
|
41383
|
-
style: styles$
|
|
41957
|
+
style: styles$4.transcriptLink
|
|
41384
41958
|
}, /*#__PURE__*/React.createElement(Text$1, null, video == null ? void 0 : video.title), /*#__PURE__*/React.createElement(Strut, {
|
|
41385
41959
|
size: 10
|
|
41386
41960
|
}), /*#__PURE__*/React.createElement(Link, {
|
|
@@ -41397,7 +41971,7 @@ const VideoTranscriptLink = props => {
|
|
|
41397
41971
|
return /*#__PURE__*/React.createElement(View, null, i18n._("Something went wrong."));
|
|
41398
41972
|
}
|
|
41399
41973
|
};
|
|
41400
|
-
const styles$
|
|
41974
|
+
const styles$4 = StyleSheet.create({
|
|
41401
41975
|
transcriptLink: {
|
|
41402
41976
|
flexDirection: "row",
|
|
41403
41977
|
width: "100%",
|
|
@@ -41550,7 +42124,7 @@ const init = function init(options) {
|
|
|
41550
42124
|
|
|
41551
42125
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41552
42126
|
const libName = "@khanacademy/perseus";
|
|
41553
|
-
const libVersion = "19.
|
|
42127
|
+
const libVersion = "19.7.0";
|
|
41554
42128
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41555
42129
|
|
|
41556
42130
|
const apiVersion = {
|
|
@@ -41760,7 +42334,7 @@ class HintRenderer extends React.Component {
|
|
|
41760
42334
|
const {
|
|
41761
42335
|
isMobile
|
|
41762
42336
|
} = apiOptions;
|
|
41763
|
-
const classNames$1 = classNames("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$
|
|
42337
|
+
const classNames$1 = classNames("hint", !isMobile && "perseus-hint-renderer", isMobile && css(styles$3.newHint), isMobile && lastRendered && css(styles$3.lastRenderedNewHint), lastHint && "last-hint", lastRendered && "last-rendered", className);
|
|
41764
42338
|
|
|
41765
42339
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
41766
42340
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -41803,7 +42377,7 @@ class HintRenderer extends React.Component {
|
|
|
41803
42377
|
HintRenderer.defaultProps = {
|
|
41804
42378
|
linterContext: PerseusLinter.linterContextDefault
|
|
41805
42379
|
};
|
|
41806
|
-
const styles$
|
|
42380
|
+
const styles$3 = StyleSheet.create({
|
|
41807
42381
|
newHint: {
|
|
41808
42382
|
marginBottom: 1.5 * baseUnitPx,
|
|
41809
42383
|
borderLeftColor: gray97,
|
|
@@ -41976,15 +42550,15 @@ class HintsRenderer extends React.Component {
|
|
|
41976
42550
|
} = apiOptions;
|
|
41977
42551
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
41978
42552
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
41979
|
-
const classNames$1 = classNames(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$
|
|
42553
|
+
const classNames$1 = classNames(this.props.className, apiOptions.isMobile && hintsVisible > 0 && css(styles$2.mobileHintStylesHintsRenderer));
|
|
41980
42554
|
return /*#__PURE__*/React.createElement("div", {
|
|
41981
42555
|
className: classNames$1
|
|
41982
42556
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React.createElement("div", {
|
|
41983
|
-
className: css(styles$
|
|
42557
|
+
className: css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
41984
42558
|
}, i18n._("Hints")), hints, showGetAnotherHint && /*#__PURE__*/React.createElement("button", {
|
|
41985
42559
|
// @ts-expect-error - TS2322 - Type '{ children: Element[]; rel: string; className: string; onClick: (evt: MouseEvent<HTMLButtonElement, MouseEvent>) => void; }' is not assignable to type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'.
|
|
41986
42560
|
rel: "button",
|
|
41987
|
-
className: css(styles$
|
|
42561
|
+
className: css(styles$2.linkButton, styles$2.getAnotherHintButton, apiOptions.isMobile && styles$2.mobileHintStylesGetAnotherHintButton),
|
|
41988
42562
|
onClick: evt => {
|
|
41989
42563
|
evt.preventDefault();
|
|
41990
42564
|
evt.stopPropagation();
|
|
@@ -41993,9 +42567,9 @@ class HintsRenderer extends React.Component {
|
|
|
41993
42567
|
}
|
|
41994
42568
|
}
|
|
41995
42569
|
}, /*#__PURE__*/React.createElement("span", {
|
|
41996
|
-
className: css(styles$
|
|
42570
|
+
className: css(styles$2.plusText, apiOptions.isMobile && styles$2.mobileHintStylesPlusText)
|
|
41997
42571
|
}, "+"), /*#__PURE__*/React.createElement("span", {
|
|
41998
|
-
className: css(styles$
|
|
42572
|
+
className: css(styles$2.getAnotherHintText)
|
|
41999
42573
|
}, i18n._("Get another hint"), " ", hintRatioCopy)));
|
|
42000
42574
|
}
|
|
42001
42575
|
}
|
|
@@ -42003,7 +42577,7 @@ HintsRenderer.defaultProps = {
|
|
|
42003
42577
|
linterContext: PerseusLinter.linterContextDefault
|
|
42004
42578
|
};
|
|
42005
42579
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
42006
|
-
const styles$
|
|
42580
|
+
const styles$2 = StyleSheet.create({
|
|
42007
42581
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
42008
42582
|
rendererMargins: {
|
|
42009
42583
|
marginTop: baseUnitPx
|
|
@@ -42410,7 +42984,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
42410
42984
|
// mobile hint styles, which are flush to the left.
|
|
42411
42985
|
// NOTE(charlie): We may still want to apply this
|
|
42412
42986
|
// padding for desktop exercises.
|
|
42413
|
-
apiOptions.isMobile ? undefined : css(styles$
|
|
42987
|
+
apiOptions.isMobile ? undefined : css(styles$1.hintsContainer)
|
|
42414
42988
|
}, hintsRenderer)));
|
|
42415
42989
|
}
|
|
42416
42990
|
}
|
|
@@ -42420,7 +42994,7 @@ ServerItemRenderer.defaultProps = {
|
|
|
42420
42994
|
linterContext: PerseusLinter.linterContextDefault,
|
|
42421
42995
|
onRendered: isRendered => {}
|
|
42422
42996
|
};
|
|
42423
|
-
const styles$
|
|
42997
|
+
const styles$1 = StyleSheet.create({
|
|
42424
42998
|
hintsContainer: {
|
|
42425
42999
|
marginLeft: 50
|
|
42426
43000
|
}
|
|
@@ -42554,345 +43128,6 @@ ElementContainer.defaultProps = {
|
|
|
42554
43128
|
title: "More"
|
|
42555
43129
|
};
|
|
42556
43130
|
|
|
42557
|
-
// Displays a stylized open eye: lint warnings are visible
|
|
42558
|
-
const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
42559
|
-
width: "24",
|
|
42560
|
-
height: "24",
|
|
42561
|
-
viewBox: "0 0 24 24",
|
|
42562
|
-
className: css(styles$2.icon)
|
|
42563
|
-
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
42564
|
-
id: "a",
|
|
42565
|
-
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"
|
|
42566
|
-
})), /*#__PURE__*/React.createElement("g", {
|
|
42567
|
-
fill: "none",
|
|
42568
|
-
fillRule: "evenodd"
|
|
42569
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42570
|
-
fill: "none",
|
|
42571
|
-
d: "M0 0h24v24H0z"
|
|
42572
|
-
}), /*#__PURE__*/React.createElement("mask", {
|
|
42573
|
-
id: "b",
|
|
42574
|
-
fill: "#fff"
|
|
42575
|
-
}, /*#__PURE__*/React.createElement("use", {
|
|
42576
|
-
href: "#a"
|
|
42577
|
-
})), /*#__PURE__*/React.createElement("use", {
|
|
42578
|
-
fill: "#fff",
|
|
42579
|
-
fillRule: "nonzero",
|
|
42580
|
-
href: "#a"
|
|
42581
|
-
}), /*#__PURE__*/React.createElement("g", {
|
|
42582
|
-
fill: "#fff",
|
|
42583
|
-
mask: "url(#b)"
|
|
42584
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42585
|
-
d: "M0 0h24v24H0z"
|
|
42586
|
-
}))));
|
|
42587
|
-
|
|
42588
|
-
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
42589
|
-
const HiddenIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
42590
|
-
width: "24",
|
|
42591
|
-
height: "24",
|
|
42592
|
-
viewBox: "0 0 24 24",
|
|
42593
|
-
className: css(styles$2.icon)
|
|
42594
|
-
}, /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
|
|
42595
|
-
id: "a",
|
|
42596
|
-
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"
|
|
42597
|
-
})), /*#__PURE__*/React.createElement("g", {
|
|
42598
|
-
fill: "none",
|
|
42599
|
-
fillRule: "evenodd"
|
|
42600
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42601
|
-
fill: "none",
|
|
42602
|
-
d: "M0 0h24v24H0z"
|
|
42603
|
-
}), /*#__PURE__*/React.createElement("mask", {
|
|
42604
|
-
id: "b",
|
|
42605
|
-
fill: "#fff"
|
|
42606
|
-
}, /*#__PURE__*/React.createElement("use", {
|
|
42607
|
-
href: "#a"
|
|
42608
|
-
})), /*#__PURE__*/React.createElement("use", {
|
|
42609
|
-
fill: "#fff",
|
|
42610
|
-
fillRule: "nonzero",
|
|
42611
|
-
href: "#a"
|
|
42612
|
-
}), /*#__PURE__*/React.createElement("g", {
|
|
42613
|
-
fill: "#fff",
|
|
42614
|
-
mask: "url(#b)"
|
|
42615
|
-
}, /*#__PURE__*/React.createElement("path", {
|
|
42616
|
-
d: "M0 0h24v24H0z"
|
|
42617
|
-
}))));
|
|
42618
|
-
const HUD = ({
|
|
42619
|
-
message,
|
|
42620
|
-
enabled,
|
|
42621
|
-
onClick,
|
|
42622
|
-
fixedPosition: _fixedPosition = true
|
|
42623
|
-
}) => {
|
|
42624
|
-
let state;
|
|
42625
|
-
let icon;
|
|
42626
|
-
if (enabled) {
|
|
42627
|
-
state = styles$2.enabled;
|
|
42628
|
-
icon = /*#__PURE__*/React.createElement(VisibleIcon, null);
|
|
42629
|
-
} else {
|
|
42630
|
-
state = styles$2.disabled;
|
|
42631
|
-
icon = /*#__PURE__*/React.createElement(HiddenIcon, null);
|
|
42632
|
-
}
|
|
42633
|
-
return /*#__PURE__*/React.createElement("button", {
|
|
42634
|
-
className: css(styles$2.hud, _fixedPosition && styles$2.hudFixedPosition, state),
|
|
42635
|
-
onClick: e => {
|
|
42636
|
-
onClick();
|
|
42637
|
-
}
|
|
42638
|
-
}, icon, message);
|
|
42639
|
-
};
|
|
42640
|
-
const styles$2 = StyleSheet.create({
|
|
42641
|
-
hud: {
|
|
42642
|
-
boxSizing: "border-box",
|
|
42643
|
-
height: 36,
|
|
42644
|
-
padding: "9px 16px",
|
|
42645
|
-
borderRadius: 18,
|
|
42646
|
-
fontFamily: boldFontFamily,
|
|
42647
|
-
fontSize: "15px",
|
|
42648
|
-
lineHeight: "18px",
|
|
42649
|
-
color: white$1,
|
|
42650
|
-
userSelect: "none",
|
|
42651
|
-
borderWidth: 0 // <button> gives us a border by default
|
|
42652
|
-
},
|
|
42653
|
-
|
|
42654
|
-
// We want to render the element in-place in our fixtures, so allow us to
|
|
42655
|
-
// render in the bottom corner in production and in-place in testing.
|
|
42656
|
-
hudFixedPosition: {
|
|
42657
|
-
bottom: 20,
|
|
42658
|
-
position: "fixed",
|
|
42659
|
-
right: 20,
|
|
42660
|
-
zIndex: 1
|
|
42661
|
-
},
|
|
42662
|
-
icon: {
|
|
42663
|
-
width: 24,
|
|
42664
|
-
height: 24,
|
|
42665
|
-
marginRight: 8,
|
|
42666
|
-
marginTop: -3,
|
|
42667
|
-
verticalAlign: "middle"
|
|
42668
|
-
},
|
|
42669
|
-
enabled: {
|
|
42670
|
-
backgroundColor: warningColor,
|
|
42671
|
-
":hover": {
|
|
42672
|
-
backgroundColor: warningColorHover
|
|
42673
|
-
},
|
|
42674
|
-
":active": {
|
|
42675
|
-
backgroundColor: warningColorActive
|
|
42676
|
-
}
|
|
42677
|
-
},
|
|
42678
|
-
disabled: {
|
|
42679
|
-
backgroundColor: gray76,
|
|
42680
|
-
":hover": {
|
|
42681
|
-
backgroundColor: "#a1a5a9" // in between those two grays
|
|
42682
|
-
},
|
|
42683
|
-
|
|
42684
|
-
":active": {
|
|
42685
|
-
backgroundColor: gray68
|
|
42686
|
-
}
|
|
42687
|
-
}
|
|
42688
|
-
});
|
|
42689
|
-
|
|
42690
|
-
/**
|
|
42691
|
-
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
42692
|
-
* which allows multiple buttons to be selected at the same time.
|
|
42693
|
-
*
|
|
42694
|
-
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
42695
|
-
* this component allows multiple selection!
|
|
42696
|
-
*/
|
|
42697
|
-
class MultiButtonGroup extends React.Component {
|
|
42698
|
-
constructor(...args) {
|
|
42699
|
-
super(...args);
|
|
42700
|
-
this.toggleSelect = newValue => {
|
|
42701
|
-
const values = (this.props.values || []).slice(0);
|
|
42702
|
-
const allowEmpty = this.props.allowEmpty;
|
|
42703
|
-
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
42704
|
-
// If the value is already selected, unselect it
|
|
42705
|
-
values.splice(values.indexOf(newValue), 1);
|
|
42706
|
-
} else {
|
|
42707
|
-
// Otherwise merge with other values and return
|
|
42708
|
-
if (values.indexOf(newValue) < 0) {
|
|
42709
|
-
values.push(newValue);
|
|
42710
|
-
}
|
|
42711
|
-
}
|
|
42712
|
-
this.props.onChange(values);
|
|
42713
|
-
};
|
|
42714
|
-
}
|
|
42715
|
-
focus() {
|
|
42716
|
-
var _ReactDOM$findDOMNode;
|
|
42717
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
42718
|
-
(_ReactDOM$findDOMNode = ReactDOM.findDOMNode(this)) == null || _ReactDOM$findDOMNode.focus();
|
|
42719
|
-
return true;
|
|
42720
|
-
}
|
|
42721
|
-
render() {
|
|
42722
|
-
const values = this.props.values || [];
|
|
42723
|
-
const buttons = this.props.buttons.map((button, i) => {
|
|
42724
|
-
const selected = values.indexOf(button.value) >= 0;
|
|
42725
|
-
return /*#__PURE__*/React.createElement("button", {
|
|
42726
|
-
title: button.title,
|
|
42727
|
-
type: "button",
|
|
42728
|
-
id: "" + i,
|
|
42729
|
-
key: "" + i,
|
|
42730
|
-
ref: "button" + i,
|
|
42731
|
-
className: css(styles$1.buttonStyle, selected && styles$1.selectedStyle),
|
|
42732
|
-
onClick: () => this.toggleSelect(button.value)
|
|
42733
|
-
}, button.content || "" + button.value);
|
|
42734
|
-
});
|
|
42735
|
-
const outerStyle = {
|
|
42736
|
-
display: "inline-block"
|
|
42737
|
-
};
|
|
42738
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
42739
|
-
style: outerStyle
|
|
42740
|
-
}, buttons);
|
|
42741
|
-
}
|
|
42742
|
-
}
|
|
42743
|
-
MultiButtonGroup.defaultProps = {
|
|
42744
|
-
values: [],
|
|
42745
|
-
allowEmpty: true
|
|
42746
|
-
};
|
|
42747
|
-
const styles$1 = StyleSheet.create({
|
|
42748
|
-
buttonStyle: {
|
|
42749
|
-
backgroundColor: "white",
|
|
42750
|
-
border: "1px solid #ccc",
|
|
42751
|
-
borderLeft: "0",
|
|
42752
|
-
cursor: "pointer",
|
|
42753
|
-
margin: "0",
|
|
42754
|
-
padding: "5px 10px",
|
|
42755
|
-
position: "relative",
|
|
42756
|
-
// for hover
|
|
42757
|
-
|
|
42758
|
-
":first-child": {
|
|
42759
|
-
borderLeft: "1px solid #ccc",
|
|
42760
|
-
borderTopLeftRadius: "3px",
|
|
42761
|
-
borderBottomLeftRadius: "3px"
|
|
42762
|
-
},
|
|
42763
|
-
":last-child": {
|
|
42764
|
-
borderRight: "1px solid #ccc",
|
|
42765
|
-
borderTopRightRadius: "3px",
|
|
42766
|
-
borderBottomRightRadius: "3px"
|
|
42767
|
-
},
|
|
42768
|
-
":hover": {
|
|
42769
|
-
backgroundColor: "#ccc"
|
|
42770
|
-
},
|
|
42771
|
-
":focus": {
|
|
42772
|
-
zIndex: 2
|
|
42773
|
-
}
|
|
42774
|
-
},
|
|
42775
|
-
selectedStyle: {
|
|
42776
|
-
backgroundColor: "#ddd"
|
|
42777
|
-
}
|
|
42778
|
-
});
|
|
42779
|
-
|
|
42780
|
-
/* eslint-disable @babel/no-invalid-this */
|
|
42781
|
-
|
|
42782
|
-
/* A checkbox that syncs its value to props using the
|
|
42783
|
-
* renderer's onChange method, and gets the prop name
|
|
42784
|
-
* dynamically from its props list
|
|
42785
|
-
*/
|
|
42786
|
-
const PropCheckBox = createReactClass({
|
|
42787
|
-
displayName: "PropCheckBox",
|
|
42788
|
-
propTypes: {
|
|
42789
|
-
labelAlignment: PropTypes.oneOf(["left", "right"])
|
|
42790
|
-
},
|
|
42791
|
-
DEFAULT_PROPS: {
|
|
42792
|
-
label: null,
|
|
42793
|
-
onChange: null,
|
|
42794
|
-
labelAlignment: "left"
|
|
42795
|
-
},
|
|
42796
|
-
getDefaultProps: function () {
|
|
42797
|
-
return this.DEFAULT_PROPS;
|
|
42798
|
-
},
|
|
42799
|
-
propName: function () {
|
|
42800
|
-
const propName = _.find(_.keys(this.props), function (localPropName) {
|
|
42801
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
42802
|
-
return !_.has(this.DEFAULT_PROPS, localPropName);
|
|
42803
|
-
}, this);
|
|
42804
|
-
if (!propName) {
|
|
42805
|
-
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
42806
|
-
}
|
|
42807
|
-
return propName;
|
|
42808
|
-
},
|
|
42809
|
-
_labelAlignLeft: function () {
|
|
42810
|
-
return this.props.labelAlignment === "left";
|
|
42811
|
-
},
|
|
42812
|
-
render: function () {
|
|
42813
|
-
const propName = this.propName();
|
|
42814
|
-
return /*#__PURE__*/React.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React.createElement("input", {
|
|
42815
|
-
type: "checkbox",
|
|
42816
|
-
checked: this.props[propName],
|
|
42817
|
-
onChange: this.toggle
|
|
42818
|
-
}), !this._labelAlignLeft() && this.props.label);
|
|
42819
|
-
},
|
|
42820
|
-
toggle: function () {
|
|
42821
|
-
const propName = this.propName();
|
|
42822
|
-
const changes = {};
|
|
42823
|
-
changes[propName] = !this.props[propName];
|
|
42824
|
-
this.props.onChange(changes);
|
|
42825
|
-
}
|
|
42826
|
-
});
|
|
42827
|
-
|
|
42828
|
-
const truth = () => true;
|
|
42829
|
-
|
|
42830
|
-
/* A minor abstraction on top of NumberInput for ranges
|
|
42831
|
-
*
|
|
42832
|
-
*/
|
|
42833
|
-
class RangeInput extends React.Component {
|
|
42834
|
-
constructor(...args) {
|
|
42835
|
-
super(...args);
|
|
42836
|
-
this.onChange = (i, newVal) => {
|
|
42837
|
-
const value = this.props.value;
|
|
42838
|
-
if (i === 0) {
|
|
42839
|
-
this.props.onChange([newVal, value[1]]);
|
|
42840
|
-
} else {
|
|
42841
|
-
this.props.onChange([value[0], newVal]);
|
|
42842
|
-
}
|
|
42843
|
-
};
|
|
42844
|
-
}
|
|
42845
|
-
render() {
|
|
42846
|
-
const value = this.props.value;
|
|
42847
|
-
const checkValidity = this.props.checkValidity || truth;
|
|
42848
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
42849
|
-
className: "range-input"
|
|
42850
|
-
}, /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
42851
|
-
value: value[0],
|
|
42852
|
-
checkValidity: val => checkValidity([val, value[1]])
|
|
42853
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
42854
|
-
,
|
|
42855
|
-
onChange: this.onChange.bind(this, 0),
|
|
42856
|
-
placeholder: this.props.placeholder[0]
|
|
42857
|
-
})), /*#__PURE__*/React.createElement(NumberInput, _extends({}, this.props, {
|
|
42858
|
-
value: value[1],
|
|
42859
|
-
checkValidity: val => checkValidity([value[0], val])
|
|
42860
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
42861
|
-
,
|
|
42862
|
-
onChange: this.onChange.bind(this, 1),
|
|
42863
|
-
placeholder: this.props.placeholder[1]
|
|
42864
|
-
})));
|
|
42865
|
-
}
|
|
42866
|
-
}
|
|
42867
|
-
RangeInput.propTypes = {
|
|
42868
|
-
value: PropTypes.array.isRequired,
|
|
42869
|
-
onChange: PropTypes.func.isRequired,
|
|
42870
|
-
placeholder: PropTypes.array,
|
|
42871
|
-
checkValidity: PropTypes.func
|
|
42872
|
-
};
|
|
42873
|
-
RangeInput.defaultProps = {
|
|
42874
|
-
placeholder: [null, null]
|
|
42875
|
-
};
|
|
42876
|
-
|
|
42877
|
-
var components = /*#__PURE__*/Object.freeze({
|
|
42878
|
-
__proto__: null,
|
|
42879
|
-
ButtonGroup: ButtonGroup,
|
|
42880
|
-
Graph: Graph,
|
|
42881
|
-
Graphie: Graphie,
|
|
42882
|
-
HUD: HUD,
|
|
42883
|
-
Icon: Icon,
|
|
42884
|
-
InfoTip: InfoTip,
|
|
42885
|
-
InlineIcon: InlineIcon,
|
|
42886
|
-
MathInput: MathInput,
|
|
42887
|
-
MultiButtonGroup: MultiButtonGroup,
|
|
42888
|
-
NumberInput: NumberInput,
|
|
42889
|
-
PropCheckBox: PropCheckBox,
|
|
42890
|
-
RangeInput: RangeInput,
|
|
42891
|
-
SvgImage: SvgImage,
|
|
42892
|
-
TextInput: TextInput,
|
|
42893
|
-
TextListEditor: TextListEditor
|
|
42894
|
-
});
|
|
42895
|
-
|
|
42896
43131
|
const devices = {
|
|
42897
43132
|
PHONE: "phone",
|
|
42898
43133
|
TABLET: "tablet",
|