@khanacademy/perseus 19.6.3 → 19.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +171 -0
- package/dist/es/index.js +975 -745
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +171 -0
- package/dist/index.js +972 -740
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +1 -0
- package/dist/perseus-types.d.ts +14 -2
- package/dist/server-item-renderer.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/widgets/expression.d.ts +6 -0
- package/dist/widgets/interactive-graph.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/segment.d.ts +5 -0
- package/dist/widgets/interactive-graphs/grid.d.ts +11 -0
- package/dist/widgets/interactive-graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/legacy-grid.d.ts +7 -0
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +81 -0
- package/dist/widgets/interactive-graphs/types.d.ts +9 -0
- package/dist/widgets/interactive-graphs/utils.d.ts +15 -0
- package/dist/widgets/label-image.d.ts +2 -0
- package/package.json +3 -2
package/dist/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] = props.box;
|
|
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,28 @@ 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() {
|
|
29521
30392
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
30393
|
+
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
30394
|
+
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
30395
|
+
|
|
30396
|
+
// Mafs shim
|
|
30397
|
+
if (this.props.apiOptions?.flags?.["mafs"]?.[this.props.graph.type]) {
|
|
30398
|
+
return /*#__PURE__*/React__namespace.createElement(MafsGraph, _extends({}, this.props, {
|
|
30399
|
+
ref: this.mafsRef,
|
|
30400
|
+
gridStep: gridStep,
|
|
30401
|
+
snapStep: snapStep,
|
|
30402
|
+
box: box
|
|
30403
|
+
}));
|
|
30404
|
+
}
|
|
29522
30405
|
let instructions;
|
|
30406
|
+
// isClickToAddPoints() only applies to points and polygons
|
|
29523
30407
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
29524
30408
|
if (this.props.graph.type === "point") {
|
|
29525
30409
|
instructions = i18n__namespace._("Click to add points");
|
|
@@ -29533,8 +30417,6 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29533
30417
|
if (this.isClickToAddPoints()) {
|
|
29534
30418
|
onMouseDown = this.handleAddPointsMouseDown;
|
|
29535
30419
|
}
|
|
29536
|
-
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
29537
|
-
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
29538
30420
|
const isMobile = this.props.apiOptions.isMobile;
|
|
29539
30421
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
29540
30422
|
className: "perseus-widget " + "perseus-widget-interactive-graph",
|
|
@@ -30804,7 +31686,7 @@ var globalConstants = /*#__PURE__*/Object.freeze({
|
|
|
30804
31686
|
pureLgMax: pureLgMax
|
|
30805
31687
|
});
|
|
30806
31688
|
|
|
30807
|
-
const colors
|
|
31689
|
+
const colors = {
|
|
30808
31690
|
white: "#FFFFFF",
|
|
30809
31691
|
gray98: "#FAFAFA",
|
|
30810
31692
|
gray97: "#F6F7F7",
|
|
@@ -30864,7 +31746,7 @@ const colors$1 = {
|
|
|
30864
31746
|
};
|
|
30865
31747
|
const borderRadius = 4;
|
|
30866
31748
|
const breadcrumbStyles = {
|
|
30867
|
-
color: colors
|
|
31749
|
+
color: colors.breadcrumbs,
|
|
30868
31750
|
fontFamily: "inherit",
|
|
30869
31751
|
fontSize: 15,
|
|
30870
31752
|
fontWeight: "bold",
|
|
@@ -30934,14 +31816,14 @@ const typography = {
|
|
|
30934
31816
|
},
|
|
30935
31817
|
// For callouts
|
|
30936
31818
|
smallHeading: {
|
|
30937
|
-
color: colors
|
|
31819
|
+
color: colors.gray25,
|
|
30938
31820
|
fontFamily: "inherit",
|
|
30939
31821
|
fontSize: 17,
|
|
30940
31822
|
fontWeight: "bold",
|
|
30941
31823
|
lineHeight: "23px"
|
|
30942
31824
|
},
|
|
30943
31825
|
smallHeadingMobile: {
|
|
30944
|
-
color: colors
|
|
31826
|
+
color: colors.gray25,
|
|
30945
31827
|
fontFamily: "inherit",
|
|
30946
31828
|
fontSize: 15,
|
|
30947
31829
|
fontWeight: "bold",
|
|
@@ -30949,7 +31831,7 @@ const typography = {
|
|
|
30949
31831
|
},
|
|
30950
31832
|
// Accent headings
|
|
30951
31833
|
accentHeading: {
|
|
30952
|
-
color: colors
|
|
31834
|
+
color: colors.gray68,
|
|
30953
31835
|
fontFamily: "inherit",
|
|
30954
31836
|
fontSize: 15,
|
|
30955
31837
|
fontWeight: "bold",
|
|
@@ -31057,7 +31939,7 @@ const typography = {
|
|
|
31057
31939
|
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
31058
31940
|
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
31059
31941
|
wonderBlocksTitle: {
|
|
31060
|
-
color: colors
|
|
31942
|
+
color: colors.white,
|
|
31061
31943
|
fontWeight: 900,
|
|
31062
31944
|
// "Black" weight
|
|
31063
31945
|
fontSize: 28,
|
|
@@ -31079,7 +31961,7 @@ const typography = {
|
|
|
31079
31961
|
|
|
31080
31962
|
var globalStyles = /*#__PURE__*/Object.freeze({
|
|
31081
31963
|
__proto__: null,
|
|
31082
|
-
colors: colors
|
|
31964
|
+
colors: colors,
|
|
31083
31965
|
borderRadius: borderRadius,
|
|
31084
31966
|
fonts: fonts,
|
|
31085
31967
|
typography: typography
|
|
@@ -31144,7 +32026,7 @@ const HideAnswersToggle = props => {
|
|
|
31144
32026
|
const switchId = idFactory.get("hide-answers-toggle");
|
|
31145
32027
|
const labelId = idFactory.get("hide-answers-label");
|
|
31146
32028
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31147
|
-
style: styles$
|
|
32029
|
+
style: styles$g.switchWrapper
|
|
31148
32030
|
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
31149
32031
|
id: switchId,
|
|
31150
32032
|
checked: props.areAnswersHidden,
|
|
@@ -31156,7 +32038,7 @@ const HideAnswersToggle = props => {
|
|
|
31156
32038
|
tag: "label"
|
|
31157
32039
|
}, strings.hideAnswersToggleLabel));
|
|
31158
32040
|
};
|
|
31159
|
-
const styles$
|
|
32041
|
+
const styles$g = aphrodite.StyleSheet.create({
|
|
31160
32042
|
switchWrapper: {
|
|
31161
32043
|
display: "flex",
|
|
31162
32044
|
flexDirection: "row",
|
|
@@ -31211,14 +32093,14 @@ const AnswerPill = props => {
|
|
|
31211
32093
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31212
32094
|
onClick: correct ? undefined : onClick,
|
|
31213
32095
|
ref: ref,
|
|
31214
|
-
style: [style, popperStyle, styles$
|
|
32096
|
+
style: [style, popperStyle, styles$f.pill, correct && styles$f.correct, incorrect && styles$f.incorrect, (focused || hovered) && BringToFront]
|
|
31215
32097
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31216
32098
|
content: answerString,
|
|
31217
32099
|
inline: true
|
|
31218
32100
|
}));
|
|
31219
32101
|
});
|
|
31220
32102
|
};
|
|
31221
|
-
const styles$
|
|
32103
|
+
const styles$f = aphrodite.StyleSheet.create({
|
|
31222
32104
|
correct: {
|
|
31223
32105
|
// WB green darkened by 18%
|
|
31224
32106
|
backgroundColor: "#00880b"
|
|
@@ -31272,25 +32154,25 @@ class Marker extends React__namespace.Component {
|
|
|
31272
32154
|
icon: iconNull
|
|
31273
32155
|
};
|
|
31274
32156
|
if (showCorrectness) {
|
|
31275
|
-
iconStyles = [styles$
|
|
32157
|
+
iconStyles = [styles$e.markerGraded, showCorrectness === "correct" ? styles$e.markerCorrect : styles$e.markerIncorrect, isOpen && styles$e.markerSelected];
|
|
31276
32158
|
args = {
|
|
31277
32159
|
...args,
|
|
31278
32160
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31279
32161
|
};
|
|
31280
32162
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31281
|
-
iconStyles = [styles$
|
|
32163
|
+
iconStyles = [styles$e.markerFilled, isOpen && styles$e.markerSelected];
|
|
31282
32164
|
} else if (isOpen) {
|
|
31283
|
-
iconStyles = [styles$
|
|
32165
|
+
iconStyles = [styles$e.markerSelected];
|
|
31284
32166
|
args = {
|
|
31285
32167
|
...args,
|
|
31286
32168
|
icon: iconChevronDown,
|
|
31287
32169
|
size: 8
|
|
31288
32170
|
};
|
|
31289
32171
|
} else if (showPulsate) {
|
|
31290
|
-
iconStyles = [styles$
|
|
32172
|
+
iconStyles = [styles$e.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$e.markerUnfilledPulsateOnce : showPulsate && styles$e.markerUnfilledPulsateInfinite];
|
|
31291
32173
|
}
|
|
31292
32174
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31293
|
-
style: [styles$
|
|
32175
|
+
style: [styles$e.markerIcon, iconStyles],
|
|
31294
32176
|
ref: node => this._icon = node
|
|
31295
32177
|
}, /*#__PURE__*/React__namespace.createElement(Icon, args));
|
|
31296
32178
|
}
|
|
@@ -31311,7 +32193,7 @@ class Marker extends React__namespace.Component {
|
|
|
31311
32193
|
const markerDisabled = showCorrectness === "correct";
|
|
31312
32194
|
const active = hovered || focused;
|
|
31313
32195
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31314
|
-
style: [styles$
|
|
32196
|
+
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive]
|
|
31315
32197
|
// already translated in: /widgets/graded-group.tsx
|
|
31316
32198
|
,
|
|
31317
32199
|
"aria-label": markerDisabled ? i18n__namespace._("Correct!") : label
|
|
@@ -31326,7 +32208,7 @@ class Marker extends React__namespace.Component {
|
|
|
31326
32208
|
}));
|
|
31327
32209
|
}
|
|
31328
32210
|
}
|
|
31329
|
-
const styles$
|
|
32211
|
+
const styles$e = aphrodite.StyleSheet.create({
|
|
31330
32212
|
marker: {
|
|
31331
32213
|
position: "absolute",
|
|
31332
32214
|
backgroundColor: Color__default["default"].white,
|
|
@@ -31903,13 +32785,13 @@ class LabelImage extends React__namespace.Component {
|
|
|
31903
32785
|
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
32786
|
const choicesString = i18n__namespace._("Choices:");
|
|
31905
32787
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
31906
|
-
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$
|
|
32788
|
+
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$d.instructions))
|
|
31907
32789
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
31908
|
-
className: aphrodite.css(styles$
|
|
32790
|
+
className: aphrodite.css(styles$d.instructionsCaption)
|
|
31909
32791
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React__namespace.createElement("div", {
|
|
31910
|
-
className: aphrodite.css(styles$
|
|
32792
|
+
className: aphrodite.css(styles$d.instructionsChoices)
|
|
31911
32793
|
}, choices.map((choice, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
31912
|
-
className: aphrodite.css(styles$
|
|
32794
|
+
className: aphrodite.css(styles$d.instructionsChoice),
|
|
31913
32795
|
key: index
|
|
31914
32796
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31915
32797
|
content: choice
|
|
@@ -31926,20 +32808,20 @@ class LabelImage extends React__namespace.Component {
|
|
|
31926
32808
|
activeMarkerIndex
|
|
31927
32809
|
} = this.state;
|
|
31928
32810
|
return /*#__PURE__*/React__namespace.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React__namespace.createElement("div", {
|
|
31929
|
-
className: aphrodite.css(styles$
|
|
32811
|
+
className: aphrodite.css(styles$d.markersCanvas),
|
|
31930
32812
|
style: {
|
|
31931
32813
|
maxWidth: imageWidth,
|
|
31932
32814
|
maxHeight: imageHeight
|
|
31933
32815
|
}
|
|
31934
32816
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
31935
|
-
className: aphrodite.css(styles$
|
|
32817
|
+
className: aphrodite.css(styles$d.imageContainer,
|
|
31936
32818
|
// Ensure image interaction is disabled while answer
|
|
31937
32819
|
// choices popup is visible. This addresses specific
|
|
31938
32820
|
// case where user may click on question image to
|
|
31939
32821
|
// dismiss the popup. If the image is larger in size
|
|
31940
32822
|
// than its rendered in the widget, this would
|
|
31941
32823
|
// result in a zoom of the image.
|
|
31942
|
-
activeMarkerIndex !== -1 && styles$
|
|
32824
|
+
activeMarkerIndex !== -1 && styles$d.imageInteractionDisabled)
|
|
31943
32825
|
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref3 => {
|
|
31944
32826
|
let {
|
|
31945
32827
|
setAssetStatus
|
|
@@ -31965,7 +32847,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
31965
32847
|
}));
|
|
31966
32848
|
}
|
|
31967
32849
|
}
|
|
31968
|
-
const styles$
|
|
32850
|
+
const styles$d = aphrodite.StyleSheet.create({
|
|
31969
32851
|
instructions: {
|
|
31970
32852
|
paddingBottom: 16
|
|
31971
32853
|
},
|
|
@@ -32326,7 +33208,7 @@ class Placeholder extends React__namespace.Component {
|
|
|
32326
33208
|
const {
|
|
32327
33209
|
layout
|
|
32328
33210
|
} = this.props;
|
|
32329
|
-
const className = aphrodite.css(styles$
|
|
33211
|
+
const className = aphrodite.css(styles$c.card, styles$c.placeholder, layout === Layout.HORIZONTAL && styles$c.horizontalCard);
|
|
32330
33212
|
const style = {
|
|
32331
33213
|
width: this.props.width,
|
|
32332
33214
|
height: this.props.height
|
|
@@ -32424,7 +33306,7 @@ class Draggable extends React__namespace.Component {
|
|
|
32424
33306
|
// We need to keep backwards compatbility with rules specified directly
|
|
32425
33307
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
32426
33308
|
// See sortable.less for details.
|
|
32427
|
-
let className = aphrodite.css(styles$
|
|
33309
|
+
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
33310
|
if (!includePadding) {
|
|
32429
33311
|
className += " perseus-sortable-draggable-unpadded";
|
|
32430
33312
|
}
|
|
@@ -32724,7 +33606,7 @@ class Sortable extends React__namespace.Component {
|
|
|
32724
33606
|
} = this.props;
|
|
32725
33607
|
// We need to keep backwards compatbility with rules specified directly
|
|
32726
33608
|
// in CSS. See sortable.less for details.
|
|
32727
|
-
const className = aphrodite.css(styles$
|
|
33609
|
+
const className = aphrodite.css(styles$c.sortable) + " perseus-sortable";
|
|
32728
33610
|
const syncWidth = this.props.constraints?.width || layout === Layout.VERTICAL;
|
|
32729
33611
|
const syncHeight = this.props.constraints?.height || layout === Layout.HORIZONTAL;
|
|
32730
33612
|
___default["default"].each(this.state.items, function (item, i, items) {
|
|
@@ -32955,7 +33837,7 @@ class Sortable extends React__namespace.Component {
|
|
|
32955
33837
|
return ___default["default"].pluck(this.state.items, "option");
|
|
32956
33838
|
}
|
|
32957
33839
|
}
|
|
32958
|
-
const styles$
|
|
33840
|
+
const styles$c = aphrodite.StyleSheet.create({
|
|
32959
33841
|
sortable: {
|
|
32960
33842
|
boxSizing: "border-box",
|
|
32961
33843
|
float: "left",
|
|
@@ -33083,23 +33965,23 @@ class Matcher extends React__namespace.Component {
|
|
|
33083
33965
|
};
|
|
33084
33966
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
33085
33967
|
return /*#__PURE__*/React__namespace.createElement("table", {
|
|
33086
|
-
className: aphrodite.css(styles$
|
|
33968
|
+
className: aphrodite.css(styles$b.widget) + " " + HACKY_CSS_CLASSNAME
|
|
33087
33969
|
}, /*#__PURE__*/React__namespace.createElement("tbody", null, showLabels && /*#__PURE__*/React__namespace.createElement("tr", {
|
|
33088
|
-
className: aphrodite.css(styles$
|
|
33970
|
+
className: aphrodite.css(styles$b.row)
|
|
33089
33971
|
}, /*#__PURE__*/React__namespace.createElement("th", {
|
|
33090
|
-
className: aphrodite.css(styles$
|
|
33972
|
+
className: aphrodite.css(styles$b.column, styles$b.columnLabel)
|
|
33091
33973
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33092
33974
|
content: this.props.labels[0] || "...",
|
|
33093
33975
|
linterContext: this.props.linterContext
|
|
33094
33976
|
})), /*#__PURE__*/React__namespace.createElement("th", {
|
|
33095
|
-
className: aphrodite.css(styles$
|
|
33977
|
+
className: aphrodite.css(styles$b.column, styles$b.columnRight, styles$b.columnLabel)
|
|
33096
33978
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33097
33979
|
content: this.props.labels[1] || "...",
|
|
33098
33980
|
linterContext: this.props.linterContext
|
|
33099
33981
|
}))), /*#__PURE__*/React__namespace.createElement("tr", {
|
|
33100
|
-
className: aphrodite.css(styles$
|
|
33982
|
+
className: aphrodite.css(styles$b.row)
|
|
33101
33983
|
}, /*#__PURE__*/React__namespace.createElement("td", {
|
|
33102
|
-
className: aphrodite.css(styles$
|
|
33984
|
+
className: aphrodite.css(styles$b.column)
|
|
33103
33985
|
}, /*#__PURE__*/React__namespace.createElement(Sortable, {
|
|
33104
33986
|
options: left,
|
|
33105
33987
|
layout: Layout.VERTICAL,
|
|
@@ -33114,7 +33996,7 @@ class Matcher extends React__namespace.Component {
|
|
|
33114
33996
|
,
|
|
33115
33997
|
ref: "left"
|
|
33116
33998
|
})), /*#__PURE__*/React__namespace.createElement("td", {
|
|
33117
|
-
className: aphrodite.css(styles$
|
|
33999
|
+
className: aphrodite.css(styles$b.column, styles$b.columnRight)
|
|
33118
34000
|
}, /*#__PURE__*/React__namespace.createElement(Sortable
|
|
33119
34001
|
// @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
|
|
33120
34002
|
, {
|
|
@@ -33200,7 +34082,7 @@ ___default["default"].extend(Matcher, {
|
|
|
33200
34082
|
});
|
|
33201
34083
|
const padding = 5;
|
|
33202
34084
|
const border = "1px solid #444";
|
|
33203
|
-
const styles$
|
|
34085
|
+
const styles$b = aphrodite.StyleSheet.create({
|
|
33204
34086
|
widget: {
|
|
33205
34087
|
paddingTop: padding,
|
|
33206
34088
|
maxWidth: "100%",
|
|
@@ -33233,204 +34115,6 @@ var Matcher$1 = {
|
|
|
33233
34115
|
isLintable: true
|
|
33234
34116
|
};
|
|
33235
34117
|
|
|
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
34118
|
// Type imports
|
|
33435
34119
|
|
|
33436
34120
|
const {
|
|
@@ -34073,9 +34757,9 @@ function drawText(ctx, item) {
|
|
|
34073
34757
|
if (item.value === null) {
|
|
34074
34758
|
return;
|
|
34075
34759
|
}
|
|
34076
|
-
ctx.fillStyle = styles$
|
|
34077
|
-
ctx.font = styles$
|
|
34078
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
34760
|
+
ctx.fillStyle = styles$a.fgColor;
|
|
34761
|
+
ctx.font = styles$a.font;
|
|
34762
|
+
ctx.fillText(item.value, item.pos[0] - styles$a.fontSizePx / 2 + 1, item.pos[1] + styles$a.fontSizePx / 2);
|
|
34079
34763
|
}
|
|
34080
34764
|
|
|
34081
34765
|
/**
|
|
@@ -34096,16 +34780,16 @@ function drawText(ctx, item) {
|
|
|
34096
34780
|
function drawDoubleLine(ctx, item) {
|
|
34097
34781
|
// Outer line that forms both of the bond lines.
|
|
34098
34782
|
let path = new Path2D();
|
|
34099
|
-
ctx.lineWidth = 5 * styles$
|
|
34100
|
-
ctx.strokeStyle = styles$
|
|
34783
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34784
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34101
34785
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34102
34786
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34103
34787
|
ctx.stroke(path);
|
|
34104
34788
|
|
|
34105
34789
|
// Inner white line that separates the two bond lines.
|
|
34106
34790
|
path = new Path2D();
|
|
34107
|
-
ctx.lineWidth = 3 * styles$
|
|
34108
|
-
ctx.strokeStyle = styles$
|
|
34791
|
+
ctx.lineWidth = 3 * styles$a.lineWidth;
|
|
34792
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34109
34793
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34110
34794
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34111
34795
|
ctx.stroke(path);
|
|
@@ -34132,16 +34816,16 @@ function drawTripleLine(ctx, item) {
|
|
|
34132
34816
|
|
|
34133
34817
|
// Outer line that will form the two outer bond lines.
|
|
34134
34818
|
let path = new Path2D();
|
|
34135
|
-
ctx.lineWidth = 7 * styles$
|
|
34136
|
-
ctx.strokeStyle = styles$
|
|
34819
|
+
ctx.lineWidth = 7 * styles$a.lineWidth;
|
|
34820
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34137
34821
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34138
34822
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34139
34823
|
ctx.stroke(path);
|
|
34140
34824
|
|
|
34141
34825
|
// Middle white line that separates the bonds
|
|
34142
34826
|
path = new Path2D();
|
|
34143
|
-
ctx.lineWidth = 5 * styles$
|
|
34144
|
-
ctx.strokeStyle = styles$
|
|
34827
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34828
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34145
34829
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34146
34830
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34147
34831
|
ctx.stroke(path);
|
|
@@ -34163,8 +34847,8 @@ function drawTripleLine(ctx, item) {
|
|
|
34163
34847
|
*/
|
|
34164
34848
|
function drawLine(ctx, item) {
|
|
34165
34849
|
const path = new Path2D();
|
|
34166
|
-
ctx.lineWidth = styles$
|
|
34167
|
-
ctx.strokeStyle = styles$
|
|
34850
|
+
ctx.lineWidth = styles$a.lineWidth;
|
|
34851
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34168
34852
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34169
34853
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34170
34854
|
ctx.stroke(path);
|
|
@@ -34216,7 +34900,7 @@ function compareElements(item0, item1) {
|
|
|
34216
34900
|
function draw(ctx, items) {
|
|
34217
34901
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
34218
34902
|
}
|
|
34219
|
-
const styles$
|
|
34903
|
+
const styles$a = {
|
|
34220
34904
|
bgColor: "rgb(255, 255, 255)",
|
|
34221
34905
|
fgColor: "rgb(0, 0, 0)",
|
|
34222
34906
|
fontSizePx: 12,
|
|
@@ -36780,7 +37464,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
36780
37464
|
const rects = this.state.cachedHighlightRects;
|
|
36781
37465
|
return /*#__PURE__*/React__namespace.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
36782
37466
|
key: index,
|
|
36783
|
-
className: aphrodite.css(styles$
|
|
37467
|
+
className: aphrodite.css(styles$9.highlightRect),
|
|
36784
37468
|
style: {
|
|
36785
37469
|
// NOTE(mdr): We apply `position: absolute` here
|
|
36786
37470
|
// rather than in Aphrodite styles, because
|
|
@@ -36799,7 +37483,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
36799
37483
|
})));
|
|
36800
37484
|
}
|
|
36801
37485
|
}
|
|
36802
|
-
const styles$
|
|
37486
|
+
const styles$9 = aphrodite.StyleSheet.create({
|
|
36803
37487
|
highlightRect: {
|
|
36804
37488
|
background: "#fffabe" // highlighter yellow :)
|
|
36805
37489
|
}
|
|
@@ -36880,7 +37564,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
36880
37564
|
// TooltipContent wouldn't let me overwrite
|
|
36881
37565
|
// user-select and onClick
|
|
36882
37566
|
const content = /*#__PURE__*/React__namespace.createElement("div", {
|
|
36883
|
-
className: aphrodite.css(styles$
|
|
37567
|
+
className: aphrodite.css(styles$8.tooltipLabel),
|
|
36884
37568
|
onClick: this.props.onClick
|
|
36885
37569
|
}, this.props.label);
|
|
36886
37570
|
const style = {
|
|
@@ -36900,7 +37584,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
36900
37584
|
}, /*#__PURE__*/React__namespace.createElement("div", null)));
|
|
36901
37585
|
}
|
|
36902
37586
|
}
|
|
36903
|
-
const styles$
|
|
37587
|
+
const styles$8 = aphrodite.StyleSheet.create({
|
|
36904
37588
|
tooltipLabel: {
|
|
36905
37589
|
// Unlike most tooltip contents, we don't want this label to be
|
|
36906
37590
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -37458,7 +38142,7 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
37458
38142
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
37459
38143
|
const buildHighlight = r => this._buildHighlight(r);
|
|
37460
38144
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
37461
|
-
className: aphrodite.css(styles$
|
|
38145
|
+
className: aphrodite.css(styles$7.container),
|
|
37462
38146
|
ref: container => this._container = container
|
|
37463
38147
|
}, /*#__PURE__*/React__namespace.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React__namespace.createElement(HighlightingUI, {
|
|
37464
38148
|
buildHighlight: buildHighlight,
|
|
@@ -37479,14 +38163,14 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
37479
38163
|
onAddHighlight: this._handleAddHighlight,
|
|
37480
38164
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
37481
38165
|
})), /*#__PURE__*/React__namespace.createElement("div", {
|
|
37482
|
-
className: aphrodite.css(styles$
|
|
38166
|
+
className: aphrodite.css(styles$7.content),
|
|
37483
38167
|
ref: content => this._content = content
|
|
37484
38168
|
}, /*#__PURE__*/React__namespace.createElement(WordIndexer, {
|
|
37485
38169
|
onWordsUpdate: this._handleWordsUpdate
|
|
37486
38170
|
}, this.props.children)));
|
|
37487
38171
|
}
|
|
37488
38172
|
}
|
|
37489
|
-
const styles$
|
|
38173
|
+
const styles$7 = aphrodite.StyleSheet.create({
|
|
37490
38174
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
37491
38175
|
// content will receive the browser's native pointer events. (Highlights
|
|
37492
38176
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -37882,7 +38566,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
37882
38566
|
}
|
|
37883
38567
|
render() {
|
|
37884
38568
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
37885
|
-
className: aphrodite.css(styles$
|
|
38569
|
+
className: aphrodite.css(styles$6.measurer),
|
|
37886
38570
|
"aria-hidden": "true"
|
|
37887
38571
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
37888
38572
|
ref: ref => this._line = ref,
|
|
@@ -37890,7 +38574,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
37890
38574
|
}, "Line Height Measurement"));
|
|
37891
38575
|
}
|
|
37892
38576
|
}
|
|
37893
|
-
const styles$
|
|
38577
|
+
const styles$6 = aphrodite.StyleSheet.create({
|
|
37894
38578
|
measurer: {
|
|
37895
38579
|
position: "absolute",
|
|
37896
38580
|
top: 0,
|
|
@@ -39202,7 +39886,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
39202
39886
|
// creator "went wild".
|
|
39203
39887
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
39204
39888
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
39205
|
-
style: styles$
|
|
39889
|
+
style: styles$5.container
|
|
39206
39890
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
39207
39891
|
sandbox: sandboxOptions,
|
|
39208
39892
|
src: url,
|
|
@@ -39211,7 +39895,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
39211
39895
|
}));
|
|
39212
39896
|
}
|
|
39213
39897
|
}
|
|
39214
|
-
const styles$
|
|
39898
|
+
const styles$5 = aphrodite.StyleSheet.create({
|
|
39215
39899
|
container: {
|
|
39216
39900
|
margin: "auto",
|
|
39217
39901
|
width: "100%"
|
|
@@ -39448,125 +40132,6 @@ var Sequence$1 = {
|
|
|
39448
40132
|
isLintable: true
|
|
39449
40133
|
};
|
|
39450
40134
|
|
|
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
40135
|
/* eslint-disable @typescript-eslint/no-unused-vars, react/no-unsafe, react/sort-comp */
|
|
39571
40136
|
const {
|
|
39572
40137
|
assert: assert$1
|
|
@@ -41524,7 +42089,7 @@ const VideoTranscriptLink = props => {
|
|
|
41524
42089
|
{
|
|
41525
42090
|
const video = result.data?.video;
|
|
41526
42091
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
41527
|
-
style: styles$
|
|
42092
|
+
style: styles$4.transcriptLink
|
|
41528
42093
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.Text, null, video?.title), /*#__PURE__*/React__namespace.createElement(wonderBlocksLayout.Strut, {
|
|
41529
42094
|
size: 10
|
|
41530
42095
|
}), /*#__PURE__*/React__namespace.createElement(Link__default["default"], {
|
|
@@ -41541,7 +42106,7 @@ const VideoTranscriptLink = props => {
|
|
|
41541
42106
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, i18n__namespace._("Something went wrong."));
|
|
41542
42107
|
}
|
|
41543
42108
|
};
|
|
41544
|
-
const styles$
|
|
42109
|
+
const styles$4 = aphrodite.StyleSheet.create({
|
|
41545
42110
|
transcriptLink: {
|
|
41546
42111
|
flexDirection: "row",
|
|
41547
42112
|
width: "100%",
|
|
@@ -41697,7 +42262,7 @@ const init = function (options) {
|
|
|
41697
42262
|
|
|
41698
42263
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41699
42264
|
const libName = "@khanacademy/perseus";
|
|
41700
|
-
const libVersion = "19.
|
|
42265
|
+
const libVersion = "19.7.1";
|
|
41701
42266
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41702
42267
|
|
|
41703
42268
|
const apiVersion = {
|
|
@@ -41910,7 +42475,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
41910
42475
|
const {
|
|
41911
42476
|
isMobile
|
|
41912
42477
|
} = apiOptions;
|
|
41913
|
-
const classNames = classNames__default["default"]("hint", !isMobile && "perseus-hint-renderer", isMobile && aphrodite.css(styles$
|
|
42478
|
+
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
42479
|
|
|
41915
42480
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
41916
42481
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -41951,7 +42516,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
41951
42516
|
);
|
|
41952
42517
|
}
|
|
41953
42518
|
}
|
|
41954
|
-
const styles$
|
|
42519
|
+
const styles$3 = aphrodite.StyleSheet.create({
|
|
41955
42520
|
newHint: {
|
|
41956
42521
|
marginBottom: 1.5 * baseUnitPx,
|
|
41957
42522
|
borderLeftColor: gray97,
|
|
@@ -42128,15 +42693,15 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
42128
42693
|
} = apiOptions;
|
|
42129
42694
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
42130
42695
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
42131
|
-
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$
|
|
42696
|
+
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$2.mobileHintStylesHintsRenderer));
|
|
42132
42697
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42133
42698
|
className: classNames
|
|
42134
42699
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React__namespace.createElement("div", {
|
|
42135
|
-
className: aphrodite.css(styles$
|
|
42700
|
+
className: aphrodite.css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
42136
42701
|
}, i18n__namespace._("Hints")), hints, showGetAnotherHint && /*#__PURE__*/React__namespace.createElement("button", {
|
|
42137
42702
|
// @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
42703
|
rel: "button",
|
|
42139
|
-
className: aphrodite.css(styles$
|
|
42704
|
+
className: aphrodite.css(styles$2.linkButton, styles$2.getAnotherHintButton, apiOptions.isMobile && styles$2.mobileHintStylesGetAnotherHintButton),
|
|
42140
42705
|
onClick: evt => {
|
|
42141
42706
|
evt.preventDefault();
|
|
42142
42707
|
evt.stopPropagation();
|
|
@@ -42145,14 +42710,14 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
42145
42710
|
}
|
|
42146
42711
|
}
|
|
42147
42712
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
42148
|
-
className: aphrodite.css(styles$
|
|
42713
|
+
className: aphrodite.css(styles$2.plusText, apiOptions.isMobile && styles$2.mobileHintStylesPlusText)
|
|
42149
42714
|
}, "+"), /*#__PURE__*/React__namespace.createElement("span", {
|
|
42150
|
-
className: aphrodite.css(styles$
|
|
42715
|
+
className: aphrodite.css(styles$2.getAnotherHintText)
|
|
42151
42716
|
}, i18n__namespace._("Get another hint"), " ", hintRatioCopy)));
|
|
42152
42717
|
}
|
|
42153
42718
|
}
|
|
42154
42719
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
42155
|
-
const styles$
|
|
42720
|
+
const styles$2 = aphrodite.StyleSheet.create({
|
|
42156
42721
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
42157
42722
|
rendererMargins: {
|
|
42158
42723
|
marginTop: baseUnitPx
|
|
@@ -42564,11 +43129,11 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
42564
43129
|
// mobile hint styles, which are flush to the left.
|
|
42565
43130
|
// NOTE(charlie): We may still want to apply this
|
|
42566
43131
|
// padding for desktop exercises.
|
|
42567
|
-
apiOptions.isMobile ? undefined : aphrodite.css(styles$
|
|
43132
|
+
apiOptions.isMobile ? undefined : aphrodite.css(styles$1.hintsContainer)
|
|
42568
43133
|
}, hintsRenderer)));
|
|
42569
43134
|
}
|
|
42570
43135
|
}
|
|
42571
|
-
const styles$
|
|
43136
|
+
const styles$1 = aphrodite.StyleSheet.create({
|
|
42572
43137
|
hintsContainer: {
|
|
42573
43138
|
marginLeft: 50
|
|
42574
43139
|
}
|
|
@@ -42705,339 +43270,6 @@ class ElementContainer extends React__namespace.Component {
|
|
|
42705
43270
|
}
|
|
42706
43271
|
}
|
|
42707
43272
|
|
|
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
43273
|
const devices = {
|
|
43042
43274
|
PHONE: "phone",
|
|
43043
43275
|
TABLET: "tablet",
|