@khanacademy/perseus 21.1.0 → 21.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +28 -4
- package/dist/es/index.js +231 -64
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +28 -4
- package/dist/index.js +239 -72
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +1 -1
- package/dist/perseus-types.d.ts +6 -2
- package/dist/server-item-renderer.d.ts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/util.d.ts +3 -0
- package/dist/widgets/expression.d.ts +6 -6
- package/dist/widgets/interactive-graph.d.ts +4 -1
- package/dist/widgets/interactive-graphs/axis-ticks.d.ts +8 -0
- package/dist/widgets/interactive-graphs/graphs/components/movable-line.d.ts +6 -4
- package/dist/widgets/interactive-graphs/grid.d.ts +14 -3
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +2 -2
- package/dist/widgets/interactive-graphs/reducer/interactive-graph-action.d.ts +14 -1
- package/dist/widgets/interactive-graphs/utils.d.ts +2 -0
- package/dist/widgets/label-image.d.ts +2 -2
- package/package.json +1 -1
package/dist/es/index.css
CHANGED
|
@@ -4284,6 +4284,7 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4284
4284
|
--movable-point-ring-radius: calc(2px + var(--movable-point-center-radius));
|
|
4285
4285
|
--movable-point-halo-radius: calc(3px + var(--movable-point-ring-radius));
|
|
4286
4286
|
--movable-point-hover-expansion: 2px;
|
|
4287
|
+
--movable-point-focus-ring-offset: 2px;
|
|
4287
4288
|
|
|
4288
4289
|
--movable-line-stroke-color: var(--mafs-blue);
|
|
4289
4290
|
--movable-line-stroke-weight: 2px;
|
|
@@ -4305,7 +4306,13 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4305
4306
|
fill: transparent;
|
|
4306
4307
|
}
|
|
4307
4308
|
|
|
4308
|
-
.MafsView
|
|
4309
|
+
.MafsView
|
|
4310
|
+
:is(
|
|
4311
|
+
.movable-point-center,
|
|
4312
|
+
.movable-point-ring,
|
|
4313
|
+
.movable-point-halo,
|
|
4314
|
+
.movable-point-focus-outline
|
|
4315
|
+
) {
|
|
4309
4316
|
transition: r 0.15s ease-out;
|
|
4310
4317
|
}
|
|
4311
4318
|
|
|
@@ -4344,7 +4351,24 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4344
4351
|
);
|
|
4345
4352
|
}
|
|
4346
4353
|
|
|
4347
|
-
.MafsView .movable-point
|
|
4348
|
-
|
|
4349
|
-
|
|
4354
|
+
.MafsView .movable-point .movable-point-focus-outline {
|
|
4355
|
+
visibility: hidden;
|
|
4356
|
+
r: calc(
|
|
4357
|
+
var(--movable-point-halo-radius) +
|
|
4358
|
+
var(--movable-point-focus-ring-offset)
|
|
4359
|
+
);
|
|
4360
|
+
stroke-width: 2px;
|
|
4361
|
+
fill: none;
|
|
4362
|
+
stroke: var(--mafs-blue);
|
|
4363
|
+
}
|
|
4364
|
+
|
|
4365
|
+
.MafsView .movable-point:hover .movable-point-focus-outline {
|
|
4366
|
+
r: calc(
|
|
4367
|
+
var(--movable-point-hover-expansion) + var(--movable-point-halo-radius) +
|
|
4368
|
+
var(--movable-point-focus-ring-offset)
|
|
4369
|
+
);
|
|
4370
|
+
}
|
|
4371
|
+
|
|
4372
|
+
.MafsView .movable-point:focus-visible .movable-point-focus-outline {
|
|
4373
|
+
visibility: visible;
|
|
4350
4374
|
}
|
package/dist/es/index.js
CHANGED
|
@@ -3258,6 +3258,15 @@ const textarea = {
|
|
|
3258
3258
|
*/
|
|
3259
3259
|
const unescapeMathMode$1 = label => label.startsWith("$") && label.endsWith("$") ? label.slice(1, -1) : label;
|
|
3260
3260
|
const random$1 = seededRNG$1(new Date().getTime() & 0xffffffff);
|
|
3261
|
+
|
|
3262
|
+
// TODO(benchristel): in the future, we may want to make deepClone work for
|
|
3263
|
+
// Record<string, Cloneable> as well. Currently, it only does arrays.
|
|
3264
|
+
function deepClone(obj) {
|
|
3265
|
+
if (Array.isArray(obj)) {
|
|
3266
|
+
return obj.map(deepClone);
|
|
3267
|
+
}
|
|
3268
|
+
return obj;
|
|
3269
|
+
}
|
|
3261
3270
|
const Util = {
|
|
3262
3271
|
inputPathsEqual,
|
|
3263
3272
|
nestedMap: nestedMap$2,
|
|
@@ -3303,7 +3312,8 @@ const Util = {
|
|
|
3303
3312
|
getDataUrl: getDataUrl,
|
|
3304
3313
|
textarea,
|
|
3305
3314
|
unescapeMathMode: unescapeMathMode$1,
|
|
3306
|
-
random: random$1
|
|
3315
|
+
random: random$1,
|
|
3316
|
+
deepClone
|
|
3307
3317
|
};
|
|
3308
3318
|
|
|
3309
3319
|
// Derived from the MIT-licensed:
|
|
@@ -28212,6 +28222,28 @@ function movePoint(index, destination) {
|
|
|
28212
28222
|
destination
|
|
28213
28223
|
};
|
|
28214
28224
|
}
|
|
28225
|
+
const CHANGE_SNAP_STEP = "change-snap-step";
|
|
28226
|
+
function changeSnapStep(snapStep) {
|
|
28227
|
+
return {
|
|
28228
|
+
type: CHANGE_SNAP_STEP,
|
|
28229
|
+
snapStep
|
|
28230
|
+
};
|
|
28231
|
+
}
|
|
28232
|
+
const CHANGE_RANGE = "change-range";
|
|
28233
|
+
function changeRange(range) {
|
|
28234
|
+
return {
|
|
28235
|
+
type: CHANGE_RANGE,
|
|
28236
|
+
range
|
|
28237
|
+
};
|
|
28238
|
+
}
|
|
28239
|
+
|
|
28240
|
+
const GraphStateContext = /*#__PURE__*/createContext({
|
|
28241
|
+
state: {},
|
|
28242
|
+
dispatch: () => {}
|
|
28243
|
+
});
|
|
28244
|
+
function useGraphState() {
|
|
28245
|
+
return React__default.useContext(GraphStateContext);
|
|
28246
|
+
}
|
|
28215
28247
|
|
|
28216
28248
|
/**
|
|
28217
28249
|
* 44 is touch best practice and AAA compliant for WCAG
|
|
@@ -28238,6 +28270,11 @@ const normalizeCoords = (coordsList, ranges) => coordsList.map(coords => coords.
|
|
|
28238
28270
|
const extent = ranges[i][1] - ranges[i][0];
|
|
28239
28271
|
return (coord + ranges[i][1]) / extent;
|
|
28240
28272
|
}));
|
|
28273
|
+
function snap(snapStep, point) {
|
|
28274
|
+
const [requestedX, requestedY] = point;
|
|
28275
|
+
const [snapX, snapY] = snapStep;
|
|
28276
|
+
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
28277
|
+
}
|
|
28241
28278
|
|
|
28242
28279
|
const useTransform = (...points) => {
|
|
28243
28280
|
const {
|
|
@@ -28293,6 +28330,9 @@ const getLines = points => points.map((point, i) => {
|
|
|
28293
28330
|
|
|
28294
28331
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
28295
28332
|
const MovableLine = props => {
|
|
28333
|
+
const {
|
|
28334
|
+
state
|
|
28335
|
+
} = useGraphState();
|
|
28296
28336
|
const {
|
|
28297
28337
|
start,
|
|
28298
28338
|
end,
|
|
@@ -28317,7 +28357,7 @@ const MovableLine = props => {
|
|
|
28317
28357
|
onMove: newPoint => {
|
|
28318
28358
|
onMove(vec.sub(newPoint, midpoint));
|
|
28319
28359
|
},
|
|
28320
|
-
constrain: p => p
|
|
28360
|
+
constrain: p => snap(state.snapStep, p)
|
|
28321
28361
|
});
|
|
28322
28362
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("g", {
|
|
28323
28363
|
ref: line,
|
|
@@ -28368,7 +28408,13 @@ function SVGLine(props) {
|
|
|
28368
28408
|
});
|
|
28369
28409
|
}
|
|
28370
28410
|
|
|
28411
|
+
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
28412
|
+
// graph.
|
|
28413
|
+
const hitboxSizePx = 48;
|
|
28371
28414
|
const StyledMovablePoint = props => {
|
|
28415
|
+
const {
|
|
28416
|
+
state
|
|
28417
|
+
} = useGraphState();
|
|
28372
28418
|
const hitboxRef = useRef(null);
|
|
28373
28419
|
const {
|
|
28374
28420
|
point,
|
|
@@ -28381,7 +28427,7 @@ const StyledMovablePoint = props => {
|
|
|
28381
28427
|
gestureTarget: hitboxRef,
|
|
28382
28428
|
point,
|
|
28383
28429
|
onMove,
|
|
28384
|
-
constrain: p => p
|
|
28430
|
+
constrain: p => snap(state.snapStep, p)
|
|
28385
28431
|
});
|
|
28386
28432
|
const [[x, y]] = useTransform(point);
|
|
28387
28433
|
return /*#__PURE__*/React.createElement("g", {
|
|
@@ -28396,7 +28442,7 @@ const StyledMovablePoint = props => {
|
|
|
28396
28442
|
}
|
|
28397
28443
|
}, /*#__PURE__*/React.createElement("circle", {
|
|
28398
28444
|
className: "movable-point-hitbox",
|
|
28399
|
-
r:
|
|
28445
|
+
r: hitboxSizePx / 2,
|
|
28400
28446
|
cx: x,
|
|
28401
28447
|
cy: y
|
|
28402
28448
|
}), /*#__PURE__*/React.createElement("circle", {
|
|
@@ -28407,6 +28453,10 @@ const StyledMovablePoint = props => {
|
|
|
28407
28453
|
className: "movable-point-ring",
|
|
28408
28454
|
cx: x,
|
|
28409
28455
|
cy: y
|
|
28456
|
+
}), /*#__PURE__*/React.createElement("circle", {
|
|
28457
|
+
className: "movable-point-focus-outline",
|
|
28458
|
+
cx: x,
|
|
28459
|
+
cy: y
|
|
28410
28460
|
}), /*#__PURE__*/React.createElement("circle", {
|
|
28411
28461
|
className: "movable-point-center",
|
|
28412
28462
|
cx: x,
|
|
@@ -28725,7 +28775,8 @@ const PolygonGraph = props => {
|
|
|
28725
28775
|
type,
|
|
28726
28776
|
showAngles,
|
|
28727
28777
|
showSides,
|
|
28728
|
-
range
|
|
28778
|
+
range,
|
|
28779
|
+
snapStep
|
|
28729
28780
|
} = props.graphState;
|
|
28730
28781
|
const points = coords != null ? coords : [[0, 0]];
|
|
28731
28782
|
const pointsSum = points.reduce((acc, point) => vec.add(acc, point), [0, 0]);
|
|
@@ -28740,7 +28791,7 @@ const PolygonGraph = props => {
|
|
|
28740
28791
|
const delta = vec.sub(newPoint, midpoint);
|
|
28741
28792
|
dispatch(moveAll(delta));
|
|
28742
28793
|
},
|
|
28743
|
-
constrain: p => p
|
|
28794
|
+
constrain: p => snap(snapStep, p)
|
|
28744
28795
|
});
|
|
28745
28796
|
const active = hovered || focused || dragging;
|
|
28746
28797
|
const lines = getLines(points);
|
|
@@ -28808,14 +28859,6 @@ function PointGraph(props) {
|
|
|
28808
28859
|
})));
|
|
28809
28860
|
}
|
|
28810
28861
|
|
|
28811
|
-
const GraphStateContext = /*#__PURE__*/createContext({
|
|
28812
|
-
state: {},
|
|
28813
|
-
dispatch: () => {}
|
|
28814
|
-
});
|
|
28815
|
-
function useGraphState() {
|
|
28816
|
-
return React__default.useContext(GraphStateContext);
|
|
28817
|
-
}
|
|
28818
|
-
|
|
28819
28862
|
function Arrow(props) {
|
|
28820
28863
|
const {
|
|
28821
28864
|
userTransform,
|
|
@@ -28859,17 +28902,120 @@ function AxisArrows() {
|
|
|
28859
28902
|
}));
|
|
28860
28903
|
}
|
|
28861
28904
|
|
|
28862
|
-
const
|
|
28863
|
-
const
|
|
28864
|
-
|
|
28865
|
-
|
|
28866
|
-
|
|
28867
|
-
|
|
28868
|
-
|
|
28869
|
-
|
|
28870
|
-
|
|
28871
|
-
|
|
28872
|
-
|
|
28905
|
+
const tickSize = 10;
|
|
28906
|
+
const tickStyle = {
|
|
28907
|
+
stroke: "black",
|
|
28908
|
+
strokeWidth: 1
|
|
28909
|
+
};
|
|
28910
|
+
const YGridTick = ({
|
|
28911
|
+
y
|
|
28912
|
+
}) => {
|
|
28913
|
+
const pointOnAxis = [0, y];
|
|
28914
|
+
const [[xPosition, yPosition]] = useTransform(pointOnAxis);
|
|
28915
|
+
return /*#__PURE__*/React.createElement("g", {
|
|
28916
|
+
className: "y-axis-ticks"
|
|
28917
|
+
}, /*#__PURE__*/React.createElement("line", {
|
|
28918
|
+
x1: xPosition - tickSize / 2,
|
|
28919
|
+
y1: yPosition,
|
|
28920
|
+
x2: xPosition + tickSize / 2,
|
|
28921
|
+
y2: yPosition,
|
|
28922
|
+
style: tickStyle
|
|
28923
|
+
}));
|
|
28924
|
+
};
|
|
28925
|
+
const XGridTick = ({
|
|
28926
|
+
x
|
|
28927
|
+
}) => {
|
|
28928
|
+
const pointOnAxis = [x, 0];
|
|
28929
|
+
const [[xPosition, yPosition]] = useTransform(pointOnAxis);
|
|
28930
|
+
return /*#__PURE__*/React.createElement("g", {
|
|
28931
|
+
className: "x-axis-ticks"
|
|
28932
|
+
}, /*#__PURE__*/React.createElement("line", {
|
|
28933
|
+
x1: xPosition,
|
|
28934
|
+
y1: yPosition + tickSize / 2,
|
|
28935
|
+
x2: xPosition,
|
|
28936
|
+
y2: yPosition - tickSize / 2,
|
|
28937
|
+
style: tickStyle
|
|
28938
|
+
}));
|
|
28939
|
+
};
|
|
28940
|
+
function generateTickLocations(tickStep, min, max) {
|
|
28941
|
+
const ticks = [];
|
|
28942
|
+
for (let i = 0 + tickStep; i < max; i += tickStep) {
|
|
28943
|
+
ticks.push(i);
|
|
28944
|
+
}
|
|
28945
|
+
for (let i = 0 - tickStep; i > min; i -= tickStep) {
|
|
28946
|
+
ticks.push(i);
|
|
28947
|
+
}
|
|
28948
|
+
return ticks;
|
|
28949
|
+
}
|
|
28950
|
+
const AxisTicks = props => {
|
|
28951
|
+
const range = props.range;
|
|
28952
|
+
const [xMin, xMax] = range[0];
|
|
28953
|
+
const [yMin, yMax] = range[1];
|
|
28954
|
+
const yTickStep = props.tickStep[1];
|
|
28955
|
+
const xTickStep = props.tickStep[0];
|
|
28956
|
+
const yGridTicks = generateTickLocations(yTickStep, yMin, yMax);
|
|
28957
|
+
const xGridTicks = generateTickLocations(xTickStep, xMin, xMax);
|
|
28958
|
+
return /*#__PURE__*/React.createElement("g", {
|
|
28959
|
+
className: "axis-ticks"
|
|
28960
|
+
}, yGridTicks.map(y => {
|
|
28961
|
+
return /*#__PURE__*/React.createElement(YGridTick, {
|
|
28962
|
+
y: y,
|
|
28963
|
+
key: `y-grid-tick-${y}`
|
|
28964
|
+
});
|
|
28965
|
+
}), xGridTicks.map(x => {
|
|
28966
|
+
return /*#__PURE__*/React.createElement(XGridTick, {
|
|
28967
|
+
x: x,
|
|
28968
|
+
key: `x-grid-tick-${x}`
|
|
28969
|
+
});
|
|
28970
|
+
}));
|
|
28971
|
+
};
|
|
28972
|
+
|
|
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
|
+
/**
|
|
28992
|
+
* axisOptions determine axis options for Mafs
|
|
28993
|
+
*
|
|
28994
|
+
* axisIndex is for grabbing data in an array that contains
|
|
28995
|
+
* data for multiple axes. For example range: [[-10, 10], [-10, 10]]
|
|
28996
|
+
* range[0] is data for the x axis and range[1] is data for the y axis
|
|
28997
|
+
*
|
|
28998
|
+
* @param {GridProps} props
|
|
28999
|
+
* @param {number} axisIndex which axis we're getting options for
|
|
29000
|
+
*/
|
|
29001
|
+
const axisOptions = (props, axisIndex) => {
|
|
29002
|
+
const axisStep = props.tickStep[axisIndex];
|
|
29003
|
+
const axisRange = props.range[axisIndex];
|
|
29004
|
+
return {
|
|
29005
|
+
axis: props.markings === "graph",
|
|
29006
|
+
lines: props.gridStep[axisIndex],
|
|
29007
|
+
labels: n => lineLabelText(n, axisStep, axisRange)
|
|
29008
|
+
};
|
|
29009
|
+
};
|
|
29010
|
+
const Grid = props => {
|
|
29011
|
+
return props.markings === "none" ? null : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Coordinates.Cartesian, {
|
|
29012
|
+
xAxis: axisOptions(props, 0),
|
|
29013
|
+
yAxis: axisOptions(props, 1)
|
|
29014
|
+
}), /*#__PURE__*/React.createElement(AxisTicks, {
|
|
29015
|
+
range: props.range,
|
|
29016
|
+
tickStep: props.tickStep
|
|
29017
|
+
}), props.markings === "graph" && /*#__PURE__*/React.createElement(AxisArrows, null));
|
|
29018
|
+
};
|
|
28873
29019
|
|
|
28874
29020
|
// Displays a stylized open eye: lint warnings are visible
|
|
28875
29021
|
const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
@@ -29576,6 +29722,10 @@ function interactiveGraphReducer(state, action) {
|
|
|
29576
29722
|
return doMoveAll(state, action);
|
|
29577
29723
|
case MOVE_POINT:
|
|
29578
29724
|
return doMovePoint(state, action);
|
|
29725
|
+
case CHANGE_SNAP_STEP:
|
|
29726
|
+
return doChangeSnapStep(state, action);
|
|
29727
|
+
case CHANGE_RANGE:
|
|
29728
|
+
return doChangeRange(state, action);
|
|
29579
29729
|
default:
|
|
29580
29730
|
throw new UnreachableCaseError(action);
|
|
29581
29731
|
}
|
|
@@ -29597,14 +29747,11 @@ function doMoveControlPoint(state, action) {
|
|
|
29597
29747
|
update: tuple => setAtIndex({
|
|
29598
29748
|
array: tuple,
|
|
29599
29749
|
index: action.pointIndex,
|
|
29600
|
-
newValue: snap({
|
|
29750
|
+
newValue: snap(snapStep, bound$1({
|
|
29601
29751
|
snapStep,
|
|
29602
|
-
|
|
29603
|
-
|
|
29604
|
-
|
|
29605
|
-
point: action.destination
|
|
29606
|
-
})
|
|
29607
|
-
})
|
|
29752
|
+
range,
|
|
29753
|
+
point: action.destination
|
|
29754
|
+
}))
|
|
29608
29755
|
})
|
|
29609
29756
|
});
|
|
29610
29757
|
const coordsToCheck = newCoords[action.itemIndex];
|
|
@@ -29647,13 +29794,7 @@ function doMoveLine(state, action) {
|
|
|
29647
29794
|
snapStep,
|
|
29648
29795
|
range
|
|
29649
29796
|
});
|
|
29650
|
-
const newLine = [snap(
|
|
29651
|
-
snapStep,
|
|
29652
|
-
point: vec.add(currentLine[0], change)
|
|
29653
|
-
}), snap({
|
|
29654
|
-
snapStep,
|
|
29655
|
-
point: vec.add(currentLine[1], change)
|
|
29656
|
-
})];
|
|
29797
|
+
const newLine = [snap(snapStep, vec.add(currentLine[0], change)), snap(snapStep, vec.add(currentLine[1], change))];
|
|
29657
29798
|
const newCoords = setAtIndex({
|
|
29658
29799
|
array: state.coords,
|
|
29659
29800
|
index: action.itemIndex,
|
|
@@ -29683,10 +29824,7 @@ function doMoveAll(state, action) {
|
|
|
29683
29824
|
snapStep,
|
|
29684
29825
|
range
|
|
29685
29826
|
});
|
|
29686
|
-
const newCoords = state.coords.map(point => snap(
|
|
29687
|
-
snapStep,
|
|
29688
|
-
point: vec.add(point, change)
|
|
29689
|
-
}));
|
|
29827
|
+
const newCoords = state.coords.map(point => snap(snapStep, vec.add(point, change)));
|
|
29690
29828
|
return _extends({}, state, {
|
|
29691
29829
|
hasBeenInteractedWith: true,
|
|
29692
29830
|
coords: newCoords
|
|
@@ -29707,14 +29845,11 @@ function doMovePoint(state, action) {
|
|
|
29707
29845
|
coords: setAtIndex({
|
|
29708
29846
|
array: state.coords,
|
|
29709
29847
|
index: action.index,
|
|
29710
|
-
newValue: snap({
|
|
29848
|
+
newValue: snap(state.snapStep, bound$1({
|
|
29711
29849
|
snapStep: state.snapStep,
|
|
29712
|
-
|
|
29713
|
-
|
|
29714
|
-
|
|
29715
|
-
point: action.destination
|
|
29716
|
-
})
|
|
29717
|
-
})
|
|
29850
|
+
range: state.range,
|
|
29851
|
+
point: action.destination
|
|
29852
|
+
}))
|
|
29718
29853
|
})
|
|
29719
29854
|
});
|
|
29720
29855
|
}
|
|
@@ -29722,6 +29857,26 @@ function doMovePoint(state, action) {
|
|
|
29722
29857
|
throw new Error("The movePoint action is only for point and polygon graphs");
|
|
29723
29858
|
}
|
|
29724
29859
|
}
|
|
29860
|
+
function doChangeSnapStep(state, action) {
|
|
29861
|
+
if (
|
|
29862
|
+
// Deep equality check since these are arrays
|
|
29863
|
+
_.isEqual(state.snapStep, action.snapStep)) {
|
|
29864
|
+
return state;
|
|
29865
|
+
}
|
|
29866
|
+
return _extends({}, state, {
|
|
29867
|
+
snapStep: action.snapStep
|
|
29868
|
+
});
|
|
29869
|
+
}
|
|
29870
|
+
function doChangeRange(state, action) {
|
|
29871
|
+
if (
|
|
29872
|
+
// Deep equality check since these are arrays
|
|
29873
|
+
_.isEqual(state.range, action.range)) {
|
|
29874
|
+
return state;
|
|
29875
|
+
}
|
|
29876
|
+
return _extends({}, state, {
|
|
29877
|
+
range: action.range
|
|
29878
|
+
});
|
|
29879
|
+
}
|
|
29725
29880
|
const getChange = (coords, delta, constraintOpts) => {
|
|
29726
29881
|
const [deltaX, deltaY] = delta;
|
|
29727
29882
|
const maxMoves = coords.map(point => maxMove(_extends({}, constraintOpts, {
|
|
@@ -29738,15 +29893,6 @@ const getChange = (coords, delta, constraintOpts) => {
|
|
|
29738
29893
|
const dy = clamp(deltaY, minYMove, maxYMove);
|
|
29739
29894
|
return [dx, dy];
|
|
29740
29895
|
};
|
|
29741
|
-
function snap({
|
|
29742
|
-
snapStep,
|
|
29743
|
-
point
|
|
29744
|
-
}) {
|
|
29745
|
-
const [requestedX, requestedY] = point;
|
|
29746
|
-
const [snapX, snapY] = snapStep;
|
|
29747
|
-
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
29748
|
-
}
|
|
29749
|
-
|
|
29750
29896
|
// Returns the closest point to the given `point` that is within the graph
|
|
29751
29897
|
// bounds given in `state`.
|
|
29752
29898
|
function bound$1({
|
|
@@ -30098,6 +30244,18 @@ const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
30098
30244
|
}
|
|
30099
30245
|
prevState.current = state;
|
|
30100
30246
|
}, [props, state]);
|
|
30247
|
+
|
|
30248
|
+
// Destructuring first to keep useEffect from making excess calls
|
|
30249
|
+
const [xSnap, ySnap] = props.snapStep;
|
|
30250
|
+
useEffect(() => {
|
|
30251
|
+
dispatch(changeSnapStep([xSnap, ySnap]));
|
|
30252
|
+
}, [xSnap, ySnap]);
|
|
30253
|
+
|
|
30254
|
+
// Destructuring first to keep useEffect from making excess calls
|
|
30255
|
+
const [[xMinRange, xMaxRange], [yMinRange, yMaxRange]] = props.range;
|
|
30256
|
+
useEffect(() => {
|
|
30257
|
+
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
30258
|
+
}, [xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
30101
30259
|
React.useImperativeHandle(ref, () => ({
|
|
30102
30260
|
getUserInput: () => getGradableGraph(state, props.graph)
|
|
30103
30261
|
}));
|
|
@@ -30132,7 +30290,13 @@ const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
30132
30290
|
zoom: false,
|
|
30133
30291
|
width: width,
|
|
30134
30292
|
height: height
|
|
30135
|
-
}, /*#__PURE__*/React.createElement(SvgDefs, null), /*#__PURE__*/React.createElement(Grid,
|
|
30293
|
+
}, /*#__PURE__*/React.createElement(SvgDefs, null), /*#__PURE__*/React.createElement(Grid, {
|
|
30294
|
+
tickStep: props.step,
|
|
30295
|
+
gridStep: props.gridStep,
|
|
30296
|
+
range: props.range,
|
|
30297
|
+
containerSizeClass: props.containerSizeClass,
|
|
30298
|
+
markings: props.markings
|
|
30299
|
+
}), props.lockedFigures && /*#__PURE__*/React.createElement(GraphLockedLayer, {
|
|
30136
30300
|
lockedFigures: props.lockedFigures
|
|
30137
30301
|
}), renderGraph({
|
|
30138
30302
|
state,
|
|
@@ -31911,9 +32075,9 @@ class InteractiveGraph extends React.Component {
|
|
|
31911
32075
|
};
|
|
31912
32076
|
}
|
|
31913
32077
|
} else if (userInput.type === "segment" && rubric.correct.type === "segment" && userInput.coords != null) {
|
|
31914
|
-
var _rubric$correct
|
|
31915
|
-
let guess = userInput.coords
|
|
31916
|
-
let correct = (_rubric$correct
|
|
32078
|
+
var _rubric$correct;
|
|
32079
|
+
let guess = Util.deepClone(userInput.coords);
|
|
32080
|
+
let correct = Util.deepClone((_rubric$correct = rubric.correct) == null ? void 0 : _rubric$correct.coords);
|
|
31917
32081
|
guess = _.invoke(guess, "sort").sort();
|
|
31918
32082
|
// @ts-expect-error - TS2345 - Argument of type '(readonly Coord[])[] | undefined' is not assignable to parameter of type 'Collection<any>'.
|
|
31919
32083
|
correct = _.invoke(correct, "sort").sort();
|
|
@@ -42181,7 +42345,7 @@ const init = function init(options) {
|
|
|
42181
42345
|
|
|
42182
42346
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
42183
42347
|
const libName = "@khanacademy/perseus";
|
|
42184
|
-
const libVersion = "21.1
|
|
42348
|
+
const libVersion = "21.2.1";
|
|
42185
42349
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
42186
42350
|
|
|
42187
42351
|
const apiVersion = {
|
|
@@ -43305,6 +43469,9 @@ const ItemExtras = [
|
|
|
43305
43469
|
// A background image applied to various widgets.
|
|
43306
43470
|
|
|
43307
43471
|
const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
|
|
43472
|
+
|
|
43473
|
+
// 2D range: xMin, xMax, yMin, yMax
|
|
43474
|
+
|
|
43308
43475
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
43309
43476
|
|
|
43310
43477
|
/**
|