@khanacademy/perseus 22.0.2 → 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/components/info-tip/info-tip.d.ts +2 -10
- package/dist/es/index.css +15 -1
- package/dist/es/index.js +342 -310
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +15 -1
- package/dist/index.js +343 -305
- package/dist/index.js.map +1 -1
- package/dist/widgets/interactive-graph.d.ts +3 -3
- package/dist/widgets/interactive-graphs/axis-labels.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graph-locked-layer.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/components/arrowhead.d.ts +2 -2
- package/dist/widgets/interactive-graphs/graphs/components/movable-line.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/components/vector.d.ts +2 -1
- package/dist/widgets/interactive-graphs/graphs/use-transform.d.ts +9 -2
- package/dist/widgets/interactive-graphs/graphs/utils.d.ts +6 -4
- package/dist/widgets/interactive-graphs/locked-line.d.ts +5 -1
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +1 -0
- package/dist/widgets/interactive-graphs/reducer/use-graph-config.d.ts +4 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -32,8 +32,8 @@ var caretUp = require('@phosphor-icons/core/assets/regular/caret-up.svg');
|
|
|
32
32
|
var debounce$1 = require('lodash.debounce');
|
|
33
33
|
var mafs = require('mafs');
|
|
34
34
|
var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
|
|
35
|
-
var questionIcon = require('@phosphor-icons/core/regular/question.svg');
|
|
36
35
|
var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
|
|
36
|
+
var questionIcon = require('@phosphor-icons/core/regular/question.svg');
|
|
37
37
|
var createReactClass = require('create-react-class');
|
|
38
38
|
var Switch = require('@khanacademy/wonder-blocks-switch');
|
|
39
39
|
var Pill = require('@khanacademy/wonder-blocks-pill');
|
|
@@ -28761,6 +28761,93 @@ class Graph extends React__namespace.Component {
|
|
|
28761
28761
|
}
|
|
28762
28762
|
}
|
|
28763
28763
|
|
|
28764
|
+
const defaultGraphConfig = {
|
|
28765
|
+
range: [[0, 1], [0, 1]],
|
|
28766
|
+
snapStep: [1, 1],
|
|
28767
|
+
markings: "none",
|
|
28768
|
+
showTooltips: false,
|
|
28769
|
+
graphDimensionsInPixels: [1, 1],
|
|
28770
|
+
width: 0,
|
|
28771
|
+
height: 0,
|
|
28772
|
+
labels: []
|
|
28773
|
+
};
|
|
28774
|
+
const GraphConfigContext = /*#__PURE__*/React.createContext(defaultGraphConfig);
|
|
28775
|
+
function useGraphConfig() {
|
|
28776
|
+
return React__default["default"].useContext(GraphConfigContext);
|
|
28777
|
+
}
|
|
28778
|
+
|
|
28779
|
+
const matrixBuilder = mafs.vec.matrixBuilder;
|
|
28780
|
+
// When converting vectors, we don't need to translate because a vector
|
|
28781
|
+
// is like a pair of x and y distances, which are not bound to specific graph locations.
|
|
28782
|
+
function vectorsToPixels(vectors, graphState) {
|
|
28783
|
+
let translation = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
|
|
28784
|
+
const {
|
|
28785
|
+
range,
|
|
28786
|
+
width,
|
|
28787
|
+
height
|
|
28788
|
+
} = graphState;
|
|
28789
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
28790
|
+
const transformToPx = matrixBuilder().translate(...translation).scale(width / (xMax - xMin), -height / (yMax - yMin)).get();
|
|
28791
|
+
return vectors.map(p => mafs.vec.transform(p, transformToPx));
|
|
28792
|
+
}
|
|
28793
|
+
|
|
28794
|
+
// When converting points, we translate so the pixel point ends up in the right location.
|
|
28795
|
+
// This is because points are specific locations on graphs, unlike vectors.
|
|
28796
|
+
function pointToPixel(point, graphState) {
|
|
28797
|
+
const [[xMin], [, yMax]] = graphState.range;
|
|
28798
|
+
const [a, b] = [-xMin, -yMax];
|
|
28799
|
+
return vectorsToPixels([point], graphState, [a, b])[0];
|
|
28800
|
+
}
|
|
28801
|
+
const useTransformVectorsToPixels = function () {
|
|
28802
|
+
const graphState = useGraphConfig();
|
|
28803
|
+
for (var _len = arguments.length, vectors = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
28804
|
+
vectors[_key] = arguments[_key];
|
|
28805
|
+
}
|
|
28806
|
+
return vectorsToPixels(vectors, graphState);
|
|
28807
|
+
};
|
|
28808
|
+
|
|
28809
|
+
function AxisLabels() {
|
|
28810
|
+
const {
|
|
28811
|
+
range,
|
|
28812
|
+
labels,
|
|
28813
|
+
width,
|
|
28814
|
+
height
|
|
28815
|
+
} = useGraphConfig();
|
|
28816
|
+
const yAxisLabelLocation = [0, range[1][1]];
|
|
28817
|
+
const xAxisLabelLocation = [range[0][1], 0];
|
|
28818
|
+
const [xAxisLabelText, yAxisLabelText] = labels;
|
|
28819
|
+
const graphInfo = {
|
|
28820
|
+
range,
|
|
28821
|
+
width,
|
|
28822
|
+
height
|
|
28823
|
+
};
|
|
28824
|
+
const [x1, y1] = pointToPixel(xAxisLabelLocation, graphInfo);
|
|
28825
|
+
// The default location for the y-axis-label is at the maximum y point
|
|
28826
|
+
// This is just underneath the tick line for that point. The -24 moves the
|
|
28827
|
+
// label up one grid square, so it sits on top of the graph
|
|
28828
|
+
const [x2, y2] = mafs.vec.add(pointToPixel(yAxisLabelLocation, graphInfo), [0, -24]);
|
|
28829
|
+
const {
|
|
28830
|
+
TeX
|
|
28831
|
+
} = getDependencies();
|
|
28832
|
+
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("span", {
|
|
28833
|
+
style: {
|
|
28834
|
+
position: "absolute",
|
|
28835
|
+
left: x1,
|
|
28836
|
+
top: y1,
|
|
28837
|
+
fontSize: "14px",
|
|
28838
|
+
transform: "translate(7px, -50%)"
|
|
28839
|
+
}
|
|
28840
|
+
}, /*#__PURE__*/React__default["default"].createElement(TeX, null, xAxisLabelText)), /*#__PURE__*/React__default["default"].createElement("span", {
|
|
28841
|
+
style: {
|
|
28842
|
+
position: "absolute",
|
|
28843
|
+
left: x2,
|
|
28844
|
+
top: y2,
|
|
28845
|
+
fontSize: "14px",
|
|
28846
|
+
transform: "translate(-50%, 0px)"
|
|
28847
|
+
}
|
|
28848
|
+
}, /*#__PURE__*/React__default["default"].createElement(TeX, null, yAxisLabelText)));
|
|
28849
|
+
}
|
|
28850
|
+
|
|
28764
28851
|
// TODO(FEI-4010): Remove `Perseus` prefix for all types here
|
|
28765
28852
|
// TODO(FEI-4011): Use types generated by https://github.com/jaredly/generate-perseus-flowtypes
|
|
28766
28853
|
|
|
@@ -28878,6 +28965,162 @@ const lockedFigureColors = {
|
|
|
28878
28965
|
};
|
|
28879
28966
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
28880
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
|
+
|
|
28881
29124
|
const LockedLine = props => {
|
|
28882
29125
|
const {
|
|
28883
29126
|
color,
|
|
@@ -28885,11 +29128,27 @@ const LockedLine = props => {
|
|
|
28885
29128
|
kind,
|
|
28886
29129
|
points,
|
|
28887
29130
|
showStartPoint,
|
|
28888
|
-
showEndPoint
|
|
29131
|
+
showEndPoint,
|
|
29132
|
+
range
|
|
28889
29133
|
} = props;
|
|
28890
29134
|
const [point1, point2] = points;
|
|
28891
29135
|
let line;
|
|
28892
|
-
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 {
|
|
28893
29152
|
const LineType = kind === "segment" ? mafs.Line.Segment : mafs.Line.ThroughPoints;
|
|
28894
29153
|
line = /*#__PURE__*/React__namespace.createElement(LineType, {
|
|
28895
29154
|
point1: point1.coord,
|
|
@@ -28897,12 +29156,9 @@ const LockedLine = props => {
|
|
|
28897
29156
|
color: lockedFigureColors[color],
|
|
28898
29157
|
style: lineStyle
|
|
28899
29158
|
});
|
|
28900
|
-
} else {
|
|
28901
|
-
// TODO(LEMS-1928): Implement rays
|
|
28902
|
-
return null;
|
|
28903
29159
|
}
|
|
28904
29160
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
28905
|
-
className: "locked-line"
|
|
29161
|
+
className: kind === "ray" ? "locked-ray" : "locked-line"
|
|
28906
29162
|
}, line, showStartPoint && /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
28907
29163
|
x: point1.coord[0],
|
|
28908
29164
|
y: point1.coord[1],
|
|
@@ -28951,14 +29207,16 @@ const GraphLockedLayer = props => {
|
|
|
28951
29207
|
lockedFigures
|
|
28952
29208
|
} = props;
|
|
28953
29209
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lockedFigures.map((figure, index) => {
|
|
28954
|
-
let Figure;
|
|
28955
29210
|
switch (figure.type) {
|
|
28956
29211
|
case "point":
|
|
28957
|
-
|
|
28958
|
-
|
|
29212
|
+
return /*#__PURE__*/React__namespace.createElement(LockedPoint, _extends({
|
|
29213
|
+
key: `point-${index}`
|
|
29214
|
+
}, figure));
|
|
28959
29215
|
case "line":
|
|
28960
|
-
|
|
28961
|
-
|
|
29216
|
+
return /*#__PURE__*/React__namespace.createElement(LockedLine, _extends({
|
|
29217
|
+
key: `line-${index}`,
|
|
29218
|
+
range: props.range
|
|
29219
|
+
}, figure));
|
|
28962
29220
|
default:
|
|
28963
29221
|
/**
|
|
28964
29222
|
* Devlopment-time future-proofing: This should
|
|
@@ -28968,9 +29226,6 @@ const GraphLockedLayer = props => {
|
|
|
28968
29226
|
*/
|
|
28969
29227
|
throw new wonderStuffCore.UnreachableCaseError(figure);
|
|
28970
29228
|
}
|
|
28971
|
-
return /*#__PURE__*/React__namespace.createElement(Figure, _extends({
|
|
28972
|
-
key: `${figure.type}-${index}`
|
|
28973
|
-
}, figure));
|
|
28974
29229
|
}));
|
|
28975
29230
|
};
|
|
28976
29231
|
|
|
@@ -29052,173 +29307,6 @@ function snap(snapStep, point) {
|
|
|
29052
29307
|
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
29053
29308
|
}
|
|
29054
29309
|
|
|
29055
|
-
const useTransform = function () {
|
|
29056
|
-
const {
|
|
29057
|
-
viewTransform,
|
|
29058
|
-
userTransform
|
|
29059
|
-
} = mafs.useTransformContext();
|
|
29060
|
-
const transformToPx = mafs.vec.matrixMult(viewTransform, userTransform);
|
|
29061
|
-
for (var _len = arguments.length, points = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
29062
|
-
points[_key] = arguments[_key];
|
|
29063
|
-
}
|
|
29064
|
-
const transformedPoints = points.map(point => mafs.vec.transform(point, transformToPx));
|
|
29065
|
-
return transformedPoints;
|
|
29066
|
-
};
|
|
29067
|
-
|
|
29068
|
-
/**
|
|
29069
|
-
* Given two points, find the tips that extends through the points to the edge of the range.
|
|
29070
|
-
* @param collinearPoint - The point that the line passes through. Needed to establish slope.
|
|
29071
|
-
* @param extendFrom - The point that the line extends from to the edge of the graph.
|
|
29072
|
-
*/
|
|
29073
|
-
const getRayIntersectionCoords = (collinearPoint, extendFrom, range) => {
|
|
29074
|
-
// edges of the graph
|
|
29075
|
-
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
29076
|
-
const [aX, aY] = collinearPoint;
|
|
29077
|
-
const [bX, bY] = extendFrom;
|
|
29078
|
-
const yDiff = bY - aY;
|
|
29079
|
-
const xDiff = bX - aX;
|
|
29080
|
-
const slope = yDiff / xDiff;
|
|
29081
|
-
const yAtXMin = slope * (xMin - aX) + aY;
|
|
29082
|
-
const yAtXMax = slope * (xMax - aX) + aY;
|
|
29083
|
-
const xAtYMin = (yMin - aY) / slope + aX;
|
|
29084
|
-
const xAtYMax = (yMax - aY) / slope + aX;
|
|
29085
|
-
|
|
29086
|
-
// clock analogy to describe quadrants
|
|
29087
|
-
switch (true) {
|
|
29088
|
-
// 12 o'clock to 2:59
|
|
29089
|
-
case yDiff > 0 && xDiff >= 0:
|
|
29090
|
-
return xAtYMax > xMax ? [xMax, yAtXMax] : [xAtYMax, yMax];
|
|
29091
|
-
// 3 o'clock to 5:59
|
|
29092
|
-
case yDiff <= 0 && xDiff > 0:
|
|
29093
|
-
// xAtYMin evaluates to -Infinity here, so we use absolute value
|
|
29094
|
-
return Math.abs(xAtYMin) > xMax ? [xMax, yAtXMax] : [xAtYMin, yMin];
|
|
29095
|
-
// 9 o'clock to 11:59
|
|
29096
|
-
case yDiff >= 0 && xDiff < 0:
|
|
29097
|
-
return xAtYMax < xMin ? [xMin, yAtXMin] : [xAtYMax, yMax];
|
|
29098
|
-
// 6 o'clock to 8:59
|
|
29099
|
-
case yDiff < 0 && xDiff <= 0:
|
|
29100
|
-
return xAtYMin < xMin ? [xMin, yAtXMin] : [xAtYMin, yMin];
|
|
29101
|
-
default:
|
|
29102
|
-
return [xMax, yAtXMax];
|
|
29103
|
-
}
|
|
29104
|
-
};
|
|
29105
|
-
const getLines = points => points.map((point, i) => {
|
|
29106
|
-
const next = points[(i + 1) % points.length];
|
|
29107
|
-
return [point, next];
|
|
29108
|
-
});
|
|
29109
|
-
|
|
29110
|
-
function SVGLine(props) {
|
|
29111
|
-
const {
|
|
29112
|
-
start,
|
|
29113
|
-
end,
|
|
29114
|
-
style,
|
|
29115
|
-
className,
|
|
29116
|
-
testId
|
|
29117
|
-
} = props;
|
|
29118
|
-
return /*#__PURE__*/React__namespace.createElement("line", {
|
|
29119
|
-
x1: start[0],
|
|
29120
|
-
y1: start[1],
|
|
29121
|
-
x2: end[0],
|
|
29122
|
-
y2: end[1],
|
|
29123
|
-
style: style,
|
|
29124
|
-
className: `${className}`,
|
|
29125
|
-
"data-testid": testId
|
|
29126
|
-
});
|
|
29127
|
-
}
|
|
29128
|
-
|
|
29129
|
-
function pathBuilder() {
|
|
29130
|
-
return new PathBuilder();
|
|
29131
|
-
}
|
|
29132
|
-
class PathBuilder {
|
|
29133
|
-
path = [];
|
|
29134
|
-
scaleFactor = 1;
|
|
29135
|
-
build() {
|
|
29136
|
-
return this.path.map(scaleCommandBy(this.scaleFactor)).map(commandToString).join("");
|
|
29137
|
-
}
|
|
29138
|
-
|
|
29139
|
-
// add a move (M) command to the path
|
|
29140
|
-
move(x, y) {
|
|
29141
|
-
this.path.push({
|
|
29142
|
-
action: "M",
|
|
29143
|
-
coords: [x, y]
|
|
29144
|
-
});
|
|
29145
|
-
return this;
|
|
29146
|
-
}
|
|
29147
|
-
|
|
29148
|
-
// add a curve (C) command to the path
|
|
29149
|
-
curve(control1X, control1Y, control2X, control2Y, endX, endY) {
|
|
29150
|
-
this.path.push({
|
|
29151
|
-
action: "C",
|
|
29152
|
-
coords: [control1X, control1Y, control2X, control2Y, endX, endY]
|
|
29153
|
-
});
|
|
29154
|
-
return this;
|
|
29155
|
-
}
|
|
29156
|
-
|
|
29157
|
-
// Scale all coordinates of the path by a factor
|
|
29158
|
-
scale(factor) {
|
|
29159
|
-
this.scaleFactor *= factor;
|
|
29160
|
-
return this;
|
|
29161
|
-
}
|
|
29162
|
-
}
|
|
29163
|
-
function commandToString(command) {
|
|
29164
|
-
return `${command.action}${command.coords.join(" ")}`;
|
|
29165
|
-
}
|
|
29166
|
-
function scaleCommandBy(scaleFactor) {
|
|
29167
|
-
return command => ({
|
|
29168
|
-
...command,
|
|
29169
|
-
coords: command.coords.map(c => c * scaleFactor)
|
|
29170
|
-
});
|
|
29171
|
-
}
|
|
29172
|
-
|
|
29173
|
-
// We use the pathBuilder here to scale up the SVG path coordinates used
|
|
29174
|
-
// elsewhere for arrowheads. We scale in the path itself instead of using a CSS
|
|
29175
|
-
// transform because a transform would also scale up the stroke weight, and we
|
|
29176
|
-
// don't want that.
|
|
29177
|
-
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();
|
|
29178
|
-
function Arrowhead(props) {
|
|
29179
|
-
const [point] = useTransform([props.x, props.y]);
|
|
29180
|
-
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29181
|
-
transform: `translate(${point[0]} ${point[1]}) rotate(${-props.angle})`
|
|
29182
|
-
}, /*#__PURE__*/React__namespace.createElement("g", {
|
|
29183
|
-
transform: "translate(-1.5)"
|
|
29184
|
-
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
29185
|
-
d: arrowPath,
|
|
29186
|
-
fill: "none",
|
|
29187
|
-
style: {
|
|
29188
|
-
stroke: props.color ?? "inherit"
|
|
29189
|
-
},
|
|
29190
|
-
strokeLinejoin: "round",
|
|
29191
|
-
strokeLinecap: "round"
|
|
29192
|
-
})));
|
|
29193
|
-
}
|
|
29194
|
-
|
|
29195
|
-
function Vector(props) {
|
|
29196
|
-
const {
|
|
29197
|
-
tail,
|
|
29198
|
-
tip,
|
|
29199
|
-
color
|
|
29200
|
-
} = props;
|
|
29201
|
-
const [tailPx, tipPx] = useTransform(tail, tip);
|
|
29202
|
-
const direction = mafs.vec.sub(tip, tail);
|
|
29203
|
-
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29204
|
-
style: {
|
|
29205
|
-
stroke: color,
|
|
29206
|
-
strokeWidth: 2
|
|
29207
|
-
}
|
|
29208
|
-
}, /*#__PURE__*/React__namespace.createElement(SVGLine, {
|
|
29209
|
-
start: tailPx,
|
|
29210
|
-
end: tipPx
|
|
29211
|
-
}), /*#__PURE__*/React__namespace.createElement(Arrowhead, {
|
|
29212
|
-
x: tip[0],
|
|
29213
|
-
y: tip[1],
|
|
29214
|
-
angle: angleDegrees(direction)
|
|
29215
|
-
}));
|
|
29216
|
-
}
|
|
29217
|
-
function angleDegrees(_ref) {
|
|
29218
|
-
let [x, y] = _ref;
|
|
29219
|
-
return Math.atan2(y, x) * 180 / Math.PI;
|
|
29220
|
-
}
|
|
29221
|
-
|
|
29222
29310
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
29223
29311
|
const MovableLine = props => {
|
|
29224
29312
|
const {
|
|
@@ -29229,12 +29317,16 @@ const MovableLine = props => {
|
|
|
29229
29317
|
stroke = defaultStroke
|
|
29230
29318
|
} = props;
|
|
29231
29319
|
const midpoint = mafs.vec.midpoint(start, end);
|
|
29232
|
-
const [startPtPx, endPtPx] =
|
|
29320
|
+
const [startPtPx, endPtPx] = useTransformVectorsToPixels(start, end);
|
|
29321
|
+
const {
|
|
29322
|
+
graphDimensionsInPixels
|
|
29323
|
+
} = useGraphConfig();
|
|
29233
29324
|
let startExtend = undefined;
|
|
29234
29325
|
let endExtend = undefined;
|
|
29235
29326
|
if (extend) {
|
|
29236
|
-
|
|
29237
|
-
|
|
29327
|
+
const trimmedRange = trimRange(extend.range, graphDimensionsInPixels);
|
|
29328
|
+
startExtend = extend.start ? getIntersectionOfRayWithBox(start, end, trimmedRange) : undefined;
|
|
29329
|
+
endExtend = extend.end ? getIntersectionOfRayWithBox(end, start, trimmedRange) : undefined;
|
|
29238
29330
|
}
|
|
29239
29331
|
const line = React.useRef(null);
|
|
29240
29332
|
const {
|
|
@@ -29291,16 +29383,24 @@ const MovableLine = props => {
|
|
|
29291
29383
|
color: stroke
|
|
29292
29384
|
}));
|
|
29293
29385
|
};
|
|
29294
|
-
|
|
29295
|
-
const
|
|
29296
|
-
|
|
29297
|
-
|
|
29298
|
-
|
|
29299
|
-
|
|
29300
|
-
|
|
29301
|
-
const
|
|
29302
|
-
|
|
29303
|
-
|
|
29386
|
+
function trimRange(range, graphDimensionsInPixels) {
|
|
29387
|
+
const pixelsToTrim = 4;
|
|
29388
|
+
const [xRange, yRange] = range;
|
|
29389
|
+
const [pixelsWide, pixelsTall] = graphDimensionsInPixels;
|
|
29390
|
+
const graphUnitsPerPixelX = size(xRange) / pixelsWide;
|
|
29391
|
+
const graphUnitsPerPixelY = size(yRange) / pixelsTall;
|
|
29392
|
+
const graphUnitsToTrimX = pixelsToTrim * graphUnitsPerPixelX;
|
|
29393
|
+
const graphUnitsToTrimY = pixelsToTrim * graphUnitsPerPixelY;
|
|
29394
|
+
return [trim(xRange, graphUnitsToTrimX), trim(yRange, graphUnitsToTrimY)];
|
|
29395
|
+
}
|
|
29396
|
+
function trim(interval, amount) {
|
|
29397
|
+
if (size(interval) < amount * 2) {
|
|
29398
|
+
return [0, 0];
|
|
29399
|
+
}
|
|
29400
|
+
return [interval[0] + amount, interval[1] - amount];
|
|
29401
|
+
}
|
|
29402
|
+
function size(interval) {
|
|
29403
|
+
return interval[1] - interval[0];
|
|
29304
29404
|
}
|
|
29305
29405
|
|
|
29306
29406
|
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
@@ -29335,13 +29435,13 @@ const StyledMovablePoint = props => {
|
|
|
29335
29435
|
constrain: p => snap(snapStep, p)
|
|
29336
29436
|
});
|
|
29337
29437
|
const pointClasses = `movable-point ${dragging ? "movable-point--dragging" : ""}`;
|
|
29338
|
-
const [[x, y]] =
|
|
29438
|
+
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
29339
29439
|
const [xMin, xMax] = range[0];
|
|
29340
29440
|
const [yMin, yMax] = range[1];
|
|
29341
|
-
const [[verticalStartX]] =
|
|
29342
|
-
const [[verticalEndX]] =
|
|
29343
|
-
const [[_, horizontalStartY]] =
|
|
29344
|
-
const [[__, horizontalEndY]] =
|
|
29441
|
+
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
29442
|
+
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
29443
|
+
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
29444
|
+
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
29345
29445
|
const showHairlines = dragging && markings !== "none";
|
|
29346
29446
|
const hairlines = /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
29347
29447
|
x1: verticalStartX,
|
|
@@ -29669,7 +29769,7 @@ const isRightAngle = angle => Math.abs(angle - Math.PI / 2) < 0.01;
|
|
|
29669
29769
|
*/
|
|
29670
29770
|
const shouldDrawArcOutside = (midpoint, vertex, range, polygonLines) => {
|
|
29671
29771
|
// Create a ray from the midpoint (inside angle) to the edge of the range
|
|
29672
|
-
const rangeIntersectionPoint =
|
|
29772
|
+
const rangeIntersectionPoint = getIntersectionOfRayWithBox(vertex, midpoint, range);
|
|
29673
29773
|
let lineIntersectionCount = 0;
|
|
29674
29774
|
polygonLines.forEach(line => linesIntersect([vertex, rangeIntersectionPoint], line) && lineIntersectionCount++);
|
|
29675
29775
|
|
|
@@ -29794,23 +29894,19 @@ function AxisArrows() {
|
|
|
29794
29894
|
const axisColor = "var(--mafs-fg)";
|
|
29795
29895
|
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29796
29896
|
color: axisColor,
|
|
29797
|
-
|
|
29798
|
-
y: 0,
|
|
29897
|
+
tip: [xMin, 0],
|
|
29799
29898
|
angle: 180
|
|
29800
29899
|
}), /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29801
29900
|
color: axisColor,
|
|
29802
|
-
|
|
29803
|
-
y: 0,
|
|
29901
|
+
tip: [xMax, 0],
|
|
29804
29902
|
angle: 0
|
|
29805
29903
|
}), /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29806
29904
|
color: axisColor,
|
|
29807
|
-
|
|
29808
|
-
y: yMin,
|
|
29905
|
+
tip: [0, yMin],
|
|
29809
29906
|
angle: 270
|
|
29810
29907
|
}), /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29811
29908
|
color: axisColor,
|
|
29812
|
-
|
|
29813
|
-
y: yMax,
|
|
29909
|
+
tip: [0, yMax],
|
|
29814
29910
|
angle: 90
|
|
29815
29911
|
}));
|
|
29816
29912
|
}
|
|
@@ -29836,7 +29932,7 @@ const YGridTick = _ref => {
|
|
|
29836
29932
|
tickStep
|
|
29837
29933
|
} = _ref;
|
|
29838
29934
|
const pointOnAxis = [0, y];
|
|
29839
|
-
const [[xPosition, yPosition]] =
|
|
29935
|
+
const [[xPosition, yPosition]] = useTransformVectorsToPixels(pointOnAxis);
|
|
29840
29936
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29841
29937
|
className: "y-axis-ticks"
|
|
29842
29938
|
}, /*#__PURE__*/React__namespace.createElement("line", {
|
|
@@ -29860,7 +29956,7 @@ const XGridTick = _ref2 => {
|
|
|
29860
29956
|
tickStep
|
|
29861
29957
|
} = _ref2;
|
|
29862
29958
|
const pointOnAxis = [x, 0];
|
|
29863
|
-
const [[xPosition, yPosition]] =
|
|
29959
|
+
const [[xPosition, yPosition]] = useTransformVectorsToPixels(pointOnAxis);
|
|
29864
29960
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29865
29961
|
className: "x-axis-ticks"
|
|
29866
29962
|
}, /*#__PURE__*/React__namespace.createElement("line", {
|
|
@@ -30082,96 +30178,26 @@ const styles$k = aphrodite.StyleSheet.create({
|
|
|
30082
30178
|
}
|
|
30083
30179
|
});
|
|
30084
30180
|
|
|
30085
|
-
const
|
|
30086
|
-
|
|
30087
|
-
|
|
30088
|
-
|
|
30089
|
-
}
|
|
30090
|
-
|
|
30091
|
-
|
|
30092
|
-
|
|
30093
|
-
|
|
30094
|
-
|
|
30095
|
-
|
|
30096
|
-
top: "0",
|
|
30097
|
-
width: "0"
|
|
30181
|
+
const InfoTip$1 = props => {
|
|
30182
|
+
return /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
30183
|
+
content: /*#__PURE__*/React__namespace.createElement(wonderBlocksTypography.Body, {
|
|
30184
|
+
style: styles$j.body
|
|
30185
|
+
}, props.children),
|
|
30186
|
+
placement: "right"
|
|
30187
|
+
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
|
|
30188
|
+
size: "small",
|
|
30189
|
+
icon: questionIcon__default["default"],
|
|
30190
|
+
style: styles$j.spacingLeft
|
|
30191
|
+
}));
|
|
30098
30192
|
};
|
|
30099
30193
|
const styles$j = aphrodite.StyleSheet.create({
|
|
30100
|
-
|
|
30101
|
-
|
|
30102
|
-
marginLeft: "5px",
|
|
30103
|
-
position: "relative"
|
|
30194
|
+
spacingLeft: {
|
|
30195
|
+
marginInlineStart: wonderBlocksTokens.spacing.xxxSmall_4
|
|
30104
30196
|
},
|
|
30105
|
-
|
|
30106
|
-
|
|
30107
|
-
top: "-12px",
|
|
30108
|
-
left: "22px",
|
|
30109
|
-
zIndex: 1000
|
|
30110
|
-
},
|
|
30111
|
-
infoTipTriangle: {
|
|
30112
|
-
height: "10px",
|
|
30113
|
-
left: "0",
|
|
30114
|
-
position: "absolute",
|
|
30115
|
-
top: "8px",
|
|
30116
|
-
width: "0",
|
|
30117
|
-
zIndex: 1,
|
|
30118
|
-
":before": {
|
|
30119
|
-
...triangleBeforeAfter,
|
|
30120
|
-
borderRight: "9px solid #bbb",
|
|
30121
|
-
right: "0"
|
|
30122
|
-
},
|
|
30123
|
-
":after": {
|
|
30124
|
-
...triangleBeforeAfter,
|
|
30125
|
-
borderRight: `9px solid ${colors$1.white}`,
|
|
30126
|
-
right: "-1px"
|
|
30127
|
-
}
|
|
30128
|
-
},
|
|
30129
|
-
verticalShadow: {
|
|
30130
|
-
border: `1px solid ${colors$1.basicBorderColor}`,
|
|
30131
|
-
boxShadow: `0 1px 3px ${colors$1.basicBorderColor}`,
|
|
30132
|
-
borderBottom: `1px solid ${colors$1.grayLight}`
|
|
30133
|
-
},
|
|
30134
|
-
infoTipContentContainer: {
|
|
30135
|
-
background: colors$1.white,
|
|
30136
|
-
padding: "5px 10px",
|
|
30137
|
-
width: "240px"
|
|
30197
|
+
body: {
|
|
30198
|
+
padding: wonderBlocksTokens.spacing.medium_16
|
|
30138
30199
|
}
|
|
30139
30200
|
});
|
|
30140
|
-
class InfoTip$1 extends React__namespace.Component {
|
|
30141
|
-
state = {
|
|
30142
|
-
hover: false
|
|
30143
|
-
};
|
|
30144
|
-
handleMouseEnter = () => {
|
|
30145
|
-
this.setState({
|
|
30146
|
-
hover: true
|
|
30147
|
-
});
|
|
30148
|
-
};
|
|
30149
|
-
handleMouseLeave = () => {
|
|
30150
|
-
this.setState({
|
|
30151
|
-
hover: false
|
|
30152
|
-
});
|
|
30153
|
-
};
|
|
30154
|
-
render() {
|
|
30155
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
30156
|
-
className: aphrodite.css(styles$j.infoTip)
|
|
30157
|
-
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30158
|
-
onMouseEnter: this.handleMouseEnter,
|
|
30159
|
-
onMouseLeave: this.handleMouseLeave
|
|
30160
|
-
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
|
|
30161
|
-
size: "small",
|
|
30162
|
-
icon: questionIcon__default["default"]
|
|
30163
|
-
})), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30164
|
-
className: aphrodite.css(styles$j.infoTipContainer),
|
|
30165
|
-
style: {
|
|
30166
|
-
display: this.state.hover ? "block" : "none"
|
|
30167
|
-
}
|
|
30168
|
-
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
30169
|
-
className: aphrodite.css(styles$j.infoTipTriangle)
|
|
30170
|
-
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
30171
|
-
className: aphrodite.css(styles$j.verticalShadow, styles$j.infoTipContentContainer)
|
|
30172
|
-
}, this.props.children)));
|
|
30173
|
-
}
|
|
30174
|
-
}
|
|
30175
30201
|
|
|
30176
30202
|
/**
|
|
30177
30203
|
* A wrapper around info-tip/info-tip.jsx that can be rendered on the
|
|
@@ -31028,7 +31054,7 @@ const getDefaultPoints = _ref => {
|
|
|
31028
31054
|
function getGradableGraph(state, initialGraph) {
|
|
31029
31055
|
if (!state.hasBeenInteractedWith) {
|
|
31030
31056
|
return {
|
|
31031
|
-
|
|
31057
|
+
...initialGraph
|
|
31032
31058
|
};
|
|
31033
31059
|
}
|
|
31034
31060
|
if (initialGraph.type === "linear-system" && state.type === "linear-system") {
|
|
@@ -31195,7 +31221,8 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
|
|
|
31195
31221
|
const MafsGraph = props => {
|
|
31196
31222
|
const {
|
|
31197
31223
|
state,
|
|
31198
|
-
dispatch
|
|
31224
|
+
dispatch,
|
|
31225
|
+
labels
|
|
31199
31226
|
} = props;
|
|
31200
31227
|
const [width, height] = props.box;
|
|
31201
31228
|
const prevState = React.useRef(state);
|
|
@@ -31224,7 +31251,11 @@ const MafsGraph = props => {
|
|
|
31224
31251
|
range: state.range,
|
|
31225
31252
|
snapStep: state.snapStep,
|
|
31226
31253
|
markings: props.markings,
|
|
31227
|
-
showTooltips: !!props.showTooltips
|
|
31254
|
+
showTooltips: !!props.showTooltips,
|
|
31255
|
+
graphDimensionsInPixels: props.box,
|
|
31256
|
+
width,
|
|
31257
|
+
height,
|
|
31258
|
+
labels
|
|
31228
31259
|
}
|
|
31229
31260
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
31230
31261
|
style: {
|
|
@@ -31243,7 +31274,7 @@ const MafsGraph = props => {
|
|
|
31243
31274
|
bottom: 0,
|
|
31244
31275
|
left: 0
|
|
31245
31276
|
}
|
|
31246
|
-
}, /*#__PURE__*/React__namespace.createElement(mafs.Mafs, {
|
|
31277
|
+
}, props.markings === "graph" && /*#__PURE__*/React__namespace.createElement(AxisLabels, null), /*#__PURE__*/React__namespace.createElement(mafs.Mafs, {
|
|
31247
31278
|
preserveAspectRatio: false,
|
|
31248
31279
|
viewBox: {
|
|
31249
31280
|
x: props.range[0],
|
|
@@ -31261,7 +31292,8 @@ const MafsGraph = props => {
|
|
|
31261
31292
|
containerSizeClass: props.containerSizeClass,
|
|
31262
31293
|
markings: props.markings
|
|
31263
31294
|
}), props.lockedFigures && /*#__PURE__*/React__namespace.createElement(GraphLockedLayer, {
|
|
31264
|
-
lockedFigures: props.lockedFigures
|
|
31295
|
+
lockedFigures: props.lockedFigures,
|
|
31296
|
+
range: props.range
|
|
31265
31297
|
}), renderGraph({
|
|
31266
31298
|
state,
|
|
31267
31299
|
dispatch
|
|
@@ -32470,8 +32502,12 @@ class LegacyInteractiveGraph extends React__namespace.Component {
|
|
|
32470
32502
|
graph: graph
|
|
32471
32503
|
});
|
|
32472
32504
|
};
|
|
32473
|
-
getUserInput
|
|
32474
|
-
|
|
32505
|
+
getUserInput() {
|
|
32506
|
+
return InteractiveGraph.getUserInputFromProps(this.props);
|
|
32507
|
+
}
|
|
32508
|
+
simpleValidate(rubric) {
|
|
32509
|
+
return InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
32510
|
+
}
|
|
32475
32511
|
focus = $__default["default"].noop;
|
|
32476
32512
|
render() {
|
|
32477
32513
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
@@ -32550,7 +32586,9 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
32550
32586
|
}
|
|
32551
32587
|
throw new PerseusError("Cannot getUserInput from a graph that has never rendered", Errors.NotAllowed);
|
|
32552
32588
|
};
|
|
32553
|
-
simpleValidate
|
|
32589
|
+
simpleValidate(rubric) {
|
|
32590
|
+
return InteractiveGraph.validate(this.getUserInput?.(), rubric, this);
|
|
32591
|
+
}
|
|
32554
32592
|
render() {
|
|
32555
32593
|
// Mafs shim
|
|
32556
32594
|
if (this.props.apiOptions?.flags?.["mafs"]?.[this.props.graph.type]) {
|
|
@@ -43351,7 +43389,7 @@ const init = function (options) {
|
|
|
43351
43389
|
|
|
43352
43390
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43353
43391
|
const libName = "@khanacademy/perseus";
|
|
43354
|
-
const libVersion = "22.0
|
|
43392
|
+
const libVersion = "22.2.0";
|
|
43355
43393
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43356
43394
|
|
|
43357
43395
|
const apiVersion = {
|