@khanacademy/perseus 21.2.1 → 21.3.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 +33 -2
- package/dist/es/index.js +78 -53
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +33 -2
- package/dist/index.js +77 -52
- package/dist/index.js.map +1 -1
- package/dist/widgets/interactive-graphs/index.d.ts +1 -1
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +9 -4
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -4291,9 +4291,13 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4291
4291
|
--movable-line-stroke-weight-active: 4px;
|
|
4292
4292
|
}
|
|
4293
4293
|
|
|
4294
|
-
.MafsView
|
|
4294
|
+
.MafsView > svg {
|
|
4295
|
+
/* Chrome/Safari bugfix for LEMS-1906 */
|
|
4296
|
+
display: block;
|
|
4297
|
+
}
|
|
4298
|
+
|
|
4299
|
+
.MafsView .movable-line:hover,
|
|
4295
4300
|
.movable-dragging {
|
|
4296
|
-
outline: none;
|
|
4297
4301
|
--movable-line-stroke-weight: var(--movable-line-stroke-weight-active);
|
|
4298
4302
|
}
|
|
4299
4303
|
|
|
@@ -4302,6 +4306,22 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4302
4306
|
outline: none;
|
|
4303
4307
|
}
|
|
4304
4308
|
|
|
4309
|
+
.MafsView
|
|
4310
|
+
.movable-line
|
|
4311
|
+
:is(.movable-line-focus-outline, .movable-line-focus-outline-gap) {
|
|
4312
|
+
stroke: transparent;
|
|
4313
|
+
}
|
|
4314
|
+
|
|
4315
|
+
.MafsView .movable-line:focus-visible .movable-line-focus-outline {
|
|
4316
|
+
stroke: var(--mafs-blue);
|
|
4317
|
+
stroke-width: 10px;
|
|
4318
|
+
}
|
|
4319
|
+
|
|
4320
|
+
.MafsView .movable-line:focus-visible .movable-line-focus-outline-gap {
|
|
4321
|
+
stroke: white;
|
|
4322
|
+
stroke-width: 6px;
|
|
4323
|
+
}
|
|
4324
|
+
|
|
4305
4325
|
.MafsView .movable-point-hitbox {
|
|
4306
4326
|
fill: transparent;
|
|
4307
4327
|
}
|
|
@@ -4372,3 +4392,14 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4372
4392
|
.MafsView .movable-point:focus-visible .movable-point-focus-outline {
|
|
4373
4393
|
visibility: visible;
|
|
4374
4394
|
}
|
|
4395
|
+
|
|
4396
|
+
@font-face {
|
|
4397
|
+
font-family: Mafs-MJXTEX;
|
|
4398
|
+
src: url("https://cdn.kastatic.org/fonts/mathjax/MathJax_Main-Regular.woff")
|
|
4399
|
+
format("woff");
|
|
4400
|
+
}
|
|
4401
|
+
|
|
4402
|
+
.MafsView .axis-ticks text {
|
|
4403
|
+
font-size: 14px;
|
|
4404
|
+
font-family: "Mafs-MJXTEX";
|
|
4405
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -25037,6 +25037,7 @@ class Explanation extends React__namespace.Component {
|
|
|
25037
25037
|
// While the button is not normally included in a block of text, it needs to be able to accommodate such a case.
|
|
25038
25038
|
const buttonStyleOverrides = {
|
|
25039
25039
|
height: "auto",
|
|
25040
|
+
lineHeight: "inherit",
|
|
25040
25041
|
marginLeft: "-2px",
|
|
25041
25042
|
// transfer space on the left side to the padding
|
|
25042
25043
|
marginRight: "2px",
|
|
@@ -25046,7 +25047,8 @@ class Explanation extends React__namespace.Component {
|
|
|
25046
25047
|
|
|
25047
25048
|
const labelStyle = {
|
|
25048
25049
|
fontSize: "18px",
|
|
25049
|
-
lineHeight: "
|
|
25050
|
+
lineHeight: "inherit",
|
|
25051
|
+
"text-align": "left",
|
|
25050
25052
|
// The following property adjusts the large space between the button text and the caret icon.
|
|
25051
25053
|
// Since we are unable to adjust the styling of the icon (where the extra space exists),
|
|
25052
25054
|
// we are adjusting it on the text label by using a negative margin.
|
|
@@ -28389,14 +28391,6 @@ function changeRange(range) {
|
|
|
28389
28391
|
};
|
|
28390
28392
|
}
|
|
28391
28393
|
|
|
28392
|
-
const GraphStateContext = /*#__PURE__*/React.createContext({
|
|
28393
|
-
state: {},
|
|
28394
|
-
dispatch: () => {}
|
|
28395
|
-
});
|
|
28396
|
-
function useGraphState() {
|
|
28397
|
-
return React__default["default"].useContext(GraphStateContext);
|
|
28398
|
-
}
|
|
28399
|
-
|
|
28400
28394
|
/**
|
|
28401
28395
|
* 44 is touch best practice and AAA compliant for WCAG
|
|
28402
28396
|
* https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
|
|
@@ -28485,9 +28479,6 @@ const getLines = points => points.map((point, i) => {
|
|
|
28485
28479
|
|
|
28486
28480
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
28487
28481
|
const MovableLine = props => {
|
|
28488
|
-
const {
|
|
28489
|
-
state
|
|
28490
|
-
} = useGraphState();
|
|
28491
28482
|
const {
|
|
28492
28483
|
start,
|
|
28493
28484
|
end,
|
|
@@ -28512,12 +28503,13 @@ const MovableLine = props => {
|
|
|
28512
28503
|
onMove: newPoint => {
|
|
28513
28504
|
onMove(mafs.vec.sub(newPoint, midpoint));
|
|
28514
28505
|
},
|
|
28515
|
-
constrain: p =>
|
|
28506
|
+
constrain: p => p
|
|
28516
28507
|
});
|
|
28517
28508
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("g", {
|
|
28518
28509
|
ref: line,
|
|
28519
28510
|
tabIndex: 0,
|
|
28520
28511
|
className: "movable-line",
|
|
28512
|
+
"data-test-id": "movable-line",
|
|
28521
28513
|
style: {
|
|
28522
28514
|
cursor: dragging ? "grabbing" : "grab"
|
|
28523
28515
|
}
|
|
@@ -28528,6 +28520,16 @@ const MovableLine = props => {
|
|
|
28528
28520
|
stroke: "transparent",
|
|
28529
28521
|
strokeWidth: TARGET_SIZE
|
|
28530
28522
|
}
|
|
28523
|
+
}), /*#__PURE__*/React__namespace.createElement(SVGLine, {
|
|
28524
|
+
start: startPtPx,
|
|
28525
|
+
end: endPtPx,
|
|
28526
|
+
className: "movable-line-focus-outline",
|
|
28527
|
+
style: {}
|
|
28528
|
+
}), /*#__PURE__*/React__namespace.createElement(SVGLine, {
|
|
28529
|
+
start: startPtPx,
|
|
28530
|
+
end: endPtPx,
|
|
28531
|
+
className: "movable-line-focus-outline-gap",
|
|
28532
|
+
style: {}
|
|
28531
28533
|
}), /*#__PURE__*/React__namespace.createElement(SVGLine, {
|
|
28532
28534
|
start: startPtPx,
|
|
28533
28535
|
end: endPtPx,
|
|
@@ -28535,7 +28537,8 @@ const MovableLine = props => {
|
|
|
28535
28537
|
stroke,
|
|
28536
28538
|
strokeWidth: "var(--movable-line-stroke-weight)"
|
|
28537
28539
|
},
|
|
28538
|
-
dragging: dragging
|
|
28540
|
+
dragging: dragging,
|
|
28541
|
+
testId: "movable-line__line"
|
|
28539
28542
|
})), startExtend && /*#__PURE__*/React__namespace.createElement(mafs.Vector, {
|
|
28540
28543
|
tail: start,
|
|
28541
28544
|
tip: startExtend,
|
|
@@ -28551,18 +28554,30 @@ function SVGLine(props) {
|
|
|
28551
28554
|
start,
|
|
28552
28555
|
end,
|
|
28553
28556
|
style,
|
|
28554
|
-
dragging
|
|
28557
|
+
dragging,
|
|
28558
|
+
className,
|
|
28559
|
+
testId
|
|
28555
28560
|
} = props;
|
|
28561
|
+
const draggingClass = dragging ? "movable-dragging" : "";
|
|
28556
28562
|
return /*#__PURE__*/React__namespace.createElement("line", {
|
|
28557
28563
|
x1: start[0],
|
|
28558
28564
|
y1: start[1],
|
|
28559
28565
|
x2: end[0],
|
|
28560
28566
|
y2: end[1],
|
|
28561
28567
|
style: style,
|
|
28562
|
-
className:
|
|
28568
|
+
className: `${className} ${draggingClass}`,
|
|
28569
|
+
"data-test-id": testId
|
|
28563
28570
|
});
|
|
28564
28571
|
}
|
|
28565
28572
|
|
|
28573
|
+
const GraphStateContext = /*#__PURE__*/React.createContext({
|
|
28574
|
+
state: {},
|
|
28575
|
+
dispatch: () => {}
|
|
28576
|
+
});
|
|
28577
|
+
function useGraphState() {
|
|
28578
|
+
return React__default["default"].useContext(GraphStateContext);
|
|
28579
|
+
}
|
|
28580
|
+
|
|
28566
28581
|
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
28567
28582
|
// graph.
|
|
28568
28583
|
const hitboxSizePx = 48;
|
|
@@ -28594,7 +28609,8 @@ const StyledMovablePoint = props => {
|
|
|
28594
28609
|
touchAction: "none",
|
|
28595
28610
|
outline: "none",
|
|
28596
28611
|
"--movable-point-color": color
|
|
28597
|
-
}
|
|
28612
|
+
},
|
|
28613
|
+
"data-test-id": "movable-point"
|
|
28598
28614
|
}, /*#__PURE__*/React__namespace.createElement("circle", {
|
|
28599
28615
|
className: "movable-point-hitbox",
|
|
28600
28616
|
r: hitboxSizePx / 2,
|
|
@@ -28618,7 +28634,8 @@ const StyledMovablePoint = props => {
|
|
|
28618
28634
|
cy: y,
|
|
28619
28635
|
style: {
|
|
28620
28636
|
fill: color
|
|
28621
|
-
}
|
|
28637
|
+
},
|
|
28638
|
+
"data-test-id": "movable-point__center"
|
|
28622
28639
|
}));
|
|
28623
28640
|
};
|
|
28624
28641
|
|
|
@@ -29084,7 +29101,13 @@ const YGridTick = _ref => {
|
|
|
29084
29101
|
x2: xPosition + tickSize / 2,
|
|
29085
29102
|
y2: yPosition,
|
|
29086
29103
|
style: tickStyle
|
|
29087
|
-
})
|
|
29104
|
+
}), y !== -1 && /*#__PURE__*/React__namespace.createElement("text", {
|
|
29105
|
+
height: 20,
|
|
29106
|
+
width: 50,
|
|
29107
|
+
textAnchor: "end",
|
|
29108
|
+
x: xPosition - 10,
|
|
29109
|
+
y: yPosition + 5
|
|
29110
|
+
}, y.toString()));
|
|
29088
29111
|
};
|
|
29089
29112
|
const XGridTick = _ref2 => {
|
|
29090
29113
|
let {
|
|
@@ -29100,13 +29123,23 @@ const XGridTick = _ref2 => {
|
|
|
29100
29123
|
x2: xPosition,
|
|
29101
29124
|
y2: yPosition - tickSize / 2,
|
|
29102
29125
|
style: tickStyle
|
|
29103
|
-
})
|
|
29126
|
+
}), x !== -1 && /*#__PURE__*/React__namespace.createElement("text", {
|
|
29127
|
+
height: 20,
|
|
29128
|
+
width: 50,
|
|
29129
|
+
textAnchor: "middle",
|
|
29130
|
+
x: xPosition,
|
|
29131
|
+
y: yPosition + 25
|
|
29132
|
+
}, x.toString()));
|
|
29104
29133
|
};
|
|
29105
29134
|
function generateTickLocations(tickStep, min, max) {
|
|
29106
29135
|
const ticks = [];
|
|
29136
|
+
|
|
29137
|
+
// Add ticks in the positive direction
|
|
29107
29138
|
for (let i = 0 + tickStep; i < max; i += tickStep) {
|
|
29108
29139
|
ticks.push(i);
|
|
29109
29140
|
}
|
|
29141
|
+
|
|
29142
|
+
// Add ticks in the negative direction
|
|
29110
29143
|
for (let i = 0 - tickStep; i > min; i -= tickStep) {
|
|
29111
29144
|
ticks.push(i);
|
|
29112
29145
|
}
|
|
@@ -29135,24 +29168,6 @@ const AxisTicks = props => {
|
|
|
29135
29168
|
}));
|
|
29136
29169
|
};
|
|
29137
29170
|
|
|
29138
|
-
/**
|
|
29139
|
-
* lineLabelText get the text that should
|
|
29140
|
-
* be displayed for a specific tick place
|
|
29141
|
-
*
|
|
29142
|
-
* @param {number} n the tick number
|
|
29143
|
-
* @param {number} tickStep how frequently a label should appear
|
|
29144
|
-
* @param {vec.Vector2} range the min/max range on the axis
|
|
29145
|
-
*/
|
|
29146
|
-
const lineLabelText = (n, tickStep, range) => {
|
|
29147
|
-
const [min, max] = range;
|
|
29148
|
-
const isOnStep = n % tickStep === 0;
|
|
29149
|
-
const isNegativeOne = n === -1;
|
|
29150
|
-
const isMin = n === min;
|
|
29151
|
-
const isMax = n === max;
|
|
29152
|
-
const shouldRender = isOnStep && !isNegativeOne && !isMin && !isMax;
|
|
29153
|
-
return shouldRender ? `${n}` : "";
|
|
29154
|
-
};
|
|
29155
|
-
|
|
29156
29171
|
/**
|
|
29157
29172
|
* axisOptions determine axis options for Mafs
|
|
29158
29173
|
*
|
|
@@ -29164,12 +29179,10 @@ const lineLabelText = (n, tickStep, range) => {
|
|
|
29164
29179
|
* @param {number} axisIndex which axis we're getting options for
|
|
29165
29180
|
*/
|
|
29166
29181
|
const axisOptions = (props, axisIndex) => {
|
|
29167
|
-
const axisStep = props.tickStep[axisIndex];
|
|
29168
|
-
const axisRange = props.range[axisIndex];
|
|
29169
29182
|
return {
|
|
29170
29183
|
axis: props.markings === "graph",
|
|
29171
29184
|
lines: props.gridStep[axisIndex],
|
|
29172
|
-
labels:
|
|
29185
|
+
labels: false
|
|
29173
29186
|
};
|
|
29174
29187
|
};
|
|
29175
29188
|
const Grid = props => {
|
|
@@ -30416,9 +30429,22 @@ const renderGraph = props => {
|
|
|
30416
30429
|
return new wonderStuffCore.UnreachableCaseError(type);
|
|
30417
30430
|
}
|
|
30418
30431
|
};
|
|
30419
|
-
const
|
|
30420
|
-
const [width, height] = props.box;
|
|
30432
|
+
const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
30421
30433
|
const [state, dispatch] = React__namespace.useReducer(interactiveGraphReducer, props, initializeGraphState);
|
|
30434
|
+
React.useImperativeHandle(ref, () => ({
|
|
30435
|
+
getUserInput: () => getGradableGraph(state, props.graph)
|
|
30436
|
+
}));
|
|
30437
|
+
return /*#__PURE__*/React__namespace.createElement(MafsGraph, _extends({
|
|
30438
|
+
state: state,
|
|
30439
|
+
dispatch: dispatch
|
|
30440
|
+
}, props));
|
|
30441
|
+
});
|
|
30442
|
+
const MafsGraph = props => {
|
|
30443
|
+
const {
|
|
30444
|
+
state,
|
|
30445
|
+
dispatch
|
|
30446
|
+
} = props;
|
|
30447
|
+
const [width, height] = props.box;
|
|
30422
30448
|
const prevState = React.useRef(state);
|
|
30423
30449
|
React.useEffect(() => {
|
|
30424
30450
|
if (prevState.current !== state) {
|
|
@@ -30433,16 +30459,13 @@ const MafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
|
30433
30459
|
const [xSnap, ySnap] = props.snapStep;
|
|
30434
30460
|
React.useEffect(() => {
|
|
30435
30461
|
dispatch(changeSnapStep([xSnap, ySnap]));
|
|
30436
|
-
}, [xSnap, ySnap]);
|
|
30462
|
+
}, [dispatch, xSnap, ySnap]);
|
|
30437
30463
|
|
|
30438
30464
|
// Destructuring first to keep useEffect from making excess calls
|
|
30439
30465
|
const [[xMinRange, xMaxRange], [yMinRange, yMaxRange]] = props.range;
|
|
30440
30466
|
React.useEffect(() => {
|
|
30441
30467
|
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
30442
|
-
}, [xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
30443
|
-
React__namespace.useImperativeHandle(ref, () => ({
|
|
30444
|
-
getUserInput: () => getGradableGraph(state, props.graph)
|
|
30445
|
-
}));
|
|
30468
|
+
}, [dispatch, xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
30446
30469
|
return /*#__PURE__*/React__namespace.createElement(GraphStateContext.Provider, {
|
|
30447
30470
|
value: {
|
|
30448
30471
|
state,
|
|
@@ -30452,7 +30475,9 @@ const MafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
|
30452
30475
|
style: {
|
|
30453
30476
|
width,
|
|
30454
30477
|
height,
|
|
30455
|
-
position: "relative"
|
|
30478
|
+
position: "relative",
|
|
30479
|
+
padding: "25px 25px 0 0",
|
|
30480
|
+
boxSizing: "content-box"
|
|
30456
30481
|
}
|
|
30457
30482
|
}, /*#__PURE__*/React__namespace.createElement(LegacyGrid, {
|
|
30458
30483
|
box: props.box,
|
|
@@ -30486,7 +30511,7 @@ const MafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
|
30486
30511
|
state,
|
|
30487
30512
|
dispatch
|
|
30488
30513
|
})))));
|
|
30489
|
-
}
|
|
30514
|
+
};
|
|
30490
30515
|
|
|
30491
30516
|
const {
|
|
30492
30517
|
DeprecationMixin
|
|
@@ -31762,7 +31787,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
31762
31787
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
31763
31788
|
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
31764
31789
|
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
31765
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
31790
|
+
return /*#__PURE__*/React__namespace.createElement(StatefulMafsGraph, _extends({}, this.props, {
|
|
31766
31791
|
ref: this.mafsRef,
|
|
31767
31792
|
gridStep: gridStep,
|
|
31768
31793
|
snapStep: snapStep,
|
|
@@ -42493,7 +42518,7 @@ const init = function (options) {
|
|
|
42493
42518
|
|
|
42494
42519
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
42495
42520
|
const libName = "@khanacademy/perseus";
|
|
42496
|
-
const libVersion = "21.
|
|
42521
|
+
const libVersion = "21.3.0";
|
|
42497
42522
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
42498
42523
|
|
|
42499
42524
|
const apiVersion = {
|