@khanacademy/perseus 22.1.0 → 22.2.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 +1 -0
- package/dist/es/index.js +186 -171
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +1 -0
- package/dist/index.js +185 -170
- package/dist/index.js.map +1 -1
- package/dist/widgets/interactive-graphs/graph-locked-layer.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/components/vector.d.ts +2 -1
- package/dist/widgets/interactive-graphs/locked-line.d.ts +5 -1
- package/package.json +4 -4
package/dist/index.css
CHANGED
|
@@ -4172,6 +4172,7 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4172
4172
|
|
|
4173
4173
|
--mafs-origin-color: var(--mafs-fg);
|
|
4174
4174
|
--mafs-line-color: #555;
|
|
4175
|
+
--mafs-line-stroke-dash-style: 4, 3;
|
|
4175
4176
|
--grid-line-subdivision-color: #222;
|
|
4176
4177
|
|
|
4177
4178
|
--mafs-red: #f11d0e;
|
package/dist/index.js
CHANGED
|
@@ -28965,6 +28965,162 @@ const lockedFigureColors = {
|
|
|
28965
28965
|
};
|
|
28966
28966
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
28967
28967
|
|
|
28968
|
+
function pathBuilder() {
|
|
28969
|
+
return new PathBuilder();
|
|
28970
|
+
}
|
|
28971
|
+
class PathBuilder {
|
|
28972
|
+
path = [];
|
|
28973
|
+
scaleFactor = 1;
|
|
28974
|
+
build() {
|
|
28975
|
+
return this.path.map(scaleCommandBy(this.scaleFactor)).map(commandToString).join("");
|
|
28976
|
+
}
|
|
28977
|
+
|
|
28978
|
+
// add a move (M) command to the path
|
|
28979
|
+
move(x, y) {
|
|
28980
|
+
this.path.push({
|
|
28981
|
+
action: "M",
|
|
28982
|
+
coords: [x, y]
|
|
28983
|
+
});
|
|
28984
|
+
return this;
|
|
28985
|
+
}
|
|
28986
|
+
|
|
28987
|
+
// add a curve (C) command to the path
|
|
28988
|
+
curve(control1X, control1Y, control2X, control2Y, endX, endY) {
|
|
28989
|
+
this.path.push({
|
|
28990
|
+
action: "C",
|
|
28991
|
+
coords: [control1X, control1Y, control2X, control2Y, endX, endY]
|
|
28992
|
+
});
|
|
28993
|
+
return this;
|
|
28994
|
+
}
|
|
28995
|
+
|
|
28996
|
+
// Scale all coordinates of the path by a factor
|
|
28997
|
+
scale(factor) {
|
|
28998
|
+
this.scaleFactor *= factor;
|
|
28999
|
+
return this;
|
|
29000
|
+
}
|
|
29001
|
+
}
|
|
29002
|
+
function commandToString(command) {
|
|
29003
|
+
return `${command.action}${command.coords.join(" ")}`;
|
|
29004
|
+
}
|
|
29005
|
+
function scaleCommandBy(scaleFactor) {
|
|
29006
|
+
return command => ({
|
|
29007
|
+
...command,
|
|
29008
|
+
coords: command.coords.map(c => c * scaleFactor)
|
|
29009
|
+
});
|
|
29010
|
+
}
|
|
29011
|
+
|
|
29012
|
+
// We use the pathBuilder here to scale up the SVG path coordinates used
|
|
29013
|
+
// elsewhere for arrowheads. We scale in the path itself instead of using a CSS
|
|
29014
|
+
// transform because a transform would also scale up the stroke weight, and we
|
|
29015
|
+
// don't want that.
|
|
29016
|
+
const arrowPath = pathBuilder().move(-3, 4).curve(-2.75, 2.5, 0, 0.25, 0.75, 0).curve(0, -0.25, -2.75, -2.5, -3, -4).scale(1.4).build();
|
|
29017
|
+
function Arrowhead(props) {
|
|
29018
|
+
const [point] = useTransformVectorsToPixels(props.tip);
|
|
29019
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29020
|
+
transform: `translate(${point[0]} ${point[1]}) rotate(${-props.angle})`
|
|
29021
|
+
}, /*#__PURE__*/React__namespace.createElement("g", {
|
|
29022
|
+
transform: "translate(-1.5)"
|
|
29023
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
29024
|
+
d: arrowPath,
|
|
29025
|
+
fill: "none",
|
|
29026
|
+
style: {
|
|
29027
|
+
stroke: props.color ?? "inherit"
|
|
29028
|
+
},
|
|
29029
|
+
strokeLinejoin: "round",
|
|
29030
|
+
strokeLinecap: "round"
|
|
29031
|
+
})));
|
|
29032
|
+
}
|
|
29033
|
+
|
|
29034
|
+
function SVGLine(props) {
|
|
29035
|
+
const {
|
|
29036
|
+
start,
|
|
29037
|
+
end,
|
|
29038
|
+
style,
|
|
29039
|
+
className,
|
|
29040
|
+
testId
|
|
29041
|
+
} = props;
|
|
29042
|
+
return /*#__PURE__*/React__namespace.createElement("line", {
|
|
29043
|
+
x1: start[0],
|
|
29044
|
+
y1: start[1],
|
|
29045
|
+
x2: end[0],
|
|
29046
|
+
y2: end[1],
|
|
29047
|
+
style: style,
|
|
29048
|
+
className: className,
|
|
29049
|
+
"data-testid": testId
|
|
29050
|
+
});
|
|
29051
|
+
}
|
|
29052
|
+
|
|
29053
|
+
function Vector(props) {
|
|
29054
|
+
const {
|
|
29055
|
+
tail,
|
|
29056
|
+
tip,
|
|
29057
|
+
color,
|
|
29058
|
+
style
|
|
29059
|
+
} = props;
|
|
29060
|
+
const [tailPx, tipPx] = useTransformVectorsToPixels(tail, tip);
|
|
29061
|
+
const direction = mafs.vec.sub(tip, tail);
|
|
29062
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29063
|
+
style: {
|
|
29064
|
+
stroke: color,
|
|
29065
|
+
strokeWidth: 2
|
|
29066
|
+
}
|
|
29067
|
+
}, /*#__PURE__*/React__namespace.createElement(SVGLine, {
|
|
29068
|
+
start: tailPx,
|
|
29069
|
+
end: tipPx,
|
|
29070
|
+
style: style
|
|
29071
|
+
}), /*#__PURE__*/React__namespace.createElement(Arrowhead, {
|
|
29072
|
+
tip: tip,
|
|
29073
|
+
angle: angleDegrees(direction)
|
|
29074
|
+
}));
|
|
29075
|
+
}
|
|
29076
|
+
function angleDegrees(_ref) {
|
|
29077
|
+
let [x, y] = _ref;
|
|
29078
|
+
return Math.atan2(y, x) * 180 / Math.PI;
|
|
29079
|
+
}
|
|
29080
|
+
|
|
29081
|
+
/**
|
|
29082
|
+
* Given a ray and a rectangular box, find the point where the ray intersects
|
|
29083
|
+
* the edge of the box. Assumes the `initialPoint` is inside the box.
|
|
29084
|
+
* @param initialPoint - The starting point of the ray.
|
|
29085
|
+
* @param throughPoint - A point that the ray passes through. Must be different from initialPoint.
|
|
29086
|
+
* @param box - The box with which to intersect the ray, in the form [[xMin, xMax], [yMin, yMax]]
|
|
29087
|
+
*/
|
|
29088
|
+
const getIntersectionOfRayWithBox = (initialPoint, throughPoint, box) => {
|
|
29089
|
+
const [[xMin, xMax], [yMin, yMax]] = box;
|
|
29090
|
+
const [aX, aY] = throughPoint;
|
|
29091
|
+
const [bX, bY] = initialPoint;
|
|
29092
|
+
const yDiff = bY - aY;
|
|
29093
|
+
const xDiff = bX - aX;
|
|
29094
|
+
const slope = yDiff / xDiff;
|
|
29095
|
+
const yAtXMin = slope * (xMin - aX) + aY;
|
|
29096
|
+
const yAtXMax = slope * (xMax - aX) + aY;
|
|
29097
|
+
const xAtYMin = (yMin - aY) / slope + aX;
|
|
29098
|
+
const xAtYMax = (yMax - aY) / slope + aX;
|
|
29099
|
+
|
|
29100
|
+
// clock analogy to describe quadrants
|
|
29101
|
+
switch (true) {
|
|
29102
|
+
// 12 o'clock to 2:59
|
|
29103
|
+
case yDiff > 0 && xDiff >= 0:
|
|
29104
|
+
return xAtYMax > xMax ? [xMax, yAtXMax] : [xAtYMax, yMax];
|
|
29105
|
+
// 3 o'clock to 5:59
|
|
29106
|
+
case yDiff <= 0 && xDiff > 0:
|
|
29107
|
+
// xAtYMin evaluates to -Infinity here, so we use absolute value
|
|
29108
|
+
return Math.abs(xAtYMin) > xMax ? [xMax, yAtXMax] : [xAtYMin, yMin];
|
|
29109
|
+
// 9 o'clock to 11:59
|
|
29110
|
+
case yDiff >= 0 && xDiff < 0:
|
|
29111
|
+
return xAtYMax < xMin ? [xMin, yAtXMin] : [xAtYMax, yMax];
|
|
29112
|
+
// 6 o'clock to 8:59
|
|
29113
|
+
case yDiff < 0 && xDiff <= 0:
|
|
29114
|
+
return xAtYMin < xMin ? [xMin, yAtXMin] : [xAtYMin, yMin];
|
|
29115
|
+
default:
|
|
29116
|
+
return [xMax, yAtXMax];
|
|
29117
|
+
}
|
|
29118
|
+
};
|
|
29119
|
+
const getLines = points => points.map((point, i) => {
|
|
29120
|
+
const next = points[(i + 1) % points.length];
|
|
29121
|
+
return [point, next];
|
|
29122
|
+
});
|
|
29123
|
+
|
|
28968
29124
|
const LockedLine = props => {
|
|
28969
29125
|
const {
|
|
28970
29126
|
color,
|
|
@@ -28972,11 +29128,27 @@ const LockedLine = props => {
|
|
|
28972
29128
|
kind,
|
|
28973
29129
|
points,
|
|
28974
29130
|
showStartPoint,
|
|
28975
|
-
showEndPoint
|
|
29131
|
+
showEndPoint,
|
|
29132
|
+
range
|
|
28976
29133
|
} = props;
|
|
28977
29134
|
const [point1, point2] = points;
|
|
28978
29135
|
let line;
|
|
28979
|
-
if (kind === "
|
|
29136
|
+
if (kind === "ray") {
|
|
29137
|
+
// Rays extend to the end of the graph in one direction.
|
|
29138
|
+
const endExtend = getIntersectionOfRayWithBox(point2.coord, point1.coord, range);
|
|
29139
|
+
line = /*#__PURE__*/React__namespace.createElement(Vector, {
|
|
29140
|
+
tail: point1.coord,
|
|
29141
|
+
tip: endExtend,
|
|
29142
|
+
color: lockedFigureColors[color],
|
|
29143
|
+
style: {
|
|
29144
|
+
strokeDasharray: lineStyle === "dashed" ?
|
|
29145
|
+
// TODO(lems-1930): Uncomment this line when the
|
|
29146
|
+
// dashed style is updated in Mafs.
|
|
29147
|
+
// ? "var(--mafs-line-stroke-dash-style)"
|
|
29148
|
+
"4, 3" : undefined
|
|
29149
|
+
}
|
|
29150
|
+
});
|
|
29151
|
+
} else {
|
|
28980
29152
|
const LineType = kind === "segment" ? mafs.Line.Segment : mafs.Line.ThroughPoints;
|
|
28981
29153
|
line = /*#__PURE__*/React__namespace.createElement(LineType, {
|
|
28982
29154
|
point1: point1.coord,
|
|
@@ -28984,12 +29156,9 @@ const LockedLine = props => {
|
|
|
28984
29156
|
color: lockedFigureColors[color],
|
|
28985
29157
|
style: lineStyle
|
|
28986
29158
|
});
|
|
28987
|
-
} else {
|
|
28988
|
-
// TODO(LEMS-1928): Implement rays
|
|
28989
|
-
return null;
|
|
28990
29159
|
}
|
|
28991
29160
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
28992
|
-
className: "locked-line"
|
|
29161
|
+
className: kind === "ray" ? "locked-ray" : "locked-line"
|
|
28993
29162
|
}, line, showStartPoint && /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
28994
29163
|
x: point1.coord[0],
|
|
28995
29164
|
y: point1.coord[1],
|
|
@@ -29038,14 +29207,16 @@ const GraphLockedLayer = props => {
|
|
|
29038
29207
|
lockedFigures
|
|
29039
29208
|
} = props;
|
|
29040
29209
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lockedFigures.map((figure, index) => {
|
|
29041
|
-
let Figure;
|
|
29042
29210
|
switch (figure.type) {
|
|
29043
29211
|
case "point":
|
|
29044
|
-
|
|
29045
|
-
|
|
29212
|
+
return /*#__PURE__*/React__namespace.createElement(LockedPoint, _extends({
|
|
29213
|
+
key: `point-${index}`
|
|
29214
|
+
}, figure));
|
|
29046
29215
|
case "line":
|
|
29047
|
-
|
|
29048
|
-
|
|
29216
|
+
return /*#__PURE__*/React__namespace.createElement(LockedLine, _extends({
|
|
29217
|
+
key: `line-${index}`,
|
|
29218
|
+
range: props.range
|
|
29219
|
+
}, figure));
|
|
29049
29220
|
default:
|
|
29050
29221
|
/**
|
|
29051
29222
|
* Devlopment-time future-proofing: This should
|
|
@@ -29055,9 +29226,6 @@ const GraphLockedLayer = props => {
|
|
|
29055
29226
|
*/
|
|
29056
29227
|
throw new wonderStuffCore.UnreachableCaseError(figure);
|
|
29057
29228
|
}
|
|
29058
|
-
return /*#__PURE__*/React__namespace.createElement(Figure, _extends({
|
|
29059
|
-
key: `${figure.type}-${index}`
|
|
29060
|
-
}, figure));
|
|
29061
29229
|
}));
|
|
29062
29230
|
};
|
|
29063
29231
|
|
|
@@ -29139,160 +29307,6 @@ function snap(snapStep, point) {
|
|
|
29139
29307
|
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
29140
29308
|
}
|
|
29141
29309
|
|
|
29142
|
-
/**
|
|
29143
|
-
* Given a ray and a rectangular box, find the point where the ray intersects
|
|
29144
|
-
* the edge of the box. Assumes the `initialPoint` is inside the box.
|
|
29145
|
-
* @param initialPoint - The starting point of the ray.
|
|
29146
|
-
* @param throughPoint - A point that the ray passes through. Must be different from initialPoint.
|
|
29147
|
-
* @param box - The box with which to intersect the ray, in the form [[xMin, xMax], [yMin, yMax]]
|
|
29148
|
-
*/
|
|
29149
|
-
const getIntersectionOfRayWithBox = (initialPoint, throughPoint, box) => {
|
|
29150
|
-
const [[xMin, xMax], [yMin, yMax]] = box;
|
|
29151
|
-
const [aX, aY] = throughPoint;
|
|
29152
|
-
const [bX, bY] = initialPoint;
|
|
29153
|
-
const yDiff = bY - aY;
|
|
29154
|
-
const xDiff = bX - aX;
|
|
29155
|
-
const slope = yDiff / xDiff;
|
|
29156
|
-
const yAtXMin = slope * (xMin - aX) + aY;
|
|
29157
|
-
const yAtXMax = slope * (xMax - aX) + aY;
|
|
29158
|
-
const xAtYMin = (yMin - aY) / slope + aX;
|
|
29159
|
-
const xAtYMax = (yMax - aY) / slope + aX;
|
|
29160
|
-
|
|
29161
|
-
// clock analogy to describe quadrants
|
|
29162
|
-
switch (true) {
|
|
29163
|
-
// 12 o'clock to 2:59
|
|
29164
|
-
case yDiff > 0 && xDiff >= 0:
|
|
29165
|
-
return xAtYMax > xMax ? [xMax, yAtXMax] : [xAtYMax, yMax];
|
|
29166
|
-
// 3 o'clock to 5:59
|
|
29167
|
-
case yDiff <= 0 && xDiff > 0:
|
|
29168
|
-
// xAtYMin evaluates to -Infinity here, so we use absolute value
|
|
29169
|
-
return Math.abs(xAtYMin) > xMax ? [xMax, yAtXMax] : [xAtYMin, yMin];
|
|
29170
|
-
// 9 o'clock to 11:59
|
|
29171
|
-
case yDiff >= 0 && xDiff < 0:
|
|
29172
|
-
return xAtYMax < xMin ? [xMin, yAtXMin] : [xAtYMax, yMax];
|
|
29173
|
-
// 6 o'clock to 8:59
|
|
29174
|
-
case yDiff < 0 && xDiff <= 0:
|
|
29175
|
-
return xAtYMin < xMin ? [xMin, yAtXMin] : [xAtYMin, yMin];
|
|
29176
|
-
default:
|
|
29177
|
-
return [xMax, yAtXMax];
|
|
29178
|
-
}
|
|
29179
|
-
};
|
|
29180
|
-
const getLines = points => points.map((point, i) => {
|
|
29181
|
-
const next = points[(i + 1) % points.length];
|
|
29182
|
-
return [point, next];
|
|
29183
|
-
});
|
|
29184
|
-
|
|
29185
|
-
function SVGLine(props) {
|
|
29186
|
-
const {
|
|
29187
|
-
start,
|
|
29188
|
-
end,
|
|
29189
|
-
style,
|
|
29190
|
-
className,
|
|
29191
|
-
testId
|
|
29192
|
-
} = props;
|
|
29193
|
-
return /*#__PURE__*/React__namespace.createElement("line", {
|
|
29194
|
-
x1: start[0],
|
|
29195
|
-
y1: start[1],
|
|
29196
|
-
x2: end[0],
|
|
29197
|
-
y2: end[1],
|
|
29198
|
-
style: style,
|
|
29199
|
-
className: `${className}`,
|
|
29200
|
-
"data-testid": testId
|
|
29201
|
-
});
|
|
29202
|
-
}
|
|
29203
|
-
|
|
29204
|
-
function pathBuilder() {
|
|
29205
|
-
return new PathBuilder();
|
|
29206
|
-
}
|
|
29207
|
-
class PathBuilder {
|
|
29208
|
-
path = [];
|
|
29209
|
-
scaleFactor = 1;
|
|
29210
|
-
build() {
|
|
29211
|
-
return this.path.map(scaleCommandBy(this.scaleFactor)).map(commandToString).join("");
|
|
29212
|
-
}
|
|
29213
|
-
|
|
29214
|
-
// add a move (M) command to the path
|
|
29215
|
-
move(x, y) {
|
|
29216
|
-
this.path.push({
|
|
29217
|
-
action: "M",
|
|
29218
|
-
coords: [x, y]
|
|
29219
|
-
});
|
|
29220
|
-
return this;
|
|
29221
|
-
}
|
|
29222
|
-
|
|
29223
|
-
// add a curve (C) command to the path
|
|
29224
|
-
curve(control1X, control1Y, control2X, control2Y, endX, endY) {
|
|
29225
|
-
this.path.push({
|
|
29226
|
-
action: "C",
|
|
29227
|
-
coords: [control1X, control1Y, control2X, control2Y, endX, endY]
|
|
29228
|
-
});
|
|
29229
|
-
return this;
|
|
29230
|
-
}
|
|
29231
|
-
|
|
29232
|
-
// Scale all coordinates of the path by a factor
|
|
29233
|
-
scale(factor) {
|
|
29234
|
-
this.scaleFactor *= factor;
|
|
29235
|
-
return this;
|
|
29236
|
-
}
|
|
29237
|
-
}
|
|
29238
|
-
function commandToString(command) {
|
|
29239
|
-
return `${command.action}${command.coords.join(" ")}`;
|
|
29240
|
-
}
|
|
29241
|
-
function scaleCommandBy(scaleFactor) {
|
|
29242
|
-
return command => ({
|
|
29243
|
-
...command,
|
|
29244
|
-
coords: command.coords.map(c => c * scaleFactor)
|
|
29245
|
-
});
|
|
29246
|
-
}
|
|
29247
|
-
|
|
29248
|
-
// We use the pathBuilder here to scale up the SVG path coordinates used
|
|
29249
|
-
// elsewhere for arrowheads. We scale in the path itself instead of using a CSS
|
|
29250
|
-
// transform because a transform would also scale up the stroke weight, and we
|
|
29251
|
-
// don't want that.
|
|
29252
|
-
const arrowPath = pathBuilder().move(-3, 4).curve(-2.75, 2.5, 0, 0.25, 0.75, 0).curve(0, -0.25, -2.75, -2.5, -3, -4).scale(1.4).build();
|
|
29253
|
-
function Arrowhead(props) {
|
|
29254
|
-
const [point] = useTransformVectorsToPixels(props.tip);
|
|
29255
|
-
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29256
|
-
transform: `translate(${point[0]} ${point[1]}) rotate(${-props.angle})`
|
|
29257
|
-
}, /*#__PURE__*/React__namespace.createElement("g", {
|
|
29258
|
-
transform: "translate(-1.5)"
|
|
29259
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
29260
|
-
d: arrowPath,
|
|
29261
|
-
fill: "none",
|
|
29262
|
-
style: {
|
|
29263
|
-
stroke: props.color ?? "inherit"
|
|
29264
|
-
},
|
|
29265
|
-
strokeLinejoin: "round",
|
|
29266
|
-
strokeLinecap: "round"
|
|
29267
|
-
})));
|
|
29268
|
-
}
|
|
29269
|
-
|
|
29270
|
-
function Vector(props) {
|
|
29271
|
-
const {
|
|
29272
|
-
tail,
|
|
29273
|
-
tip,
|
|
29274
|
-
color
|
|
29275
|
-
} = props;
|
|
29276
|
-
const [tailPx, tipPx] = useTransformVectorsToPixels(tail, tip);
|
|
29277
|
-
const direction = mafs.vec.sub(tip, tail);
|
|
29278
|
-
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29279
|
-
style: {
|
|
29280
|
-
stroke: color,
|
|
29281
|
-
strokeWidth: 2
|
|
29282
|
-
}
|
|
29283
|
-
}, /*#__PURE__*/React__namespace.createElement(SVGLine, {
|
|
29284
|
-
start: tailPx,
|
|
29285
|
-
end: tipPx
|
|
29286
|
-
}), /*#__PURE__*/React__namespace.createElement(Arrowhead, {
|
|
29287
|
-
tip: tip,
|
|
29288
|
-
angle: angleDegrees(direction)
|
|
29289
|
-
}));
|
|
29290
|
-
}
|
|
29291
|
-
function angleDegrees(_ref) {
|
|
29292
|
-
let [x, y] = _ref;
|
|
29293
|
-
return Math.atan2(y, x) * 180 / Math.PI;
|
|
29294
|
-
}
|
|
29295
|
-
|
|
29296
29310
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
29297
29311
|
const MovableLine = props => {
|
|
29298
29312
|
const {
|
|
@@ -31278,7 +31292,8 @@ const MafsGraph = props => {
|
|
|
31278
31292
|
containerSizeClass: props.containerSizeClass,
|
|
31279
31293
|
markings: props.markings
|
|
31280
31294
|
}), props.lockedFigures && /*#__PURE__*/React__namespace.createElement(GraphLockedLayer, {
|
|
31281
|
-
lockedFigures: props.lockedFigures
|
|
31295
|
+
lockedFigures: props.lockedFigures,
|
|
31296
|
+
range: props.range
|
|
31282
31297
|
}), renderGraph({
|
|
31283
31298
|
state,
|
|
31284
31299
|
dispatch
|
|
@@ -43374,7 +43389,7 @@ const init = function (options) {
|
|
|
43374
43389
|
|
|
43375
43390
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43376
43391
|
const libName = "@khanacademy/perseus";
|
|
43377
|
-
const libVersion = "22.
|
|
43392
|
+
const libVersion = "22.2.0";
|
|
43378
43393
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43379
43394
|
|
|
43380
43395
|
const apiVersion = {
|