@khanacademy/perseus 19.6.2 → 19.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +168 -0
- package/dist/es/index.js +978 -743
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +168 -0
- package/dist/index.js +975 -738
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +1 -0
- package/dist/perseus-types.d.ts +14 -2
- package/dist/renderer.d.ts +9 -0
- package/dist/server-item-renderer.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/widgets/expression.d.ts +6 -0
- package/dist/widgets/interactive-graph.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/segment.d.ts +5 -0
- package/dist/widgets/interactive-graphs/grid.d.ts +11 -0
- package/dist/widgets/interactive-graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/legacy-grid.d.ts +7 -0
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +79 -0
- package/dist/widgets/interactive-graphs/types.d.ts +9 -0
- package/dist/widgets/interactive-graphs/utils.d.ts +15 -0
- package/dist/widgets/label-image.d.ts +2 -0
- package/package.json +3 -2
package/dist/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() {
|
|
@@ -19315,6 +19316,15 @@ const isIdPathPrefix = function (prefixArray, wholeArray) {
|
|
|
19315
19316
|
// some return a custom-built object, some delegate to
|
|
19316
19317
|
// `WidgetJsonifyDeprecated` which returns an object containing widget props
|
|
19317
19318
|
// (filtered by deprecated keys)).
|
|
19319
|
+
/**
|
|
19320
|
+
* The Widget type represents the common API that the Renderer uses to interact
|
|
19321
|
+
* with all widgets. All widgets must implement the methods in this API, unless
|
|
19322
|
+
* they are marked as optional (?: ...).
|
|
19323
|
+
*
|
|
19324
|
+
* These methods are called on the widget ref and allow the renderer to
|
|
19325
|
+
* communicate with the individual widgets to coordinate actions such as
|
|
19326
|
+
* scoring, state serialization/deserialization, and focus management.
|
|
19327
|
+
*/
|
|
19318
19328
|
class Renderer extends React__namespace.Component {
|
|
19319
19329
|
// @ts-expect-error - TS2564 - Property '_foundTextNodes' has no initializer and is not definitely assigned in the constructor.
|
|
19320
19330
|
|
|
@@ -28316,7 +28326,875 @@ class Graph extends React__namespace.Component {
|
|
|
28316
28326
|
}
|
|
28317
28327
|
}
|
|
28318
28328
|
|
|
28319
|
-
|
|
28329
|
+
const useInteractivePoint = (coords, snaps, range) => mafs.useMovablePoint(coords, {
|
|
28330
|
+
constrain: coord => constrain(coord, snaps, range),
|
|
28331
|
+
color: Color__default["default"].blue
|
|
28332
|
+
});
|
|
28333
|
+
|
|
28334
|
+
/**
|
|
28335
|
+
* We do not want to call `onGraphChange` until the user
|
|
28336
|
+
* has interacted with the graph. See the test,
|
|
28337
|
+
* "should reject no interaction"
|
|
28338
|
+
*/
|
|
28339
|
+
const useEffectAfterFirstRender = (fn, deps) => {
|
|
28340
|
+
const firstRender = React.useRef(true);
|
|
28341
|
+
React.useEffect(() => {
|
|
28342
|
+
if (firstRender.current) {
|
|
28343
|
+
firstRender.current = false;
|
|
28344
|
+
return;
|
|
28345
|
+
}
|
|
28346
|
+
fn();
|
|
28347
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28348
|
+
}, [fn, ...deps]);
|
|
28349
|
+
};
|
|
28350
|
+
const snap = (val, step) => {
|
|
28351
|
+
const inverse = 1 / step;
|
|
28352
|
+
return Math.round(val * inverse) / inverse;
|
|
28353
|
+
};
|
|
28354
|
+
const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
|
|
28355
|
+
const constrain = (coord, snapStep, range) => {
|
|
28356
|
+
const [x, y] = coord;
|
|
28357
|
+
const [xSnap, ySnap] = snapStep;
|
|
28358
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
28359
|
+
return [clamp(snap(x, xSnap), xMin, xMax), clamp(snap(y, ySnap), yMin, yMax)];
|
|
28360
|
+
};
|
|
28361
|
+
|
|
28362
|
+
// same as pointsFromNormalized in interactive-graph.tsx
|
|
28363
|
+
const normalizePoints = (range, step, coordsList, noSnap) => coordsList.map(coords =>
|
|
28364
|
+
// maps over [x, y]
|
|
28365
|
+
coords.map((coord, i) => {
|
|
28366
|
+
const axisRange = range[i];
|
|
28367
|
+
if (noSnap) {
|
|
28368
|
+
return axisRange[0] + (axisRange[1] - axisRange[0]) * coord;
|
|
28369
|
+
}
|
|
28370
|
+
const axisStep = step[i];
|
|
28371
|
+
const nSteps = Math.floor((axisRange[1] - axisRange[0]) / axisStep);
|
|
28372
|
+
const tick = Math.round(coord * nSteps);
|
|
28373
|
+
return axisRange[0] + axisStep * tick;
|
|
28374
|
+
}));
|
|
28375
|
+
|
|
28376
|
+
// same as normalizeCoords in interactive-graph.tsx
|
|
28377
|
+
const normalizeCoords = (coordsList, ranges) => coordsList.map(coords => coords.map((coord, i) => {
|
|
28378
|
+
const extent = ranges[i][1] - ranges[i][0];
|
|
28379
|
+
return (coord + ranges[i][1]) / extent;
|
|
28380
|
+
}));
|
|
28381
|
+
|
|
28382
|
+
const getSegmentCoords = props => {
|
|
28383
|
+
const coords = props.graph.coords;
|
|
28384
|
+
if (coords) {
|
|
28385
|
+
return coords;
|
|
28386
|
+
}
|
|
28387
|
+
const ys = n => {
|
|
28388
|
+
switch (n) {
|
|
28389
|
+
case 2:
|
|
28390
|
+
return [5, -5];
|
|
28391
|
+
case 3:
|
|
28392
|
+
return [5, 0, -5];
|
|
28393
|
+
case 4:
|
|
28394
|
+
return [6, 2, -2, -6];
|
|
28395
|
+
case 5:
|
|
28396
|
+
return [6, 3, 0, -3, -6];
|
|
28397
|
+
case 6:
|
|
28398
|
+
return [5, 3, 1, -1, -3, -5];
|
|
28399
|
+
default:
|
|
28400
|
+
return [5];
|
|
28401
|
+
}
|
|
28402
|
+
};
|
|
28403
|
+
return ys(props.graph.numSegments).map(y => {
|
|
28404
|
+
let segment = [[-5, y], [5, y]];
|
|
28405
|
+
segment = normalizeCoords(segment, props.range);
|
|
28406
|
+
segment = normalizePoints(props.range, props.step, segment);
|
|
28407
|
+
return segment;
|
|
28408
|
+
});
|
|
28409
|
+
};
|
|
28410
|
+
const updateSegmentsArray = (segments, index, segment) => segments.map((seg, i) => index === i ? segment : seg);
|
|
28411
|
+
const SegmentGraph = props => {
|
|
28412
|
+
const segments = getSegmentCoords(props);
|
|
28413
|
+
const handleChange = (i, segment) => props.onGraphChange(current => ({
|
|
28414
|
+
...current,
|
|
28415
|
+
coords: current.coords ? updateSegmentsArray(current.coords, i, segment) : updateSegmentsArray(segments, i, segment)
|
|
28416
|
+
}));
|
|
28417
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, segments.map((segment, i) => /*#__PURE__*/React__namespace.createElement(Segment, {
|
|
28418
|
+
key: i,
|
|
28419
|
+
i: i,
|
|
28420
|
+
segment: segment,
|
|
28421
|
+
snaps: props.snapStep,
|
|
28422
|
+
range: props.range,
|
|
28423
|
+
onChange: handleChange,
|
|
28424
|
+
"data-testid": "segment" + i
|
|
28425
|
+
})));
|
|
28426
|
+
};
|
|
28427
|
+
const Segment = props => {
|
|
28428
|
+
const [start, end] = props.segment;
|
|
28429
|
+
const {
|
|
28430
|
+
point: pt1,
|
|
28431
|
+
element: el1
|
|
28432
|
+
} = useInteractivePoint(start, props.snaps, props.range);
|
|
28433
|
+
const {
|
|
28434
|
+
point: pt2,
|
|
28435
|
+
element: el2
|
|
28436
|
+
} = useInteractivePoint(end, props.snaps, props.range);
|
|
28437
|
+
useEffectAfterFirstRender(() => props.onChange(props.i, [pt1, pt2]), [pt1, pt2]);
|
|
28438
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Line.Segment, {
|
|
28439
|
+
point1: pt1,
|
|
28440
|
+
point2: pt2
|
|
28441
|
+
}), el1, el2);
|
|
28442
|
+
};
|
|
28443
|
+
|
|
28444
|
+
const renderLineLabel = (n, _ref) => {
|
|
28445
|
+
let [min, max] = _ref;
|
|
28446
|
+
return n !== -1 && n !== min && n !== max;
|
|
28447
|
+
};
|
|
28448
|
+
const axisOptions = (props, index) => ({
|
|
28449
|
+
axis: props.markings === "graph",
|
|
28450
|
+
lines: props.step[index],
|
|
28451
|
+
subdivisions: props.step[index] / props.gridStep[index],
|
|
28452
|
+
labels: n => renderLineLabel(n, props.range[index]) ? n : ""
|
|
28453
|
+
});
|
|
28454
|
+
const Grid = props => props.markings === "none" ? null : /*#__PURE__*/React__namespace.createElement(mafs.Coordinates.Cartesian, {
|
|
28455
|
+
xAxis: axisOptions(props, 0),
|
|
28456
|
+
yAxis: axisOptions(props, 1)
|
|
28457
|
+
});
|
|
28458
|
+
|
|
28459
|
+
// Displays a stylized open eye: lint warnings are visible
|
|
28460
|
+
const VisibleIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
28461
|
+
width: "24",
|
|
28462
|
+
height: "24",
|
|
28463
|
+
viewBox: "0 0 24 24",
|
|
28464
|
+
className: aphrodite.css(styles$j.icon)
|
|
28465
|
+
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28466
|
+
id: "a",
|
|
28467
|
+
d: "M7.401 10.035c-1.424.748-2.599 1.905-3.544 " + "3.48a1 1 0 0 1-1.714-1.03C4.325 8.849 7.652 7 " + "12 7c4.348 0 7.675 1.848 9.857 5.486a1 1 0 0 " + "1-1.714 1.028c-.945-1.574-2.12-2.73-3.544-" + "3.48a5 5 0 1 1-9.198 0zM12 15a3 3 0 1 0 0-6 3 3 " + "0 0 0 0 6z"
|
|
28468
|
+
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28469
|
+
fill: "none",
|
|
28470
|
+
fillRule: "evenodd"
|
|
28471
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28472
|
+
fill: "none",
|
|
28473
|
+
d: "M0 0h24v24H0z"
|
|
28474
|
+
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
28475
|
+
id: "b",
|
|
28476
|
+
fill: "#fff"
|
|
28477
|
+
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
28478
|
+
href: "#a"
|
|
28479
|
+
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
28480
|
+
fill: "#fff",
|
|
28481
|
+
fillRule: "nonzero",
|
|
28482
|
+
href: "#a"
|
|
28483
|
+
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28484
|
+
fill: "#fff",
|
|
28485
|
+
mask: "url(#b)"
|
|
28486
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28487
|
+
d: "M0 0h24v24H0z"
|
|
28488
|
+
}))));
|
|
28489
|
+
|
|
28490
|
+
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
28491
|
+
const HiddenIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
28492
|
+
width: "24",
|
|
28493
|
+
height: "24",
|
|
28494
|
+
viewBox: "0 0 24 24",
|
|
28495
|
+
className: aphrodite.css(styles$j.icon)
|
|
28496
|
+
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28497
|
+
id: "a",
|
|
28498
|
+
d: "M8.794 7.38C9.791 7.127 10.86 7 12 7c4.348 0 " + "7.675 1.848 9.857 5.486a1 1 0 0 1-1.714 " + "1.028c-.945-1.574-2.12-2.73-3.544-3.48.258." + "604.401 1.268.401 1.966 0 1.02-.305 " + "1.967-.828 2.757l2.535 2.536a1 1 0 0 " + "1-1.414 1.414l-12-12a1 1 0 0 1 " + "1.414-1.414L8.794 7.38zm5.914 5.913a3 3 0 0 " + "0-4.001-4.001l4 4.001zM6.072 8.486l2.976 " + "2.976a3 3 0 0 0 3.49 3.49l1.579 1.58A5 5 0 " + "0 1 7.4 10.035c-1.424.747-2.599 1.904-3.544 " + "3.478a1 1 0 0 1-1.714-1.028c1.049-1.75 " + "2.363-3.085 3.929-4z"
|
|
28499
|
+
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28500
|
+
fill: "none",
|
|
28501
|
+
fillRule: "evenodd"
|
|
28502
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28503
|
+
fill: "none",
|
|
28504
|
+
d: "M0 0h24v24H0z"
|
|
28505
|
+
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
28506
|
+
id: "b",
|
|
28507
|
+
fill: "#fff"
|
|
28508
|
+
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
28509
|
+
href: "#a"
|
|
28510
|
+
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
28511
|
+
fill: "#fff",
|
|
28512
|
+
fillRule: "nonzero",
|
|
28513
|
+
href: "#a"
|
|
28514
|
+
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28515
|
+
fill: "#fff",
|
|
28516
|
+
mask: "url(#b)"
|
|
28517
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28518
|
+
d: "M0 0h24v24H0z"
|
|
28519
|
+
}))));
|
|
28520
|
+
const HUD = _ref => {
|
|
28521
|
+
let {
|
|
28522
|
+
message,
|
|
28523
|
+
enabled,
|
|
28524
|
+
onClick,
|
|
28525
|
+
fixedPosition = true
|
|
28526
|
+
} = _ref;
|
|
28527
|
+
let state;
|
|
28528
|
+
let icon;
|
|
28529
|
+
if (enabled) {
|
|
28530
|
+
state = styles$j.enabled;
|
|
28531
|
+
icon = /*#__PURE__*/React__namespace.createElement(VisibleIcon, null);
|
|
28532
|
+
} else {
|
|
28533
|
+
state = styles$j.disabled;
|
|
28534
|
+
icon = /*#__PURE__*/React__namespace.createElement(HiddenIcon, null);
|
|
28535
|
+
}
|
|
28536
|
+
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
28537
|
+
className: aphrodite.css(styles$j.hud, fixedPosition && styles$j.hudFixedPosition, state),
|
|
28538
|
+
onClick: e => {
|
|
28539
|
+
onClick();
|
|
28540
|
+
}
|
|
28541
|
+
}, icon, message);
|
|
28542
|
+
};
|
|
28543
|
+
const styles$j = aphrodite.StyleSheet.create({
|
|
28544
|
+
hud: {
|
|
28545
|
+
boxSizing: "border-box",
|
|
28546
|
+
height: 36,
|
|
28547
|
+
padding: "9px 16px",
|
|
28548
|
+
borderRadius: 18,
|
|
28549
|
+
fontFamily: boldFontFamily,
|
|
28550
|
+
fontSize: "15px",
|
|
28551
|
+
lineHeight: "18px",
|
|
28552
|
+
color: white$1,
|
|
28553
|
+
userSelect: "none",
|
|
28554
|
+
borderWidth: 0 // <button> gives us a border by default
|
|
28555
|
+
},
|
|
28556
|
+
|
|
28557
|
+
// We want to render the element in-place in our fixtures, so allow us to
|
|
28558
|
+
// render in the bottom corner in production and in-place in testing.
|
|
28559
|
+
hudFixedPosition: {
|
|
28560
|
+
bottom: 20,
|
|
28561
|
+
position: "fixed",
|
|
28562
|
+
right: 20,
|
|
28563
|
+
zIndex: 1
|
|
28564
|
+
},
|
|
28565
|
+
icon: {
|
|
28566
|
+
width: 24,
|
|
28567
|
+
height: 24,
|
|
28568
|
+
marginRight: 8,
|
|
28569
|
+
marginTop: -3,
|
|
28570
|
+
verticalAlign: "middle"
|
|
28571
|
+
},
|
|
28572
|
+
enabled: {
|
|
28573
|
+
backgroundColor: warningColor,
|
|
28574
|
+
":hover": {
|
|
28575
|
+
backgroundColor: warningColorHover
|
|
28576
|
+
},
|
|
28577
|
+
":active": {
|
|
28578
|
+
backgroundColor: warningColorActive
|
|
28579
|
+
}
|
|
28580
|
+
},
|
|
28581
|
+
disabled: {
|
|
28582
|
+
backgroundColor: gray76,
|
|
28583
|
+
":hover": {
|
|
28584
|
+
backgroundColor: "#a1a5a9" // in between those two grays
|
|
28585
|
+
},
|
|
28586
|
+
|
|
28587
|
+
":active": {
|
|
28588
|
+
backgroundColor: gray68
|
|
28589
|
+
}
|
|
28590
|
+
}
|
|
28591
|
+
});
|
|
28592
|
+
|
|
28593
|
+
const colors$1 = {
|
|
28594
|
+
grayLight: "#aaa",
|
|
28595
|
+
basicBorderColor: "#ccc",
|
|
28596
|
+
white: "#fff"
|
|
28597
|
+
};
|
|
28598
|
+
const triangleBeforeAfter = {
|
|
28599
|
+
borderBottom: "9px solid transparent",
|
|
28600
|
+
borderTop: "9px solid transparent",
|
|
28601
|
+
content: '" "',
|
|
28602
|
+
height: "0",
|
|
28603
|
+
position: "absolute",
|
|
28604
|
+
top: "0",
|
|
28605
|
+
width: "0"
|
|
28606
|
+
};
|
|
28607
|
+
const styles$i = aphrodite.StyleSheet.create({
|
|
28608
|
+
infoTip: {
|
|
28609
|
+
display: "inline-block",
|
|
28610
|
+
marginLeft: "5px",
|
|
28611
|
+
position: "relative"
|
|
28612
|
+
},
|
|
28613
|
+
infoTipContainer: {
|
|
28614
|
+
position: "absolute",
|
|
28615
|
+
top: "-12px",
|
|
28616
|
+
left: "22px",
|
|
28617
|
+
zIndex: 1000
|
|
28618
|
+
},
|
|
28619
|
+
infoTipTriangle: {
|
|
28620
|
+
height: "10px",
|
|
28621
|
+
left: "0",
|
|
28622
|
+
position: "absolute",
|
|
28623
|
+
top: "8px",
|
|
28624
|
+
width: "0",
|
|
28625
|
+
zIndex: 1,
|
|
28626
|
+
":before": {
|
|
28627
|
+
...triangleBeforeAfter,
|
|
28628
|
+
borderRight: "9px solid #bbb",
|
|
28629
|
+
right: "0"
|
|
28630
|
+
},
|
|
28631
|
+
":after": {
|
|
28632
|
+
...triangleBeforeAfter,
|
|
28633
|
+
borderRight: `9px solid ${colors$1.white}`,
|
|
28634
|
+
right: "-1px"
|
|
28635
|
+
}
|
|
28636
|
+
},
|
|
28637
|
+
verticalShadow: {
|
|
28638
|
+
border: `1px solid ${colors$1.basicBorderColor}`,
|
|
28639
|
+
boxShadow: `0 1px 3px ${colors$1.basicBorderColor}`,
|
|
28640
|
+
borderBottom: `1px solid ${colors$1.grayLight}`
|
|
28641
|
+
},
|
|
28642
|
+
infoTipContentContainer: {
|
|
28643
|
+
background: colors$1.white,
|
|
28644
|
+
padding: "5px 10px",
|
|
28645
|
+
width: "240px"
|
|
28646
|
+
}
|
|
28647
|
+
});
|
|
28648
|
+
const questionMark = "data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAGXRFWHRTb2Z0d2FyZQBB" + "ZG9iZSBJbWFnZVJlYWR5ccllPAAAA3NpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/" + "eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+" + "IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2Jl" + "IFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAg" + "ICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5" + "LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9" + "IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHht" + "bG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3Vy" + "Y2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHht" + "cE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo2N2M3NTAxYS04YmVlLTQ0M2Mt" + "YmRiNS04OGM2N2IxN2NhYzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUJCRTk4" + "Qjc4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5p" + "aWQ6OUJCRTk4QjY4NjAwMTFFMzg3QUJDNEI4Mzk2QTRGQkQiIHhtcDpDcmVhdG9yVG9v" + "bD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRG" + "cm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NGE5ZDI0OTMtODk1NC00OGFkLTlh" + "MTgtZDAwM2MwYWNjNDJlIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY3Yzc1MDFh" + "LThiZWUtNDQzYy1iZGI1LTg4YzY3YjE3Y2FjMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4g" + "PC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pqm89uYAAADM" + "SURBVHjaXJA9DoJAEIUH1M4TUHIFsCMGen9OwCGw1YRGW2ntKel0exsojHIBC0ouQAyU" + "viFDstmXfNmZeS+zm7XSNCXRFiRgJf0bXIHixpbhGdxBBJYC1w/xaA424MhNEATkui71" + "fU9KqfEU78UbD9PdbJRlOdae55GmhIP+1NV1TcMwkOM41DSNHvRtMhTHMRVFQW3b6mOL" + "gx99kue5GRp/gIOZuZGvNpTNwjD8oliANU+qqqKu6/TQBdymN57AHjzBT+B6Jx79BRgA" + "vc49kQA4yxgAAAAASUVORK5CYII=";
|
|
28649
|
+
class InfoTip$1 extends React__namespace.Component {
|
|
28650
|
+
state = {
|
|
28651
|
+
hover: false
|
|
28652
|
+
};
|
|
28653
|
+
handleMouseEnter = () => {
|
|
28654
|
+
this.setState({
|
|
28655
|
+
hover: true
|
|
28656
|
+
});
|
|
28657
|
+
};
|
|
28658
|
+
handleMouseLeave = () => {
|
|
28659
|
+
this.setState({
|
|
28660
|
+
hover: false
|
|
28661
|
+
});
|
|
28662
|
+
};
|
|
28663
|
+
render() {
|
|
28664
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28665
|
+
className: aphrodite.css(styles$i.infoTip)
|
|
28666
|
+
}, /*#__PURE__*/React__namespace.createElement("img", {
|
|
28667
|
+
alt: "",
|
|
28668
|
+
width: 10,
|
|
28669
|
+
height: 10,
|
|
28670
|
+
src: questionMark,
|
|
28671
|
+
onMouseEnter: this.handleMouseEnter,
|
|
28672
|
+
onMouseLeave: this.handleMouseLeave
|
|
28673
|
+
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
28674
|
+
className: aphrodite.css(styles$i.infoTipContainer),
|
|
28675
|
+
style: {
|
|
28676
|
+
display: this.state.hover ? "block" : "none"
|
|
28677
|
+
}
|
|
28678
|
+
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
28679
|
+
className: aphrodite.css(styles$i.infoTipTriangle)
|
|
28680
|
+
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
28681
|
+
className: aphrodite.css(styles$i.verticalShadow, styles$i.infoTipContentContainer)
|
|
28682
|
+
}, this.props.children)));
|
|
28683
|
+
}
|
|
28684
|
+
}
|
|
28685
|
+
|
|
28686
|
+
/**
|
|
28687
|
+
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
28688
|
+
* server without causing a checksum mismatch on the client.
|
|
28689
|
+
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
28690
|
+
* two sets of generated classnames will not match.)
|
|
28691
|
+
*/
|
|
28692
|
+
class InfoTip extends React__namespace.Component {
|
|
28693
|
+
state = {
|
|
28694
|
+
didMount: false
|
|
28695
|
+
};
|
|
28696
|
+
componentDidMount() {
|
|
28697
|
+
/* eslint-disable react/no-did-mount-set-state */
|
|
28698
|
+
this.setState({
|
|
28699
|
+
didMount: true
|
|
28700
|
+
});
|
|
28701
|
+
/* eslint-enable react/no-did-mount-set-state */
|
|
28702
|
+
}
|
|
28703
|
+
|
|
28704
|
+
render() {
|
|
28705
|
+
if (this.state.didMount) {
|
|
28706
|
+
return /*#__PURE__*/React__namespace.createElement(InfoTip$1, this.props);
|
|
28707
|
+
}
|
|
28708
|
+
return /*#__PURE__*/React__namespace.createElement("div", null);
|
|
28709
|
+
}
|
|
28710
|
+
}
|
|
28711
|
+
|
|
28712
|
+
/**
|
|
28713
|
+
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
28714
|
+
* which allows multiple buttons to be selected at the same time.
|
|
28715
|
+
*
|
|
28716
|
+
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
28717
|
+
* this component allows multiple selection!
|
|
28718
|
+
*/
|
|
28719
|
+
class MultiButtonGroup extends React__namespace.Component {
|
|
28720
|
+
static defaultProps = {
|
|
28721
|
+
values: [],
|
|
28722
|
+
allowEmpty: true
|
|
28723
|
+
};
|
|
28724
|
+
focus() {
|
|
28725
|
+
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28726
|
+
ReactDOM__namespace.findDOMNode(this)?.focus();
|
|
28727
|
+
return true;
|
|
28728
|
+
}
|
|
28729
|
+
toggleSelect = newValue => {
|
|
28730
|
+
const values = (this.props.values || []).slice(0);
|
|
28731
|
+
const allowEmpty = this.props.allowEmpty;
|
|
28732
|
+
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
28733
|
+
// If the value is already selected, unselect it
|
|
28734
|
+
values.splice(values.indexOf(newValue), 1);
|
|
28735
|
+
} else {
|
|
28736
|
+
// Otherwise merge with other values and return
|
|
28737
|
+
if (values.indexOf(newValue) < 0) {
|
|
28738
|
+
values.push(newValue);
|
|
28739
|
+
}
|
|
28740
|
+
}
|
|
28741
|
+
this.props.onChange(values);
|
|
28742
|
+
};
|
|
28743
|
+
render() {
|
|
28744
|
+
const values = this.props.values || [];
|
|
28745
|
+
const buttons = this.props.buttons.map((button, i) => {
|
|
28746
|
+
const selected = values.indexOf(button.value) >= 0;
|
|
28747
|
+
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
28748
|
+
title: button.title,
|
|
28749
|
+
type: "button",
|
|
28750
|
+
id: "" + i,
|
|
28751
|
+
key: "" + i,
|
|
28752
|
+
ref: "button" + i,
|
|
28753
|
+
className: aphrodite.css(styles$h.buttonStyle, selected && styles$h.selectedStyle),
|
|
28754
|
+
onClick: () => this.toggleSelect(button.value)
|
|
28755
|
+
}, button.content || "" + button.value);
|
|
28756
|
+
});
|
|
28757
|
+
const outerStyle = {
|
|
28758
|
+
display: "inline-block"
|
|
28759
|
+
};
|
|
28760
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
28761
|
+
style: outerStyle
|
|
28762
|
+
}, buttons);
|
|
28763
|
+
}
|
|
28764
|
+
}
|
|
28765
|
+
const styles$h = aphrodite.StyleSheet.create({
|
|
28766
|
+
buttonStyle: {
|
|
28767
|
+
backgroundColor: "white",
|
|
28768
|
+
border: "1px solid #ccc",
|
|
28769
|
+
borderLeft: "0",
|
|
28770
|
+
cursor: "pointer",
|
|
28771
|
+
margin: "0",
|
|
28772
|
+
padding: "5px 10px",
|
|
28773
|
+
position: "relative",
|
|
28774
|
+
// for hover
|
|
28775
|
+
|
|
28776
|
+
":first-child": {
|
|
28777
|
+
borderLeft: "1px solid #ccc",
|
|
28778
|
+
borderTopLeftRadius: "3px",
|
|
28779
|
+
borderBottomLeftRadius: "3px"
|
|
28780
|
+
},
|
|
28781
|
+
":last-child": {
|
|
28782
|
+
borderRight: "1px solid #ccc",
|
|
28783
|
+
borderTopRightRadius: "3px",
|
|
28784
|
+
borderBottomRightRadius: "3px"
|
|
28785
|
+
},
|
|
28786
|
+
":hover": {
|
|
28787
|
+
backgroundColor: "#ccc"
|
|
28788
|
+
},
|
|
28789
|
+
":focus": {
|
|
28790
|
+
zIndex: 2
|
|
28791
|
+
}
|
|
28792
|
+
},
|
|
28793
|
+
selectedStyle: {
|
|
28794
|
+
backgroundColor: "#ddd"
|
|
28795
|
+
}
|
|
28796
|
+
});
|
|
28797
|
+
|
|
28798
|
+
const {
|
|
28799
|
+
firstNumericalParse,
|
|
28800
|
+
captureScratchpadTouchStart
|
|
28801
|
+
} = Util;
|
|
28802
|
+
const toNumericString = KhanMath.toNumericString;
|
|
28803
|
+
const getNumericFormat = KhanMath.getNumericFormat;
|
|
28804
|
+
|
|
28805
|
+
/* An input box that accepts only numeric strings
|
|
28806
|
+
*
|
|
28807
|
+
* Calls onChange(value, format) for valid numbers.
|
|
28808
|
+
* Reverts to the current value onBlur or on [ENTER],
|
|
28809
|
+
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
28810
|
+
* Accepts empty input and sends it to onChange as null
|
|
28811
|
+
* if no numeric placeholder is set.
|
|
28812
|
+
* If given a checkValidity function, will turn
|
|
28813
|
+
* the background/outline red when invalid
|
|
28814
|
+
* If useArrowKeys is set to true, up/down arrows will
|
|
28815
|
+
* increment/decrement integers
|
|
28816
|
+
* Optionally takes a size ("mini", "small", "normal")
|
|
28817
|
+
*/
|
|
28818
|
+
class NumberInput extends React__namespace.Component {
|
|
28819
|
+
static propTypes = {
|
|
28820
|
+
value: PropTypes__default["default"].number,
|
|
28821
|
+
format: PropTypes__default["default"].string,
|
|
28822
|
+
placeholder: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].number]),
|
|
28823
|
+
onChange: PropTypes__default["default"].func.isRequired,
|
|
28824
|
+
onFormatChange: PropTypes__default["default"].func,
|
|
28825
|
+
checkValidity: PropTypes__default["default"].func,
|
|
28826
|
+
size: PropTypes__default["default"].string,
|
|
28827
|
+
label: PropTypes__default["default"].oneOf(["put your labels outside your inputs!"])
|
|
28828
|
+
};
|
|
28829
|
+
static defaultProps = {
|
|
28830
|
+
value: null,
|
|
28831
|
+
placeholder: null,
|
|
28832
|
+
format: null,
|
|
28833
|
+
onFormatChange: () => null,
|
|
28834
|
+
checkValidity: () => true,
|
|
28835
|
+
useArrowKeys: false
|
|
28836
|
+
};
|
|
28837
|
+
state = {
|
|
28838
|
+
format: this.props.format
|
|
28839
|
+
};
|
|
28840
|
+
render() {
|
|
28841
|
+
let classes = classNames__default["default"]({
|
|
28842
|
+
"number-input": true,
|
|
28843
|
+
"invalid-input": !this._checkValidity(this.props.value),
|
|
28844
|
+
mini: this.props.size === "mini",
|
|
28845
|
+
small: this.props.size === "small",
|
|
28846
|
+
normal: this.props.size === "normal"
|
|
28847
|
+
});
|
|
28848
|
+
if (this.props.className != null) {
|
|
28849
|
+
classes = classes + " " + this.props.className;
|
|
28850
|
+
}
|
|
28851
|
+
const {
|
|
28852
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28853
|
+
onFormatChange,
|
|
28854
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28855
|
+
checkValidity,
|
|
28856
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28857
|
+
useArrowKeys,
|
|
28858
|
+
...restProps
|
|
28859
|
+
} = this.props;
|
|
28860
|
+
return /*#__PURE__*/React__namespace.createElement("input", _extends({}, restProps, {
|
|
28861
|
+
className: classes,
|
|
28862
|
+
type: "text"
|
|
28863
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28864
|
+
,
|
|
28865
|
+
ref: "input",
|
|
28866
|
+
onChange: this._handleChange,
|
|
28867
|
+
onFocus: this._handleFocus,
|
|
28868
|
+
onBlur: this._handleBlur,
|
|
28869
|
+
onKeyPress: this._handleBlur,
|
|
28870
|
+
onKeyDown: this._onKeyDown
|
|
28871
|
+
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
28872
|
+
,
|
|
28873
|
+
onTouchStart: captureScratchpadTouchStart,
|
|
28874
|
+
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
28875
|
+
value: undefined
|
|
28876
|
+
}));
|
|
28877
|
+
}
|
|
28878
|
+
componentDidUpdate(prevProps) {
|
|
28879
|
+
if (!kmath.number.equal(this.getValue(), this.props.value)) {
|
|
28880
|
+
this._setValue(this.props.value, this.state.format);
|
|
28881
|
+
}
|
|
28882
|
+
}
|
|
28883
|
+
|
|
28884
|
+
/* Return the current "value" of this input
|
|
28885
|
+
* If empty, it returns the placeholder (if it is a number) or null
|
|
28886
|
+
*/
|
|
28887
|
+
getValue = () => {
|
|
28888
|
+
return this.parseInputValue(
|
|
28889
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28890
|
+
ReactDOM__default["default"].findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
28891
|
+
);
|
|
28892
|
+
};
|
|
28893
|
+
|
|
28894
|
+
/* Return the current string value of this input */
|
|
28895
|
+
getStringValue = () => {
|
|
28896
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
28897
|
+
return ReactDOM__default["default"].findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
28898
|
+
};
|
|
28899
|
+
|
|
28900
|
+
parseInputValue = value => {
|
|
28901
|
+
if (value === "") {
|
|
28902
|
+
const placeholder = this.props.placeholder;
|
|
28903
|
+
return ___default["default"].isFinite(placeholder) ? +placeholder : null;
|
|
28904
|
+
}
|
|
28905
|
+
const result = firstNumericalParse(value);
|
|
28906
|
+
return ___default["default"].isFinite(result) ? result : this.props.value;
|
|
28907
|
+
};
|
|
28908
|
+
|
|
28909
|
+
/* Set text input focus to this input */
|
|
28910
|
+
focus = () => {
|
|
28911
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
28912
|
+
ReactDOM__default["default"].findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
28913
|
+
this._handleFocus();
|
|
28914
|
+
};
|
|
28915
|
+
blur = () => {
|
|
28916
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
28917
|
+
ReactDOM__default["default"].findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
28918
|
+
this._handleBlur();
|
|
28919
|
+
};
|
|
28920
|
+
setSelectionRange = (selectionStart, selectionEnd) => {
|
|
28921
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
28922
|
+
ReactDOM__default["default"].findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
28923
|
+
};
|
|
28924
|
+
getSelectionStart = () => {
|
|
28925
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
28926
|
+
return ReactDOM__default["default"].findDOMNode(this).selectionStart;
|
|
28927
|
+
};
|
|
28928
|
+
getSelectionEnd = () => {
|
|
28929
|
+
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
28930
|
+
return ReactDOM__default["default"].findDOMNode(this).selectionEnd;
|
|
28931
|
+
};
|
|
28932
|
+
_checkValidity = value => {
|
|
28933
|
+
if (value == null) {
|
|
28934
|
+
return true;
|
|
28935
|
+
}
|
|
28936
|
+
const val = firstNumericalParse(value);
|
|
28937
|
+
const checkValidity = this.props.checkValidity;
|
|
28938
|
+
return ___default["default"].isFinite(val) && checkValidity(val);
|
|
28939
|
+
};
|
|
28940
|
+
_handleChange = e => {
|
|
28941
|
+
const text = e.target.value;
|
|
28942
|
+
const value = this.parseInputValue(text);
|
|
28943
|
+
const format = getNumericFormat(text);
|
|
28944
|
+
this.props.onChange(value);
|
|
28945
|
+
if (format) {
|
|
28946
|
+
this.props.onFormatChange(value, format);
|
|
28947
|
+
this.setState({
|
|
28948
|
+
format: format
|
|
28949
|
+
});
|
|
28950
|
+
}
|
|
28951
|
+
};
|
|
28952
|
+
_handleFocus = () => {
|
|
28953
|
+
if (this.props.onFocus) {
|
|
28954
|
+
this.props.onFocus();
|
|
28955
|
+
}
|
|
28956
|
+
};
|
|
28957
|
+
_handleBlur = e => {
|
|
28958
|
+
// Only continue on blur or "enter"
|
|
28959
|
+
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
28960
|
+
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
28961
|
+
return;
|
|
28962
|
+
}
|
|
28963
|
+
this._setValue(this.props.value, this.state.format);
|
|
28964
|
+
if (this.props.onBlur) {
|
|
28965
|
+
this.props.onBlur();
|
|
28966
|
+
}
|
|
28967
|
+
};
|
|
28968
|
+
_onKeyDown = e => {
|
|
28969
|
+
if (this.props.onKeyDown) {
|
|
28970
|
+
this.props.onKeyDown(e);
|
|
28971
|
+
}
|
|
28972
|
+
if (!this.props.useArrowKeys || !___default["default"].contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
28973
|
+
return;
|
|
28974
|
+
}
|
|
28975
|
+
let val = this.getValue();
|
|
28976
|
+
if (val !== Math.floor(val)) {
|
|
28977
|
+
return; // bail if not an integer
|
|
28978
|
+
}
|
|
28979
|
+
|
|
28980
|
+
if (e.key === "ArrowUp") {
|
|
28981
|
+
val = val + 1;
|
|
28982
|
+
} else if (e.key === "ArrowDown") {
|
|
28983
|
+
val = val - 1;
|
|
28984
|
+
}
|
|
28985
|
+
if (this._checkValidity(val)) {
|
|
28986
|
+
this.props.onChange(val);
|
|
28987
|
+
}
|
|
28988
|
+
};
|
|
28989
|
+
_setValue = (val, format) => {
|
|
28990
|
+
// eslint-disable-next-line react/no-string-refs
|
|
28991
|
+
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
28992
|
+
$__default["default"](ReactDOM__default["default"].findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
28993
|
+
};
|
|
28994
|
+
}
|
|
28995
|
+
|
|
28996
|
+
/* eslint-disable @babel/no-invalid-this */
|
|
28997
|
+
|
|
28998
|
+
/* A checkbox that syncs its value to props using the
|
|
28999
|
+
* renderer's onChange method, and gets the prop name
|
|
29000
|
+
* dynamically from its props list
|
|
29001
|
+
*/
|
|
29002
|
+
const PropCheckBox = createReactClass__default["default"]({
|
|
29003
|
+
displayName: "PropCheckBox",
|
|
29004
|
+
propTypes: {
|
|
29005
|
+
labelAlignment: PropTypes__default["default"].oneOf(["left", "right"])
|
|
29006
|
+
},
|
|
29007
|
+
DEFAULT_PROPS: {
|
|
29008
|
+
label: null,
|
|
29009
|
+
onChange: null,
|
|
29010
|
+
labelAlignment: "left"
|
|
29011
|
+
},
|
|
29012
|
+
getDefaultProps: function () {
|
|
29013
|
+
return this.DEFAULT_PROPS;
|
|
29014
|
+
},
|
|
29015
|
+
propName: function () {
|
|
29016
|
+
const propName = ___default["default"].find(___default["default"].keys(this.props), function (localPropName) {
|
|
29017
|
+
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
29018
|
+
return !___default["default"].has(this.DEFAULT_PROPS, localPropName);
|
|
29019
|
+
}, this);
|
|
29020
|
+
if (!propName) {
|
|
29021
|
+
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
29022
|
+
}
|
|
29023
|
+
return propName;
|
|
29024
|
+
},
|
|
29025
|
+
_labelAlignLeft: function () {
|
|
29026
|
+
return this.props.labelAlignment === "left";
|
|
29027
|
+
},
|
|
29028
|
+
render: function () {
|
|
29029
|
+
const propName = this.propName();
|
|
29030
|
+
return /*#__PURE__*/React__namespace.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React__namespace.createElement("input", {
|
|
29031
|
+
type: "checkbox",
|
|
29032
|
+
checked: this.props[propName],
|
|
29033
|
+
onChange: this.toggle
|
|
29034
|
+
}), !this._labelAlignLeft() && this.props.label);
|
|
29035
|
+
},
|
|
29036
|
+
toggle: function () {
|
|
29037
|
+
const propName = this.propName();
|
|
29038
|
+
const changes = {};
|
|
29039
|
+
changes[propName] = !this.props[propName];
|
|
29040
|
+
this.props.onChange(changes);
|
|
29041
|
+
}
|
|
29042
|
+
});
|
|
29043
|
+
|
|
29044
|
+
const truth = () => true;
|
|
29045
|
+
|
|
29046
|
+
/* A minor abstraction on top of NumberInput for ranges
|
|
29047
|
+
*
|
|
29048
|
+
*/
|
|
29049
|
+
class RangeInput extends React__namespace.Component {
|
|
29050
|
+
static propTypes = {
|
|
29051
|
+
value: PropTypes__default["default"].array.isRequired,
|
|
29052
|
+
onChange: PropTypes__default["default"].func.isRequired,
|
|
29053
|
+
placeholder: PropTypes__default["default"].array,
|
|
29054
|
+
checkValidity: PropTypes__default["default"].func
|
|
29055
|
+
};
|
|
29056
|
+
static defaultProps = {
|
|
29057
|
+
placeholder: [null, null]
|
|
29058
|
+
};
|
|
29059
|
+
render() {
|
|
29060
|
+
const value = this.props.value;
|
|
29061
|
+
const checkValidity = this.props.checkValidity || truth;
|
|
29062
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
29063
|
+
className: "range-input"
|
|
29064
|
+
}, /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
29065
|
+
value: value[0],
|
|
29066
|
+
checkValidity: val => checkValidity([val, value[1]])
|
|
29067
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
29068
|
+
,
|
|
29069
|
+
onChange: this.onChange.bind(this, 0),
|
|
29070
|
+
placeholder: this.props.placeholder[0]
|
|
29071
|
+
})), /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
29072
|
+
value: value[1],
|
|
29073
|
+
checkValidity: val => checkValidity([value[0], val])
|
|
29074
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
29075
|
+
,
|
|
29076
|
+
onChange: this.onChange.bind(this, 1),
|
|
29077
|
+
placeholder: this.props.placeholder[1]
|
|
29078
|
+
})));
|
|
29079
|
+
}
|
|
29080
|
+
onChange = (i, newVal) => {
|
|
29081
|
+
const value = this.props.value;
|
|
29082
|
+
if (i === 0) {
|
|
29083
|
+
this.props.onChange([newVal, value[1]]);
|
|
29084
|
+
} else {
|
|
29085
|
+
this.props.onChange([value[0], newVal]);
|
|
29086
|
+
}
|
|
29087
|
+
};
|
|
29088
|
+
}
|
|
29089
|
+
|
|
29090
|
+
var components = /*#__PURE__*/Object.freeze({
|
|
29091
|
+
__proto__: null,
|
|
29092
|
+
ButtonGroup: ButtonGroup,
|
|
29093
|
+
Graph: Graph,
|
|
29094
|
+
Graphie: Graphie,
|
|
29095
|
+
HUD: HUD,
|
|
29096
|
+
Icon: Icon,
|
|
29097
|
+
InfoTip: InfoTip,
|
|
29098
|
+
InlineIcon: InlineIcon,
|
|
29099
|
+
MathInput: MathInput,
|
|
29100
|
+
MultiButtonGroup: MultiButtonGroup,
|
|
29101
|
+
NumberInput: NumberInput,
|
|
29102
|
+
PropCheckBox: PropCheckBox,
|
|
29103
|
+
RangeInput: RangeInput,
|
|
29104
|
+
SvgImage: SvgImage,
|
|
29105
|
+
TextInput: TextInput,
|
|
29106
|
+
TextListEditor: TextListEditor
|
|
29107
|
+
});
|
|
29108
|
+
|
|
29109
|
+
/**
|
|
29110
|
+
* If a graphie URL is provided in `backgroundImage`, will return the rendered graphie background.
|
|
29111
|
+
* Otherwise, returns `null`.
|
|
29112
|
+
*/
|
|
29113
|
+
const getLegacyGrid = (box, backgroundImage) => {
|
|
29114
|
+
const {
|
|
29115
|
+
url,
|
|
29116
|
+
width,
|
|
29117
|
+
height
|
|
29118
|
+
} = backgroundImage ?? {};
|
|
29119
|
+
if (url && typeof url === "string") {
|
|
29120
|
+
const scale = box[0] / interactiveSizes$1.defaultBoxSize;
|
|
29121
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29122
|
+
style: {
|
|
29123
|
+
position: "absolute",
|
|
29124
|
+
bottom: 0,
|
|
29125
|
+
left: 0
|
|
29126
|
+
}
|
|
29127
|
+
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref => {
|
|
29128
|
+
let {
|
|
29129
|
+
setAssetStatus
|
|
29130
|
+
} = _ref;
|
|
29131
|
+
return /*#__PURE__*/React__namespace.createElement(SvgImage, {
|
|
29132
|
+
src: url,
|
|
29133
|
+
width: width,
|
|
29134
|
+
height: height,
|
|
29135
|
+
scale: scale,
|
|
29136
|
+
responsive: false,
|
|
29137
|
+
setAssetStatus: setAssetStatus,
|
|
29138
|
+
alt: ""
|
|
29139
|
+
});
|
|
29140
|
+
}));
|
|
29141
|
+
}
|
|
29142
|
+
return null;
|
|
29143
|
+
};
|
|
29144
|
+
|
|
29145
|
+
const renderGraph = props => {
|
|
29146
|
+
const {
|
|
29147
|
+
graph,
|
|
29148
|
+
...rest
|
|
29149
|
+
} = props;
|
|
29150
|
+
switch (graph.type) {
|
|
29151
|
+
case "segment":
|
|
29152
|
+
return /*#__PURE__*/React__namespace.createElement(SegmentGraph, _extends({}, rest, {
|
|
29153
|
+
graph: graph,
|
|
29154
|
+
onGraphChange: props.onGraphChange
|
|
29155
|
+
}));
|
|
29156
|
+
}
|
|
29157
|
+
};
|
|
29158
|
+
const MafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
29159
|
+
// Storing the gradable state in a ref so that it can be updated without
|
|
29160
|
+
// causing a re-render.
|
|
29161
|
+
const graphRef = React__namespace.useRef(props.graph);
|
|
29162
|
+
const handleGraphUpdate = callback => {
|
|
29163
|
+
graphRef.current = callback(graphRef.current);
|
|
29164
|
+
};
|
|
29165
|
+
React__namespace.useImperativeHandle(ref, () => ({
|
|
29166
|
+
getUserInput: () => graphRef.current
|
|
29167
|
+
}));
|
|
29168
|
+
const [width, height] = getInteractiveBoxFromSizeClass(props.containerSizeClass);
|
|
29169
|
+
const legacyGrid = getLegacyGrid([width, height], props.backgroundImage);
|
|
29170
|
+
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29171
|
+
style: {
|
|
29172
|
+
width: props.backgroundImage?.width ?? width,
|
|
29173
|
+
height: props.backgroundImage?.height ?? height,
|
|
29174
|
+
position: "relative"
|
|
29175
|
+
}
|
|
29176
|
+
}, legacyGrid, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
29177
|
+
style: {
|
|
29178
|
+
position: "absolute",
|
|
29179
|
+
bottom: 0,
|
|
29180
|
+
left: 0
|
|
29181
|
+
}
|
|
29182
|
+
}, /*#__PURE__*/React__namespace.createElement(mafs.Mafs, {
|
|
29183
|
+
viewBox: {
|
|
29184
|
+
x: props.range[0],
|
|
29185
|
+
y: props.range[1],
|
|
29186
|
+
padding: 0
|
|
29187
|
+
},
|
|
29188
|
+
pan: false,
|
|
29189
|
+
zoom: false,
|
|
29190
|
+
width: width,
|
|
29191
|
+
height: height
|
|
29192
|
+
}, !!legacyGrid && /*#__PURE__*/React__namespace.createElement(Grid, props), renderGraph({
|
|
29193
|
+
...props,
|
|
29194
|
+
onGraphChange: handleGraphUpdate
|
|
29195
|
+
}))));
|
|
29196
|
+
});
|
|
29197
|
+
|
|
28320
29198
|
const {
|
|
28321
29199
|
DeprecationMixin
|
|
28322
29200
|
} = Util;
|
|
@@ -28393,6 +29271,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
28393
29271
|
type: "linear"
|
|
28394
29272
|
}
|
|
28395
29273
|
};
|
|
29274
|
+
mafsRef = /*#__PURE__*/React__namespace.createRef();
|
|
28396
29275
|
state = {
|
|
28397
29276
|
shouldShowInstructions: _getShouldShowInstructions(this.props)
|
|
28398
29277
|
};
|
|
@@ -28402,9 +29281,11 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
28402
29281
|
DeprecationMixin.UNSAFE_componentWillMount.call(this);
|
|
28403
29282
|
}
|
|
28404
29283
|
componentDidMount() {
|
|
28405
|
-
|
|
28406
|
-
|
|
28407
|
-
|
|
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
|
+
}
|
|
28408
29289
|
}
|
|
28409
29290
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
28410
29291
|
if (this.isClickToAddPoints() !== this.isClickToAddPoints(nextProps)) {
|
|
@@ -29501,16 +30382,22 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29501
30382
|
graph: graph
|
|
29502
30383
|
});
|
|
29503
30384
|
};
|
|
29504
|
-
getUserInput = () =>
|
|
29505
|
-
|
|
29506
|
-
};
|
|
29507
|
-
simpleValidate = rubric => {
|
|
29508
|
-
return InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
29509
|
-
};
|
|
30385
|
+
getUserInput = () => this.mafsRef.current?.getUserInput?.() ?? InteractiveGraph.getUserInputFromProps(this.props);
|
|
30386
|
+
simpleValidate = rubric => InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
29510
30387
|
focus = $__default["default"].noop;
|
|
30388
|
+
|
|
30389
|
+
// const segment: boolean = useFeatureIsOn("mafs-segment-graph");
|
|
30390
|
+
// <Renderer apiOptions={{flags: {mafs: {segment}}}}
|
|
29511
30391
|
render() {
|
|
30392
|
+
// Mafs shim
|
|
30393
|
+
if (this.props.apiOptions?.flags?.["mafs"]?.[this.props.graph.type]) {
|
|
30394
|
+
return /*#__PURE__*/React__namespace.createElement(MafsGraph, _extends({}, this.props, {
|
|
30395
|
+
ref: this.mafsRef
|
|
30396
|
+
}));
|
|
30397
|
+
}
|
|
29512
30398
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
29513
30399
|
let instructions;
|
|
30400
|
+
// isClickToAddPoints() only applies to points and polygons
|
|
29514
30401
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
29515
30402
|
if (this.props.graph.type === "point") {
|
|
29516
30403
|
instructions = i18n__namespace._("Click to add points");
|
|
@@ -30795,7 +31682,7 @@ var globalConstants = /*#__PURE__*/Object.freeze({
|
|
|
30795
31682
|
pureLgMax: pureLgMax
|
|
30796
31683
|
});
|
|
30797
31684
|
|
|
30798
|
-
const colors
|
|
31685
|
+
const colors = {
|
|
30799
31686
|
white: "#FFFFFF",
|
|
30800
31687
|
gray98: "#FAFAFA",
|
|
30801
31688
|
gray97: "#F6F7F7",
|
|
@@ -30855,7 +31742,7 @@ const colors$1 = {
|
|
|
30855
31742
|
};
|
|
30856
31743
|
const borderRadius = 4;
|
|
30857
31744
|
const breadcrumbStyles = {
|
|
30858
|
-
color: colors
|
|
31745
|
+
color: colors.breadcrumbs,
|
|
30859
31746
|
fontFamily: "inherit",
|
|
30860
31747
|
fontSize: 15,
|
|
30861
31748
|
fontWeight: "bold",
|
|
@@ -30925,14 +31812,14 @@ const typography = {
|
|
|
30925
31812
|
},
|
|
30926
31813
|
// For callouts
|
|
30927
31814
|
smallHeading: {
|
|
30928
|
-
color: colors
|
|
31815
|
+
color: colors.gray25,
|
|
30929
31816
|
fontFamily: "inherit",
|
|
30930
31817
|
fontSize: 17,
|
|
30931
31818
|
fontWeight: "bold",
|
|
30932
31819
|
lineHeight: "23px"
|
|
30933
31820
|
},
|
|
30934
31821
|
smallHeadingMobile: {
|
|
30935
|
-
color: colors
|
|
31822
|
+
color: colors.gray25,
|
|
30936
31823
|
fontFamily: "inherit",
|
|
30937
31824
|
fontSize: 15,
|
|
30938
31825
|
fontWeight: "bold",
|
|
@@ -30940,7 +31827,7 @@ const typography = {
|
|
|
30940
31827
|
},
|
|
30941
31828
|
// Accent headings
|
|
30942
31829
|
accentHeading: {
|
|
30943
|
-
color: colors
|
|
31830
|
+
color: colors.gray68,
|
|
30944
31831
|
fontFamily: "inherit",
|
|
30945
31832
|
fontSize: 15,
|
|
30946
31833
|
fontWeight: "bold",
|
|
@@ -31048,7 +31935,7 @@ const typography = {
|
|
|
31048
31935
|
// HACK(kevinb): temporary wonder blocks styles for header only
|
|
31049
31936
|
// TODO(kevinb): use components from wonder-blocks-typography instead
|
|
31050
31937
|
wonderBlocksTitle: {
|
|
31051
|
-
color: colors
|
|
31938
|
+
color: colors.white,
|
|
31052
31939
|
fontWeight: 900,
|
|
31053
31940
|
// "Black" weight
|
|
31054
31941
|
fontSize: 28,
|
|
@@ -31070,7 +31957,7 @@ const typography = {
|
|
|
31070
31957
|
|
|
31071
31958
|
var globalStyles = /*#__PURE__*/Object.freeze({
|
|
31072
31959
|
__proto__: null,
|
|
31073
|
-
colors: colors
|
|
31960
|
+
colors: colors,
|
|
31074
31961
|
borderRadius: borderRadius,
|
|
31075
31962
|
fonts: fonts,
|
|
31076
31963
|
typography: typography
|
|
@@ -31135,7 +32022,7 @@ const HideAnswersToggle = props => {
|
|
|
31135
32022
|
const switchId = idFactory.get("hide-answers-toggle");
|
|
31136
32023
|
const labelId = idFactory.get("hide-answers-label");
|
|
31137
32024
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31138
|
-
style: styles$
|
|
32025
|
+
style: styles$g.switchWrapper
|
|
31139
32026
|
}, /*#__PURE__*/React__namespace.createElement(Switch__default["default"], {
|
|
31140
32027
|
id: switchId,
|
|
31141
32028
|
checked: props.areAnswersHidden,
|
|
@@ -31147,7 +32034,7 @@ const HideAnswersToggle = props => {
|
|
|
31147
32034
|
tag: "label"
|
|
31148
32035
|
}, strings.hideAnswersToggleLabel));
|
|
31149
32036
|
};
|
|
31150
|
-
const styles$
|
|
32037
|
+
const styles$g = aphrodite.StyleSheet.create({
|
|
31151
32038
|
switchWrapper: {
|
|
31152
32039
|
display: "flex",
|
|
31153
32040
|
flexDirection: "row",
|
|
@@ -31202,14 +32089,14 @@ const AnswerPill = props => {
|
|
|
31202
32089
|
id: idFactory.get("perseus-label-image-widget-answer-pill"),
|
|
31203
32090
|
onClick: correct ? undefined : onClick,
|
|
31204
32091
|
ref: ref,
|
|
31205
|
-
style: [style, popperStyle, styles$
|
|
32092
|
+
style: [style, popperStyle, styles$f.pill, correct && styles$f.correct, incorrect && styles$f.incorrect, (focused || hovered) && BringToFront]
|
|
31206
32093
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31207
32094
|
content: answerString,
|
|
31208
32095
|
inline: true
|
|
31209
32096
|
}));
|
|
31210
32097
|
});
|
|
31211
32098
|
};
|
|
31212
|
-
const styles$
|
|
32099
|
+
const styles$f = aphrodite.StyleSheet.create({
|
|
31213
32100
|
correct: {
|
|
31214
32101
|
// WB green darkened by 18%
|
|
31215
32102
|
backgroundColor: "#00880b"
|
|
@@ -31263,25 +32150,25 @@ class Marker extends React__namespace.Component {
|
|
|
31263
32150
|
icon: iconNull
|
|
31264
32151
|
};
|
|
31265
32152
|
if (showCorrectness) {
|
|
31266
|
-
iconStyles = [styles$
|
|
32153
|
+
iconStyles = [styles$e.markerGraded, showCorrectness === "correct" ? styles$e.markerCorrect : styles$e.markerIncorrect, isOpen && styles$e.markerSelected];
|
|
31267
32154
|
args = {
|
|
31268
32155
|
...args,
|
|
31269
32156
|
icon: showCorrectness === "correct" ? iconCheck : iconMinus
|
|
31270
32157
|
};
|
|
31271
32158
|
} else if (selectedAnswers && selectedAnswers.length > 0) {
|
|
31272
|
-
iconStyles = [styles$
|
|
32159
|
+
iconStyles = [styles$e.markerFilled, isOpen && styles$e.markerSelected];
|
|
31273
32160
|
} else if (isOpen) {
|
|
31274
|
-
iconStyles = [styles$
|
|
32161
|
+
iconStyles = [styles$e.markerSelected];
|
|
31275
32162
|
args = {
|
|
31276
32163
|
...args,
|
|
31277
32164
|
icon: iconChevronDown,
|
|
31278
32165
|
size: 8
|
|
31279
32166
|
};
|
|
31280
32167
|
} else if (showPulsate) {
|
|
31281
|
-
iconStyles = [styles$
|
|
32168
|
+
iconStyles = [styles$e.markerPulsateBase, shouldReduceMotion() ? showPulsate && styles$e.markerUnfilledPulsateOnce : showPulsate && styles$e.markerUnfilledPulsateInfinite];
|
|
31282
32169
|
}
|
|
31283
32170
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31284
|
-
style: [styles$
|
|
32171
|
+
style: [styles$e.markerIcon, iconStyles],
|
|
31285
32172
|
ref: node => this._icon = node
|
|
31286
32173
|
}, /*#__PURE__*/React__namespace.createElement(Icon, args));
|
|
31287
32174
|
}
|
|
@@ -31302,7 +32189,7 @@ class Marker extends React__namespace.Component {
|
|
|
31302
32189
|
const markerDisabled = showCorrectness === "correct";
|
|
31303
32190
|
const active = hovered || focused;
|
|
31304
32191
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31305
|
-
style: [styles$
|
|
32192
|
+
style: [styles$e.marker, active && !markerDisabled && styles$e.markerActive]
|
|
31306
32193
|
// already translated in: /widgets/graded-group.tsx
|
|
31307
32194
|
,
|
|
31308
32195
|
"aria-label": markerDisabled ? i18n__namespace._("Correct!") : label
|
|
@@ -31317,7 +32204,7 @@ class Marker extends React__namespace.Component {
|
|
|
31317
32204
|
}));
|
|
31318
32205
|
}
|
|
31319
32206
|
}
|
|
31320
|
-
const styles$
|
|
32207
|
+
const styles$e = aphrodite.StyleSheet.create({
|
|
31321
32208
|
marker: {
|
|
31322
32209
|
position: "absolute",
|
|
31323
32210
|
backgroundColor: Color__default["default"].white,
|
|
@@ -31894,13 +32781,13 @@ class LabelImage extends React__namespace.Component {
|
|
|
31894
32781
|
const promptString = isMobile ? multipleAnswers ? i18n__namespace._("Tap each dot on the image to select all answers that apply.") : i18n__namespace._("Tap each dot on the image to select an answer.") : multipleAnswers ? i18n__namespace._("Click each dot on the image to select all answers that apply.") : i18n__namespace._("Click each dot on the image to select an answer.");
|
|
31895
32782
|
const choicesString = i18n__namespace._("Choices:");
|
|
31896
32783
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
31897
|
-
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$
|
|
32784
|
+
className: classNames__default["default"]("perseus-label-image-widget-instructions", aphrodite.css(styles$d.instructions))
|
|
31898
32785
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
31899
|
-
className: aphrodite.css(styles$
|
|
32786
|
+
className: aphrodite.css(styles$d.instructionsCaption)
|
|
31900
32787
|
}, promptString, " ", !hideChoices && choicesString), !hideChoices && /*#__PURE__*/React__namespace.createElement("div", {
|
|
31901
|
-
className: aphrodite.css(styles$
|
|
32788
|
+
className: aphrodite.css(styles$d.instructionsChoices)
|
|
31902
32789
|
}, choices.map((choice, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
31903
|
-
className: aphrodite.css(styles$
|
|
32790
|
+
className: aphrodite.css(styles$d.instructionsChoice),
|
|
31904
32791
|
key: index
|
|
31905
32792
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
31906
32793
|
content: choice
|
|
@@ -31917,20 +32804,20 @@ class LabelImage extends React__namespace.Component {
|
|
|
31917
32804
|
activeMarkerIndex
|
|
31918
32805
|
} = this.state;
|
|
31919
32806
|
return /*#__PURE__*/React__namespace.createElement("div", null, this.renderInstructions(), /*#__PURE__*/React__namespace.createElement("div", {
|
|
31920
|
-
className: aphrodite.css(styles$
|
|
32807
|
+
className: aphrodite.css(styles$d.markersCanvas),
|
|
31921
32808
|
style: {
|
|
31922
32809
|
maxWidth: imageWidth,
|
|
31923
32810
|
maxHeight: imageHeight
|
|
31924
32811
|
}
|
|
31925
32812
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
31926
|
-
className: aphrodite.css(styles$
|
|
32813
|
+
className: aphrodite.css(styles$d.imageContainer,
|
|
31927
32814
|
// Ensure image interaction is disabled while answer
|
|
31928
32815
|
// choices popup is visible. This addresses specific
|
|
31929
32816
|
// case where user may click on question image to
|
|
31930
32817
|
// dismiss the popup. If the image is larger in size
|
|
31931
32818
|
// than its rendered in the widget, this would
|
|
31932
32819
|
// result in a zoom of the image.
|
|
31933
|
-
activeMarkerIndex !== -1 && styles$
|
|
32820
|
+
activeMarkerIndex !== -1 && styles$d.imageInteractionDisabled)
|
|
31934
32821
|
}, /*#__PURE__*/React__namespace.createElement(context$1.Consumer, null, _ref3 => {
|
|
31935
32822
|
let {
|
|
31936
32823
|
setAssetStatus
|
|
@@ -31956,7 +32843,7 @@ class LabelImage extends React__namespace.Component {
|
|
|
31956
32843
|
}));
|
|
31957
32844
|
}
|
|
31958
32845
|
}
|
|
31959
|
-
const styles$
|
|
32846
|
+
const styles$d = aphrodite.StyleSheet.create({
|
|
31960
32847
|
instructions: {
|
|
31961
32848
|
paddingBottom: 16
|
|
31962
32849
|
},
|
|
@@ -32317,7 +33204,7 @@ class Placeholder extends React__namespace.Component {
|
|
|
32317
33204
|
const {
|
|
32318
33205
|
layout
|
|
32319
33206
|
} = this.props;
|
|
32320
|
-
const className = aphrodite.css(styles$
|
|
33207
|
+
const className = aphrodite.css(styles$c.card, styles$c.placeholder, layout === Layout.HORIZONTAL && styles$c.horizontalCard);
|
|
32321
33208
|
const style = {
|
|
32322
33209
|
width: this.props.width,
|
|
32323
33210
|
height: this.props.height
|
|
@@ -32415,7 +33302,7 @@ class Draggable extends React__namespace.Component {
|
|
|
32415
33302
|
// We need to keep backwards compatbility with rules specified directly
|
|
32416
33303
|
// in CSS. Hence the hacky tacking on of manual classNames.
|
|
32417
33304
|
// See sortable.less for details.
|
|
32418
|
-
let className = aphrodite.css(styles$
|
|
33305
|
+
let className = aphrodite.css(styles$c.card, styles$c.draggable, layout === Layout.HORIZONTAL && styles$c.horizontalCard, layout === Layout.VERTICAL && styles$c.verticalCard, type === ItemState.DRAGGING && styles$c.dragging, type === ItemState.DISABLED && styles$c.disabled, !includePadding && styles$c.unpaddedCard) + " " + ClassNames.INTERACTIVE + " perseus-sortable-draggable";
|
|
32419
33306
|
if (!includePadding) {
|
|
32420
33307
|
className += " perseus-sortable-draggable-unpadded";
|
|
32421
33308
|
}
|
|
@@ -32715,7 +33602,7 @@ class Sortable extends React__namespace.Component {
|
|
|
32715
33602
|
} = this.props;
|
|
32716
33603
|
// We need to keep backwards compatbility with rules specified directly
|
|
32717
33604
|
// in CSS. See sortable.less for details.
|
|
32718
|
-
const className = aphrodite.css(styles$
|
|
33605
|
+
const className = aphrodite.css(styles$c.sortable) + " perseus-sortable";
|
|
32719
33606
|
const syncWidth = this.props.constraints?.width || layout === Layout.VERTICAL;
|
|
32720
33607
|
const syncHeight = this.props.constraints?.height || layout === Layout.HORIZONTAL;
|
|
32721
33608
|
___default["default"].each(this.state.items, function (item, i, items) {
|
|
@@ -32946,7 +33833,7 @@ class Sortable extends React__namespace.Component {
|
|
|
32946
33833
|
return ___default["default"].pluck(this.state.items, "option");
|
|
32947
33834
|
}
|
|
32948
33835
|
}
|
|
32949
|
-
const styles$
|
|
33836
|
+
const styles$c = aphrodite.StyleSheet.create({
|
|
32950
33837
|
sortable: {
|
|
32951
33838
|
boxSizing: "border-box",
|
|
32952
33839
|
float: "left",
|
|
@@ -33074,23 +33961,23 @@ class Matcher extends React__namespace.Component {
|
|
|
33074
33961
|
};
|
|
33075
33962
|
const cellMarginPx = this.props.apiOptions.isMobile ? 8 : 5;
|
|
33076
33963
|
return /*#__PURE__*/React__namespace.createElement("table", {
|
|
33077
|
-
className: aphrodite.css(styles$
|
|
33964
|
+
className: aphrodite.css(styles$b.widget) + " " + HACKY_CSS_CLASSNAME
|
|
33078
33965
|
}, /*#__PURE__*/React__namespace.createElement("tbody", null, showLabels && /*#__PURE__*/React__namespace.createElement("tr", {
|
|
33079
|
-
className: aphrodite.css(styles$
|
|
33966
|
+
className: aphrodite.css(styles$b.row)
|
|
33080
33967
|
}, /*#__PURE__*/React__namespace.createElement("th", {
|
|
33081
|
-
className: aphrodite.css(styles$
|
|
33968
|
+
className: aphrodite.css(styles$b.column, styles$b.columnLabel)
|
|
33082
33969
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33083
33970
|
content: this.props.labels[0] || "...",
|
|
33084
33971
|
linterContext: this.props.linterContext
|
|
33085
33972
|
})), /*#__PURE__*/React__namespace.createElement("th", {
|
|
33086
|
-
className: aphrodite.css(styles$
|
|
33973
|
+
className: aphrodite.css(styles$b.column, styles$b.columnRight, styles$b.columnLabel)
|
|
33087
33974
|
}, /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
33088
33975
|
content: this.props.labels[1] || "...",
|
|
33089
33976
|
linterContext: this.props.linterContext
|
|
33090
33977
|
}))), /*#__PURE__*/React__namespace.createElement("tr", {
|
|
33091
|
-
className: aphrodite.css(styles$
|
|
33978
|
+
className: aphrodite.css(styles$b.row)
|
|
33092
33979
|
}, /*#__PURE__*/React__namespace.createElement("td", {
|
|
33093
|
-
className: aphrodite.css(styles$
|
|
33980
|
+
className: aphrodite.css(styles$b.column)
|
|
33094
33981
|
}, /*#__PURE__*/React__namespace.createElement(Sortable, {
|
|
33095
33982
|
options: left,
|
|
33096
33983
|
layout: Layout.VERTICAL,
|
|
@@ -33105,7 +33992,7 @@ class Matcher extends React__namespace.Component {
|
|
|
33105
33992
|
,
|
|
33106
33993
|
ref: "left"
|
|
33107
33994
|
})), /*#__PURE__*/React__namespace.createElement("td", {
|
|
33108
|
-
className: aphrodite.css(styles$
|
|
33995
|
+
className: aphrodite.css(styles$b.column, styles$b.columnRight)
|
|
33109
33996
|
}, /*#__PURE__*/React__namespace.createElement(Sortable
|
|
33110
33997
|
// @ts-expect-error - TS2322 - Type 'readonly unknown[]' is not assignable to type 'readonly string[]'.
|
|
33111
33998
|
, {
|
|
@@ -33191,7 +34078,7 @@ ___default["default"].extend(Matcher, {
|
|
|
33191
34078
|
});
|
|
33192
34079
|
const padding = 5;
|
|
33193
34080
|
const border = "1px solid #444";
|
|
33194
|
-
const styles$
|
|
34081
|
+
const styles$b = aphrodite.StyleSheet.create({
|
|
33195
34082
|
widget: {
|
|
33196
34083
|
paddingTop: padding,
|
|
33197
34084
|
maxWidth: "100%",
|
|
@@ -33224,204 +34111,6 @@ var Matcher$1 = {
|
|
|
33224
34111
|
isLintable: true
|
|
33225
34112
|
};
|
|
33226
34113
|
|
|
33227
|
-
const {
|
|
33228
|
-
firstNumericalParse,
|
|
33229
|
-
captureScratchpadTouchStart
|
|
33230
|
-
} = Util;
|
|
33231
|
-
const toNumericString = KhanMath.toNumericString;
|
|
33232
|
-
const getNumericFormat = KhanMath.getNumericFormat;
|
|
33233
|
-
|
|
33234
|
-
/* An input box that accepts only numeric strings
|
|
33235
|
-
*
|
|
33236
|
-
* Calls onChange(value, format) for valid numbers.
|
|
33237
|
-
* Reverts to the current value onBlur or on [ENTER],
|
|
33238
|
-
* but maintains the format (i.e. 3/2, 1 1/2, 150%)
|
|
33239
|
-
* Accepts empty input and sends it to onChange as null
|
|
33240
|
-
* if no numeric placeholder is set.
|
|
33241
|
-
* If given a checkValidity function, will turn
|
|
33242
|
-
* the background/outline red when invalid
|
|
33243
|
-
* If useArrowKeys is set to true, up/down arrows will
|
|
33244
|
-
* increment/decrement integers
|
|
33245
|
-
* Optionally takes a size ("mini", "small", "normal")
|
|
33246
|
-
*/
|
|
33247
|
-
class NumberInput extends React__namespace.Component {
|
|
33248
|
-
static propTypes = {
|
|
33249
|
-
value: PropTypes__default["default"].number,
|
|
33250
|
-
format: PropTypes__default["default"].string,
|
|
33251
|
-
placeholder: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].number]),
|
|
33252
|
-
onChange: PropTypes__default["default"].func.isRequired,
|
|
33253
|
-
onFormatChange: PropTypes__default["default"].func,
|
|
33254
|
-
checkValidity: PropTypes__default["default"].func,
|
|
33255
|
-
size: PropTypes__default["default"].string,
|
|
33256
|
-
label: PropTypes__default["default"].oneOf(["put your labels outside your inputs!"])
|
|
33257
|
-
};
|
|
33258
|
-
static defaultProps = {
|
|
33259
|
-
value: null,
|
|
33260
|
-
placeholder: null,
|
|
33261
|
-
format: null,
|
|
33262
|
-
onFormatChange: () => null,
|
|
33263
|
-
checkValidity: () => true,
|
|
33264
|
-
useArrowKeys: false
|
|
33265
|
-
};
|
|
33266
|
-
state = {
|
|
33267
|
-
format: this.props.format
|
|
33268
|
-
};
|
|
33269
|
-
render() {
|
|
33270
|
-
let classes = classNames__default["default"]({
|
|
33271
|
-
"number-input": true,
|
|
33272
|
-
"invalid-input": !this._checkValidity(this.props.value),
|
|
33273
|
-
mini: this.props.size === "mini",
|
|
33274
|
-
small: this.props.size === "small",
|
|
33275
|
-
normal: this.props.size === "normal"
|
|
33276
|
-
});
|
|
33277
|
-
if (this.props.className != null) {
|
|
33278
|
-
classes = classes + " " + this.props.className;
|
|
33279
|
-
}
|
|
33280
|
-
const {
|
|
33281
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33282
|
-
onFormatChange,
|
|
33283
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33284
|
-
checkValidity,
|
|
33285
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33286
|
-
useArrowKeys,
|
|
33287
|
-
...restProps
|
|
33288
|
-
} = this.props;
|
|
33289
|
-
return /*#__PURE__*/React__namespace.createElement("input", _extends({}, restProps, {
|
|
33290
|
-
className: classes,
|
|
33291
|
-
type: "text"
|
|
33292
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33293
|
-
,
|
|
33294
|
-
ref: "input",
|
|
33295
|
-
onChange: this._handleChange,
|
|
33296
|
-
onFocus: this._handleFocus,
|
|
33297
|
-
onBlur: this._handleBlur,
|
|
33298
|
-
onKeyPress: this._handleBlur,
|
|
33299
|
-
onKeyDown: this._onKeyDown
|
|
33300
|
-
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
33301
|
-
,
|
|
33302
|
-
onTouchStart: captureScratchpadTouchStart,
|
|
33303
|
-
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
33304
|
-
value: undefined
|
|
33305
|
-
}));
|
|
33306
|
-
}
|
|
33307
|
-
componentDidUpdate(prevProps) {
|
|
33308
|
-
if (!kmath.number.equal(this.getValue(), this.props.value)) {
|
|
33309
|
-
this._setValue(this.props.value, this.state.format);
|
|
33310
|
-
}
|
|
33311
|
-
}
|
|
33312
|
-
|
|
33313
|
-
/* Return the current "value" of this input
|
|
33314
|
-
* If empty, it returns the placeholder (if it is a number) or null
|
|
33315
|
-
*/
|
|
33316
|
-
getValue = () => {
|
|
33317
|
-
return this.parseInputValue(
|
|
33318
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33319
|
-
ReactDOM__default["default"].findDOMNode(this.refs.input).value // eslint-disable-line react/no-string-refs
|
|
33320
|
-
);
|
|
33321
|
-
};
|
|
33322
|
-
|
|
33323
|
-
/* Return the current string value of this input */
|
|
33324
|
-
getStringValue = () => {
|
|
33325
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'.
|
|
33326
|
-
return ReactDOM__default["default"].findDOMNode(this.refs.input).value.toString(); // eslint-disable-line react/no-string-refs
|
|
33327
|
-
};
|
|
33328
|
-
|
|
33329
|
-
parseInputValue = value => {
|
|
33330
|
-
if (value === "") {
|
|
33331
|
-
const placeholder = this.props.placeholder;
|
|
33332
|
-
return ___default["default"].isFinite(placeholder) ? +placeholder : null;
|
|
33333
|
-
}
|
|
33334
|
-
const result = firstNumericalParse(value);
|
|
33335
|
-
return ___default["default"].isFinite(result) ? result : this.props.value;
|
|
33336
|
-
};
|
|
33337
|
-
|
|
33338
|
-
/* Set text input focus to this input */
|
|
33339
|
-
focus = () => {
|
|
33340
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
33341
|
-
ReactDOM__default["default"].findDOMNode(this.refs.input).focus(); // eslint-disable-line react/no-string-refs
|
|
33342
|
-
this._handleFocus();
|
|
33343
|
-
};
|
|
33344
|
-
blur = () => {
|
|
33345
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
33346
|
-
ReactDOM__default["default"].findDOMNode(this.refs.input).blur(); // eslint-disable-line react/no-string-refs
|
|
33347
|
-
this._handleBlur();
|
|
33348
|
-
};
|
|
33349
|
-
setSelectionRange = (selectionStart, selectionEnd) => {
|
|
33350
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'setSelectionRange' does not exist on type 'Element | Text'.
|
|
33351
|
-
ReactDOM__default["default"].findDOMNode(this).setSelectionRange(selectionStart, selectionEnd);
|
|
33352
|
-
};
|
|
33353
|
-
getSelectionStart = () => {
|
|
33354
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionStart' does not exist on type 'Element | Text'.
|
|
33355
|
-
return ReactDOM__default["default"].findDOMNode(this).selectionStart;
|
|
33356
|
-
};
|
|
33357
|
-
getSelectionEnd = () => {
|
|
33358
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'selectionEnd' does not exist on type 'Element | Text'.
|
|
33359
|
-
return ReactDOM__default["default"].findDOMNode(this).selectionEnd;
|
|
33360
|
-
};
|
|
33361
|
-
_checkValidity = value => {
|
|
33362
|
-
if (value == null) {
|
|
33363
|
-
return true;
|
|
33364
|
-
}
|
|
33365
|
-
const val = firstNumericalParse(value);
|
|
33366
|
-
const checkValidity = this.props.checkValidity;
|
|
33367
|
-
return ___default["default"].isFinite(val) && checkValidity(val);
|
|
33368
|
-
};
|
|
33369
|
-
_handleChange = e => {
|
|
33370
|
-
const text = e.target.value;
|
|
33371
|
-
const value = this.parseInputValue(text);
|
|
33372
|
-
const format = getNumericFormat(text);
|
|
33373
|
-
this.props.onChange(value);
|
|
33374
|
-
if (format) {
|
|
33375
|
-
this.props.onFormatChange(value, format);
|
|
33376
|
-
this.setState({
|
|
33377
|
-
format: format
|
|
33378
|
-
});
|
|
33379
|
-
}
|
|
33380
|
-
};
|
|
33381
|
-
_handleFocus = () => {
|
|
33382
|
-
if (this.props.onFocus) {
|
|
33383
|
-
this.props.onFocus();
|
|
33384
|
-
}
|
|
33385
|
-
};
|
|
33386
|
-
_handleBlur = e => {
|
|
33387
|
-
// Only continue on blur or "enter"
|
|
33388
|
-
// @ts-expect-error - TS2339 - Property 'keyCode' does not exist on type 'KeyboardEvent<Element> | FocusEvent<Element, Element>'.
|
|
33389
|
-
if (e && e.type === "keypress" && e.keyCode !== 13) {
|
|
33390
|
-
return;
|
|
33391
|
-
}
|
|
33392
|
-
this._setValue(this.props.value, this.state.format);
|
|
33393
|
-
if (this.props.onBlur) {
|
|
33394
|
-
this.props.onBlur();
|
|
33395
|
-
}
|
|
33396
|
-
};
|
|
33397
|
-
_onKeyDown = e => {
|
|
33398
|
-
if (this.props.onKeyDown) {
|
|
33399
|
-
this.props.onKeyDown(e);
|
|
33400
|
-
}
|
|
33401
|
-
if (!this.props.useArrowKeys || !___default["default"].contains(["ArrowUp", "ArrowDown"], e.key)) {
|
|
33402
|
-
return;
|
|
33403
|
-
}
|
|
33404
|
-
let val = this.getValue();
|
|
33405
|
-
if (val !== Math.floor(val)) {
|
|
33406
|
-
return; // bail if not an integer
|
|
33407
|
-
}
|
|
33408
|
-
|
|
33409
|
-
if (e.key === "ArrowUp") {
|
|
33410
|
-
val = val + 1;
|
|
33411
|
-
} else if (e.key === "ArrowDown") {
|
|
33412
|
-
val = val - 1;
|
|
33413
|
-
}
|
|
33414
|
-
if (this._checkValidity(val)) {
|
|
33415
|
-
this.props.onChange(val);
|
|
33416
|
-
}
|
|
33417
|
-
};
|
|
33418
|
-
_setValue = (val, format) => {
|
|
33419
|
-
// eslint-disable-next-line react/no-string-refs
|
|
33420
|
-
// @ts-expect-error - TS2769 - No overload matches this call. | TS2339 - Property 'val' does not exist on type 'JQueryStatic'.
|
|
33421
|
-
$__default["default"](ReactDOM__default["default"].findDOMNode(this.refs.input)).val(toNumericString(val, format));
|
|
33422
|
-
};
|
|
33423
|
-
}
|
|
33424
|
-
|
|
33425
34114
|
// Type imports
|
|
33426
34115
|
|
|
33427
34116
|
const {
|
|
@@ -34064,9 +34753,9 @@ function drawText(ctx, item) {
|
|
|
34064
34753
|
if (item.value === null) {
|
|
34065
34754
|
return;
|
|
34066
34755
|
}
|
|
34067
|
-
ctx.fillStyle = styles$
|
|
34068
|
-
ctx.font = styles$
|
|
34069
|
-
ctx.fillText(item.value, item.pos[0] - styles$
|
|
34756
|
+
ctx.fillStyle = styles$a.fgColor;
|
|
34757
|
+
ctx.font = styles$a.font;
|
|
34758
|
+
ctx.fillText(item.value, item.pos[0] - styles$a.fontSizePx / 2 + 1, item.pos[1] + styles$a.fontSizePx / 2);
|
|
34070
34759
|
}
|
|
34071
34760
|
|
|
34072
34761
|
/**
|
|
@@ -34087,16 +34776,16 @@ function drawText(ctx, item) {
|
|
|
34087
34776
|
function drawDoubleLine(ctx, item) {
|
|
34088
34777
|
// Outer line that forms both of the bond lines.
|
|
34089
34778
|
let path = new Path2D();
|
|
34090
|
-
ctx.lineWidth = 5 * styles$
|
|
34091
|
-
ctx.strokeStyle = styles$
|
|
34779
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34780
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34092
34781
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34093
34782
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34094
34783
|
ctx.stroke(path);
|
|
34095
34784
|
|
|
34096
34785
|
// Inner white line that separates the two bond lines.
|
|
34097
34786
|
path = new Path2D();
|
|
34098
|
-
ctx.lineWidth = 3 * styles$
|
|
34099
|
-
ctx.strokeStyle = styles$
|
|
34787
|
+
ctx.lineWidth = 3 * styles$a.lineWidth;
|
|
34788
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34100
34789
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34101
34790
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34102
34791
|
ctx.stroke(path);
|
|
@@ -34123,16 +34812,16 @@ function drawTripleLine(ctx, item) {
|
|
|
34123
34812
|
|
|
34124
34813
|
// Outer line that will form the two outer bond lines.
|
|
34125
34814
|
let path = new Path2D();
|
|
34126
|
-
ctx.lineWidth = 7 * styles$
|
|
34127
|
-
ctx.strokeStyle = styles$
|
|
34815
|
+
ctx.lineWidth = 7 * styles$a.lineWidth;
|
|
34816
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34128
34817
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34129
34818
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34130
34819
|
ctx.stroke(path);
|
|
34131
34820
|
|
|
34132
34821
|
// Middle white line that separates the bonds
|
|
34133
34822
|
path = new Path2D();
|
|
34134
|
-
ctx.lineWidth = 5 * styles$
|
|
34135
|
-
ctx.strokeStyle = styles$
|
|
34823
|
+
ctx.lineWidth = 5 * styles$a.lineWidth;
|
|
34824
|
+
ctx.strokeStyle = styles$a.bgColor;
|
|
34136
34825
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34137
34826
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34138
34827
|
ctx.stroke(path);
|
|
@@ -34154,8 +34843,8 @@ function drawTripleLine(ctx, item) {
|
|
|
34154
34843
|
*/
|
|
34155
34844
|
function drawLine(ctx, item) {
|
|
34156
34845
|
const path = new Path2D();
|
|
34157
|
-
ctx.lineWidth = styles$
|
|
34158
|
-
ctx.strokeStyle = styles$
|
|
34846
|
+
ctx.lineWidth = styles$a.lineWidth;
|
|
34847
|
+
ctx.strokeStyle = styles$a.fgColor;
|
|
34159
34848
|
path.moveTo(item.startPos[0], item.startPos[1]);
|
|
34160
34849
|
path.lineTo(item.endPos[0], item.endPos[1]);
|
|
34161
34850
|
ctx.stroke(path);
|
|
@@ -34207,7 +34896,7 @@ function compareElements(item0, item1) {
|
|
|
34207
34896
|
function draw(ctx, items) {
|
|
34208
34897
|
items.sort(compareElements).forEach(drawItem(ctx));
|
|
34209
34898
|
}
|
|
34210
|
-
const styles$
|
|
34899
|
+
const styles$a = {
|
|
34211
34900
|
bgColor: "rgb(255, 255, 255)",
|
|
34212
34901
|
fgColor: "rgb(0, 0, 0)",
|
|
34213
34902
|
fontSizePx: 12,
|
|
@@ -36771,7 +37460,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
36771
37460
|
const rects = this.state.cachedHighlightRects;
|
|
36772
37461
|
return /*#__PURE__*/React__namespace.createElement("div", null, rects.map((rect, index) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
36773
37462
|
key: index,
|
|
36774
|
-
className: aphrodite.css(styles$
|
|
37463
|
+
className: aphrodite.css(styles$9.highlightRect),
|
|
36775
37464
|
style: {
|
|
36776
37465
|
// NOTE(mdr): We apply `position: absolute` here
|
|
36777
37466
|
// rather than in Aphrodite styles, because
|
|
@@ -36790,7 +37479,7 @@ class HighlightRenderer extends React__namespace.PureComponent {
|
|
|
36790
37479
|
})));
|
|
36791
37480
|
}
|
|
36792
37481
|
}
|
|
36793
|
-
const styles$
|
|
37482
|
+
const styles$9 = aphrodite.StyleSheet.create({
|
|
36794
37483
|
highlightRect: {
|
|
36795
37484
|
background: "#fffabe" // highlighter yellow :)
|
|
36796
37485
|
}
|
|
@@ -36871,7 +37560,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
36871
37560
|
// TooltipContent wouldn't let me overwrite
|
|
36872
37561
|
// user-select and onClick
|
|
36873
37562
|
const content = /*#__PURE__*/React__namespace.createElement("div", {
|
|
36874
|
-
className: aphrodite.css(styles$
|
|
37563
|
+
className: aphrodite.css(styles$8.tooltipLabel),
|
|
36875
37564
|
onClick: this.props.onClick
|
|
36876
37565
|
}, this.props.label);
|
|
36877
37566
|
const style = {
|
|
@@ -36891,7 +37580,7 @@ class HighlightTooltip extends React__namespace.PureComponent {
|
|
|
36891
37580
|
}, /*#__PURE__*/React__namespace.createElement("div", null)));
|
|
36892
37581
|
}
|
|
36893
37582
|
}
|
|
36894
|
-
const styles$
|
|
37583
|
+
const styles$8 = aphrodite.StyleSheet.create({
|
|
36895
37584
|
tooltipLabel: {
|
|
36896
37585
|
// Unlike most tooltip contents, we don't want this label to be
|
|
36897
37586
|
// selectable. Selecting it is not only unhelpful, but dangerous: if
|
|
@@ -37449,7 +38138,7 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
37449
38138
|
// starting point: https://phabricator.khanacademy.org/D35623?id=170698
|
|
37450
38139
|
const buildHighlight = r => this._buildHighlight(r);
|
|
37451
38140
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
37452
|
-
className: aphrodite.css(styles$
|
|
38141
|
+
className: aphrodite.css(styles$7.container),
|
|
37453
38142
|
ref: container => this._container = container
|
|
37454
38143
|
}, /*#__PURE__*/React__namespace.createElement("div", null, this.props.enabled && this._container && this._content && /*#__PURE__*/React__namespace.createElement(HighlightingUI, {
|
|
37455
38144
|
buildHighlight: buildHighlight,
|
|
@@ -37470,14 +38159,14 @@ class HighlightableContent extends React__namespace.PureComponent {
|
|
|
37470
38159
|
onAddHighlight: this._handleAddHighlight,
|
|
37471
38160
|
onRemoveHighlight: this._handleRemoveHighlight
|
|
37472
38161
|
})), /*#__PURE__*/React__namespace.createElement("div", {
|
|
37473
|
-
className: aphrodite.css(styles$
|
|
38162
|
+
className: aphrodite.css(styles$7.content),
|
|
37474
38163
|
ref: content => this._content = content
|
|
37475
38164
|
}, /*#__PURE__*/React__namespace.createElement(WordIndexer, {
|
|
37476
38165
|
onWordsUpdate: this._handleWordsUpdate
|
|
37477
38166
|
}, this.props.children)));
|
|
37478
38167
|
}
|
|
37479
38168
|
}
|
|
37480
|
-
const styles$
|
|
38169
|
+
const styles$7 = aphrodite.StyleSheet.create({
|
|
37481
38170
|
// We render content with z-index 1, and highlights with z-index 0, so that
|
|
37482
38171
|
// content will receive the browser's native pointer events. (Highlights
|
|
37483
38172
|
// have their own magic code to manage hover detection, despite being
|
|
@@ -37873,7 +38562,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
37873
38562
|
}
|
|
37874
38563
|
render() {
|
|
37875
38564
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
37876
|
-
className: aphrodite.css(styles$
|
|
38565
|
+
className: aphrodite.css(styles$6.measurer),
|
|
37877
38566
|
"aria-hidden": "true"
|
|
37878
38567
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
37879
38568
|
ref: ref => this._line = ref,
|
|
@@ -37881,7 +38570,7 @@ class LineHeightMeasurer extends React__namespace.Component {
|
|
|
37881
38570
|
}, "Line Height Measurement"));
|
|
37882
38571
|
}
|
|
37883
38572
|
}
|
|
37884
|
-
const styles$
|
|
38573
|
+
const styles$6 = aphrodite.StyleSheet.create({
|
|
37885
38574
|
measurer: {
|
|
37886
38575
|
position: "absolute",
|
|
37887
38576
|
top: 0,
|
|
@@ -39193,7 +39882,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
39193
39882
|
// creator "went wild".
|
|
39194
39883
|
// http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
|
|
39195
39884
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
39196
|
-
style: styles$
|
|
39885
|
+
style: styles$5.container
|
|
39197
39886
|
}, /*#__PURE__*/React__namespace.createElement("iframe", {
|
|
39198
39887
|
sandbox: sandboxOptions,
|
|
39199
39888
|
src: url,
|
|
@@ -39202,7 +39891,7 @@ class PythonProgram extends React__namespace.Component {
|
|
|
39202
39891
|
}));
|
|
39203
39892
|
}
|
|
39204
39893
|
}
|
|
39205
|
-
const styles$
|
|
39894
|
+
const styles$5 = aphrodite.StyleSheet.create({
|
|
39206
39895
|
container: {
|
|
39207
39896
|
margin: "auto",
|
|
39208
39897
|
width: "100%"
|
|
@@ -39439,125 +40128,6 @@ var Sequence$1 = {
|
|
|
39439
40128
|
isLintable: true
|
|
39440
40129
|
};
|
|
39441
40130
|
|
|
39442
|
-
const colors = {
|
|
39443
|
-
grayLight: "#aaa",
|
|
39444
|
-
basicBorderColor: "#ccc",
|
|
39445
|
-
white: "#fff"
|
|
39446
|
-
};
|
|
39447
|
-
const triangleBeforeAfter = {
|
|
39448
|
-
borderBottom: "9px solid transparent",
|
|
39449
|
-
borderTop: "9px solid transparent",
|
|
39450
|
-
content: '" "',
|
|
39451
|
-
height: "0",
|
|
39452
|
-
position: "absolute",
|
|
39453
|
-
top: "0",
|
|
39454
|
-
width: "0"
|
|
39455
|
-
};
|
|
39456
|
-
const styles$7 = aphrodite.StyleSheet.create({
|
|
39457
|
-
infoTip: {
|
|
39458
|
-
display: "inline-block",
|
|
39459
|
-
marginLeft: "5px",
|
|
39460
|
-
position: "relative"
|
|
39461
|
-
},
|
|
39462
|
-
infoTipContainer: {
|
|
39463
|
-
position: "absolute",
|
|
39464
|
-
top: "-12px",
|
|
39465
|
-
left: "22px",
|
|
39466
|
-
zIndex: 1000
|
|
39467
|
-
},
|
|
39468
|
-
infoTipTriangle: {
|
|
39469
|
-
height: "10px",
|
|
39470
|
-
left: "0",
|
|
39471
|
-
position: "absolute",
|
|
39472
|
-
top: "8px",
|
|
39473
|
-
width: "0",
|
|
39474
|
-
zIndex: 1,
|
|
39475
|
-
":before": {
|
|
39476
|
-
...triangleBeforeAfter,
|
|
39477
|
-
borderRight: "9px solid #bbb",
|
|
39478
|
-
right: "0"
|
|
39479
|
-
},
|
|
39480
|
-
":after": {
|
|
39481
|
-
...triangleBeforeAfter,
|
|
39482
|
-
borderRight: `9px solid ${colors.white}`,
|
|
39483
|
-
right: "-1px"
|
|
39484
|
-
}
|
|
39485
|
-
},
|
|
39486
|
-
verticalShadow: {
|
|
39487
|
-
border: `1px solid ${colors.basicBorderColor}`,
|
|
39488
|
-
boxShadow: `0 1px 3px ${colors.basicBorderColor}`,
|
|
39489
|
-
borderBottom: `1px solid ${colors.grayLight}`
|
|
39490
|
-
},
|
|
39491
|
-
infoTipContentContainer: {
|
|
39492
|
-
background: colors.white,
|
|
39493
|
-
padding: "5px 10px",
|
|
39494
|
-
width: "240px"
|
|
39495
|
-
}
|
|
39496
|
-
});
|
|
39497
|
-
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=";
|
|
39498
|
-
class InfoTip$1 extends React__namespace.Component {
|
|
39499
|
-
state = {
|
|
39500
|
-
hover: false
|
|
39501
|
-
};
|
|
39502
|
-
handleMouseEnter = () => {
|
|
39503
|
-
this.setState({
|
|
39504
|
-
hover: true
|
|
39505
|
-
});
|
|
39506
|
-
};
|
|
39507
|
-
handleMouseLeave = () => {
|
|
39508
|
-
this.setState({
|
|
39509
|
-
hover: false
|
|
39510
|
-
});
|
|
39511
|
-
};
|
|
39512
|
-
render() {
|
|
39513
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
39514
|
-
className: aphrodite.css(styles$7.infoTip)
|
|
39515
|
-
}, /*#__PURE__*/React__namespace.createElement("img", {
|
|
39516
|
-
alt: "",
|
|
39517
|
-
width: 10,
|
|
39518
|
-
height: 10,
|
|
39519
|
-
src: questionMark,
|
|
39520
|
-
onMouseEnter: this.handleMouseEnter,
|
|
39521
|
-
onMouseLeave: this.handleMouseLeave
|
|
39522
|
-
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
39523
|
-
className: aphrodite.css(styles$7.infoTipContainer),
|
|
39524
|
-
style: {
|
|
39525
|
-
display: this.state.hover ? "block" : "none"
|
|
39526
|
-
}
|
|
39527
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
39528
|
-
className: aphrodite.css(styles$7.infoTipTriangle)
|
|
39529
|
-
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
39530
|
-
className: aphrodite.css(styles$7.verticalShadow, styles$7.infoTipContentContainer)
|
|
39531
|
-
}, this.props.children)));
|
|
39532
|
-
}
|
|
39533
|
-
}
|
|
39534
|
-
|
|
39535
|
-
/**
|
|
39536
|
-
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
39537
|
-
* server without causing a checksum mismatch on the client.
|
|
39538
|
-
* (RCSS generates classnames with a randomSuffix, which ensures that any
|
|
39539
|
-
* two sets of generated classnames will not match.)
|
|
39540
|
-
*/
|
|
39541
|
-
class InfoTip extends React__namespace.Component {
|
|
39542
|
-
state = {
|
|
39543
|
-
didMount: false
|
|
39544
|
-
};
|
|
39545
|
-
componentDidMount() {
|
|
39546
|
-
/* eslint-disable react/no-did-mount-set-state */
|
|
39547
|
-
this.setState({
|
|
39548
|
-
didMount: true
|
|
39549
|
-
});
|
|
39550
|
-
/* eslint-enable react/no-did-mount-set-state */
|
|
39551
|
-
}
|
|
39552
|
-
|
|
39553
|
-
render() {
|
|
39554
|
-
if (this.state.didMount) {
|
|
39555
|
-
return /*#__PURE__*/React__namespace.createElement(InfoTip$1, this.props);
|
|
39556
|
-
}
|
|
39557
|
-
return /*#__PURE__*/React__namespace.createElement("div", null);
|
|
39558
|
-
}
|
|
39559
|
-
}
|
|
39560
|
-
|
|
39561
40131
|
/* eslint-disable @typescript-eslint/no-unused-vars, react/no-unsafe, react/sort-comp */
|
|
39562
40132
|
const {
|
|
39563
40133
|
assert: assert$1
|
|
@@ -41515,7 +42085,7 @@ const VideoTranscriptLink = props => {
|
|
|
41515
42085
|
{
|
|
41516
42086
|
const video = result.data?.video;
|
|
41517
42087
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
41518
|
-
style: styles$
|
|
42088
|
+
style: styles$4.transcriptLink
|
|
41519
42089
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.Text, null, video?.title), /*#__PURE__*/React__namespace.createElement(wonderBlocksLayout.Strut, {
|
|
41520
42090
|
size: 10
|
|
41521
42091
|
}), /*#__PURE__*/React__namespace.createElement(Link__default["default"], {
|
|
@@ -41532,7 +42102,7 @@ const VideoTranscriptLink = props => {
|
|
|
41532
42102
|
return /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, null, i18n__namespace._("Something went wrong."));
|
|
41533
42103
|
}
|
|
41534
42104
|
};
|
|
41535
|
-
const styles$
|
|
42105
|
+
const styles$4 = aphrodite.StyleSheet.create({
|
|
41536
42106
|
transcriptLink: {
|
|
41537
42107
|
flexDirection: "row",
|
|
41538
42108
|
width: "100%",
|
|
@@ -41688,7 +42258,7 @@ const init = function (options) {
|
|
|
41688
42258
|
|
|
41689
42259
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41690
42260
|
const libName = "@khanacademy/perseus";
|
|
41691
|
-
const libVersion = "19.
|
|
42261
|
+
const libVersion = "19.7.0";
|
|
41692
42262
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41693
42263
|
|
|
41694
42264
|
const apiVersion = {
|
|
@@ -41901,7 +42471,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
41901
42471
|
const {
|
|
41902
42472
|
isMobile
|
|
41903
42473
|
} = apiOptions;
|
|
41904
|
-
const classNames = classNames__default["default"]("hint", !isMobile && "perseus-hint-renderer", isMobile && aphrodite.css(styles$
|
|
42474
|
+
const classNames = classNames__default["default"]("hint", !isMobile && "perseus-hint-renderer", isMobile && aphrodite.css(styles$3.newHint), isMobile && lastRendered && aphrodite.css(styles$3.lastRenderedNewHint), lastHint && "last-hint", lastRendered && "last-rendered", className);
|
|
41905
42475
|
|
|
41906
42476
|
// TODO(charlie): Allowing `customKeypad` would require that we
|
|
41907
42477
|
// extend `ItemRenderer` to support nested inputs in the `HintsRenderer`.
|
|
@@ -41942,7 +42512,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
41942
42512
|
);
|
|
41943
42513
|
}
|
|
41944
42514
|
}
|
|
41945
|
-
const styles$
|
|
42515
|
+
const styles$3 = aphrodite.StyleSheet.create({
|
|
41946
42516
|
newHint: {
|
|
41947
42517
|
marginBottom: 1.5 * baseUnitPx,
|
|
41948
42518
|
borderLeftColor: gray97,
|
|
@@ -42119,15 +42689,15 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
42119
42689
|
} = apiOptions;
|
|
42120
42690
|
const showGetAnotherHint = getAnotherHint && hintsVisible > 0 && hintsVisible < this.props.hints.length;
|
|
42121
42691
|
const hintRatioCopy = `(${hintsVisible}/${this.props.hints.length})`;
|
|
42122
|
-
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$
|
|
42692
|
+
const classNames = classNames__default["default"](this.props.className, apiOptions.isMobile && hintsVisible > 0 && aphrodite.css(styles$2.mobileHintStylesHintsRenderer));
|
|
42123
42693
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42124
42694
|
className: classNames
|
|
42125
42695
|
}, apiOptions.isMobile && hintsVisible > 0 && /*#__PURE__*/React__namespace.createElement("div", {
|
|
42126
|
-
className: aphrodite.css(styles$
|
|
42696
|
+
className: aphrodite.css(styles$2.mobileHintStylesHintTitle, sharedStyles.responsiveLabel)
|
|
42127
42697
|
}, i18n__namespace._("Hints")), hints, showGetAnotherHint && /*#__PURE__*/React__namespace.createElement("button", {
|
|
42128
42698
|
// @ts-expect-error - TS2322 - Type '{ children: Element[]; rel: string; className: string; onClick: (evt: MouseEvent<HTMLButtonElement, MouseEvent>) => void; }' is not assignable to type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'.
|
|
42129
42699
|
rel: "button",
|
|
42130
|
-
className: aphrodite.css(styles$
|
|
42700
|
+
className: aphrodite.css(styles$2.linkButton, styles$2.getAnotherHintButton, apiOptions.isMobile && styles$2.mobileHintStylesGetAnotherHintButton),
|
|
42131
42701
|
onClick: evt => {
|
|
42132
42702
|
evt.preventDefault();
|
|
42133
42703
|
evt.stopPropagation();
|
|
@@ -42136,14 +42706,14 @@ class HintsRenderer extends React__namespace.Component {
|
|
|
42136
42706
|
}
|
|
42137
42707
|
}
|
|
42138
42708
|
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
42139
|
-
className: aphrodite.css(styles$
|
|
42709
|
+
className: aphrodite.css(styles$2.plusText, apiOptions.isMobile && styles$2.mobileHintStylesPlusText)
|
|
42140
42710
|
}, "+"), /*#__PURE__*/React__namespace.createElement("span", {
|
|
42141
|
-
className: aphrodite.css(styles$
|
|
42711
|
+
className: aphrodite.css(styles$2.getAnotherHintText)
|
|
42142
42712
|
}, i18n__namespace._("Get another hint"), " ", hintRatioCopy)));
|
|
42143
42713
|
}
|
|
42144
42714
|
}
|
|
42145
42715
|
const hintIndentation = baseUnitPx + hintBorderWidth;
|
|
42146
|
-
const styles$
|
|
42716
|
+
const styles$2 = aphrodite.StyleSheet.create({
|
|
42147
42717
|
// eslint-disable-next-line react-native/no-unused-styles
|
|
42148
42718
|
rendererMargins: {
|
|
42149
42719
|
marginTop: baseUnitPx
|
|
@@ -42555,11 +43125,11 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
42555
43125
|
// mobile hint styles, which are flush to the left.
|
|
42556
43126
|
// NOTE(charlie): We may still want to apply this
|
|
42557
43127
|
// padding for desktop exercises.
|
|
42558
|
-
apiOptions.isMobile ? undefined : aphrodite.css(styles$
|
|
43128
|
+
apiOptions.isMobile ? undefined : aphrodite.css(styles$1.hintsContainer)
|
|
42559
43129
|
}, hintsRenderer)));
|
|
42560
43130
|
}
|
|
42561
43131
|
}
|
|
42562
|
-
const styles$
|
|
43132
|
+
const styles$1 = aphrodite.StyleSheet.create({
|
|
42563
43133
|
hintsContainer: {
|
|
42564
43134
|
marginLeft: 50
|
|
42565
43135
|
}
|
|
@@ -42696,339 +43266,6 @@ class ElementContainer extends React__namespace.Component {
|
|
|
42696
43266
|
}
|
|
42697
43267
|
}
|
|
42698
43268
|
|
|
42699
|
-
// Displays a stylized open eye: lint warnings are visible
|
|
42700
|
-
const VisibleIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
42701
|
-
width: "24",
|
|
42702
|
-
height: "24",
|
|
42703
|
-
viewBox: "0 0 24 24",
|
|
42704
|
-
className: aphrodite.css(styles$2.icon)
|
|
42705
|
-
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42706
|
-
id: "a",
|
|
42707
|
-
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"
|
|
42708
|
-
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42709
|
-
fill: "none",
|
|
42710
|
-
fillRule: "evenodd"
|
|
42711
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42712
|
-
fill: "none",
|
|
42713
|
-
d: "M0 0h24v24H0z"
|
|
42714
|
-
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
42715
|
-
id: "b",
|
|
42716
|
-
fill: "#fff"
|
|
42717
|
-
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
42718
|
-
href: "#a"
|
|
42719
|
-
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
42720
|
-
fill: "#fff",
|
|
42721
|
-
fillRule: "nonzero",
|
|
42722
|
-
href: "#a"
|
|
42723
|
-
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42724
|
-
fill: "#fff",
|
|
42725
|
-
mask: "url(#b)"
|
|
42726
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42727
|
-
d: "M0 0h24v24H0z"
|
|
42728
|
-
}))));
|
|
42729
|
-
|
|
42730
|
-
// Displays a stylized eye with a line through it: I don't want to see lint
|
|
42731
|
-
const HiddenIcon = () => /*#__PURE__*/React__namespace.createElement("svg", {
|
|
42732
|
-
width: "24",
|
|
42733
|
-
height: "24",
|
|
42734
|
-
viewBox: "0 0 24 24",
|
|
42735
|
-
className: aphrodite.css(styles$2.icon)
|
|
42736
|
-
}, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42737
|
-
id: "a",
|
|
42738
|
-
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"
|
|
42739
|
-
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42740
|
-
fill: "none",
|
|
42741
|
-
fillRule: "evenodd"
|
|
42742
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42743
|
-
fill: "none",
|
|
42744
|
-
d: "M0 0h24v24H0z"
|
|
42745
|
-
}), /*#__PURE__*/React__namespace.createElement("mask", {
|
|
42746
|
-
id: "b",
|
|
42747
|
-
fill: "#fff"
|
|
42748
|
-
}, /*#__PURE__*/React__namespace.createElement("use", {
|
|
42749
|
-
href: "#a"
|
|
42750
|
-
})), /*#__PURE__*/React__namespace.createElement("use", {
|
|
42751
|
-
fill: "#fff",
|
|
42752
|
-
fillRule: "nonzero",
|
|
42753
|
-
href: "#a"
|
|
42754
|
-
}), /*#__PURE__*/React__namespace.createElement("g", {
|
|
42755
|
-
fill: "#fff",
|
|
42756
|
-
mask: "url(#b)"
|
|
42757
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
42758
|
-
d: "M0 0h24v24H0z"
|
|
42759
|
-
}))));
|
|
42760
|
-
const HUD = _ref => {
|
|
42761
|
-
let {
|
|
42762
|
-
message,
|
|
42763
|
-
enabled,
|
|
42764
|
-
onClick,
|
|
42765
|
-
fixedPosition = true
|
|
42766
|
-
} = _ref;
|
|
42767
|
-
let state;
|
|
42768
|
-
let icon;
|
|
42769
|
-
if (enabled) {
|
|
42770
|
-
state = styles$2.enabled;
|
|
42771
|
-
icon = /*#__PURE__*/React__namespace.createElement(VisibleIcon, null);
|
|
42772
|
-
} else {
|
|
42773
|
-
state = styles$2.disabled;
|
|
42774
|
-
icon = /*#__PURE__*/React__namespace.createElement(HiddenIcon, null);
|
|
42775
|
-
}
|
|
42776
|
-
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
42777
|
-
className: aphrodite.css(styles$2.hud, fixedPosition && styles$2.hudFixedPosition, state),
|
|
42778
|
-
onClick: e => {
|
|
42779
|
-
onClick();
|
|
42780
|
-
}
|
|
42781
|
-
}, icon, message);
|
|
42782
|
-
};
|
|
42783
|
-
const styles$2 = aphrodite.StyleSheet.create({
|
|
42784
|
-
hud: {
|
|
42785
|
-
boxSizing: "border-box",
|
|
42786
|
-
height: 36,
|
|
42787
|
-
padding: "9px 16px",
|
|
42788
|
-
borderRadius: 18,
|
|
42789
|
-
fontFamily: boldFontFamily,
|
|
42790
|
-
fontSize: "15px",
|
|
42791
|
-
lineHeight: "18px",
|
|
42792
|
-
color: white$1,
|
|
42793
|
-
userSelect: "none",
|
|
42794
|
-
borderWidth: 0 // <button> gives us a border by default
|
|
42795
|
-
},
|
|
42796
|
-
|
|
42797
|
-
// We want to render the element in-place in our fixtures, so allow us to
|
|
42798
|
-
// render in the bottom corner in production and in-place in testing.
|
|
42799
|
-
hudFixedPosition: {
|
|
42800
|
-
bottom: 20,
|
|
42801
|
-
position: "fixed",
|
|
42802
|
-
right: 20,
|
|
42803
|
-
zIndex: 1
|
|
42804
|
-
},
|
|
42805
|
-
icon: {
|
|
42806
|
-
width: 24,
|
|
42807
|
-
height: 24,
|
|
42808
|
-
marginRight: 8,
|
|
42809
|
-
marginTop: -3,
|
|
42810
|
-
verticalAlign: "middle"
|
|
42811
|
-
},
|
|
42812
|
-
enabled: {
|
|
42813
|
-
backgroundColor: warningColor,
|
|
42814
|
-
":hover": {
|
|
42815
|
-
backgroundColor: warningColorHover
|
|
42816
|
-
},
|
|
42817
|
-
":active": {
|
|
42818
|
-
backgroundColor: warningColorActive
|
|
42819
|
-
}
|
|
42820
|
-
},
|
|
42821
|
-
disabled: {
|
|
42822
|
-
backgroundColor: gray76,
|
|
42823
|
-
":hover": {
|
|
42824
|
-
backgroundColor: "#a1a5a9" // in between those two grays
|
|
42825
|
-
},
|
|
42826
|
-
|
|
42827
|
-
":active": {
|
|
42828
|
-
backgroundColor: gray68
|
|
42829
|
-
}
|
|
42830
|
-
}
|
|
42831
|
-
});
|
|
42832
|
-
|
|
42833
|
-
/**
|
|
42834
|
-
* MultiButtonGroup is an aesthetically pleasing group of buttons,
|
|
42835
|
-
* which allows multiple buttons to be selected at the same time.
|
|
42836
|
-
*
|
|
42837
|
-
* NOTE: This component is almost identical to ./button-group.jsx except that
|
|
42838
|
-
* this component allows multiple selection!
|
|
42839
|
-
*/
|
|
42840
|
-
class MultiButtonGroup extends React__namespace.Component {
|
|
42841
|
-
static defaultProps = {
|
|
42842
|
-
values: [],
|
|
42843
|
-
allowEmpty: true
|
|
42844
|
-
};
|
|
42845
|
-
focus() {
|
|
42846
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
42847
|
-
ReactDOM__namespace.findDOMNode(this)?.focus();
|
|
42848
|
-
return true;
|
|
42849
|
-
}
|
|
42850
|
-
toggleSelect = newValue => {
|
|
42851
|
-
const values = (this.props.values || []).slice(0);
|
|
42852
|
-
const allowEmpty = this.props.allowEmpty;
|
|
42853
|
-
if (values.indexOf(newValue) >= 0 && (values.length > 1 || allowEmpty)) {
|
|
42854
|
-
// If the value is already selected, unselect it
|
|
42855
|
-
values.splice(values.indexOf(newValue), 1);
|
|
42856
|
-
} else {
|
|
42857
|
-
// Otherwise merge with other values and return
|
|
42858
|
-
if (values.indexOf(newValue) < 0) {
|
|
42859
|
-
values.push(newValue);
|
|
42860
|
-
}
|
|
42861
|
-
}
|
|
42862
|
-
this.props.onChange(values);
|
|
42863
|
-
};
|
|
42864
|
-
render() {
|
|
42865
|
-
const values = this.props.values || [];
|
|
42866
|
-
const buttons = this.props.buttons.map((button, i) => {
|
|
42867
|
-
const selected = values.indexOf(button.value) >= 0;
|
|
42868
|
-
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
42869
|
-
title: button.title,
|
|
42870
|
-
type: "button",
|
|
42871
|
-
id: "" + i,
|
|
42872
|
-
key: "" + i,
|
|
42873
|
-
ref: "button" + i,
|
|
42874
|
-
className: aphrodite.css(styles$1.buttonStyle, selected && styles$1.selectedStyle),
|
|
42875
|
-
onClick: () => this.toggleSelect(button.value)
|
|
42876
|
-
}, button.content || "" + button.value);
|
|
42877
|
-
});
|
|
42878
|
-
const outerStyle = {
|
|
42879
|
-
display: "inline-block"
|
|
42880
|
-
};
|
|
42881
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42882
|
-
style: outerStyle
|
|
42883
|
-
}, buttons);
|
|
42884
|
-
}
|
|
42885
|
-
}
|
|
42886
|
-
const styles$1 = aphrodite.StyleSheet.create({
|
|
42887
|
-
buttonStyle: {
|
|
42888
|
-
backgroundColor: "white",
|
|
42889
|
-
border: "1px solid #ccc",
|
|
42890
|
-
borderLeft: "0",
|
|
42891
|
-
cursor: "pointer",
|
|
42892
|
-
margin: "0",
|
|
42893
|
-
padding: "5px 10px",
|
|
42894
|
-
position: "relative",
|
|
42895
|
-
// for hover
|
|
42896
|
-
|
|
42897
|
-
":first-child": {
|
|
42898
|
-
borderLeft: "1px solid #ccc",
|
|
42899
|
-
borderTopLeftRadius: "3px",
|
|
42900
|
-
borderBottomLeftRadius: "3px"
|
|
42901
|
-
},
|
|
42902
|
-
":last-child": {
|
|
42903
|
-
borderRight: "1px solid #ccc",
|
|
42904
|
-
borderTopRightRadius: "3px",
|
|
42905
|
-
borderBottomRightRadius: "3px"
|
|
42906
|
-
},
|
|
42907
|
-
":hover": {
|
|
42908
|
-
backgroundColor: "#ccc"
|
|
42909
|
-
},
|
|
42910
|
-
":focus": {
|
|
42911
|
-
zIndex: 2
|
|
42912
|
-
}
|
|
42913
|
-
},
|
|
42914
|
-
selectedStyle: {
|
|
42915
|
-
backgroundColor: "#ddd"
|
|
42916
|
-
}
|
|
42917
|
-
});
|
|
42918
|
-
|
|
42919
|
-
/* eslint-disable @babel/no-invalid-this */
|
|
42920
|
-
|
|
42921
|
-
/* A checkbox that syncs its value to props using the
|
|
42922
|
-
* renderer's onChange method, and gets the prop name
|
|
42923
|
-
* dynamically from its props list
|
|
42924
|
-
*/
|
|
42925
|
-
const PropCheckBox = createReactClass__default["default"]({
|
|
42926
|
-
displayName: "PropCheckBox",
|
|
42927
|
-
propTypes: {
|
|
42928
|
-
labelAlignment: PropTypes__default["default"].oneOf(["left", "right"])
|
|
42929
|
-
},
|
|
42930
|
-
DEFAULT_PROPS: {
|
|
42931
|
-
label: null,
|
|
42932
|
-
onChange: null,
|
|
42933
|
-
labelAlignment: "left"
|
|
42934
|
-
},
|
|
42935
|
-
getDefaultProps: function () {
|
|
42936
|
-
return this.DEFAULT_PROPS;
|
|
42937
|
-
},
|
|
42938
|
-
propName: function () {
|
|
42939
|
-
const propName = ___default["default"].find(___default["default"].keys(this.props), function (localPropName) {
|
|
42940
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
42941
|
-
return !___default["default"].has(this.DEFAULT_PROPS, localPropName);
|
|
42942
|
-
}, this);
|
|
42943
|
-
if (!propName) {
|
|
42944
|
-
throw new PerseusError("Attempted to create a PropCheckBox with no prop!", Errors.InvalidInput);
|
|
42945
|
-
}
|
|
42946
|
-
return propName;
|
|
42947
|
-
},
|
|
42948
|
-
_labelAlignLeft: function () {
|
|
42949
|
-
return this.props.labelAlignment === "left";
|
|
42950
|
-
},
|
|
42951
|
-
render: function () {
|
|
42952
|
-
const propName = this.propName();
|
|
42953
|
-
return /*#__PURE__*/React__namespace.createElement("label", null, this._labelAlignLeft() && this.props.label, /*#__PURE__*/React__namespace.createElement("input", {
|
|
42954
|
-
type: "checkbox",
|
|
42955
|
-
checked: this.props[propName],
|
|
42956
|
-
onChange: this.toggle
|
|
42957
|
-
}), !this._labelAlignLeft() && this.props.label);
|
|
42958
|
-
},
|
|
42959
|
-
toggle: function () {
|
|
42960
|
-
const propName = this.propName();
|
|
42961
|
-
const changes = {};
|
|
42962
|
-
changes[propName] = !this.props[propName];
|
|
42963
|
-
this.props.onChange(changes);
|
|
42964
|
-
}
|
|
42965
|
-
});
|
|
42966
|
-
|
|
42967
|
-
const truth = () => true;
|
|
42968
|
-
|
|
42969
|
-
/* A minor abstraction on top of NumberInput for ranges
|
|
42970
|
-
*
|
|
42971
|
-
*/
|
|
42972
|
-
class RangeInput extends React__namespace.Component {
|
|
42973
|
-
static propTypes = {
|
|
42974
|
-
value: PropTypes__default["default"].array.isRequired,
|
|
42975
|
-
onChange: PropTypes__default["default"].func.isRequired,
|
|
42976
|
-
placeholder: PropTypes__default["default"].array,
|
|
42977
|
-
checkValidity: PropTypes__default["default"].func
|
|
42978
|
-
};
|
|
42979
|
-
static defaultProps = {
|
|
42980
|
-
placeholder: [null, null]
|
|
42981
|
-
};
|
|
42982
|
-
render() {
|
|
42983
|
-
const value = this.props.value;
|
|
42984
|
-
const checkValidity = this.props.checkValidity || truth;
|
|
42985
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
42986
|
-
className: "range-input"
|
|
42987
|
-
}, /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
42988
|
-
value: value[0],
|
|
42989
|
-
checkValidity: val => checkValidity([val, value[1]])
|
|
42990
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
42991
|
-
,
|
|
42992
|
-
onChange: this.onChange.bind(this, 0),
|
|
42993
|
-
placeholder: this.props.placeholder[0]
|
|
42994
|
-
})), /*#__PURE__*/React__namespace.createElement(NumberInput, _extends({}, this.props, {
|
|
42995
|
-
value: value[1],
|
|
42996
|
-
checkValidity: val => checkValidity([value[0], val])
|
|
42997
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
42998
|
-
,
|
|
42999
|
-
onChange: this.onChange.bind(this, 1),
|
|
43000
|
-
placeholder: this.props.placeholder[1]
|
|
43001
|
-
})));
|
|
43002
|
-
}
|
|
43003
|
-
onChange = (i, newVal) => {
|
|
43004
|
-
const value = this.props.value;
|
|
43005
|
-
if (i === 0) {
|
|
43006
|
-
this.props.onChange([newVal, value[1]]);
|
|
43007
|
-
} else {
|
|
43008
|
-
this.props.onChange([value[0], newVal]);
|
|
43009
|
-
}
|
|
43010
|
-
};
|
|
43011
|
-
}
|
|
43012
|
-
|
|
43013
|
-
var components = /*#__PURE__*/Object.freeze({
|
|
43014
|
-
__proto__: null,
|
|
43015
|
-
ButtonGroup: ButtonGroup,
|
|
43016
|
-
Graph: Graph,
|
|
43017
|
-
Graphie: Graphie,
|
|
43018
|
-
HUD: HUD,
|
|
43019
|
-
Icon: Icon,
|
|
43020
|
-
InfoTip: InfoTip,
|
|
43021
|
-
InlineIcon: InlineIcon,
|
|
43022
|
-
MathInput: MathInput,
|
|
43023
|
-
MultiButtonGroup: MultiButtonGroup,
|
|
43024
|
-
NumberInput: NumberInput,
|
|
43025
|
-
PropCheckBox: PropCheckBox,
|
|
43026
|
-
RangeInput: RangeInput,
|
|
43027
|
-
SvgImage: SvgImage,
|
|
43028
|
-
TextInput: TextInput,
|
|
43029
|
-
TextListEditor: TextListEditor
|
|
43030
|
-
});
|
|
43031
|
-
|
|
43032
43269
|
const devices = {
|
|
43033
43270
|
PHONE: "phone",
|
|
43034
43271
|
TABLET: "tablet",
|