@khanacademy/perseus 19.6.3 → 19.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +168 -0
- package/dist/es/index.js +969 -743
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +168 -0
- package/dist/index.js +966 -738
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +1 -0
- package/dist/perseus-types.d.ts +14 -2
- package/dist/server-item-renderer.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/widgets/expression.d.ts +6 -0
- package/dist/widgets/interactive-graph.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/segment.d.ts +5 -0
- package/dist/widgets/interactive-graphs/grid.d.ts +11 -0
- package/dist/widgets/interactive-graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/legacy-grid.d.ts +7 -0
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +79 -0
- package/dist/widgets/interactive-graphs/types.d.ts +9 -0
- package/dist/widgets/interactive-graphs/utils.d.ts +15 -0
- package/dist/widgets/label-image.d.ts +2 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -30,11 +30,12 @@ var wonderBlocksLayout = require('@khanacademy/wonder-blocks-layout');
|
|
|
30
30
|
var Banner = require('@khanacademy/wonder-blocks-banner');
|
|
31
31
|
var wonderBlocksDropdown = require('@khanacademy/wonder-blocks-dropdown');
|
|
32
32
|
var debounce = require('lodash.debounce');
|
|
33
|
+
var mafs = require('mafs');
|
|
34
|
+
var createReactClass = require('create-react-class');
|
|
33
35
|
var Switch = require('@khanacademy/wonder-blocks-switch');
|
|
34
36
|
var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
|
|
35
37
|
var Pill = require('@khanacademy/wonder-blocks-pill');
|
|
36
38
|
var reactPopper = require('react-popper');
|
|
37
|
-
var createReactClass = require('create-react-class');
|
|
38
39
|
var Link = require('@khanacademy/wonder-blocks-link');
|
|
39
40
|
var perseusCore = require('@khanacademy/perseus-core');
|
|
40
41
|
|
|
@@ -77,9 +78,9 @@ var SimpleMarkdown__default = /*#__PURE__*/_interopDefaultLegacy(SimpleMarkdown)
|
|
|
77
78
|
var Button__default = /*#__PURE__*/_interopDefaultLegacy(Button);
|
|
78
79
|
var Banner__default = /*#__PURE__*/_interopDefaultLegacy(Banner);
|
|
79
80
|
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
|
|
81
|
+
var createReactClass__default = /*#__PURE__*/_interopDefaultLegacy(createReactClass);
|
|
80
82
|
var Switch__default = /*#__PURE__*/_interopDefaultLegacy(Switch);
|
|
81
83
|
var Pill__default = /*#__PURE__*/_interopDefaultLegacy(Pill);
|
|
82
|
-
var createReactClass__default = /*#__PURE__*/_interopDefaultLegacy(createReactClass);
|
|
83
84
|
var Link__default = /*#__PURE__*/_interopDefaultLegacy(Link);
|
|
84
85
|
|
|
85
86
|
function _extends() {
|
|
@@ -28325,7 +28326,875 @@ class Graph extends React__namespace.Component {
|
|
|
28325
28326
|
}
|
|
28326
28327
|
}
|
|
28327
28328
|
|
|
28328
|
-
|
|
28329
|
+
const useInteractivePoint = (coords, snaps, range) => mafs.useMovablePoint(coords, {
|
|
28330
|
+
constrain: coord => constrain(coord, snaps, range),
|
|
28331
|
+
color: Color__default["default"].blue
|
|
28332
|
+
});
|
|
28333
|
+
|
|
28334
|
+
/**
|
|
28335
|
+
* We do not want to call `onGraphChange` until the user
|
|
28336
|
+
* has interacted with the graph. See the test,
|
|
28337
|
+
* "should reject no interaction"
|
|
28338
|
+
*/
|
|
28339
|
+
const useEffectAfterFirstRender = (fn, deps) => {
|
|
28340
|
+
const firstRender = React.useRef(true);
|
|
28341
|
+
React.useEffect(() => {
|
|
28342
|
+
if (firstRender.current) {
|
|
28343
|
+
firstRender.current = false;
|
|
28344
|
+
return;
|
|
28345
|
+
}
|
|
28346
|
+
fn();
|
|
28347
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28348
|
+
}, [fn, ...deps]);
|
|
28349
|
+
};
|
|
28350
|
+
const snap = (val, step) => {
|
|
28351
|
+
const inverse = 1 / step;
|
|
28352
|
+
return Math.round(val * inverse) / inverse;
|
|
28353
|
+
};
|
|
28354
|
+
const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
28355
|
+
const constrain = (coord, snapStep, range) => {
|
|
28356
|
+
const [x, y] = coord;
|
|
28357
|
+
const [xSnap, ySnap] = snapStep;
|
|
28358
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
28359
|
+
return [clamp(snap(x, xSnap), xMin, xMax), clamp(snap(y, ySnap), yMin, yMax)];
|
|
28360
|
+
};
|
|
28361
|
+
|
|
28362
|
+
// same as pointsFromNormalized in interactive-graph.tsx
|
|
28363
|
+
const normalizePoints = (range, step, coordsList, noSnap) => coordsList.map(coords =>
|
|
28364
|
+
// maps over [x, y]
|
|
28365
|
+
coords.map((coord, i) => {
|
|
28366
|
+
const axisRange = range[i];
|
|
28367
|
+
if (noSnap) {
|
|
28368
|
+
return axisRange[0] + (axisRange[1] - axisRange[0]) * coord;
|
|
28369
|
+
}
|
|
28370
|
+
const axisStep = step[i];
|
|
28371
|
+
const nSteps = Math.floor((axisRange[1] - axisRange[0]) / axisStep);
|
|
28372
|
+
const tick = Math.round(coord * nSteps);
|
|
28373
|
+
return axisRange[0] + axisStep * tick;
|
|
28374
|
+
}));
|
|
28375
|
+
|
|
28376
|
+
// same as normalizeCoords in interactive-graph.tsx
|
|
28377
|
+
const normalizeCoords = (coordsList, ranges) => coordsList.map(coords => coords.map((coord, i) => {
|
|
28378
|
+
const extent = ranges[i][1] - ranges[i][0];
|
|
28379
|
+
return (coord + ranges[i][1]) / extent;
|
|
28380
|
+
}));
|
|
28381
|
+
|
|
28382
|
+
const getSegmentCoords = props => {
|
|
28383
|
+
const coords = props.graph.coords;
|
|
28384
|
+
if (coords) {
|
|
28385
|
+
return coords;
|
|
28386
|
+
}
|
|
28387
|
+
const ys = n => {
|
|
28388
|
+
switch (n) {
|
|
28389
|
+
case 2:
|
|
28390
|
+
return [5, -5];
|
|
28391
|
+
case 3:
|
|
28392
|
+
return [5, 0, -5];
|
|
28393
|
+
case 4:
|
|
28394
|
+
return [6, 2, -2, -6];
|
|
28395
|
+
case 5:
|
|
28396
|
+
return [6, 3, 0, -3, -6];
|
|
28397
|
+
case 6:
|
|
28398
|
+
return [5, 3, 1, -1, -3, -5];
|
|
28399
|
+
default:
|
|
28400
|
+
return [5];
|
|
28401
|
+
}
|
|
28402
|
+
};
|
|
28403
|
+
return ys(props.graph.numSegments).map(y => {
|
|
28404
|
+
let segment = [[-5, y], [5, y]];
|
|
28405
|
+
segment = normalizeCoords(segment, props.range);
|
|
28406
|
+
segment = normalizePoints(props.range, props.step, segment);
|
|
28407
|
+
return segment;
|
|
28408
|
+
});
|
|
28409
|
+
};
|
|
28410
|
+
const updateSegmentsArray = (segments, index, segment) => segments.map((seg, i) => index === i ? segment : seg);
|
|
28411
|
+
const SegmentGraph = props => {
|
|
28412
|
+
const segments = getSegmentCoords(props);
|
|
28413
|
+
const handleChange = (i, segment) => props.onGraphChange(current => ({
|
|
28414
|
+
...current,
|
|
28415
|
+
coords: current.coords ? updateSegmentsArray(current.coords, i, segment) : updateSegmentsArray(segments, i, segment)
|
|
28416
|
+
}));
|
|
28417
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, segments.map((segment, i) => /*#__PURE__*/React__namespace.createElement(Segment, {
|
|
28418
|
+
key: i,
|
|
28419
|
+
i: i,
|
|
28420
|
+
segment: segment,
|
|
28421
|
+
snaps: props.snapStep,
|
|
28422
|
+
range: props.range,
|
|
28423
|
+
onChange: handleChange,
|
|
28424
|
+
"data-testid": "segment" + i
|
|
28425
|
+
})));
|
|
28426
|
+
};
|
|
28427
|
+
const Segment = props => {
|
|
28428
|
+
const [start, end] = props.segment;
|
|
28429
|
+
const {
|
|
28430
|
+
point: pt1,
|
|
28431
|
+
element: el1
|
|
28432
|
+
} = useInteractivePoint(start, props.snaps, props.range);
|
|
28433
|
+
const {
|
|
28434
|
+
point: pt2,
|
|
28435
|
+
element: el2
|
|
28436
|
+
} = useInteractivePoint(end, props.snaps, props.range);
|
|
28437
|
+
useEffectAfterFirstRender(() => props.onChange(props.i, [pt1, pt2]), [pt1, pt2]);
|
|
28438
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Line.Segment, {
|
|
28439
|
+
point1: pt1,
|
|
28440
|
+
point2: pt2
|
|
28441
|
+
}), el1, el2);
|
|
28442
|
+
};
|
|
28443
|
+
|
|
28444
|
+
const renderLineLabel = (n, _ref) => {
|
|
28445
|
+
let [min, max] = _ref;
|
|
28446
|
+
return n !== -1 && n !== min && n !== max;
|
|
28447
|
+
};
|
|
28448
|
+
const axisOptions = (props, index) => ({
|
|
28449
|
+
axis: props.markings === "graph",
|
|
28450
|
+
lines: props.step[index],
|
|
28451
|
+
subdivisions: props.step[index] / props.gridStep[index],
|
|
28452
|
+
labels: n => renderLineLabel(n, props.range[index]) ? n : ""
|
|
28453
|
+
});
|
|
28454
|
+
const Grid = props => props.markings === "none" ? null : /*#__PURE__*/React__namespace.createElement(mafs.Coordinates.Cartesian, {
|
|
28455
|
+
xAxis: axisOptions(props, 0),
|
|
28456
|
+
yAxis: axisOptions(props, 1)
|
|
28457
|
+
});
|
|
28458
|
+
|
|
28459
|
+
// Displays a stylized open eye: lint warnings are visible
|
|
28460
|
+
const VisibleIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
28461
|
+
width: "24",
|
|
28462
|
+
height: "24",
|
|
28463
|
+
viewBox: "0 0 24 24",
|
|
28464
|
+
className: aphrodite.css(styles$j.icon)
|
|
28465
|
+
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28466
|
+
id: "a",
|
|
28467
|
+
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"
|
|
28468
|
+
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28469
|
+
fill: "none",
|
|
28470
|
+
fillRule: "evenodd"
|
|
28471
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28472
|
+
fill: "none",
|
|
28473
|
+
d: "M0 0h24v24H0z"
|
|
28474
|
+
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
28475
|
+
id: "b",
|
|
28476
|
+
fill: "#fff"
|
|
28477
|
+
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
28478
|
+
href: "#a"
|
|
28479
|
+
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
28480
|
+
fill: "#fff",
|
|
28481
|
+
fillRule: "nonzero",
|
|
28482
|
+
href: "#a"
|
|
28483
|
+
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28484
|
+
fill: "#fff",
|
|
28485
|
+
mask: "url(#b)"
|
|
28486
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28487
|
+
d: "M0 0h24v24H0z"
|
|
28488
|
+
}))));
|
|
28489
|
+
|
|
28490
|
+
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
28491
|
+
const HiddenIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
28492
|
+
width: "24",
|
|
28493
|
+
height: "24",
|
|
28494
|
+
viewBox: "0 0 24 24",
|
|
28495
|
+
className: aphrodite.css(styles$j.icon)
|
|
28496
|
+
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28497
|
+
id: "a",
|
|
28498
|
+
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"
|
|
28499
|
+
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28500
|
+
fill: "none",
|
|
28501
|
+
fillRule: "evenodd"
|
|
28502
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28503
|
+
fill: "none",
|
|
28504
|
+
d: "M0 0h24v24H0z"
|
|
28505
|
+
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
28506
|
+
id: "b",
|
|
28507
|
+
fill: "#fff"
|
|
28508
|
+
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
28509
|
+
href: "#a"
|
|
28510
|
+
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
28511
|
+
fill: "#fff",
|
|
28512
|
+
fillRule: "nonzero",
|
|
28513
|
+
href: "#a"
|
|
28514
|
+
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28515
|
+
fill: "#fff",
|
|
28516
|
+
mask: "url(#b)"
|
|
28517
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28518
|
+
d: "M0 0h24v24H0z"
|
|
28519
|
+
}))));
|
|
28520
|
+
const HUD = _ref => {
|
|
28521
|
+
let {
|
|
28522
|
+
message,
|
|
28523
|
+
enabled,
|
|
28524
|
+
onClick,
|
|
28525
|
+
fixedPosition = true
|
|
28526
|
+
} = _ref;
|
|
28527
|
+
let state;
|
|
28528
|
+
let icon;
|
|
28529
|
+
if (enabled) {
|
|
28530
|
+
state = styles$j.enabled;
|
|
28531
|
+
icon = /*#__PURE__*/React__namespace.createElement(VisibleIcon, null);
|
|
28532
|
+
} else {
|
|
28533
|
+
state = styles$j.disabled;
|
|
28534
|
+
icon = /*#__PURE__*/React__namespace.createElement(HiddenIcon, null);
|
|
28535
|
+
}
|
|
28536
|
+
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
28537
|
+
className: aphrodite.css(styles$j.hud, fixedPosition && styles$j.hudFixedPosition, state),
|
|
28538
|
+
onClick: e => {
|
|
28539
|
+
onClick();
|
|
28540
|
+
}
|
|
28541
|
+
}, icon, message);
|
|
28542
|
+
};
|
|
28543
|
+
const styles$j = aphrodite.StyleSheet.create({
|
|
28544
|
+
hud: {
|
|
28545
|
+
boxSizing: "border-box",
|
|
28546
|
+
height: 36,
|
|
28547
|
+
padding: "9px 16px",
|
|
28548
|
+
borderRadius: 18,
|
|
28549
|
+
fontFamily: boldFontFamily,
|
|
28550
|
+
fontSize: "15px",
|
|
28551
|
+
lineHeight: "18px",
|
|
28552
|
+
color: white$1,
|
|
28553
|
+
userSelect: "none",
|
|
28554
|
+
borderWidth: 0 // <button> gives us a border by default
|
|
28555
|
+
},
|
|
28556
|
+
|
|
28557
|
+
// We want to render the element in-place in our fixtures, so allow us to
|
|
28558
|
+
// render in the bottom corner in production and in-place in testing.
|
|
28559
|
+
hudFixedPosition: {
|
|
28560
|
+
bottom: 20,
|
|
28561
|
+
position: "fixed",
|
|
28562
|
+
right: 20,
|
|
28563
|
+
zIndex: 1
|
|
28564
|
+
},
|
|
28565
|
+
icon: {
|
|
28566
|
+
width: 24,
|
|
28567
|
+
height: 24,
|
|
28568
|
+
marginRight: 8,
|
|
28569
|
+
marginTop: -3,
|
|
28570
|
+
verticalAlign: "middle"
|
|
28571
|
+
},
|
|
28572
|
+
enabled: {
|
|
28573
|
+
backgroundColor: warningColor,
|
|
28574
|
+
":hover": {
|
|
28575
|
+
backgroundColor: warningColorHover
|
|
28576
|
+
},
|
|
28577
|
+
":active": {
|
|
28578
|
+
backgroundColor: warningColorActive
|
|
28579
|
+
}
|
|
28580
|
+
},
|
|
28581
|
+
disabled: {
|
|
28582
|
+
backgroundColor: gray76,
|
|
28583
|
+
":hover": {
|
|
28584
|
+
backgroundColor: "#a1a5a9" // in between those two grays
|
|
28585
|
+
},
|
|
28586
|
+
|
|
28587
|
+
":active": {
|
|
28588
|
+
backgroundColor: gray68
|
|
28589
|
+
}
|
|
28590
|
+
}
|
|
28591
|
+
});
|
|
28592
|
+
|
|
28593
|
+
const colors$1 = {
|
|
28594
|
+
grayLight: "#aaa",
|
|
28595
|
+
basicBorderColor: "#ccc",
|
|
28596
|
+
white: "#fff"
|
|
28597
|
+
};
|
|
28598
|
+
const triangleBeforeAfter = {
|
|
28599
|
+
borderBottom: "9px solid transparent",
|
|
28600
|
+
borderTop: "9px solid transparent",
|
|
28601
|
+
content: '" "',
|
|
28602
|
+
height: "0",
|
|
28603
|
+
position: "absolute",
|
|
28604
|
+
top: "0",
|
|
28605
|
+
width: "0"
|
|
28606
|
+
};
|
|
28607
|
+
const styles$i = aphrodite.StyleSheet.create({
|
|
28608
|
+
infoTip: {
|
|
28609
|
+
display: "inline-block",
|
|
28610
|
+
marginLeft: "5px",
|
|
28611
|
+
position: "relative"
|
|
28612
|
+
},
|
|
28613
|
+
infoTipContainer: {
|
|
28614
|
+
position: "absolute",
|
|
28615
|
+
top: "-12px",
|
|
28616
|
+
left: "22px",
|
|
28617
|
+
zIndex: 1000
|
|
28618
|
+
},
|
|
28619
|
+
infoTipTriangle: {
|
|
28620
|
+
height: "10px",
|
|
28621
|
+
left: "0",
|
|
28622
|
+
position: "absolute",
|
|
28623
|
+
top: "8px",
|
|
28624
|
+
width: "0",
|
|
28625
|
+
zIndex: 1,
|
|
28626
|
+
":before": {
|
|
28627
|
+
...triangleBeforeAfter,
|
|
28628
|
+
borderRight: "9px solid #bbb",
|
|
28629
|
+
right: "0"
|
|
28630
|
+
},
|
|
28631
|
+
":after": {
|
|
28632
|
+
...triangleBeforeAfter,
|
|
28633
|
+
borderRight: `9px solid ${colors$1.white}`,
|
|
28634
|
+
right: "-1px"
|
|
28635
|
+
}
|
|
28636
|
+
},
|
|
28637
|
+
verticalShadow: {
|
|
28638
|
+
border: `1px solid ${colors$1.basicBorderColor}`,
|
|
28639
|
+
boxShadow: `0 1px 3px ${colors$1.basicBorderColor}`,
|
|
28640
|
+
borderBottom: `1px solid ${colors$1.grayLight}`
|
|
28641
|
+
},
|
|
28642
|
+
infoTipContentContainer: {
|
|
28643
|
+
background: colors$1.white,
|
|
28644
|
+
padding: "5px 10px",
|
|
28645
|
+
width: "240px"
|
|
28646
|
+
}
|
|
28647
|
+
});
|
|
28648
|
+
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=";
|
|
28649
|
+
class InfoTip$1 extends React__namespace.Component {
|
|
28650
|
+
state = {
|
|
28651
|
+
hover: false
|
|
28652
|
+
};
|
|
28653
|
+
handleMouseEnter = () => {
|
|
28654
|
+
this.setState({
|
|
28655
|
+
hover: true
|
|
28656
|
+
});
|
|
28657
|
+
};
|
|
28658
|
+
handleMouseLeave = () => {
|
|
28659
|
+
this.setState({
|
|
28660
|
+
hover: false
|
|
28661
|
+
});
|
|
28662
|
+
};
|
|
28663
|
+
render() {
|
|
28664
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28665
|
+
className: aphrodite.css(styles$i.infoTip)
|
|
28666
|
+
}, /*#__PURE__*/React__namespace.createElement("img", {
|
|
28667
|
+
alt: "",
|
|
28668
|
+
width: 10,
|
|
28669
|
+
height: 10,
|
|
28670
|
+
src: questionMark,
|
|
28671
|
+
onMouseEnter: this.handleMouseEnter,
|
|
28672
|
+
onMouseLeave: this.handleMouseLeave
|
|
28673
|
+
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
28674
|
+
className: aphrodite.css(styles$i.infoTipContainer),
|
|
28675
|
+
style: {
|
|
28676
|
+
display: this.state.hover ? "block" : "none"
|
|
28677
|
+
}
|
|
28678
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
28679
|
+
className: aphrodite.css(styles$i.infoTipTriangle)
|
|
28680
|
+
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
28681
|
+
className: aphrodite.css(styles$i.verticalShadow, styles$i.infoTipContentContainer)
|
|
28682
|
+
}, this.props.children)));
|
|
28683
|
+
}
|
|
28684
|
+
}
|
|
28685
|
+
|
|
28686
|
+
/**
|
|
28687
|
+
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
28688
|
+
* server without causing a checksum mismatch on the client.
|
|
28689
|
+
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
28690
|
+
* two sets of generated classnames will not match.)
|
|
28691
|
+
*/
|
|
28692
|
+
class InfoTip extends React__namespace.Component {
|
|
28693
|
+
state = {
|
|
28694
|
+
didMount: false
|
|
28695
|
+
};
|
|
28696
|
+
componentDidMount() {
|
|
28697
|
+
/* eslint-disable react/no-did-mount-set-state */
|
|
28698
|
+
this.setState({
|
|
28699
|
+
didMount: true
|
|
28700
|
+
});
|
|
28701
|
+
/* eslint-enable react/no-did-mount-set-state */
|
|
28702
|
+
}
|
|
28703
|
+
|
|
28704
|
+
render() {
|
|
28705
|
+
if (this.state.didMount) {
|
|
28706
|
+
return /*#__PURE__*/React__namespace.createElement(InfoTip$1, this.props);
|
|
28707
|
+
}
|
|
28708
|
+
return /*#__PURE__*/React__namespace.createElement("div", null);
|
|
28709
|
+
}
|
|
28710
|
+
}
|
|
28711
|
+
|
|
28712
|
+
/**
|
|
28713
|
+
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
28714
|
+
* which allows multiple buttons to be selected at the same time.
|
|
28715
|
+
*
|
|
28716
|
+
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
28717
|
+
* this component allows multiple selection!
|
|
28718
|
+
*/
|
|
28719
|
+
class MultiButtonGroup extends React__namespace.Component {
|
|
28720
|
+
static defaultProps = {
|
|
28721
|
+
values: [],
|
|
28722
|
+
allowEmpty: true
|
|
28723
|
+
};
|
|
28724
|
+
focus() {
|
|
28725
|
+
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28726
|
+
ReactDOM__namespace.findDOMNode(this)?.focus();
|
|
28727
|
+
return true;
|
|
28728
|
+
}
|
|
28729
|
+
toggleSelect = newValue => {
|
|
28730
|
+
const values = (this.props.values || []).slice(0);
|
|
28731
|
+
const allowEmpty = this.props.allowEmpty;
|
|
28732
|
+
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
28733
|
+
// If the value is already selected, unselect it
|
|
28734
|
+
values.splice(values.indexOf(newValue), 1);
|
|
28735
|
+
} else {
|
|
28736
|
+
// Otherwise merge with other values and return
|
|
28737
|
+
if (values.indexOf(newValue) < 0) {
|
|
28738
|
+
values.push(newValue);
|
|
28739
|
+
}
|
|
28740
|
+
}
|
|
28741
|
+
this.props.onChange(values);
|
|
28742
|
+
};
|
|
28743
|
+
render() {
|
|
28744
|
+
const values = this.props.values || [];
|
|
28745
|
+
const buttons = this.props.buttons.map((button, i) => {
|
|
28746
|
+
const selected = values.indexOf(button.value) >= 0;
|
|
28747
|
+
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
28748
|
+
title: button.title,
|
|
28749
|
+
type: "button",
|
|
28750
|
+
id: "" + i,
|
|
28751
|
+
key: "" + i,
|
|
28752
|
+
ref: "button" + i,
|
|
28753
|
+
className: aphrodite.css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
28754
|
+
onClick: () => this.toggleSelect(button.value)
|
|
28755
|
+
}, button.content || "" + button.value);
|
|
28756
|
+
});
|
|
28757
|
+
const outerStyle = {
|
|
28758
|
+
display: "inline-block"
|
|
28759
|
+
};
|
|
28760
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28761
|
+
style: outerStyle
|
|
28762
|
+
}, buttons);
|
|
28763
|
+
}
|
|
28764
|
+
}
|
|
28765
|
+
const styles$h = aphrodite.StyleSheet.create({
|
|
28766
|
+
buttonStyle: {
|
|
28767
|
+
backgroundColor: "white",
|
|
28768
|
+
border: "1px solid #ccc",
|
|
28769
|
+
borderLeft: "0",
|
|
28770
|
+
cursor: "pointer",
|
|
28771
|
+
margin: "0",
|
|
28772
|
+
padding: "5px 10px",
|
|
28773
|
+
position: "relative",
|
|
28774
|
+
// for hover
|
|
28775
|
+
|
|
28776
|
+
":first-child": {
|
|
28777
|
+
borderLeft: "1px solid #ccc",
|
|
28778
|
+
borderTopLeftRadius: "3px",
|
|
28779
|
+
borderBottomLeftRadius: "3px"
|
|
28780
|
+
},
|
|
28781
|
+
":last-child": {
|
|
28782
|
+
borderRight: "1px solid #ccc",
|
|
28783
|
+
borderTopRightRadius: "3px",
|
|
28784
|
+
borderBottomRightRadius: "3px"
|
|
28785
|
+
},
|
|
28786
|
+
":hover": {
|
|
28787
|
+
backgroundColor: "#ccc"
|
|
28788
|
+
},
|
|
28789
|
+
":focus": {
|
|
28790
|
+
zIndex: 2
|
|
28791
|
+
}
|
|
28792
|
+
},
|
|
28793
|
+
selectedStyle: {
|
|
28794
|
+
backgroundColor: "#ddd"
|
|
28795
|
+
}
|
|
28796
|
+
});
|
|
28797
|
+
|
|
28798
|
+
const {
|
|
28799
|
+
firstNumericalParse,
|
|
28800
|
+
captureScratchpadTouchStart
|
|
28801
|
+
} = Util;
|
|
28802
|
+
const toNumericString = KhanMath.toNumericString;
|
|
28803
|
+
const getNumericFormat = KhanMath.getNumericFormat;
|
|
28804
|
+
|
|
28805
|
+
/* An input box that accepts only numeric strings
|
|
28806
|
+
*
|
|
28807
|
+
* Calls onChange(value, format) for valid numbers.
|
|
28808
|
+
* Reverts to the current value onBlur or on [ENTER],
|
|
28809
|
+
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
28810
|
+
* Accepts empty input and sends it to onChange as null
|
|
28811
|
+
* if no numeric placeholder is set.
|
|
28812
|
+
* If given a checkValidity function, will turn
|
|
28813
|
+
* the background/outline red when invalid
|
|
28814
|
+
* If useArrowKeys is set to true, up/down arrows will
|
|
28815
|
+
* increment/decrement integers
|
|
28816
|
+
* Optionally takes a size ("mini", "small", "normal")
|
|
28817
|
+
*/
|
|
28818
|
+
class NumberInput extends React__namespace.Component {
|
|
28819
|
+
static propTypes = {
|
|
28820
|
+
value: PropTypes__default["default"].number,
|
|
28821
|
+
format: PropTypes__default["default"].string,
|
|
28822
|
+
placeholder: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].number]),
|
|
28823
|
+
onChange: PropTypes__default["default"].func.isRequired,
|
|
28824
|
+
onFormatChange: PropTypes__default["default"].func,
|
|
28825
|
+
checkValidity: PropTypes__default["default"].func,
|
|
28826
|
+
size: PropTypes__default["default"].string,
|
|
28827
|
+
label: PropTypes__default["default"].oneOf(["put your labels outside your inputs!"])
|
|
28828
|
+
};
|
|
28829
|
+
static defaultProps = {
|
|
28830
|
+
value: null,
|
|
28831
|
+
placeholder: null,
|
|
28832
|
+
format: null,
|
|
28833
|
+
onFormatChange: () => null,
|
|
28834
|
+
checkValidity: () => true,
|
|
28835
|
+
useArrowKeys: false
|
|
28836
|
+
};
|
|
28837
|
+
state = {
|
|
28838
|
+
format: this.props.format
|
|
28839
|
+
};
|
|
28840
|
+
render() {
|
|
28841
|
+
let classes = classNames__default["default"]({
|
|
28842
|
+
"number-input": true,
|
|
28843
|
+
"invalid-input": !this._checkValidity(this.props.value),
|
|
28844
|
+
mini: this.props.size === "mini",
|
|
28845
|
+
small: this.props.size === "small",
|
|
28846
|
+
normal: this.props.size === "normal"
|
|
28847
|
+
});
|
|
28848
|
+
if (this.props.className != null) {
|
|
28849
|
+
classes = classes + " " + this.props.className;
|
|
28850
|
+
}
|
|
28851
|
+
const {
|
|
28852
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28853
|
+
onFormatChange,
|
|
28854
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28855
|
+
checkValidity,
|
|
28856
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28857
|
+
useArrowKeys,
|
|
28858
|
+
...restProps
|
|
28859
|
+
} = this.props;
|
|
28860
|
+
return /*#__PURE__*/React__namespace.createElement("input", _extends({}, restProps, {
|
|
28861
|
+
className: classes,
|
|
28862
|
+
type: "text"
|
|
28863
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28864
|
+
,
|
|
28865
|
+
ref: "input",
|
|
28866
|
+
onChange: this._handleChange,
|
|
28867
|
+
onFocus: this._handleFocus,
|
|
28868
|
+
onBlur: this._handleBlur,
|
|
28869
|
+
onKeyPress: this._handleBlur,
|
|
28870
|
+
onKeyDown: this._onKeyDown
|
|
28871
|
+
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
28872
|
+
,
|
|
28873
|
+
onTouchStart: captureScratchpadTouchStart,
|
|
28874
|
+
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
28875
|
+
value: undefined
|
|
28876
|
+
}));
|
|
28877
|
+
}
|
|
28878
|
+
componentDidUpdate(prevProps) {
|
|
28879
|
+
if (!kmath.number.equal(this.getValue(), this.props.value)) {
|
|
28880
|
+
this._setValue(this.props.value, this.state.format);
|
|
28881
|
+
}
|
|
28882
|
+
}
|
|
28883
|
+
|
|
28884
|
+
/* Return the current "value" of this input
|
|
28885
|
+
* If empty, it returns the placeholder (if it is a number) or null
|
|
28886
|
+
*/
|
|
28887
|
+
getValue = () => {
|
|
28888
|
+
return this.parseInputValue(
|
|
28889
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28890
|
+
ReactDOM__default["default"].findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
28891
|
+
);
|
|
28892
|
+
};
|
|
28893
|
+
|
|
28894
|
+
/* Return the current string value of this input */
|
|
28895
|
+
getStringValue = () => {
|
|
28896
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28897
|
+
return ReactDOM__default["default"].findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
28898
|
+
};
|
|
28899
|
+
|
|
28900
|
+
parseInputValue = value => {
|
|
28901
|
+
if (value === "") {
|
|
28902
|
+
const placeholder = this.props.placeholder;
|
|
28903
|
+
return ___default["default"].isFinite(placeholder) ? +placeholder : null;
|
|
28904
|
+
}
|
|
28905
|
+
const result = firstNumericalParse(value);
|
|
28906
|
+
return ___default["default"].isFinite(result) ? result : this.props.value;
|
|
28907
|
+
};
|
|
28908
|
+
|
|
28909
|
+
/* Set text input focus to this input */
|
|
28910
|
+
focus = () => {
|
|
28911
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28912
|
+
ReactDOM__default["default"].findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
28913
|
+
this._handleFocus();
|
|
28914
|
+
};
|
|
28915
|
+
blur = () => {
|
|
28916
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
28917
|
+
ReactDOM__default["default"].findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
28918
|
+
this._handleBlur();
|
|
28919
|
+
};
|
|
28920
|
+
setSelectionRange = (selectionStart, selectionEnd) => {
|
|
28921
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
28922
|
+
ReactDOM__default["default"].findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
28923
|
+
};
|
|
28924
|
+
getSelectionStart = () => {
|
|
28925
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
28926
|
+
return ReactDOM__default["default"].findDOMNode(this).selectionStart;
|
|
28927
|
+
};
|
|
28928
|
+
getSelectionEnd = () => {
|
|
28929
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
28930
|
+
return ReactDOM__default["default"].findDOMNode(this).selectionEnd;
|
|
28931
|
+
};
|
|
28932
|
+
_checkValidity = value => {
|
|
28933
|
+
if (value == null) {
|
|
28934
|
+
return true;
|
|
28935
|
+
}
|
|
28936
|
+
const val = firstNumericalParse(value);
|
|
28937
|
+
const checkValidity = this.props.checkValidity;
|
|
28938
|
+
return ___default["default"].isFinite(val) && checkValidity(val);
|
|
28939
|
+
};
|
|
28940
|
+
_handleChange = e => {
|
|
28941
|
+
const text = e.target.value;
|
|
28942
|
+
const value = this.parseInputValue(text);
|
|
28943
|
+
const format = getNumericFormat(text);
|
|
28944
|
+
this.props.onChange(value);
|
|
28945
|
+
if (format) {
|
|
28946
|
+
this.props.onFormatChange(value, format);
|
|
28947
|
+
this.setState({
|
|
28948
|
+
format: format
|
|
28949
|
+
});
|
|
28950
|
+
}
|
|
28951
|
+
};
|
|
28952
|
+
_handleFocus = () => {
|
|
28953
|
+
if (this.props.onFocus) {
|
|
28954
|
+
this.props.onFocus();
|
|
28955
|
+
}
|
|
28956
|
+
};
|
|
28957
|
+
_handleBlur = e => {
|
|
28958
|
+
// Only continue on blur or "enter"
|
|
28959
|
+
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
28960
|
+
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
28961
|
+
return;
|
|
28962
|
+
}
|
|
28963
|
+
this._setValue(this.props.value, this.state.format);
|
|
28964
|
+
if (this.props.onBlur) {
|
|
28965
|
+
this.props.onBlur();
|
|
28966
|
+
}
|
|
28967
|
+
};
|
|
28968
|
+
_onKeyDown = e => {
|
|
28969
|
+
if (this.props.onKeyDown) {
|
|
28970
|
+
this.props.onKeyDown(e);
|
|
28971
|
+
}
|
|
28972
|
+
if (!this.props.useArrowKeys || !___default["default"].contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
28973
|
+
return;
|
|
28974
|
+
}
|
|
28975
|
+
let val = this.getValue();
|
|
28976
|
+
if (val !== Math.floor(val)) {
|
|
28977
|
+
return; // bail if not an integer
|
|
28978
|
+
}
|
|
28979
|
+
|
|
28980
|
+
if (e.key === "ArrowUp") {
|
|
28981
|
+
val = val + 1;
|
|
28982
|
+
} else if (e.key === "ArrowDown") {
|
|
28983
|
+
val = val - 1;
|
|
28984
|
+
}
|
|
28985
|
+
if (this._checkValidity(val)) {
|
|
28986
|
+
this.props.onChange(val);
|
|
28987
|
+
}
|
|
28988
|
+
};
|
|
28989
|
+
_setValue = (val, format) => {
|
|
28990
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28991
|
+
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
28992
|
+
$__default["default"](ReactDOM__default["default"].findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
28993
|
+
};
|
|
28994
|
+
}
|
|
28995
|
+
|
|
28996
|
+
/* eslint-disable @babel/no-invalid-this */
|
|
28997
|
+
|
|
28998
|
+
/* A checkbox that syncs its value to props using the
|
|
28999
|
+
* renderer's onChange method, and gets the prop name
|
|
29000
|
+
* dynamically from its props list
|
|
29001
|
+
*/
|
|
29002
|
+
const PropCheckBox = createReactClass__default["default"]({
|
|
29003
|
+
displayName: "PropCheckBox",
|
|
29004
|
+
propTypes: {
|
|
29005
|
+
labelAlignment: PropTypes__default["default"].oneOf(["left", "right"])
|
|
29006
|
+
},
|
|
29007
|
+
DEFAULT_PROPS: {
|
|
29008
|
+
label: null,
|
|
29009
|
+
onChange: null,
|
|
29010
|
+
labelAlignment: "left"
|
|
29011
|
+
},
|
|
29012
|
+
getDefaultProps: function () {
|
|
29013
|
+
return this.DEFAULT_PROPS;
|
|
29014
|
+
},
|
|
29015
|
+
propName: function () {
|
|
29016
|
+
const propName = ___default["default"].find(___default["default"].keys(this.props), function (localPropName) {
|
|
29017
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
29018
|
+
return !___default["default"].has(this.DEFAULT_PROPS, localPropName);
|
|
29019
|
+
}, this);
|
|
29020
|
+
if (!propName) {
|
|
29021
|
+
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
29022
|
+
}
|
|
29023
|
+
return propName;
|
|
29024
|
+
},
|
|
29025
|
+
_labelAlignLeft: function () {
|
|
29026
|
+
return this.props.labelAlignment === "left";
|
|
29027
|
+
},
|
|
29028
|
+
render: function () {
|
|
29029
|
+
const propName = this.propName();
|
|
29030
|
+
return /*#__PURE__*/React__namespace.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React__namespace.createElement("input", {
|
|
29031
|
+
type: "checkbox",
|
|
29032
|
+
checked: this.props[propName],
|
|
29033
|
+
onChange: this.toggle
|
|
29034
|
+
}), !this._labelAlignLeft() && this.props.label);
|
|
29035
|
+
},
|
|
29036
|
+
toggle: function () {
|
|
29037
|
+
const propName = this.propName();
|
|
29038
|
+
const changes = {};
|
|
29039
|
+
changes[propName] = !this.props[propName];
|
|
29040
|
+
this.props.onChange(changes);
|
|
29041
|
+
}
|
|
29042
|
+
});
|
|
29043
|
+
|
|
29044
|
+
const truth = () => true;
|
|
29045
|
+
|
|
29046
|
+
/* A minor abstraction on top of NumberInput for ranges
|
|
29047
|
+
*
|
|
29048
|
+
*/
|
|
29049
|
+
class RangeInput extends React__namespace.Component {
|
|
29050
|
+
static propTypes = {
|
|
29051
|
+
value: PropTypes__default["default"].array.isRequired,
|
|
29052
|
+
onChange: PropTypes__default["default"].func.isRequired,
|
|
29053
|
+
placeholder: PropTypes__default["default"].array,
|
|
29054
|
+
checkValidity: PropTypes__default["default"].func
|
|
29055
|
+
};
|
|
29056
|
+
static defaultProps = {
|
|
29057
|
+
placeholder: [null, null]
|
|
29058
|
+
};
|
|
29059
|
+
render() {
|
|
29060
|
+
const value = this.props.value;
|
|
29061
|
+
const checkValidity = this.props.checkValidity || truth;
|
|
29062
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
29063
|
+
className: "range-input"
|
|
29064
|
+
}, /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
29065
|
+
value: value[0],
|
|
29066
|
+
checkValidity: val => checkValidity([val, value[1]])
|
|
29067
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
29068
|
+
,
|
|
29069
|
+
onChange: this.onChange.bind(this, 0),
|
|
29070
|
+
placeholder: this.props.placeholder[0]
|
|
29071
|
+
})), /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
29072
|
+
value: value[1],
|
|
29073
|
+
checkValidity: val => checkValidity([value[0], val])
|
|
29074
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
29075
|
+
,
|
|
29076
|
+
onChange: this.onChange.bind(this, 1),
|
|
29077
|
+
placeholder: this.props.placeholder[1]
|
|
29078
|
+
})));
|
|
29079
|
+
}
|
|
29080
|
+
onChange = (i, newVal) => {
|
|
29081
|
+
const value = this.props.value;
|
|
29082
|
+
if (i === 0) {
|
|
29083
|
+
this.props.onChange([newVal, value[1]]);
|
|
29084
|
+
} else {
|
|
29085
|
+
this.props.onChange([value[0], newVal]);
|
|
29086
|
+
}
|
|
29087
|
+
};
|
|
29088
|
+
}
|
|
29089
|
+
|
|
29090
|
+
var components = /*#__PURE__*/Object.freeze({
|
|
29091
|
+
__proto__: null,
|
|
29092
|
+
ButtonGroup: ButtonGroup,
|
|
29093
|
+
Graph: Graph,
|
|
29094
|
+
Graphie: Graphie,
|
|
29095
|
+
HUD: HUD,
|
|
29096
|
+
Icon: Icon,
|
|
29097
|
+
InfoTip: InfoTip,
|
|
29098
|
+
InlineIcon: InlineIcon,
|
|
29099
|
+
MathInput: MathInput,
|
|
29100
|
+
MultiButtonGroup: MultiButtonGroup,
|
|
29101
|
+
NumberInput: NumberInput,
|
|
29102
|
+
PropCheckBox: PropCheckBox,
|
|
29103
|
+
RangeInput: RangeInput,
|
|
29104
|
+
SvgImage: SvgImage,
|
|
29105
|
+
TextInput: TextInput,
|
|
29106
|
+
TextListEditor: TextListEditor
|
|
29107
|
+
});
|
|
29108
|
+
|
|
29109
|
+
/**
|
|
29110
|
+
* If a graphie URL is provided in `backgroundImage`, will return the rendered graphie background.
|
|
29111
|
+
* Otherwise, returns `null`.
|
|
29112
|
+
*/
|
|
29113
|
+
const getLegacyGrid = (box, backgroundImage) => {
|
|
29114
|
+
const {
|
|
29115
|
+
url,
|
|
29116
|
+
width,
|
|
29117
|
+
height
|
|
29118
|
+
} = backgroundImage ?? {};
|
|
29119
|
+
if (url && typeof url === "string") {
|
|
29120
|
+
const scale = box[0] / interactiveSizes$1.defaultBoxSize;
|
|
29121
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29122
|
+
style: {
|
|
29123
|
+
position: "absolute",
|
|
29124
|
+
bottom: 0,
|
|
29125
|
+
left: 0
|
|
29126
|
+
}
|
|
29127
|
+
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref => {
|
|
29128
|
+
let {
|
|
29129
|
+
setAssetStatus
|
|
29130
|
+
} = _ref;
|
|
29131
|
+
return /*#__PURE__*/React__namespace.createElement(SvgImage, {
|
|
29132
|
+
src: url,
|
|
29133
|
+
width: width,
|
|
29134
|
+
height: height,
|
|
29135
|
+
scale: scale,
|
|
29136
|
+
responsive: false,
|
|
29137
|
+
setAssetStatus: setAssetStatus,
|
|
29138
|
+
alt: ""
|
|
29139
|
+
});
|
|
29140
|
+
}));
|
|
29141
|
+
}
|
|
29142
|
+
return null;
|
|
29143
|
+
};
|
|
29144
|
+
|
|
29145
|
+
const renderGraph = props => {
|
|
29146
|
+
const {
|
|
29147
|
+
graph,
|
|
29148
|
+
...rest
|
|
29149
|
+
} = props;
|
|
29150
|
+
switch (graph.type) {
|
|
29151
|
+
case "segment":
|
|
29152
|
+
return /*#__PURE__*/React__namespace.createElement(SegmentGraph, _extends({}, rest, {
|
|
29153
|
+
graph: graph,
|
|
29154
|
+
onGraphChange: props.onGraphChange
|
|
29155
|
+
}));
|
|
29156
|
+
}
|
|
29157
|
+
};
|
|
29158
|
+
const MafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
29159
|
+
// Storing the gradable state in a ref so that it can be updated without
|
|
29160
|
+
// causing a re-render.
|
|
29161
|
+
const graphRef = React__namespace.useRef(props.graph);
|
|
29162
|
+
const handleGraphUpdate = callback => {
|
|
29163
|
+
graphRef.current = callback(graphRef.current);
|
|
29164
|
+
};
|
|
29165
|
+
React__namespace.useImperativeHandle(ref, () => ({
|
|
29166
|
+
getUserInput: () => graphRef.current
|
|
29167
|
+
}));
|
|
29168
|
+
const [width, height] = getInteractiveBoxFromSizeClass(props.containerSizeClass);
|
|
29169
|
+
const legacyGrid = getLegacyGrid([width, height], props.backgroundImage);
|
|
29170
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29171
|
+
style: {
|
|
29172
|
+
width: props.backgroundImage?.width ?? width,
|
|
29173
|
+
height: props.backgroundImage?.height ?? height,
|
|
29174
|
+
position: "relative"
|
|
29175
|
+
}
|
|
29176
|
+
}, legacyGrid, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29177
|
+
style: {
|
|
29178
|
+
position: "absolute",
|
|
29179
|
+
bottom: 0,
|
|
29180
|
+
left: 0
|
|
29181
|
+
}
|
|
29182
|
+
}, /*#__PURE__*/React__namespace.createElement(mafs.Mafs, {
|
|
29183
|
+
viewBox: {
|
|
29184
|
+
x: props.range[0],
|
|
29185
|
+
y: props.range[1],
|
|
29186
|
+
padding: 0
|
|
29187
|
+
},
|
|
29188
|
+
pan: false,
|
|
29189
|
+
zoom: false,
|
|
29190
|
+
width: width,
|
|
29191
|
+
height: height
|
|
29192
|
+
}, !!legacyGrid && /*#__PURE__*/React__namespace.createElement(Grid, props), renderGraph({
|
|
29193
|
+
...props,
|
|
29194
|
+
onGraphChange: handleGraphUpdate
|
|
29195
|
+
}))));
|
|
29196
|
+
});
|
|
29197
|
+
|
|
28329
29198
|
const {
|
|
28330
29199
|
DeprecationMixin
|
|
28331
29200
|
} = Util;
|
|
@@ -28402,6 +29271,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
28402
29271
|
type: "linear"
|
|
28403
29272
|
}
|
|
28404
29273
|
};
|
|
29274
|
+
mafsRef = /*#__PURE__*/React__namespace.createRef();
|
|
28405
29275
|
state = {
|
|
28406
29276
|
shouldShowInstructions: _getShouldShowInstructions(this.props)
|
|
28407
29277
|
};
|
|
@@ -28411,9 +29281,11 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
28411
29281
|
DeprecationMixin.UNSAFE_componentWillMount.call(this);
|
|
28412
29282
|
}
|
|
28413
29283
|
componentDidMount() {
|
|
28414
|
-
|
|
28415
|
-
|
|
28416
|
-
|
|
29284
|
+
if (this.refs.graph) {
|
|
29285
|
+
// eslint-disable-next-line react/no-string-refs
|
|
29286
|
+
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
|
|
29287
|
+
this.setGraphie(this.refs.graph.graphie());
|
|
29288
|
+
}
|
|
28417
29289
|
}
|
|
28418
29290
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
28419
29291
|
if (this.isClickToAddPoints() !== this.isClickToAddPoints(nextProps)) {
|
|
@@ -29510,16 +30382,22 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29510
30382
|
graph: graph
|
|
29511
30383
|
});
|
|
29512
30384
|
};
|
|
29513
|
-
getUserInput = () =>
|
|
29514
|
-
|
|
29515
|
-
};
|
|
29516
|
-
simpleValidate = rubric => {
|
|
29517
|
-
return InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
29518
|
-
};
|
|
30385
|
+
getUserInput = () => this.mafsRef.current?.getUserInput?.() ?? InteractiveGraph.getUserInputFromProps(this.props);
|
|
30386
|
+
simpleValidate = rubric => InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
29519
30387
|
focus = $__default["default"].noop;
|
|
30388
|
+
|
|
30389
|
+
// const segment: boolean = useFeatureIsOn("mafs-segment-graph");
|
|
30390
|
+
// <Renderer apiOptions={{flags: {mafs: {segment}}}}
|
|
29520
30391
|
render() {
|
|
30392
|
+
// Mafs shim
|
|
30393
|
+
if (this.props.apiOptions?.flags?.["mafs"]?.[this.props.graph.type]) {
|
|
30394
|
+
return /*#__PURE__*/React__namespace.createElement(MafsGraph, _extends({}, this.props, {
|
|
30395
|
+
ref: this.mafsRef
|
|
30396
|
+
}));
|
|
30397
|
+
}
|
|
29521
30398
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
29522
30399
|
let instructions;
|
|
30400
|
+
// isClickToAddPoints() only applies to points and polygons
|
|
29523
30401
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
29524
30402
|
if (this.props.graph.type === "point") {
|
|
29525
30403
|
instructions = i18n__namespace._("Click to add points");
|
|
@@ -30804,7 +31682,7 @@ var globalConstants = /*#__PURE__*/Object.freeze({
|
|
|
30804
31682
|
pureLgMax: pureLgMax
|
|
30805
31683
|
});
|
|
30806
31684
|
|
|
30807
|
-
const colors
|
|
31685
|
+
const colors = {
|
|
30808
31686
|
white: "#FFFFFF",
|
|
30809
31687
|
gray98: "#FAFAFA",
|
|
30810
31688
|
gray97: "#F6F7F7",
|
|
@@ -30864,7 +31742,7 @@ const colors$1 = {
|
|
|
30864
31742
|
};
|
|
30865
31743
|
const borderRadius = 4;
|
|
30866
31744
|
const breadcrumbStyles = {
|
|
30867
|
-
color: colors
|
|
31745
|
+
color: colors.breadcrumbs,
|
|
30868
31746
|
fontFamily: "inherit",
|
|
30869
31747
|
fontSize: 15,
|
|
30870
31748
|
fontWeight: "bold",
|
|
@@ -30934,14 +31812,14 @@ const typography = {
|
|
|
30934
31812
|
},
|
|
30935
31813
|
// For callouts
|
|
30936
31814
|
smallHeading: {
|
|
30937
|
-
color: colors
|
|
31815
|
+
color: colors.gray25,
|
|
30938
31816
|
fontFamily: "inherit",
|
|
30939
31817
|
fontSize: 17,
|
|
30940
31818
|
fontWeight: "bold",
|
|
30941
31819
|
lineHeight: "23px"
|
|
30942
31820
|
},
|
|
30943
31821
|
smallHeadingMobile: {
|
|
30944
|
-
color: colors
|
|
31822
|
+
color: colors.gray25,
|
|
30945
31823
|
fontFamily: "inherit",
|
|
30946
31824
|
fontSize: 15,
|
|
30947
31825
|
fontWeight: "bold",
|
|
@@ -30949,7 +31827,7 @@ const typography = {
|
|
|
30949
31827
|
},
|
|
30950
31828
|
// Accent headings
|
|
30951
31829
|
accentHeading: {
|
|
30952
|
-
color: colors
|
|
31830
|
+
color: colors.gray68,
|
|
30953
31831
|
fontFamily: "inherit",
|
|
30954
31832
|
fontSize: 15,
|
|
30955
31833
|
fontWeight: "bold",
|
|
@@ -31057,7 +31935,7 @@ const typography = {
|
|
|
31057
31935
|
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
31058
31936
|
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
31059
31937
|
wonderBlocksTitle: {
|
|
31060
|
-
color: colors
|
|
31938
|
+
color: colors.white,
|
|
31061
31939
|
fontWeight: 900,
|
|
31062
31940
|
// "Black" weight
|
|
31063
31941
|
fontSize: 28,
|
|
@@ -31079,7 +31957,7 @@ const typography = {
|
|
|
31079
31957
|
|
|
31080
31958
|
var globalStyles = /*#__PURE__*/Object.freeze({
|
|
31081
31959
|
__proto__: null,
|
|
31082
|
-
colors: colors
|
|
31960
|
+
colors: colors,
|
|
31083
31961
|
borderRadius: borderRadius,
|
|
31084
31962
|
fonts: fonts,
|
|
31085
31963
|
typography: typography
|
|
@@ -31144,7 +32022,7 @@ const HideAnswersToggle = props => {
|
|
|
31144
32022
|
const switchId = idFactory.get("hide-answers-toggle");
|
|
31145
32023
|
const labelId = idFactory.get("hide-answers-label");
|
|
31146
32024
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31147
|
-
style: styles$
|
|
32025
|
+
style: styles$g.switchWrapper
|
|
31148
32026
|
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
31149
32027
|
id: switchId,
|
|
31150
32028
|
checked: props.areAnswersHidden,
|
|
@@ -31156,7 +32034,7 @@ const HideAnswersToggle = props => {
|
|
|
31156
32034
|
tag: "label"
|
|
31157
32035
|
}, strings.hideAnswersToggleLabel));
|
|
31158
32036
|
};
|
|
31159
|
-
const styles$
|
|
32037
|
+
const styles$g = aphrodite.StyleSheet.create({
|
|
31160
32038
|
switchWrapper: {
|
|
31161
32039
|
display: "flex",
|
|
31162
32040
|
flexDirection: "row",
|
|
@@ -31211,14 +32089,14 @@ const AnswerPill = props => {
|
|
|
31211
32089
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31212
32090
|
onClick: correct ? undefined : onClick,
|
|
31213
32091
|
ref: ref,
|
|
31214
|
-
style: [style, popperStyle, styles$
|
|
32092
|
+
style: [style, popperStyle, styles$f.pill, correct && styles$f.correct, incorrect && styles$f.incorrect, (focused || hovered) && BringToFront]
|
|
31215
32093
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31216
32094
|
content: answerString,
|
|
31217
32095
|
inline: true
|
|
31218
32096
|
}));
|
|
31219
32097
|
});
|
|
31220
32098
|
};
|
|
31221
|
-
const styles$
|
|
32099
|
+
const styles$f = aphrodite.StyleSheet.create({
|
|
31222
32100
|
correct: {
|
|
31223
32101
|
// WB green darkened by 18%
|
|
31224
32102
|
backgroundColor: "#00880b"
|
|
@@ -31272,25 +32150,25 @@ class Marker extends React__namespace.Component {
|
|
|
31272
32150
|
icon: iconNull
|
|
31273
32151
|
};
|
|
31274
32152
|
if (showCorrectness) {
|
|
31275
|
-
iconStyles = [styles$
|
|
32153
|
+
iconStyles = [styles$e.markerGraded, showCorrectness === "correct" ? styles$e.markerCorrect : styles$e.markerIncorrect, isOpen && styles$e.markerSelected];
|
|
31276
32154
|
args = {
|
|
31277
32155
|
...args,
|
|
31278
32156
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31279
32157
|
};
|
|
31280
32158
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31281
|
-
iconStyles = [styles$
|
|
32159
|
+
iconStyles = [styles$e.markerFilled, isOpen && styles$e.markerSelected];
|
|
31282
32160
|
} else if (isOpen) {
|
|
31283
|
-
iconStyles = [styles$
|
|
32161
|
+
iconStyles = [styles$e.markerSelected];
|
|
31284
32162
|
args = {
|
|
31285
32163
|
...args,
|
|
31286
32164
|
icon: iconChevronDown,
|
|
31287
32165
|
size: 8
|
|
31288
32166
|
};
|
|
31289
32167
|
} else if (showPulsate) {
|
|
31290
|
-
iconStyles = [styles$
|
|
32168
|
+
iconStyles = [styles$e.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$e.markerUnfilledPulsateOnce : showPulsate && styles$e.markerUnfilledPulsateInfinite];
|
|
31291
32169
|
}
|
|
31292
32170
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31293
|
-
style: [styles$
|
|
32171
|
+
style: [styles$e.markerIcon, iconStyles],
|
|
31294
32172
|
ref: node => this._icon = node
|
|
31295
32173
|
}, /*#__PURE__*/React__namespace.createElement(Icon, args));
|
|
31296
32174
|
}
|
|
@@ -31311,7 +32189,7 @@ class Marker extends React__namespace.Component {
|
|
|
31311
32189
|
const markerDisabled = showCorrectness === "correct";
|
|
31312
32190
|
const active = hovered || focused;
|
|
31313
32191
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31314
|
-
style: [styles$
|
|
32192
|
+
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive]
|
|
31315
32193
|
// already translated in: /widgets/graded-group.tsx
|
|
31316
32194
|
,
|
|
31317
32195
|
"aria-label": markerDisabled ? i18n__namespace._("Correct!") : label
|
|
@@ -31326,7 +32204,7 @@ class Marker extends React__namespace.Component {
|
|
|
31326
32204
|
}));
|
|
31327
32205
|
}
|
|
31328
32206
|
}
|
|
31329
|
-
const styles$
|
|
32207
|
+
const styles$e = aphrodite.StyleSheet.create({
|
|
31330
32208
|
marker: {
|
|
31331
32209
|
position: "absolute",
|
|
31332
32210
|
backgroundColor: Color__default["default"].white,
|
|
@@ -31903,13 +32781,13 @@ class LabelImage extends React__namespace.Component {
|
|
|
31903
32781
|
const promptString = isMobile ? multipleAnswers ? i18n__namespace._("Tap each dot on the image to select all answers that apply.") : i18n__namespace._("Tap each dot on the image to select an answer.") : multipleAnswers ? i18n__namespace._("Click each dot on the image to select all answers that apply.") : i18n__namespace._("Click each dot on the image to select an answer.");
|
|
31904
32782
|
const choicesString = i18n__namespace._("Choices:");
|
|
31905
32783
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
31906
|
-
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$
|
|
32784
|
+
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$d.instructions))
|
|
31907
32785
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
31908
|
-
className: aphrodite.css(styles$
|
|
32786
|
+
className: aphrodite.css(styles$d.instructionsCaption)
|
|
31909
32787
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React__namespace.createElement("div", {
|
|
31910
|
-
className: aphrodite.css(styles$
|
|
32788
|
+
className: aphrodite.css(styles$d.instructionsChoices)
|
|
31911
32789
|
}, choices.map((choice, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
31912
|
-
className: aphrodite.css(styles$
|
|
32790
|
+
className: aphrodite.css(styles$d.instructionsChoice),
|
|
31913
32791
|
key: index
|
|
31914
32792
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31915
32793
|
content: choice
|
|
@@ -31926,20 +32804,20 @@ class LabelImage extends React__namespace.Component {
|
|
|
31926
32804
|
activeMarkerIndex
|
|
31927
32805
|
} = this.state;
|
|
31928
32806
|
return /*#__PURE__*/React__namespace.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React__namespace.createElement("div", {
|
|
31929
|
-
className: aphrodite.css(styles$
|
|
32807
|
+
className: aphrodite.css(styles$d.markersCanvas),
|
|
31930
32808
|
style: {
|
|
31931
32809
|
maxWidth: imageWidth,
|
|
31932
32810
|
maxHeight: imageHeight
|
|
31933
32811
|
}
|
|
31934
32812
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
31935
|
-
className: aphrodite.css(styles$
|
|
32813
|
+
className: aphrodite.css(styles$d.imageContainer,
|
|
31936
32814
|
// Ensure image interaction is disabled while answer
|
|
31937
32815
|
// choices popup is visible. This addresses specific
|
|
31938
32816
|
// case where user may click on question image to
|
|
31939
32817
|
// dismiss the popup. If the image is larger in size
|
|
31940
32818
|
// than its rendered in the widget, this would
|
|
31941
32819
|
// result in a zoom of the image.
|
|
31942
|
-
activeMarkerIndex !== -1 && styles$
|
|
32820
|
+
activeMarkerIndex !== -1 && styles$d.imageInteractionDisabled)
|
|
31943
32821
|
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref3 => {
|
|
31944
32822
|
let {
|
|
31945
32823
|
setAssetStatus
|
|
@@ -31965,7 +32843,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
31965
32843
|
}));
|
|
31966
32844
|
}
|
|
31967
32845
|
}
|
|
31968
|
-
const styles$
|
|
32846
|
+
const styles$d = aphrodite.StyleSheet.create({
|
|
31969
32847
|
instructions: {
|
|
31970
32848
|
paddingBottom: 16
|
|
31971
32849
|
},
|
|
@@ -32326,7 +33204,7 @@ class Placeholder extends React__namespace.Component {
|
|
|
32326
33204
|
const {
|
|
32327
33205
|
layout
|
|
32328
33206
|
} = this.props;
|
|
32329
|
-
const className = aphrodite.css(styles$
|
|
33207
|
+
const className = aphrodite.css(styles$c.card, styles$c.placeholder, layout === Layout.HORIZONTAL && styles$c.horizontalCard);
|
|
32330
33208
|
const style = {
|
|
32331
33209
|
width: this.props.width,
|
|
32332
33210
|
height: this.props.height
|
|
@@ -32424,7 +33302,7 @@ class Draggable extends React__namespace.Component {
|
|
|
32424
33302
|
// We need to keep backwards compatbility with rules specified directly
|
|
32425
33303
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
32426
33304
|
// See sortable.less for details.
|
|
32427
|
-
let className = aphrodite.css(styles$
|
|
33305
|
+
let className = aphrodite.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";
|
|
32428
33306
|
if (!includePadding) {
|
|
32429
33307
|
className += " perseus-sortable-draggable-unpadded";
|
|
32430
33308
|
}
|
|
@@ -32724,7 +33602,7 @@ class Sortable extends React__namespace.Component {
|
|
|
32724
33602
|
} = this.props;
|
|
32725
33603
|
// We need to keep backwards compatbility with rules specified directly
|
|
32726
33604
|
// in CSS. See sortable.less for details.
|
|
32727
|
-
const className = aphrodite.css(styles$
|
|
33605
|
+
const className = aphrodite.css(styles$c.sortable) + " perseus-sortable";
|
|
32728
33606
|
const syncWidth = this.props.constraints?.width || layout === Layout.VERTICAL;
|
|
32729
33607
|
const syncHeight = this.props.constraints?.height || layout === Layout.HORIZONTAL;
|
|
32730
33608
|
___default["default"].each(this.state.items, function (item, i, items) {
|
|
@@ -32955,7 +33833,7 @@ class Sortable extends React__namespace.Component {
|
|
|
32955
33833
|
return ___default["default"].pluck(this.state.items, "option");
|
|
32956
33834
|
}
|
|
32957
33835
|
}
|
|
32958
|
-
const styles$
|
|
33836
|
+
const styles$c = aphrodite.StyleSheet.create({
|
|
32959
33837
|
sortable: {
|
|
32960
33838
|
boxSizing: "border-box",
|
|
32961
33839
|
float: "left",
|
|
@@ -33083,23 +33961,23 @@ class Matcher extends React__namespace.Component {
|
|
|
33083
33961
|
};
|
|
33084
33962
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
33085
33963
|
return /*#__PURE__*/React__namespace.createElement("table", {
|
|
33086
|
-
className: aphrodite.css(styles$
|
|
33964
|
+
className: aphrodite.css(styles$b.widget) + " " + HACKY_CSS_CLASSNAME
|
|
33087
33965
|
}, /*#__PURE__*/React__namespace.createElement("tbody", null, showLabels && /*#__PURE__*/React__namespace.createElement("tr", {
|
|
33088
|
-
className: aphrodite.css(styles$
|
|
33966
|
+
className: aphrodite.css(styles$b.row)
|
|
33089
33967
|
}, /*#__PURE__*/React__namespace.createElement("th", {
|
|
33090
|
-
className: aphrodite.css(styles$
|
|
33968
|
+
className: aphrodite.css(styles$b.column, styles$b.columnLabel)
|
|
33091
33969
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33092
33970
|
content: this.props.labels[0] || "...",
|
|
33093
33971
|
linterContext: this.props.linterContext
|
|
33094
33972
|
})), /*#__PURE__*/React__namespace.createElement("th", {
|
|
33095
|
-
className: aphrodite.css(styles$
|
|
33973
|
+
className: aphrodite.css(styles$b.column, styles$b.columnRight, styles$b.columnLabel)
|
|
33096
33974
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33097
33975
|
content: this.props.labels[1] || "...",
|
|
33098
33976
|
linterContext: this.props.linterContext
|
|
33099
33977
|
}))), /*#__PURE__*/React__namespace.createElement("tr", {
|
|
33100
|
-
className: aphrodite.css(styles$
|
|
33978
|
+
className: aphrodite.css(styles$b.row)
|
|
33101
33979
|
}, /*#__PURE__*/React__namespace.createElement("td", {
|
|
33102
|
-
className: aphrodite.css(styles$
|
|
33980
|
+
className: aphrodite.css(styles$b.column)
|
|
33103
33981
|
}, /*#__PURE__*/React__namespace.createElement(Sortable, {
|
|
33104
33982
|
options: left,
|
|
33105
33983
|
layout: Layout.VERTICAL,
|
|
@@ -33114,7 +33992,7 @@ class Matcher extends React__namespace.Component {
|
|
|
33114
33992
|
,
|
|
33115
33993
|
ref: "left"
|
|
33116
33994
|
})), /*#__PURE__*/React__namespace.createElement("td", {
|
|
33117
|
-
className: aphrodite.css(styles$
|
|
33995
|
+
className: aphrodite.css(styles$b.column, styles$b.columnRight)
|
|
33118
33996
|
}, /*#__PURE__*/React__namespace.createElement(Sortable
|
|
33119
33997
|
// @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
|
|
33120
33998
|
, {
|
|
@@ -33200,7 +34078,7 @@ ___default["default"].extend(Matcher, {
|
|
|
33200
34078
|
});
|
|
33201
34079
|
const padding = 5;
|
|
33202
34080
|
const border = "1px solid #444";
|
|
33203
|
-
const styles$
|
|
34081
|
+
const styles$b = aphrodite.StyleSheet.create({
|
|
33204
34082
|
widget: {
|
|
33205
34083
|
paddingTop: padding,
|
|
33206
34084
|
maxWidth: "100%",
|
|
@@ -33233,204 +34111,6 @@ var Matcher$1 = {
|
|
|
33233
34111
|
isLintable: true
|
|
33234
34112
|
};
|
|
33235
34113
|
|
|
33236
|
-
const {
|
|
33237
|
-
firstNumericalParse,
|
|
33238
|
-
captureScratchpadTouchStart
|
|
33239
|
-
} = Util;
|
|
33240
|
-
const toNumericString = KhanMath.toNumericString;
|
|
33241
|
-
const getNumericFormat = KhanMath.getNumericFormat;
|
|
33242
|
-
|
|
33243
|
-
/* An input box that accepts only numeric strings
|
|
33244
|
-
*
|
|
33245
|
-
* Calls onChange(value, format) for valid numbers.
|
|
33246
|
-
* Reverts to the current value onBlur or on [ENTER],
|
|
33247
|
-
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
33248
|
-
* Accepts empty input and sends it to onChange as null
|
|
33249
|
-
* if no numeric placeholder is set.
|
|
33250
|
-
* If given a checkValidity function, will turn
|
|
33251
|
-
* the background/outline red when invalid
|
|
33252
|
-
* If useArrowKeys is set to true, up/down arrows will
|
|
33253
|
-
* increment/decrement integers
|
|
33254
|
-
* Optionally takes a size ("mini", "small", "normal")
|
|
33255
|
-
*/
|
|
33256
|
-
class NumberInput extends React__namespace.Component {
|
|
33257
|
-
static propTypes = {
|
|
33258
|
-
value: PropTypes__default["default"].number,
|
|
33259
|
-
format: PropTypes__default["default"].string,
|
|
33260
|
-
placeholder: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].number]),
|
|
33261
|
-
onChange: PropTypes__default["default"].func.isRequired,
|
|
33262
|
-
onFormatChange: PropTypes__default["default"].func,
|
|
33263
|
-
checkValidity: PropTypes__default["default"].func,
|
|
33264
|
-
size: PropTypes__default["default"].string,
|
|
33265
|
-
label: PropTypes__default["default"].oneOf(["put your labels outside your inputs!"])
|
|
33266
|
-
};
|
|
33267
|
-
static defaultProps = {
|
|
33268
|
-
value: null,
|
|
33269
|
-
placeholder: null,
|
|
33270
|
-
format: null,
|
|
33271
|
-
onFormatChange: () => null,
|
|
33272
|
-
checkValidity: () => true,
|
|
33273
|
-
useArrowKeys: false
|
|
33274
|
-
};
|
|
33275
|
-
state = {
|
|
33276
|
-
format: this.props.format
|
|
33277
|
-
};
|
|
33278
|
-
render() {
|
|
33279
|
-
let classes = classNames__default["default"]({
|
|
33280
|
-
"number-input": true,
|
|
33281
|
-
"invalid-input": !this._checkValidity(this.props.value),
|
|
33282
|
-
mini: this.props.size === "mini",
|
|
33283
|
-
small: this.props.size === "small",
|
|
33284
|
-
normal: this.props.size === "normal"
|
|
33285
|
-
});
|
|
33286
|
-
if (this.props.className != null) {
|
|
33287
|
-
classes = classes + " " + this.props.className;
|
|
33288
|
-
}
|
|
33289
|
-
const {
|
|
33290
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33291
|
-
onFormatChange,
|
|
33292
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33293
|
-
checkValidity,
|
|
33294
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33295
|
-
useArrowKeys,
|
|
33296
|
-
...restProps
|
|
33297
|
-
} = this.props;
|
|
33298
|
-
return /*#__PURE__*/React__namespace.createElement("input", _extends({}, restProps, {
|
|
33299
|
-
className: classes,
|
|
33300
|
-
type: "text"
|
|
33301
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33302
|
-
,
|
|
33303
|
-
ref: "input",
|
|
33304
|
-
onChange: this._handleChange,
|
|
33305
|
-
onFocus: this._handleFocus,
|
|
33306
|
-
onBlur: this._handleBlur,
|
|
33307
|
-
onKeyPress: this._handleBlur,
|
|
33308
|
-
onKeyDown: this._onKeyDown
|
|
33309
|
-
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
33310
|
-
,
|
|
33311
|
-
onTouchStart: captureScratchpadTouchStart,
|
|
33312
|
-
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
33313
|
-
value: undefined
|
|
33314
|
-
}));
|
|
33315
|
-
}
|
|
33316
|
-
componentDidUpdate(prevProps) {
|
|
33317
|
-
if (!kmath.number.equal(this.getValue(), this.props.value)) {
|
|
33318
|
-
this._setValue(this.props.value, this.state.format);
|
|
33319
|
-
}
|
|
33320
|
-
}
|
|
33321
|
-
|
|
33322
|
-
/* Return the current "value" of this input
|
|
33323
|
-
* If empty, it returns the placeholder (if it is a number) or null
|
|
33324
|
-
*/
|
|
33325
|
-
getValue = () => {
|
|
33326
|
-
return this.parseInputValue(
|
|
33327
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33328
|
-
ReactDOM__default["default"].findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
33329
|
-
);
|
|
33330
|
-
};
|
|
33331
|
-
|
|
33332
|
-
/* Return the current string value of this input */
|
|
33333
|
-
getStringValue = () => {
|
|
33334
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33335
|
-
return ReactDOM__default["default"].findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
33336
|
-
};
|
|
33337
|
-
|
|
33338
|
-
parseInputValue = value => {
|
|
33339
|
-
if (value === "") {
|
|
33340
|
-
const placeholder = this.props.placeholder;
|
|
33341
|
-
return ___default["default"].isFinite(placeholder) ? +placeholder : null;
|
|
33342
|
-
}
|
|
33343
|
-
const result = firstNumericalParse(value);
|
|
33344
|
-
return ___default["default"].isFinite(result) ? result : this.props.value;
|
|
33345
|
-
};
|
|
33346
|
-
|
|
33347
|
-
/* Set text input focus to this input */
|
|
33348
|
-
focus = () => {
|
|
33349
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
33350
|
-
ReactDOM__default["default"].findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
33351
|
-
this._handleFocus();
|
|
33352
|
-
};
|
|
33353
|
-
blur = () => {
|
|
33354
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
33355
|
-
ReactDOM__default["default"].findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
33356
|
-
this._handleBlur();
|
|
33357
|
-
};
|
|
33358
|
-
setSelectionRange = (selectionStart, selectionEnd) => {
|
|
33359
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
33360
|
-
ReactDOM__default["default"].findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
33361
|
-
};
|
|
33362
|
-
getSelectionStart = () => {
|
|
33363
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
33364
|
-
return ReactDOM__default["default"].findDOMNode(this).selectionStart;
|
|
33365
|
-
};
|
|
33366
|
-
getSelectionEnd = () => {
|
|
33367
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
33368
|
-
return ReactDOM__default["default"].findDOMNode(this).selectionEnd;
|
|
33369
|
-
};
|
|
33370
|
-
_checkValidity = value => {
|
|
33371
|
-
if (value == null) {
|
|
33372
|
-
return true;
|
|
33373
|
-
}
|
|
33374
|
-
const val = firstNumericalParse(value);
|
|
33375
|
-
const checkValidity = this.props.checkValidity;
|
|
33376
|
-
return ___default["default"].isFinite(val) && checkValidity(val);
|
|
33377
|
-
};
|
|
33378
|
-
_handleChange = e => {
|
|
33379
|
-
const text = e.target.value;
|
|
33380
|
-
const value = this.parseInputValue(text);
|
|
33381
|
-
const format = getNumericFormat(text);
|
|
33382
|
-
this.props.onChange(value);
|
|
33383
|
-
if (format) {
|
|
33384
|
-
this.props.onFormatChange(value, format);
|
|
33385
|
-
this.setState({
|
|
33386
|
-
format: format
|
|
33387
|
-
});
|
|
33388
|
-
}
|
|
33389
|
-
};
|
|
33390
|
-
_handleFocus = () => {
|
|
33391
|
-
if (this.props.onFocus) {
|
|
33392
|
-
this.props.onFocus();
|
|
33393
|
-
}
|
|
33394
|
-
};
|
|
33395
|
-
_handleBlur = e => {
|
|
33396
|
-
// Only continue on blur or "enter"
|
|
33397
|
-
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
33398
|
-
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
33399
|
-
return;
|
|
33400
|
-
}
|
|
33401
|
-
this._setValue(this.props.value, this.state.format);
|
|
33402
|
-
if (this.props.onBlur) {
|
|
33403
|
-
this.props.onBlur();
|
|
33404
|
-
}
|
|
33405
|
-
};
|
|
33406
|
-
_onKeyDown = e => {
|
|
33407
|
-
if (this.props.onKeyDown) {
|
|
33408
|
-
this.props.onKeyDown(e);
|
|
33409
|
-
}
|
|
33410
|
-
if (!this.props.useArrowKeys || !___default["default"].contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
33411
|
-
return;
|
|
33412
|
-
}
|
|
33413
|
-
let val = this.getValue();
|
|
33414
|
-
if (val !== Math.floor(val)) {
|
|
33415
|
-
return; // bail if not an integer
|
|
33416
|
-
}
|
|
33417
|
-
|
|
33418
|
-
if (e.key === "ArrowUp") {
|
|
33419
|
-
val = val + 1;
|
|
33420
|
-
} else if (e.key === "ArrowDown") {
|
|
33421
|
-
val = val - 1;
|
|
33422
|
-
}
|
|
33423
|
-
if (this._checkValidity(val)) {
|
|
33424
|
-
this.props.onChange(val);
|
|
33425
|
-
}
|
|
33426
|
-
};
|
|
33427
|
-
_setValue = (val, format) => {
|
|
33428
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33429
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
33430
|
-
$__default["default"](ReactDOM__default["default"].findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
33431
|
-
};
|
|
33432
|
-
}
|
|
33433
|
-
|
|
33434
34114
|
// Type imports
|
|
33435
34115
|
|
|
33436
34116
|
const {
|
|
@@ -34073,9 +34753,9 @@ function drawText(ctx, item) {
|
|
|
34073
34753
|
if (item.value === null) {
|
|
34074
34754
|
return;
|
|
34075
34755
|
}
|
|
34076
|
-
ctx.fillStyle = styles$
|
|
34077
|
-
ctx.font = styles$
|
|
34078
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
34756
|
+
ctx.fillStyle = styles$a.fgColor;
|
|
34757
|
+
ctx.font = styles$a.font;
|
|
34758
|
+
ctx.fillText(item.value, item.pos[0] - styles$a.fontSizePx / 2 + 1, item.pos[1] + styles$a.fontSizePx / 2);
|
|
34079
34759
|
}
|
|
34080
34760
|
|
|
34081
34761
|
/**
|
|
@@ -34096,16 +34776,16 @@ function drawText(ctx, item) {
|
|
|
34096
34776
|
function drawDoubleLine(ctx, item) {
|
|
34097
34777
|
// Outer line that forms both of the bond lines.
|
|
34098
34778
|
let path = new Path2D();
|
|
34099
|
-
ctx.lineWidth = 5 * styles$
|
|
34100
|
-
ctx.strokeStyle = styles$
|
|
34779
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34780
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34101
34781
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34102
34782
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34103
34783
|
ctx.stroke(path);
|
|
34104
34784
|
|
|
34105
34785
|
// Inner white line that separates the two bond lines.
|
|
34106
34786
|
path = new Path2D();
|
|
34107
|
-
ctx.lineWidth = 3 * styles$
|
|
34108
|
-
ctx.strokeStyle = styles$
|
|
34787
|
+
ctx.lineWidth = 3 * styles$a.lineWidth;
|
|
34788
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34109
34789
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34110
34790
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34111
34791
|
ctx.stroke(path);
|
|
@@ -34132,16 +34812,16 @@ function drawTripleLine(ctx, item) {
|
|
|
34132
34812
|
|
|
34133
34813
|
// Outer line that will form the two outer bond lines.
|
|
34134
34814
|
let path = new Path2D();
|
|
34135
|
-
ctx.lineWidth = 7 * styles$
|
|
34136
|
-
ctx.strokeStyle = styles$
|
|
34815
|
+
ctx.lineWidth = 7 * styles$a.lineWidth;
|
|
34816
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34137
34817
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34138
34818
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34139
34819
|
ctx.stroke(path);
|
|
34140
34820
|
|
|
34141
34821
|
// Middle white line that separates the bonds
|
|
34142
34822
|
path = new Path2D();
|
|
34143
|
-
ctx.lineWidth = 5 * styles$
|
|
34144
|
-
ctx.strokeStyle = styles$
|
|
34823
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34824
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34145
34825
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34146
34826
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34147
34827
|
ctx.stroke(path);
|
|
@@ -34163,8 +34843,8 @@ function drawTripleLine(ctx, item) {
|
|
|
34163
34843
|
*/
|
|
34164
34844
|
function drawLine(ctx, item) {
|
|
34165
34845
|
const path = new Path2D();
|
|
34166
|
-
ctx.lineWidth = styles$
|
|
34167
|
-
ctx.strokeStyle = styles$
|
|
34846
|
+
ctx.lineWidth = styles$a.lineWidth;
|
|
34847
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34168
34848
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34169
34849
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34170
34850
|
ctx.stroke(path);
|
|
@@ -34216,7 +34896,7 @@ function compareElements(item0, item1) {
|
|
|
34216
34896
|
function draw(ctx, items) {
|
|
34217
34897
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
34218
34898
|
}
|
|
34219
|
-
const styles$
|
|
34899
|
+
const styles$a = {
|
|
34220
34900
|
bgColor: "rgb(255, 255, 255)",
|
|
34221
34901
|
fgColor: "rgb(0, 0, 0)",
|
|
34222
34902
|
fontSizePx: 12,
|
|
@@ -36780,7 +37460,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
36780
37460
|
const rects = this.state.cachedHighlightRects;
|
|
36781
37461
|
return /*#__PURE__*/React__namespace.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
36782
37462
|
key: index,
|
|
36783
|
-
className: aphrodite.css(styles$
|
|
37463
|
+
className: aphrodite.css(styles$9.highlightRect),
|
|
36784
37464
|
style: {
|
|
36785
37465
|
// NOTE(mdr): We apply `position: absolute` here
|
|
36786
37466
|
// rather than in Aphrodite styles, because
|
|
@@ -36799,7 +37479,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
36799
37479
|
})));
|
|
36800
37480
|
}
|
|
36801
37481
|
}
|
|
36802
|
-
const styles$
|
|
37482
|
+
const styles$9 = aphrodite.StyleSheet.create({
|
|
36803
37483
|
highlightRect: {
|
|
36804
37484
|
background: "#fffabe" // highlighter yellow :)
|
|
36805
37485
|
}
|
|
@@ -36880,7 +37560,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
36880
37560
|
// TooltipContent wouldn't let me overwrite
|
|
36881
37561
|
// user-select and onClick
|
|
36882
37562
|
const content = /*#__PURE__*/React__namespace.createElement("div", {
|
|
36883
|
-
className: aphrodite.css(styles$
|
|
37563
|
+
className: aphrodite.css(styles$8.tooltipLabel),
|
|
36884
37564
|
onClick: this.props.onClick
|
|
36885
37565
|
}, this.props.label);
|
|
36886
37566
|
const style = {
|
|
@@ -36900,7 +37580,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
36900
37580
|
}, /*#__PURE__*/React__namespace.createElement("div", null)));
|
|
36901
37581
|
}
|
|
36902
37582
|
}
|
|
36903
|
-
const styles$
|
|
37583
|
+
const styles$8 = aphrodite.StyleSheet.create({
|
|
36904
37584
|
tooltipLabel: {
|
|
36905
37585
|
// Unlike most tooltip contents, we don't want this label to be
|
|
36906
37586
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -37458,7 +38138,7 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
37458
38138
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
37459
38139
|
const buildHighlight = r => this._buildHighlight(r);
|
|
37460
38140
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
37461
|
-
className: aphrodite.css(styles$
|
|
38141
|
+
className: aphrodite.css(styles$7.container),
|
|
37462
38142
|
ref: container => this._container = container
|
|
37463
38143
|
}, /*#__PURE__*/React__namespace.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React__namespace.createElement(HighlightingUI, {
|
|
37464
38144
|
buildHighlight: buildHighlight,
|
|
@@ -37479,14 +38159,14 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
37479
38159
|
onAddHighlight: this._handleAddHighlight,
|
|
37480
38160
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
37481
38161
|
})), /*#__PURE__*/React__namespace.createElement("div", {
|
|
37482
|
-
className: aphrodite.css(styles$
|
|
38162
|
+
className: aphrodite.css(styles$7.content),
|
|
37483
38163
|
ref: content => this._content = content
|
|
37484
38164
|
}, /*#__PURE__*/React__namespace.createElement(WordIndexer, {
|
|
37485
38165
|
onWordsUpdate: this._handleWordsUpdate
|
|
37486
38166
|
}, this.props.children)));
|
|
37487
38167
|
}
|
|
37488
38168
|
}
|
|
37489
|
-
const styles$
|
|
38169
|
+
const styles$7 = aphrodite.StyleSheet.create({
|
|
37490
38170
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
37491
38171
|
// content will receive the browser's native pointer events. (Highlights
|
|
37492
38172
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -37882,7 +38562,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
37882
38562
|
}
|
|
37883
38563
|
render() {
|
|
37884
38564
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
37885
|
-
className: aphrodite.css(styles$
|
|
38565
|
+
className: aphrodite.css(styles$6.measurer),
|
|
37886
38566
|
"aria-hidden": "true"
|
|
37887
38567
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
37888
38568
|
ref: ref => this._line = ref,
|
|
@@ -37890,7 +38570,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
37890
38570
|
}, "Line Height Measurement"));
|
|
37891
38571
|
}
|
|
37892
38572
|
}
|
|
37893
|
-
const styles$
|
|
38573
|
+
const styles$6 = aphrodite.StyleSheet.create({
|
|
37894
38574
|
measurer: {
|
|
37895
38575
|
position: "absolute",
|
|
37896
38576
|
top: 0,
|
|
@@ -39202,7 +39882,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
39202
39882
|
// creator "went wild".
|
|
39203
39883
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
39204
39884
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
39205
|
-
style: styles$
|
|
39885
|
+
style: styles$5.container
|
|
39206
39886
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
39207
39887
|
sandbox: sandboxOptions,
|
|
39208
39888
|
src: url,
|
|
@@ -39211,7 +39891,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
39211
39891
|
}));
|
|
39212
39892
|
}
|
|
39213
39893
|
}
|
|
39214
|
-
const styles$
|
|
39894
|
+
const styles$5 = aphrodite.StyleSheet.create({
|
|
39215
39895
|
container: {
|
|
39216
39896
|
margin: "auto",
|
|
39217
39897
|
width: "100%"
|
|
@@ -39448,125 +40128,6 @@ var Sequence$1 = {
|
|
|
39448
40128
|
isLintable: true
|
|
39449
40129
|
};
|
|
39450
40130
|
|
|
39451
|
-
const colors = {
|
|
39452
|
-
grayLight: "#aaa",
|
|
39453
|
-
basicBorderColor: "#ccc",
|
|
39454
|
-
white: "#fff"
|
|
39455
|
-
};
|
|
39456
|
-
const triangleBeforeAfter = {
|
|
39457
|
-
borderBottom: "9px solid transparent",
|
|
39458
|
-
borderTop: "9px solid transparent",
|
|
39459
|
-
content: '" "',
|
|
39460
|
-
height: "0",
|
|
39461
|
-
position: "absolute",
|
|
39462
|
-
top: "0",
|
|
39463
|
-
width: "0"
|
|
39464
|
-
};
|
|
39465
|
-
const styles$7 = aphrodite.StyleSheet.create({
|
|
39466
|
-
infoTip: {
|
|
39467
|
-
display: "inline-block",
|
|
39468
|
-
marginLeft: "5px",
|
|
39469
|
-
position: "relative"
|
|
39470
|
-
},
|
|
39471
|
-
infoTipContainer: {
|
|
39472
|
-
position: "absolute",
|
|
39473
|
-
top: "-12px",
|
|
39474
|
-
left: "22px",
|
|
39475
|
-
zIndex: 1000
|
|
39476
|
-
},
|
|
39477
|
-
infoTipTriangle: {
|
|
39478
|
-
height: "10px",
|
|
39479
|
-
left: "0",
|
|
39480
|
-
position: "absolute",
|
|
39481
|
-
top: "8px",
|
|
39482
|
-
width: "0",
|
|
39483
|
-
zIndex: 1,
|
|
39484
|
-
":before": {
|
|
39485
|
-
...triangleBeforeAfter,
|
|
39486
|
-
borderRight: "9px solid #bbb",
|
|
39487
|
-
right: "0"
|
|
39488
|
-
},
|
|
39489
|
-
":after": {
|
|
39490
|
-
...triangleBeforeAfter,
|
|
39491
|
-
borderRight: `9px solid ${colors.white}`,
|
|
39492
|
-
right: "-1px"
|
|
39493
|
-
}
|
|
39494
|
-
},
|
|
39495
|
-
verticalShadow: {
|
|
39496
|
-
border: `1px solid ${colors.basicBorderColor}`,
|
|
39497
|
-
boxShadow: `0 1px 3px ${colors.basicBorderColor}`,
|
|
39498
|
-
borderBottom: `1px solid ${colors.grayLight}`
|
|
39499
|
-
},
|
|
39500
|
-
infoTipContentContainer: {
|
|
39501
|
-
background: colors.white,
|
|
39502
|
-
padding: "5px 10px",
|
|
39503
|
-
width: "240px"
|
|
39504
|
-
}
|
|
39505
|
-
});
|
|
39506
|
-
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=";
|
|
39507
|
-
class InfoTip$1 extends React__namespace.Component {
|
|
39508
|
-
state = {
|
|
39509
|
-
hover: false
|
|
39510
|
-
};
|
|
39511
|
-
handleMouseEnter = () => {
|
|
39512
|
-
this.setState({
|
|
39513
|
-
hover: true
|
|
39514
|
-
});
|
|
39515
|
-
};
|
|
39516
|
-
handleMouseLeave = () => {
|
|
39517
|
-
this.setState({
|
|
39518
|
-
hover: false
|
|
39519
|
-
});
|
|
39520
|
-
};
|
|
39521
|
-
render() {
|
|
39522
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
39523
|
-
className: aphrodite.css(styles$7.infoTip)
|
|
39524
|
-
}, /*#__PURE__*/React__namespace.createElement("img", {
|
|
39525
|
-
alt: "",
|
|
39526
|
-
width: 10,
|
|
39527
|
-
height: 10,
|
|
39528
|
-
src: questionMark,
|
|
39529
|
-
onMouseEnter: this.handleMouseEnter,
|
|
39530
|
-
onMouseLeave: this.handleMouseLeave
|
|
39531
|
-
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
39532
|
-
className: aphrodite.css(styles$7.infoTipContainer),
|
|
39533
|
-
style: {
|
|
39534
|
-
display: this.state.hover ? "block" : "none"
|
|
39535
|
-
}
|
|
39536
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
39537
|
-
className: aphrodite.css(styles$7.infoTipTriangle)
|
|
39538
|
-
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
39539
|
-
className: aphrodite.css(styles$7.verticalShadow, styles$7.infoTipContentContainer)
|
|
39540
|
-
}, this.props.children)));
|
|
39541
|
-
}
|
|
39542
|
-
}
|
|
39543
|
-
|
|
39544
|
-
/**
|
|
39545
|
-
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
39546
|
-
* server without causing a checksum mismatch on the client.
|
|
39547
|
-
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
39548
|
-
* two sets of generated classnames will not match.)
|
|
39549
|
-
*/
|
|
39550
|
-
class InfoTip extends React__namespace.Component {
|
|
39551
|
-
state = {
|
|
39552
|
-
didMount: false
|
|
39553
|
-
};
|
|
39554
|
-
componentDidMount() {
|
|
39555
|
-
/* eslint-disable react/no-did-mount-set-state */
|
|
39556
|
-
this.setState({
|
|
39557
|
-
didMount: true
|
|
39558
|
-
});
|
|
39559
|
-
/* eslint-enable react/no-did-mount-set-state */
|
|
39560
|
-
}
|
|
39561
|
-
|
|
39562
|
-
render() {
|
|
39563
|
-
if (this.state.didMount) {
|
|
39564
|
-
return /*#__PURE__*/React__namespace.createElement(InfoTip$1, this.props);
|
|
39565
|
-
}
|
|
39566
|
-
return /*#__PURE__*/React__namespace.createElement("div", null);
|
|
39567
|
-
}
|
|
39568
|
-
}
|
|
39569
|
-
|
|
39570
40131
|
/* eslint-disable @typescript-eslint/no-unused-vars, react/no-unsafe, react/sort-comp */
|
|
39571
40132
|
const {
|
|
39572
40133
|
assert: assert$1
|
|
@@ -41524,7 +42085,7 @@ const VideoTranscriptLink = props => {
|
|
|
41524
42085
|
{
|
|
41525
42086
|
const video = result.data?.video;
|
|
41526
42087
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
41527
|
-
style: styles$
|
|
42088
|
+
style: styles$4.transcriptLink
|
|
41528
42089
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.Text, null, video?.title), /*#__PURE__*/React__namespace.createElement(wonderBlocksLayout.Strut, {
|
|
41529
42090
|
size: 10
|
|
41530
42091
|
}), /*#__PURE__*/React__namespace.createElement(Link__default["default"], {
|
|
@@ -41541,7 +42102,7 @@ const VideoTranscriptLink = props => {
|
|
|
41541
42102
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, i18n__namespace._("Something went wrong."));
|
|
41542
42103
|
}
|
|
41543
42104
|
};
|
|
41544
|
-
const styles$
|
|
42105
|
+
const styles$4 = aphrodite.StyleSheet.create({
|
|
41545
42106
|
transcriptLink: {
|
|
41546
42107
|
flexDirection: "row",
|
|
41547
42108
|
width: "100%",
|
|
@@ -41697,7 +42258,7 @@ const init = function (options) {
|
|
|
41697
42258
|
|
|
41698
42259
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41699
42260
|
const libName = "@khanacademy/perseus";
|
|
41700
|
-
const libVersion = "19.
|
|
42261
|
+
const libVersion = "19.7.0";
|
|
41701
42262
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41702
42263
|
|
|
41703
42264
|
const apiVersion = {
|
|
@@ -41910,7 +42471,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
41910
42471
|
const {
|
|
41911
42472
|
isMobile
|
|
41912
42473
|
} = apiOptions;
|
|
41913
|
-
const classNames = classNames__default["default"]("hint", !isMobile && "perseus-hint-renderer", isMobile && aphrodite.css(styles$
|
|
42474
|
+
const classNames = classNames__default["default"]("hint", !isMobile && "perseus-hint-renderer", isMobile && aphrodite.css(styles$3.newHint), isMobile && lastRendered && aphrodite.css(styles$3.lastRenderedNewHint), lastHint && "last-hint", lastRendered && "last-rendered", className);
|
|
41914
42475
|
|
|
41915
42476
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
41916
42477
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -41951,7 +42512,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
41951
42512
|
);
|
|
41952
42513
|
}
|
|
41953
42514
|
}
|
|
41954
|
-
const styles$
|
|
42515
|
+
const styles$3 = aphrodite.StyleSheet.create({
|
|
41955
42516
|
newHint: {
|
|
41956
42517
|
marginBottom: 1.5 * baseUnitPx,
|
|
41957
42518
|
borderLeftColor: gray97,
|
|
@@ -42128,15 +42689,15 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
42128
42689
|
} = apiOptions;
|
|
42129
42690
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
42130
42691
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
42131
|
-
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$
|
|
42692
|
+
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$2.mobileHintStylesHintsRenderer));
|
|
42132
42693
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42133
42694
|
className: classNames
|
|
42134
42695
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React__namespace.createElement("div", {
|
|
42135
|
-
className: aphrodite.css(styles$
|
|
42696
|
+
className: aphrodite.css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
42136
42697
|
}, i18n__namespace._("Hints")), hints, showGetAnotherHint && /*#__PURE__*/React__namespace.createElement("button", {
|
|
42137
42698
|
// @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>'.
|
|
42138
42699
|
rel: "button",
|
|
42139
|
-
className: aphrodite.css(styles$
|
|
42700
|
+
className: aphrodite.css(styles$2.linkButton, styles$2.getAnotherHintButton, apiOptions.isMobile && styles$2.mobileHintStylesGetAnotherHintButton),
|
|
42140
42701
|
onClick: evt => {
|
|
42141
42702
|
evt.preventDefault();
|
|
42142
42703
|
evt.stopPropagation();
|
|
@@ -42145,14 +42706,14 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
42145
42706
|
}
|
|
42146
42707
|
}
|
|
42147
42708
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
42148
|
-
className: aphrodite.css(styles$
|
|
42709
|
+
className: aphrodite.css(styles$2.plusText, apiOptions.isMobile && styles$2.mobileHintStylesPlusText)
|
|
42149
42710
|
}, "+"), /*#__PURE__*/React__namespace.createElement("span", {
|
|
42150
|
-
className: aphrodite.css(styles$
|
|
42711
|
+
className: aphrodite.css(styles$2.getAnotherHintText)
|
|
42151
42712
|
}, i18n__namespace._("Get another hint"), " ", hintRatioCopy)));
|
|
42152
42713
|
}
|
|
42153
42714
|
}
|
|
42154
42715
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
42155
|
-
const styles$
|
|
42716
|
+
const styles$2 = aphrodite.StyleSheet.create({
|
|
42156
42717
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
42157
42718
|
rendererMargins: {
|
|
42158
42719
|
marginTop: baseUnitPx
|
|
@@ -42564,11 +43125,11 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
42564
43125
|
// mobile hint styles, which are flush to the left.
|
|
42565
43126
|
// NOTE(charlie): We may still want to apply this
|
|
42566
43127
|
// padding for desktop exercises.
|
|
42567
|
-
apiOptions.isMobile ? undefined : aphrodite.css(styles$
|
|
43128
|
+
apiOptions.isMobile ? undefined : aphrodite.css(styles$1.hintsContainer)
|
|
42568
43129
|
}, hintsRenderer)));
|
|
42569
43130
|
}
|
|
42570
43131
|
}
|
|
42571
|
-
const styles$
|
|
43132
|
+
const styles$1 = aphrodite.StyleSheet.create({
|
|
42572
43133
|
hintsContainer: {
|
|
42573
43134
|
marginLeft: 50
|
|
42574
43135
|
}
|
|
@@ -42705,339 +43266,6 @@ class ElementContainer extends React__namespace.Component {
|
|
|
42705
43266
|
}
|
|
42706
43267
|
}
|
|
42707
43268
|
|
|
42708
|
-
// Displays a stylized open eye: lint warnings are visible
|
|
42709
|
-
const VisibleIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
42710
|
-
width: "24",
|
|
42711
|
-
height: "24",
|
|
42712
|
-
viewBox: "0 0 24 24",
|
|
42713
|
-
className: aphrodite.css(styles$2.icon)
|
|
42714
|
-
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42715
|
-
id: "a",
|
|
42716
|
-
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"
|
|
42717
|
-
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42718
|
-
fill: "none",
|
|
42719
|
-
fillRule: "evenodd"
|
|
42720
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42721
|
-
fill: "none",
|
|
42722
|
-
d: "M0 0h24v24H0z"
|
|
42723
|
-
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
42724
|
-
id: "b",
|
|
42725
|
-
fill: "#fff"
|
|
42726
|
-
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
42727
|
-
href: "#a"
|
|
42728
|
-
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
42729
|
-
fill: "#fff",
|
|
42730
|
-
fillRule: "nonzero",
|
|
42731
|
-
href: "#a"
|
|
42732
|
-
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42733
|
-
fill: "#fff",
|
|
42734
|
-
mask: "url(#b)"
|
|
42735
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42736
|
-
d: "M0 0h24v24H0z"
|
|
42737
|
-
}))));
|
|
42738
|
-
|
|
42739
|
-
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
42740
|
-
const HiddenIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
42741
|
-
width: "24",
|
|
42742
|
-
height: "24",
|
|
42743
|
-
viewBox: "0 0 24 24",
|
|
42744
|
-
className: aphrodite.css(styles$2.icon)
|
|
42745
|
-
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42746
|
-
id: "a",
|
|
42747
|
-
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"
|
|
42748
|
-
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42749
|
-
fill: "none",
|
|
42750
|
-
fillRule: "evenodd"
|
|
42751
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42752
|
-
fill: "none",
|
|
42753
|
-
d: "M0 0h24v24H0z"
|
|
42754
|
-
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
42755
|
-
id: "b",
|
|
42756
|
-
fill: "#fff"
|
|
42757
|
-
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
42758
|
-
href: "#a"
|
|
42759
|
-
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
42760
|
-
fill: "#fff",
|
|
42761
|
-
fillRule: "nonzero",
|
|
42762
|
-
href: "#a"
|
|
42763
|
-
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42764
|
-
fill: "#fff",
|
|
42765
|
-
mask: "url(#b)"
|
|
42766
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42767
|
-
d: "M0 0h24v24H0z"
|
|
42768
|
-
}))));
|
|
42769
|
-
const HUD = _ref => {
|
|
42770
|
-
let {
|
|
42771
|
-
message,
|
|
42772
|
-
enabled,
|
|
42773
|
-
onClick,
|
|
42774
|
-
fixedPosition = true
|
|
42775
|
-
} = _ref;
|
|
42776
|
-
let state;
|
|
42777
|
-
let icon;
|
|
42778
|
-
if (enabled) {
|
|
42779
|
-
state = styles$2.enabled;
|
|
42780
|
-
icon = /*#__PURE__*/React__namespace.createElement(VisibleIcon, null);
|
|
42781
|
-
} else {
|
|
42782
|
-
state = styles$2.disabled;
|
|
42783
|
-
icon = /*#__PURE__*/React__namespace.createElement(HiddenIcon, null);
|
|
42784
|
-
}
|
|
42785
|
-
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
42786
|
-
className: aphrodite.css(styles$2.hud, fixedPosition && styles$2.hudFixedPosition, state),
|
|
42787
|
-
onClick: e => {
|
|
42788
|
-
onClick();
|
|
42789
|
-
}
|
|
42790
|
-
}, icon, message);
|
|
42791
|
-
};
|
|
42792
|
-
const styles$2 = aphrodite.StyleSheet.create({
|
|
42793
|
-
hud: {
|
|
42794
|
-
boxSizing: "border-box",
|
|
42795
|
-
height: 36,
|
|
42796
|
-
padding: "9px 16px",
|
|
42797
|
-
borderRadius: 18,
|
|
42798
|
-
fontFamily: boldFontFamily,
|
|
42799
|
-
fontSize: "15px",
|
|
42800
|
-
lineHeight: "18px",
|
|
42801
|
-
color: white$1,
|
|
42802
|
-
userSelect: "none",
|
|
42803
|
-
borderWidth: 0 // <button> gives us a border by default
|
|
42804
|
-
},
|
|
42805
|
-
|
|
42806
|
-
// We want to render the element in-place in our fixtures, so allow us to
|
|
42807
|
-
// render in the bottom corner in production and in-place in testing.
|
|
42808
|
-
hudFixedPosition: {
|
|
42809
|
-
bottom: 20,
|
|
42810
|
-
position: "fixed",
|
|
42811
|
-
right: 20,
|
|
42812
|
-
zIndex: 1
|
|
42813
|
-
},
|
|
42814
|
-
icon: {
|
|
42815
|
-
width: 24,
|
|
42816
|
-
height: 24,
|
|
42817
|
-
marginRight: 8,
|
|
42818
|
-
marginTop: -3,
|
|
42819
|
-
verticalAlign: "middle"
|
|
42820
|
-
},
|
|
42821
|
-
enabled: {
|
|
42822
|
-
backgroundColor: warningColor,
|
|
42823
|
-
":hover": {
|
|
42824
|
-
backgroundColor: warningColorHover
|
|
42825
|
-
},
|
|
42826
|
-
":active": {
|
|
42827
|
-
backgroundColor: warningColorActive
|
|
42828
|
-
}
|
|
42829
|
-
},
|
|
42830
|
-
disabled: {
|
|
42831
|
-
backgroundColor: gray76,
|
|
42832
|
-
":hover": {
|
|
42833
|
-
backgroundColor: "#a1a5a9" // in between those two grays
|
|
42834
|
-
},
|
|
42835
|
-
|
|
42836
|
-
":active": {
|
|
42837
|
-
backgroundColor: gray68
|
|
42838
|
-
}
|
|
42839
|
-
}
|
|
42840
|
-
});
|
|
42841
|
-
|
|
42842
|
-
/**
|
|
42843
|
-
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
42844
|
-
* which allows multiple buttons to be selected at the same time.
|
|
42845
|
-
*
|
|
42846
|
-
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
42847
|
-
* this component allows multiple selection!
|
|
42848
|
-
*/
|
|
42849
|
-
class MultiButtonGroup extends React__namespace.Component {
|
|
42850
|
-
static defaultProps = {
|
|
42851
|
-
values: [],
|
|
42852
|
-
allowEmpty: true
|
|
42853
|
-
};
|
|
42854
|
-
focus() {
|
|
42855
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
42856
|
-
ReactDOM__namespace.findDOMNode(this)?.focus();
|
|
42857
|
-
return true;
|
|
42858
|
-
}
|
|
42859
|
-
toggleSelect = newValue => {
|
|
42860
|
-
const values = (this.props.values || []).slice(0);
|
|
42861
|
-
const allowEmpty = this.props.allowEmpty;
|
|
42862
|
-
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
42863
|
-
// If the value is already selected, unselect it
|
|
42864
|
-
values.splice(values.indexOf(newValue), 1);
|
|
42865
|
-
} else {
|
|
42866
|
-
// Otherwise merge with other values and return
|
|
42867
|
-
if (values.indexOf(newValue) < 0) {
|
|
42868
|
-
values.push(newValue);
|
|
42869
|
-
}
|
|
42870
|
-
}
|
|
42871
|
-
this.props.onChange(values);
|
|
42872
|
-
};
|
|
42873
|
-
render() {
|
|
42874
|
-
const values = this.props.values || [];
|
|
42875
|
-
const buttons = this.props.buttons.map((button, i) => {
|
|
42876
|
-
const selected = values.indexOf(button.value) >= 0;
|
|
42877
|
-
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
42878
|
-
title: button.title,
|
|
42879
|
-
type: "button",
|
|
42880
|
-
id: "" + i,
|
|
42881
|
-
key: "" + i,
|
|
42882
|
-
ref: "button" + i,
|
|
42883
|
-
className: aphrodite.css(styles$1.buttonStyle, selected && styles$1.selectedStyle),
|
|
42884
|
-
onClick: () => this.toggleSelect(button.value)
|
|
42885
|
-
}, button.content || "" + button.value);
|
|
42886
|
-
});
|
|
42887
|
-
const outerStyle = {
|
|
42888
|
-
display: "inline-block"
|
|
42889
|
-
};
|
|
42890
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42891
|
-
style: outerStyle
|
|
42892
|
-
}, buttons);
|
|
42893
|
-
}
|
|
42894
|
-
}
|
|
42895
|
-
const styles$1 = aphrodite.StyleSheet.create({
|
|
42896
|
-
buttonStyle: {
|
|
42897
|
-
backgroundColor: "white",
|
|
42898
|
-
border: "1px solid #ccc",
|
|
42899
|
-
borderLeft: "0",
|
|
42900
|
-
cursor: "pointer",
|
|
42901
|
-
margin: "0",
|
|
42902
|
-
padding: "5px 10px",
|
|
42903
|
-
position: "relative",
|
|
42904
|
-
// for hover
|
|
42905
|
-
|
|
42906
|
-
":first-child": {
|
|
42907
|
-
borderLeft: "1px solid #ccc",
|
|
42908
|
-
borderTopLeftRadius: "3px",
|
|
42909
|
-
borderBottomLeftRadius: "3px"
|
|
42910
|
-
},
|
|
42911
|
-
":last-child": {
|
|
42912
|
-
borderRight: "1px solid #ccc",
|
|
42913
|
-
borderTopRightRadius: "3px",
|
|
42914
|
-
borderBottomRightRadius: "3px"
|
|
42915
|
-
},
|
|
42916
|
-
":hover": {
|
|
42917
|
-
backgroundColor: "#ccc"
|
|
42918
|
-
},
|
|
42919
|
-
":focus": {
|
|
42920
|
-
zIndex: 2
|
|
42921
|
-
}
|
|
42922
|
-
},
|
|
42923
|
-
selectedStyle: {
|
|
42924
|
-
backgroundColor: "#ddd"
|
|
42925
|
-
}
|
|
42926
|
-
});
|
|
42927
|
-
|
|
42928
|
-
/* eslint-disable @babel/no-invalid-this */
|
|
42929
|
-
|
|
42930
|
-
/* A checkbox that syncs its value to props using the
|
|
42931
|
-
* renderer's onChange method, and gets the prop name
|
|
42932
|
-
* dynamically from its props list
|
|
42933
|
-
*/
|
|
42934
|
-
const PropCheckBox = createReactClass__default["default"]({
|
|
42935
|
-
displayName: "PropCheckBox",
|
|
42936
|
-
propTypes: {
|
|
42937
|
-
labelAlignment: PropTypes__default["default"].oneOf(["left", "right"])
|
|
42938
|
-
},
|
|
42939
|
-
DEFAULT_PROPS: {
|
|
42940
|
-
label: null,
|
|
42941
|
-
onChange: null,
|
|
42942
|
-
labelAlignment: "left"
|
|
42943
|
-
},
|
|
42944
|
-
getDefaultProps: function () {
|
|
42945
|
-
return this.DEFAULT_PROPS;
|
|
42946
|
-
},
|
|
42947
|
-
propName: function () {
|
|
42948
|
-
const propName = ___default["default"].find(___default["default"].keys(this.props), function (localPropName) {
|
|
42949
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
42950
|
-
return !___default["default"].has(this.DEFAULT_PROPS, localPropName);
|
|
42951
|
-
}, this);
|
|
42952
|
-
if (!propName) {
|
|
42953
|
-
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
42954
|
-
}
|
|
42955
|
-
return propName;
|
|
42956
|
-
},
|
|
42957
|
-
_labelAlignLeft: function () {
|
|
42958
|
-
return this.props.labelAlignment === "left";
|
|
42959
|
-
},
|
|
42960
|
-
render: function () {
|
|
42961
|
-
const propName = this.propName();
|
|
42962
|
-
return /*#__PURE__*/React__namespace.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React__namespace.createElement("input", {
|
|
42963
|
-
type: "checkbox",
|
|
42964
|
-
checked: this.props[propName],
|
|
42965
|
-
onChange: this.toggle
|
|
42966
|
-
}), !this._labelAlignLeft() && this.props.label);
|
|
42967
|
-
},
|
|
42968
|
-
toggle: function () {
|
|
42969
|
-
const propName = this.propName();
|
|
42970
|
-
const changes = {};
|
|
42971
|
-
changes[propName] = !this.props[propName];
|
|
42972
|
-
this.props.onChange(changes);
|
|
42973
|
-
}
|
|
42974
|
-
});
|
|
42975
|
-
|
|
42976
|
-
const truth = () => true;
|
|
42977
|
-
|
|
42978
|
-
/* A minor abstraction on top of NumberInput for ranges
|
|
42979
|
-
*
|
|
42980
|
-
*/
|
|
42981
|
-
class RangeInput extends React__namespace.Component {
|
|
42982
|
-
static propTypes = {
|
|
42983
|
-
value: PropTypes__default["default"].array.isRequired,
|
|
42984
|
-
onChange: PropTypes__default["default"].func.isRequired,
|
|
42985
|
-
placeholder: PropTypes__default["default"].array,
|
|
42986
|
-
checkValidity: PropTypes__default["default"].func
|
|
42987
|
-
};
|
|
42988
|
-
static defaultProps = {
|
|
42989
|
-
placeholder: [null, null]
|
|
42990
|
-
};
|
|
42991
|
-
render() {
|
|
42992
|
-
const value = this.props.value;
|
|
42993
|
-
const checkValidity = this.props.checkValidity || truth;
|
|
42994
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42995
|
-
className: "range-input"
|
|
42996
|
-
}, /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
42997
|
-
value: value[0],
|
|
42998
|
-
checkValidity: val => checkValidity([val, value[1]])
|
|
42999
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
43000
|
-
,
|
|
43001
|
-
onChange: this.onChange.bind(this, 0),
|
|
43002
|
-
placeholder: this.props.placeholder[0]
|
|
43003
|
-
})), /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
43004
|
-
value: value[1],
|
|
43005
|
-
checkValidity: val => checkValidity([value[0], val])
|
|
43006
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
43007
|
-
,
|
|
43008
|
-
onChange: this.onChange.bind(this, 1),
|
|
43009
|
-
placeholder: this.props.placeholder[1]
|
|
43010
|
-
})));
|
|
43011
|
-
}
|
|
43012
|
-
onChange = (i, newVal) => {
|
|
43013
|
-
const value = this.props.value;
|
|
43014
|
-
if (i === 0) {
|
|
43015
|
-
this.props.onChange([newVal, value[1]]);
|
|
43016
|
-
} else {
|
|
43017
|
-
this.props.onChange([value[0], newVal]);
|
|
43018
|
-
}
|
|
43019
|
-
};
|
|
43020
|
-
}
|
|
43021
|
-
|
|
43022
|
-
var components = /*#__PURE__*/Object.freeze({
|
|
43023
|
-
__proto__: null,
|
|
43024
|
-
ButtonGroup: ButtonGroup,
|
|
43025
|
-
Graph: Graph,
|
|
43026
|
-
Graphie: Graphie,
|
|
43027
|
-
HUD: HUD,
|
|
43028
|
-
Icon: Icon,
|
|
43029
|
-
InfoTip: InfoTip,
|
|
43030
|
-
InlineIcon: InlineIcon,
|
|
43031
|
-
MathInput: MathInput,
|
|
43032
|
-
MultiButtonGroup: MultiButtonGroup,
|
|
43033
|
-
NumberInput: NumberInput,
|
|
43034
|
-
PropCheckBox: PropCheckBox,
|
|
43035
|
-
RangeInput: RangeInput,
|
|
43036
|
-
SvgImage: SvgImage,
|
|
43037
|
-
TextInput: TextInput,
|
|
43038
|
-
TextListEditor: TextListEditor
|
|
43039
|
-
});
|
|
43040
|
-
|
|
43041
43269
|
const devices = {
|
|
43042
43270
|
PHONE: "phone",
|
|
43043
43271
|
TABLET: "tablet",
|