@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/es/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/es/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as i18n from '@khanacademy/wonder-blocks-i18n';
|
|
|
7
7
|
import Tooltip$1 from '@khanacademy/wonder-blocks-tooltip';
|
|
8
8
|
import classNames from 'classnames';
|
|
9
9
|
import * as React from 'react';
|
|
10
|
-
import React__default, { useState, useEffect, useRef, createContext } from 'react';
|
|
10
|
+
import React__default, { useState, useEffect, useRef, createContext, useImperativeHandle } from 'react';
|
|
11
11
|
import _, { debounce as debounce$1 } from 'underscore';
|
|
12
12
|
import Clickable from '@khanacademy/wonder-blocks-clickable';
|
|
13
13
|
import { Popover, PopoverContentCore, PopoverContent } from '@khanacademy/wonder-blocks-popover';
|
|
@@ -24912,6 +24912,7 @@ class Explanation extends React.Component {
|
|
|
24912
24912
|
// While the button is not normally included in a block of text, it needs to be able to accommodate such a case.
|
|
24913
24913
|
const buttonStyleOverrides = {
|
|
24914
24914
|
height: "auto",
|
|
24915
|
+
lineHeight: "inherit",
|
|
24915
24916
|
marginLeft: "-2px",
|
|
24916
24917
|
// transfer space on the left side to the padding
|
|
24917
24918
|
marginRight: "2px",
|
|
@@ -24921,7 +24922,8 @@ class Explanation extends React.Component {
|
|
|
24921
24922
|
|
|
24922
24923
|
const labelStyle = {
|
|
24923
24924
|
fontSize: "18px",
|
|
24924
|
-
lineHeight: "
|
|
24925
|
+
lineHeight: "inherit",
|
|
24926
|
+
"text-align": "left",
|
|
24925
24927
|
// The following property adjusts the large space between the button text and the caret icon.
|
|
24926
24928
|
// Since we are unable to adjust the styling of the icon (where the extra space exists),
|
|
24927
24929
|
// we are adjusting it on the text label by using a negative margin.
|
|
@@ -28237,14 +28239,6 @@ function changeRange(range) {
|
|
|
28237
28239
|
};
|
|
28238
28240
|
}
|
|
28239
28241
|
|
|
28240
|
-
const GraphStateContext = /*#__PURE__*/createContext({
|
|
28241
|
-
state: {},
|
|
28242
|
-
dispatch: () => {}
|
|
28243
|
-
});
|
|
28244
|
-
function useGraphState() {
|
|
28245
|
-
return React__default.useContext(GraphStateContext);
|
|
28246
|
-
}
|
|
28247
|
-
|
|
28248
28242
|
/**
|
|
28249
28243
|
* 44 is touch best practice and AAA compliant for WCAG
|
|
28250
28244
|
* https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
|
|
@@ -28330,9 +28324,6 @@ const getLines = points => points.map((point, i) => {
|
|
|
28330
28324
|
|
|
28331
28325
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
28332
28326
|
const MovableLine = props => {
|
|
28333
|
-
const {
|
|
28334
|
-
state
|
|
28335
|
-
} = useGraphState();
|
|
28336
28327
|
const {
|
|
28337
28328
|
start,
|
|
28338
28329
|
end,
|
|
@@ -28357,12 +28348,13 @@ const MovableLine = props => {
|
|
|
28357
28348
|
onMove: newPoint => {
|
|
28358
28349
|
onMove(vec.sub(newPoint, midpoint));
|
|
28359
28350
|
},
|
|
28360
|
-
constrain: p =>
|
|
28351
|
+
constrain: p => p
|
|
28361
28352
|
});
|
|
28362
28353
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("g", {
|
|
28363
28354
|
ref: line,
|
|
28364
28355
|
tabIndex: 0,
|
|
28365
28356
|
className: "movable-line",
|
|
28357
|
+
"data-test-id": "movable-line",
|
|
28366
28358
|
style: {
|
|
28367
28359
|
cursor: dragging ? "grabbing" : "grab"
|
|
28368
28360
|
}
|
|
@@ -28373,6 +28365,16 @@ const MovableLine = props => {
|
|
|
28373
28365
|
stroke: "transparent",
|
|
28374
28366
|
strokeWidth: TARGET_SIZE
|
|
28375
28367
|
}
|
|
28368
|
+
}), /*#__PURE__*/React.createElement(SVGLine, {
|
|
28369
|
+
start: startPtPx,
|
|
28370
|
+
end: endPtPx,
|
|
28371
|
+
className: "movable-line-focus-outline",
|
|
28372
|
+
style: {}
|
|
28373
|
+
}), /*#__PURE__*/React.createElement(SVGLine, {
|
|
28374
|
+
start: startPtPx,
|
|
28375
|
+
end: endPtPx,
|
|
28376
|
+
className: "movable-line-focus-outline-gap",
|
|
28377
|
+
style: {}
|
|
28376
28378
|
}), /*#__PURE__*/React.createElement(SVGLine, {
|
|
28377
28379
|
start: startPtPx,
|
|
28378
28380
|
end: endPtPx,
|
|
@@ -28380,7 +28382,8 @@ const MovableLine = props => {
|
|
|
28380
28382
|
stroke,
|
|
28381
28383
|
strokeWidth: "var(--movable-line-stroke-weight)"
|
|
28382
28384
|
},
|
|
28383
|
-
dragging: dragging
|
|
28385
|
+
dragging: dragging,
|
|
28386
|
+
testId: "movable-line__line"
|
|
28384
28387
|
})), startExtend && /*#__PURE__*/React.createElement(Vector, {
|
|
28385
28388
|
tail: start,
|
|
28386
28389
|
tip: startExtend,
|
|
@@ -28396,18 +28399,30 @@ function SVGLine(props) {
|
|
|
28396
28399
|
start,
|
|
28397
28400
|
end,
|
|
28398
28401
|
style,
|
|
28399
|
-
dragging
|
|
28402
|
+
dragging,
|
|
28403
|
+
className,
|
|
28404
|
+
testId
|
|
28400
28405
|
} = props;
|
|
28406
|
+
const draggingClass = dragging ? "movable-dragging" : "";
|
|
28401
28407
|
return /*#__PURE__*/React.createElement("line", {
|
|
28402
28408
|
x1: start[0],
|
|
28403
28409
|
y1: start[1],
|
|
28404
28410
|
x2: end[0],
|
|
28405
28411
|
y2: end[1],
|
|
28406
28412
|
style: style,
|
|
28407
|
-
className:
|
|
28413
|
+
className: `${className} ${draggingClass}`,
|
|
28414
|
+
"data-test-id": testId
|
|
28408
28415
|
});
|
|
28409
28416
|
}
|
|
28410
28417
|
|
|
28418
|
+
const GraphStateContext = /*#__PURE__*/createContext({
|
|
28419
|
+
state: {},
|
|
28420
|
+
dispatch: () => {}
|
|
28421
|
+
});
|
|
28422
|
+
function useGraphState() {
|
|
28423
|
+
return React__default.useContext(GraphStateContext);
|
|
28424
|
+
}
|
|
28425
|
+
|
|
28411
28426
|
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
28412
28427
|
// graph.
|
|
28413
28428
|
const hitboxSizePx = 48;
|
|
@@ -28439,7 +28454,8 @@ const StyledMovablePoint = props => {
|
|
|
28439
28454
|
touchAction: "none",
|
|
28440
28455
|
outline: "none",
|
|
28441
28456
|
"--movable-point-color": color$1
|
|
28442
|
-
}
|
|
28457
|
+
},
|
|
28458
|
+
"data-test-id": "movable-point"
|
|
28443
28459
|
}, /*#__PURE__*/React.createElement("circle", {
|
|
28444
28460
|
className: "movable-point-hitbox",
|
|
28445
28461
|
r: hitboxSizePx / 2,
|
|
@@ -28463,7 +28479,8 @@ const StyledMovablePoint = props => {
|
|
|
28463
28479
|
cy: y,
|
|
28464
28480
|
style: {
|
|
28465
28481
|
fill: color$1
|
|
28466
|
-
}
|
|
28482
|
+
},
|
|
28483
|
+
"data-test-id": "movable-point__center"
|
|
28467
28484
|
}));
|
|
28468
28485
|
};
|
|
28469
28486
|
|
|
@@ -28920,7 +28937,13 @@ const YGridTick = ({
|
|
|
28920
28937
|
x2: xPosition + tickSize / 2,
|
|
28921
28938
|
y2: yPosition,
|
|
28922
28939
|
style: tickStyle
|
|
28923
|
-
})
|
|
28940
|
+
}), y !== -1 && /*#__PURE__*/React.createElement("text", {
|
|
28941
|
+
height: 20,
|
|
28942
|
+
width: 50,
|
|
28943
|
+
textAnchor: "end",
|
|
28944
|
+
x: xPosition - 10,
|
|
28945
|
+
y: yPosition + 5
|
|
28946
|
+
}, y.toString()));
|
|
28924
28947
|
};
|
|
28925
28948
|
const XGridTick = ({
|
|
28926
28949
|
x
|
|
@@ -28935,13 +28958,23 @@ const XGridTick = ({
|
|
|
28935
28958
|
x2: xPosition,
|
|
28936
28959
|
y2: yPosition - tickSize / 2,
|
|
28937
28960
|
style: tickStyle
|
|
28938
|
-
})
|
|
28961
|
+
}), x !== -1 && /*#__PURE__*/React.createElement("text", {
|
|
28962
|
+
height: 20,
|
|
28963
|
+
width: 50,
|
|
28964
|
+
textAnchor: "middle",
|
|
28965
|
+
x: xPosition,
|
|
28966
|
+
y: yPosition + 25
|
|
28967
|
+
}, x.toString()));
|
|
28939
28968
|
};
|
|
28940
28969
|
function generateTickLocations(tickStep, min, max) {
|
|
28941
28970
|
const ticks = [];
|
|
28971
|
+
|
|
28972
|
+
// Add ticks in the positive direction
|
|
28942
28973
|
for (let i = 0 + tickStep; i < max; i += tickStep) {
|
|
28943
28974
|
ticks.push(i);
|
|
28944
28975
|
}
|
|
28976
|
+
|
|
28977
|
+
// Add ticks in the negative direction
|
|
28945
28978
|
for (let i = 0 - tickStep; i > min; i -= tickStep) {
|
|
28946
28979
|
ticks.push(i);
|
|
28947
28980
|
}
|
|
@@ -28970,24 +29003,6 @@ const AxisTicks = props => {
|
|
|
28970
29003
|
}));
|
|
28971
29004
|
};
|
|
28972
29005
|
|
|
28973
|
-
/**
|
|
28974
|
-
* lineLabelText get the text that should
|
|
28975
|
-
* be displayed for a specific tick place
|
|
28976
|
-
*
|
|
28977
|
-
* @param {number} n the tick number
|
|
28978
|
-
* @param {number} tickStep how frequently a label should appear
|
|
28979
|
-
* @param {vec.Vector2} range the min/max range on the axis
|
|
28980
|
-
*/
|
|
28981
|
-
const lineLabelText = (n, tickStep, range) => {
|
|
28982
|
-
const [min, max] = range;
|
|
28983
|
-
const isOnStep = n % tickStep === 0;
|
|
28984
|
-
const isNegativeOne = n === -1;
|
|
28985
|
-
const isMin = n === min;
|
|
28986
|
-
const isMax = n === max;
|
|
28987
|
-
const shouldRender = isOnStep && !isNegativeOne && !isMin && !isMax;
|
|
28988
|
-
return shouldRender ? `${n}` : "";
|
|
28989
|
-
};
|
|
28990
|
-
|
|
28991
29006
|
/**
|
|
28992
29007
|
* axisOptions determine axis options for Mafs
|
|
28993
29008
|
*
|
|
@@ -28999,12 +29014,10 @@ const lineLabelText = (n, tickStep, range) => {
|
|
|
28999
29014
|
* @param {number} axisIndex which axis we're getting options for
|
|
29000
29015
|
*/
|
|
29001
29016
|
const axisOptions = (props, axisIndex) => {
|
|
29002
|
-
const axisStep = props.tickStep[axisIndex];
|
|
29003
|
-
const axisRange = props.range[axisIndex];
|
|
29004
29017
|
return {
|
|
29005
29018
|
axis: props.markings === "graph",
|
|
29006
29019
|
lines: props.gridStep[axisIndex],
|
|
29007
|
-
labels:
|
|
29020
|
+
labels: false
|
|
29008
29021
|
};
|
|
29009
29022
|
};
|
|
29010
29023
|
const Grid = props => {
|
|
@@ -30232,9 +30245,22 @@ const renderGraph = props => {
|
|
|
30232
30245
|
return new UnreachableCaseError(type);
|
|
30233
30246
|
}
|
|
30234
30247
|
};
|
|
30235
|
-
const
|
|
30236
|
-
const [width, height] = props.box;
|
|
30248
|
+
const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
30237
30249
|
const [state, dispatch] = React.useReducer(interactiveGraphReducer, props, initializeGraphState);
|
|
30250
|
+
useImperativeHandle(ref, () => ({
|
|
30251
|
+
getUserInput: () => getGradableGraph(state, props.graph)
|
|
30252
|
+
}));
|
|
30253
|
+
return /*#__PURE__*/React.createElement(MafsGraph, _extends({
|
|
30254
|
+
state: state,
|
|
30255
|
+
dispatch: dispatch
|
|
30256
|
+
}, props));
|
|
30257
|
+
});
|
|
30258
|
+
const MafsGraph = props => {
|
|
30259
|
+
const {
|
|
30260
|
+
state,
|
|
30261
|
+
dispatch
|
|
30262
|
+
} = props;
|
|
30263
|
+
const [width, height] = props.box;
|
|
30238
30264
|
const prevState = useRef(state);
|
|
30239
30265
|
useEffect(() => {
|
|
30240
30266
|
if (prevState.current !== state) {
|
|
@@ -30249,16 +30275,13 @@ const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
30249
30275
|
const [xSnap, ySnap] = props.snapStep;
|
|
30250
30276
|
useEffect(() => {
|
|
30251
30277
|
dispatch(changeSnapStep([xSnap, ySnap]));
|
|
30252
|
-
}, [xSnap, ySnap]);
|
|
30278
|
+
}, [dispatch, xSnap, ySnap]);
|
|
30253
30279
|
|
|
30254
30280
|
// Destructuring first to keep useEffect from making excess calls
|
|
30255
30281
|
const [[xMinRange, xMaxRange], [yMinRange, yMaxRange]] = props.range;
|
|
30256
30282
|
useEffect(() => {
|
|
30257
30283
|
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
30258
|
-
}, [xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
30259
|
-
React.useImperativeHandle(ref, () => ({
|
|
30260
|
-
getUserInput: () => getGradableGraph(state, props.graph)
|
|
30261
|
-
}));
|
|
30284
|
+
}, [dispatch, xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
30262
30285
|
return /*#__PURE__*/React.createElement(GraphStateContext.Provider, {
|
|
30263
30286
|
value: {
|
|
30264
30287
|
state,
|
|
@@ -30268,7 +30291,9 @@ const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
30268
30291
|
style: {
|
|
30269
30292
|
width,
|
|
30270
30293
|
height,
|
|
30271
|
-
position: "relative"
|
|
30294
|
+
position: "relative",
|
|
30295
|
+
padding: "25px 25px 0 0",
|
|
30296
|
+
boxSizing: "content-box"
|
|
30272
30297
|
}
|
|
30273
30298
|
}, /*#__PURE__*/React.createElement(LegacyGrid, {
|
|
30274
30299
|
box: props.box,
|
|
@@ -30302,7 +30327,7 @@ const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
30302
30327
|
state,
|
|
30303
30328
|
dispatch
|
|
30304
30329
|
})))));
|
|
30305
|
-
}
|
|
30330
|
+
};
|
|
30306
30331
|
|
|
30307
30332
|
const {
|
|
30308
30333
|
DeprecationMixin
|
|
@@ -31606,7 +31631,7 @@ class InteractiveGraph extends React.Component {
|
|
|
31606
31631
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
31607
31632
|
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
31608
31633
|
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
31609
|
-
return /*#__PURE__*/React.createElement(
|
|
31634
|
+
return /*#__PURE__*/React.createElement(StatefulMafsGraph, _extends({}, this.props, {
|
|
31610
31635
|
ref: this.mafsRef,
|
|
31611
31636
|
gridStep: gridStep,
|
|
31612
31637
|
snapStep: snapStep,
|
|
@@ -42345,7 +42370,7 @@ const init = function init(options) {
|
|
|
42345
42370
|
|
|
42346
42371
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
42347
42372
|
const libName = "@khanacademy/perseus";
|
|
42348
|
-
const libVersion = "21.
|
|
42373
|
+
const libVersion = "21.3.0";
|
|
42349
42374
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
42350
42375
|
|
|
42351
42376
|
const apiVersion = {
|