@khanacademy/perseus 23.1.0 → 23.4.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 +8 -0
- package/dist/es/index.js +578 -320
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +8 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +593 -330
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +0 -1
- package/dist/perseus-types.d.ts +17 -9
- package/dist/server-item-renderer.d.ts +0 -1
- package/dist/types.d.ts +1 -1
- package/dist/util/geometry.d.ts +1 -0
- package/dist/widgets/expression.d.ts +0 -6
- package/dist/widgets/interactive-graphs/graphs/components/angle.d.ts +2 -1
- package/dist/widgets/interactive-graphs/graphs/components/css-cursor.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/components/movable-point-view.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/components/movable-point.d.ts +3 -0
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/linear-system.d.ts +5 -0
- package/dist/widgets/interactive-graphs/graphs/linear.d.ts +1 -1
- package/dist/widgets/interactive-graphs/graphs/quadratic.d.ts +1 -2
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +6 -3
- package/dist/widgets/interactive-graphs/locked-ellipse.d.ts +4 -0
- package/dist/widgets/interactive-graphs/locked-vector.d.ts +4 -0
- package/dist/widgets/interactive-graphs/reducer/initialize-graph-state.d.ts +9 -0
- package/dist/widgets/interactive-graphs/reducer/interactive-graph-state.d.ts +2 -9
- package/dist/widgets/interactive-graphs/types.d.ts +9 -9
- package/dist/widgets/label-image.d.ts +0 -2
- package/package.json +3 -3
- package/dist/widgets/interactive-graphs/locked-circle.d.ts +0 -4
package/dist/index.js
CHANGED
|
@@ -3304,7 +3304,7 @@ const DeprecationMixin$1 = {
|
|
|
3304
3304
|
/**
|
|
3305
3305
|
* Approximate equality on numbers and primitives.
|
|
3306
3306
|
*/
|
|
3307
|
-
function eq$
|
|
3307
|
+
function eq$3(x, y) {
|
|
3308
3308
|
if (typeof x === "number" && typeof y === "number") {
|
|
3309
3309
|
return Math.abs(x - y) < 1e-9;
|
|
3310
3310
|
}
|
|
@@ -3331,7 +3331,7 @@ function deepEq$5(x, y) {
|
|
|
3331
3331
|
return false;
|
|
3332
3332
|
}
|
|
3333
3333
|
if (typeof x === "function" && typeof y === "function") {
|
|
3334
|
-
return eq$
|
|
3334
|
+
return eq$3(x, y);
|
|
3335
3335
|
}
|
|
3336
3336
|
if (typeof x === "function" || typeof y === "function") {
|
|
3337
3337
|
return false;
|
|
@@ -3348,7 +3348,7 @@ function deepEq$5(x, y) {
|
|
|
3348
3348
|
if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
|
|
3349
3349
|
return false;
|
|
3350
3350
|
}
|
|
3351
|
-
return eq$
|
|
3351
|
+
return eq$3(x, y);
|
|
3352
3352
|
}
|
|
3353
3353
|
|
|
3354
3354
|
/**
|
|
@@ -3647,7 +3647,7 @@ const Util = {
|
|
|
3647
3647
|
tickStepFromNumTicks,
|
|
3648
3648
|
constrainedTickStepsFromTickSteps,
|
|
3649
3649
|
DeprecationMixin: DeprecationMixin$1,
|
|
3650
|
-
eq: eq$
|
|
3650
|
+
eq: eq$3,
|
|
3651
3651
|
deepEq: deepEq$5,
|
|
3652
3652
|
parseQueryString,
|
|
3653
3653
|
updateQueryString: updateQueryString$2,
|
|
@@ -10885,7 +10885,7 @@ class WrappedLine extends WrappedDrawing {
|
|
|
10885
10885
|
* A collection of geomtry-related utility functions
|
|
10886
10886
|
*/
|
|
10887
10887
|
const {
|
|
10888
|
-
eq: eq$
|
|
10888
|
+
eq: eq$2,
|
|
10889
10889
|
deepEq: deepEq$4
|
|
10890
10890
|
} = Util;
|
|
10891
10891
|
|
|
@@ -10893,17 +10893,21 @@ const {
|
|
|
10893
10893
|
|
|
10894
10894
|
// a, b, c
|
|
10895
10895
|
|
|
10896
|
+
// Given a number, return whether it is positive (1), negative (-1), or zero (0)
|
|
10896
10897
|
function sign(val) {
|
|
10897
|
-
if (eq$
|
|
10898
|
+
if (eq$2(val, 0)) {
|
|
10898
10899
|
return 0;
|
|
10899
10900
|
}
|
|
10900
10901
|
return val > 0 ? 1 : -1;
|
|
10901
10902
|
}
|
|
10903
|
+
|
|
10904
|
+
// Determine whether three points are collinear (0), for a clockwise turn (negative),
|
|
10905
|
+
// or counterclockwise turn (positive)
|
|
10902
10906
|
function ccw(a, b, c) {
|
|
10903
10907
|
return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
|
|
10904
10908
|
}
|
|
10905
10909
|
function collinear(a, b, c) {
|
|
10906
|
-
return eq$
|
|
10910
|
+
return eq$2(ccw(a, b, c), 0);
|
|
10907
10911
|
}
|
|
10908
10912
|
|
|
10909
10913
|
// Given rect bounding points A and B, whether point C is inside the rect
|
|
@@ -10928,6 +10932,33 @@ function intersects(ab, cd) {
|
|
|
10928
10932
|
}
|
|
10929
10933
|
return false;
|
|
10930
10934
|
}
|
|
10935
|
+
|
|
10936
|
+
// Whether any two sides of a polygon intersect each other
|
|
10937
|
+
function polygonSidesIntersect(vertices) {
|
|
10938
|
+
for (let i = 0; i < vertices.length; i++) {
|
|
10939
|
+
for (let k = i + 1; k < vertices.length; k++) {
|
|
10940
|
+
// If any two vertices are the same point, sides overlap
|
|
10941
|
+
if (kmath.point.equal(vertices[i], vertices[k])) {
|
|
10942
|
+
return true;
|
|
10943
|
+
}
|
|
10944
|
+
|
|
10945
|
+
// Find the other end of the sides starting at vertices i and k
|
|
10946
|
+
const iNext = (i + 1) % vertices.length;
|
|
10947
|
+
const kNext = (k + 1) % vertices.length;
|
|
10948
|
+
|
|
10949
|
+
// Adjacent sides always intersect (at the vertex); skip those
|
|
10950
|
+
if (iNext === k || kNext === i) {
|
|
10951
|
+
continue;
|
|
10952
|
+
}
|
|
10953
|
+
const side1 = [vertices[i], vertices[iNext]];
|
|
10954
|
+
const side2 = [vertices[k], vertices[kNext]];
|
|
10955
|
+
if (intersects(side1, side2)) {
|
|
10956
|
+
return true;
|
|
10957
|
+
}
|
|
10958
|
+
}
|
|
10959
|
+
}
|
|
10960
|
+
return false;
|
|
10961
|
+
}
|
|
10931
10962
|
function vector(a, b) {
|
|
10932
10963
|
return ___default["default"].map(___default["default"].zip(a, b), function (pair) {
|
|
10933
10964
|
return pair[0] - pair[1];
|
|
@@ -11021,7 +11052,7 @@ function similar(coords1, coords2, tolerance) {
|
|
|
11021
11052
|
return pair[0] / pair[1];
|
|
11022
11053
|
});
|
|
11023
11054
|
const same = ___default["default"].all(factors, function (factor) {
|
|
11024
|
-
return eq$
|
|
11055
|
+
return eq$2(factors[0], factor);
|
|
11025
11056
|
});
|
|
11026
11057
|
const congruentEnough = ___default["default"].all(sidePairs, function (pair) {
|
|
11027
11058
|
return kmath.number.equal(pair[0], pair[1], tolerance);
|
|
@@ -11074,7 +11105,7 @@ function rotate(array, n) {
|
|
|
11074
11105
|
return array.slice(n).concat(array.slice(0, n));
|
|
11075
11106
|
}
|
|
11076
11107
|
function getLineEquation(first, second) {
|
|
11077
|
-
if (eq$
|
|
11108
|
+
if (eq$2(first[0], second[0])) {
|
|
11078
11109
|
return "x = " + first[0].toFixed(3);
|
|
11079
11110
|
}
|
|
11080
11111
|
const m = (second[1] - first[1]) / (second[0] - first[0]);
|
|
@@ -28922,25 +28953,27 @@ const lockedFigureColors = {
|
|
|
28922
28953
|
pink: "#B25071",
|
|
28923
28954
|
red: "#D92916"
|
|
28924
28955
|
};
|
|
28956
|
+
const lockedEllipseFillStyles = {
|
|
28957
|
+
none: 0,
|
|
28958
|
+
solid: 1,
|
|
28959
|
+
translucent: 0.4
|
|
28960
|
+
};
|
|
28925
28961
|
const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
|
|
28926
28962
|
|
|
28927
|
-
const
|
|
28963
|
+
const LockedEllipse = props => {
|
|
28928
28964
|
const {
|
|
28929
28965
|
center,
|
|
28930
28966
|
radius,
|
|
28967
|
+
angle,
|
|
28931
28968
|
color,
|
|
28932
28969
|
fillStyle,
|
|
28933
28970
|
strokeStyle
|
|
28934
28971
|
} = props;
|
|
28935
|
-
|
|
28936
|
-
none: 0,
|
|
28937
|
-
solid: 1,
|
|
28938
|
-
translucent: 0.4
|
|
28939
|
-
};
|
|
28940
|
-
return /*#__PURE__*/React__namespace.createElement(mafs.Circle, {
|
|
28972
|
+
return /*#__PURE__*/React__namespace.createElement(mafs.Ellipse, {
|
|
28941
28973
|
center: center,
|
|
28942
28974
|
radius: radius,
|
|
28943
|
-
|
|
28975
|
+
angle: angle,
|
|
28976
|
+
fillOpacity: lockedEllipseFillStyles[fillStyle],
|
|
28944
28977
|
strokeStyle: strokeStyle,
|
|
28945
28978
|
color: lockedFigureColors[color]
|
|
28946
28979
|
});
|
|
@@ -29199,6 +29232,21 @@ const LockedPoint = props => {
|
|
|
29199
29232
|
});
|
|
29200
29233
|
};
|
|
29201
29234
|
|
|
29235
|
+
const LockedVector = props => {
|
|
29236
|
+
const {
|
|
29237
|
+
color,
|
|
29238
|
+
points
|
|
29239
|
+
} = props;
|
|
29240
|
+
const [tail, tip] = points;
|
|
29241
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29242
|
+
className: "locked-vector"
|
|
29243
|
+
}, /*#__PURE__*/React__namespace.createElement(Vector, {
|
|
29244
|
+
tail: tail,
|
|
29245
|
+
tip: tip,
|
|
29246
|
+
color: lockedFigureColors[color]
|
|
29247
|
+
}));
|
|
29248
|
+
};
|
|
29249
|
+
|
|
29202
29250
|
const GraphLockedLayer = props => {
|
|
29203
29251
|
const {
|
|
29204
29252
|
lockedFigures
|
|
@@ -29214,9 +29262,13 @@ const GraphLockedLayer = props => {
|
|
|
29214
29262
|
key: `line-${index}`,
|
|
29215
29263
|
range: props.range
|
|
29216
29264
|
}, figure));
|
|
29217
|
-
case "
|
|
29218
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
29219
|
-
key: `
|
|
29265
|
+
case "ellipse":
|
|
29266
|
+
return /*#__PURE__*/React__namespace.createElement(LockedEllipse, _extends({
|
|
29267
|
+
key: `ellipse-${index}`
|
|
29268
|
+
}, figure));
|
|
29269
|
+
case "vector":
|
|
29270
|
+
return /*#__PURE__*/React__namespace.createElement(LockedVector, _extends({
|
|
29271
|
+
key: `vector-${index}`
|
|
29220
29272
|
}, figure));
|
|
29221
29273
|
default:
|
|
29222
29274
|
/**
|
|
@@ -29345,7 +29397,8 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
29345
29397
|
point,
|
|
29346
29398
|
color = wonderBlocksTokens.color.blue,
|
|
29347
29399
|
dragging,
|
|
29348
|
-
focusBehavior
|
|
29400
|
+
focusBehavior,
|
|
29401
|
+
cursor
|
|
29349
29402
|
} = props;
|
|
29350
29403
|
|
|
29351
29404
|
// WB Tooltip requires a color name for the background color.
|
|
@@ -29380,7 +29433,8 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
29380
29433
|
ref: hitboxRef,
|
|
29381
29434
|
className: pointClasses,
|
|
29382
29435
|
style: {
|
|
29383
|
-
"--movable-point-color": color
|
|
29436
|
+
"--movable-point-color": color,
|
|
29437
|
+
cursor
|
|
29384
29438
|
},
|
|
29385
29439
|
"data-testid": "movable-point",
|
|
29386
29440
|
tabIndex: tabIndex(focusBehavior)
|
|
@@ -29492,6 +29546,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
29492
29546
|
});
|
|
29493
29547
|
const focusableHandle = /*#__PURE__*/React__namespace.createElement("g", {
|
|
29494
29548
|
"data-testid": "movable-point__focusable-handle",
|
|
29549
|
+
className: "movable-point__focusable-handle",
|
|
29495
29550
|
tabIndex: 0,
|
|
29496
29551
|
ref: keyboardHandleRef,
|
|
29497
29552
|
onFocus: () => setFocused(true),
|
|
@@ -29628,14 +29683,39 @@ const SegmentGraph = props => {
|
|
|
29628
29683
|
})));
|
|
29629
29684
|
};
|
|
29630
29685
|
|
|
29631
|
-
const LinearGraph = props => {
|
|
29686
|
+
const LinearGraph = (props, key) => {
|
|
29687
|
+
const {
|
|
29688
|
+
dispatch
|
|
29689
|
+
} = props;
|
|
29690
|
+
const {
|
|
29691
|
+
coords: line
|
|
29692
|
+
} = props.graphState;
|
|
29693
|
+
|
|
29694
|
+
// Linear graphs only have one line
|
|
29695
|
+
// (LEMS-2050): Update the reducer so that we have a separate action for moving one line
|
|
29696
|
+
// and another action for moving multiple lines
|
|
29697
|
+
return /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29698
|
+
key: 0,
|
|
29699
|
+
points: line,
|
|
29700
|
+
onMoveLine: delta => {
|
|
29701
|
+
dispatch(moveLine(0, delta));
|
|
29702
|
+
},
|
|
29703
|
+
extend: {
|
|
29704
|
+
start: true,
|
|
29705
|
+
end: true
|
|
29706
|
+
},
|
|
29707
|
+
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, 0)),
|
|
29708
|
+
color: "var(--movable-line-stroke-color)"
|
|
29709
|
+
});
|
|
29710
|
+
};
|
|
29711
|
+
|
|
29712
|
+
const LinearSystemGraph = props => {
|
|
29632
29713
|
const {
|
|
29633
29714
|
dispatch
|
|
29634
29715
|
} = props;
|
|
29635
29716
|
const {
|
|
29636
29717
|
coords: lines
|
|
29637
29718
|
} = props.graphState;
|
|
29638
|
-
const colors = ["var(--movable-line-stroke-color)", "var(--mafs-violet)"];
|
|
29639
29719
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lines?.map((line, i) => /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29640
29720
|
key: i,
|
|
29641
29721
|
points: line,
|
|
@@ -29647,8 +29727,8 @@ const LinearGraph = props => {
|
|
|
29647
29727
|
end: true
|
|
29648
29728
|
},
|
|
29649
29729
|
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i)),
|
|
29650
|
-
color:
|
|
29651
|
-
})));
|
|
29730
|
+
color: "var(--movable-line-stroke-color)"
|
|
29731
|
+
})), ";");
|
|
29652
29732
|
};
|
|
29653
29733
|
|
|
29654
29734
|
const RayGraph = props => {
|
|
@@ -29656,14 +29736,14 @@ const RayGraph = props => {
|
|
|
29656
29736
|
dispatch
|
|
29657
29737
|
} = props;
|
|
29658
29738
|
const {
|
|
29659
|
-
coords:
|
|
29739
|
+
coords: line
|
|
29660
29740
|
} = props.graphState;
|
|
29661
29741
|
const handleMoveLine = delta => dispatch(moveLine(0, delta));
|
|
29662
29742
|
const handleMovePoint = (pointIndex, newPoint) => dispatch(moveControlPoint(pointIndex, newPoint, 0));
|
|
29663
|
-
|
|
29664
|
-
//
|
|
29665
|
-
, {
|
|
29666
|
-
points:
|
|
29743
|
+
|
|
29744
|
+
// Ray graphs only have one line
|
|
29745
|
+
return /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29746
|
+
points: line,
|
|
29667
29747
|
onMoveLine: handleMoveLine,
|
|
29668
29748
|
onMovePoint: handleMovePoint,
|
|
29669
29749
|
extend: {
|
|
@@ -29722,7 +29802,8 @@ const Angle = _ref => {
|
|
|
29722
29802
|
endPoints,
|
|
29723
29803
|
range,
|
|
29724
29804
|
polygonLines,
|
|
29725
|
-
showAngles
|
|
29805
|
+
showAngles,
|
|
29806
|
+
snapTo
|
|
29726
29807
|
} = _ref;
|
|
29727
29808
|
const [centerX, centerY] = centerPoint;
|
|
29728
29809
|
const areClockwise = clockwise$1([centerPoint, ...endPoints]);
|
|
@@ -29760,7 +29841,9 @@ const Angle = _ref => {
|
|
|
29760
29841
|
if (isOutside) {
|
|
29761
29842
|
angleInDegrees = 360 - angleInDegrees;
|
|
29762
29843
|
}
|
|
29763
|
-
|
|
29844
|
+
|
|
29845
|
+
// Only want to show whole numbers when in angles mode
|
|
29846
|
+
const angleLabelNumber = parseFloat(angleInDegrees.toFixed(snapTo === "angles" ? 0 : 1));
|
|
29764
29847
|
const angleLabel = Number.isInteger(angleLabelNumber) ? angleLabelNumber : "≈ " + angleLabelNumber;
|
|
29765
29848
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("defs", null, /*#__PURE__*/React__namespace.createElement("filter", {
|
|
29766
29849
|
id: "background",
|
|
@@ -29850,15 +29933,18 @@ const StyledMovablePoint = props => {
|
|
|
29850
29933
|
const {
|
|
29851
29934
|
point,
|
|
29852
29935
|
onMove,
|
|
29853
|
-
|
|
29936
|
+
cursor,
|
|
29937
|
+
color = wonderBlocksTokens.color.blue,
|
|
29938
|
+
snapTo
|
|
29854
29939
|
} = props;
|
|
29940
|
+
const snapToValue = snapTo ?? "grid";
|
|
29855
29941
|
const {
|
|
29856
29942
|
dragging
|
|
29857
29943
|
} = mafs.useMovable({
|
|
29858
29944
|
gestureTarget: elementRef,
|
|
29859
29945
|
point,
|
|
29860
29946
|
onMove,
|
|
29861
|
-
constrain: p => snap(snapStep, p)
|
|
29947
|
+
constrain: p => ["angles", "sides"].includes(snapToValue) ? p : snap(snapStep, p)
|
|
29862
29948
|
});
|
|
29863
29949
|
return /*#__PURE__*/React__namespace.createElement(MovablePointView, {
|
|
29864
29950
|
ref: elementRef,
|
|
@@ -29868,7 +29954,8 @@ const StyledMovablePoint = props => {
|
|
|
29868
29954
|
focusBehavior: {
|
|
29869
29955
|
type: "uncontrolled",
|
|
29870
29956
|
tabIndex: 0
|
|
29871
|
-
}
|
|
29957
|
+
},
|
|
29958
|
+
cursor: cursor
|
|
29872
29959
|
});
|
|
29873
29960
|
};
|
|
29874
29961
|
|
|
@@ -29883,7 +29970,8 @@ const PolygonGraph = props => {
|
|
|
29883
29970
|
showAngles,
|
|
29884
29971
|
showSides,
|
|
29885
29972
|
range,
|
|
29886
|
-
snapStep
|
|
29973
|
+
snapStep,
|
|
29974
|
+
snapTo
|
|
29887
29975
|
} = props.graphState;
|
|
29888
29976
|
|
|
29889
29977
|
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
@@ -29891,6 +29979,7 @@ const PolygonGraph = props => {
|
|
|
29891
29979
|
const points = coords ?? [[0, 0]];
|
|
29892
29980
|
const ref = React__namespace.useRef(null);
|
|
29893
29981
|
const dragReferencePoint = points[0];
|
|
29982
|
+
const snapToValue = snapTo ?? "grid";
|
|
29894
29983
|
const {
|
|
29895
29984
|
dragging
|
|
29896
29985
|
} = mafs.useMovable({
|
|
@@ -29900,7 +29989,7 @@ const PolygonGraph = props => {
|
|
|
29900
29989
|
const delta = mafs.vec.sub(newPoint, dragReferencePoint);
|
|
29901
29990
|
dispatch(moveAll(delta));
|
|
29902
29991
|
},
|
|
29903
|
-
constrain: p => snap(snapStep, p)
|
|
29992
|
+
constrain: p => ["angles", "sides"].includes(snapToValue) ? p : snap(snapStep, p)
|
|
29904
29993
|
});
|
|
29905
29994
|
const active = hovered || focused || dragging;
|
|
29906
29995
|
const lines = getLines(points);
|
|
@@ -29923,12 +30012,13 @@ const PolygonGraph = props => {
|
|
|
29923
30012
|
active: active,
|
|
29924
30013
|
range: range,
|
|
29925
30014
|
polygonLines: lines,
|
|
29926
|
-
showAngles: !!showAngles
|
|
30015
|
+
showAngles: !!showAngles,
|
|
30016
|
+
snapTo: snapToValue
|
|
29927
30017
|
});
|
|
29928
30018
|
}), showSides && lines.map((_ref, i) => {
|
|
29929
30019
|
let [start, end] = _ref;
|
|
29930
30020
|
const [x, y] = mafs.vec.midpoint(start, end);
|
|
29931
|
-
const length = parseFloat(mafs.vec.dist(start, end).toFixed(1));
|
|
30021
|
+
const length = parseFloat(mafs.vec.dist(start, end).toFixed(snapTo === "sides" ? 0 : 1));
|
|
29932
30022
|
return /*#__PURE__*/React__namespace.createElement(TextLabel, {
|
|
29933
30023
|
key: "side-" + i,
|
|
29934
30024
|
x: x,
|
|
@@ -29952,138 +30042,12 @@ const PolygonGraph = props => {
|
|
|
29952
30042
|
}
|
|
29953
30043
|
}), points.map((point, i) => /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
29954
30044
|
key: "point-" + i,
|
|
30045
|
+
snapTo: snapTo,
|
|
29955
30046
|
point: point,
|
|
29956
30047
|
onMove: destination => dispatch(movePoint(i, destination))
|
|
29957
30048
|
})));
|
|
29958
30049
|
};
|
|
29959
30050
|
|
|
29960
|
-
function initializeGraphState(params) {
|
|
29961
|
-
const {
|
|
29962
|
-
graph,
|
|
29963
|
-
step,
|
|
29964
|
-
snapStep,
|
|
29965
|
-
range
|
|
29966
|
-
} = params;
|
|
29967
|
-
const shared = {
|
|
29968
|
-
hasBeenInteractedWith: false,
|
|
29969
|
-
range,
|
|
29970
|
-
snapStep
|
|
29971
|
-
};
|
|
29972
|
-
switch (graph.type) {
|
|
29973
|
-
case "segment":
|
|
29974
|
-
return {
|
|
29975
|
-
...shared,
|
|
29976
|
-
type: "segment",
|
|
29977
|
-
coords: getDefaultSegments({
|
|
29978
|
-
graph,
|
|
29979
|
-
step,
|
|
29980
|
-
range
|
|
29981
|
-
})
|
|
29982
|
-
};
|
|
29983
|
-
case "linear":
|
|
29984
|
-
case "linear-system":
|
|
29985
|
-
case "ray":
|
|
29986
|
-
return {
|
|
29987
|
-
...shared,
|
|
29988
|
-
type: graph.type,
|
|
29989
|
-
// Linear and ray graphs have a single tuple of points, while a
|
|
29990
|
-
// linear system has two tuples of points.
|
|
29991
|
-
coords: getLineCoords({
|
|
29992
|
-
graph,
|
|
29993
|
-
range,
|
|
29994
|
-
step
|
|
29995
|
-
})
|
|
29996
|
-
};
|
|
29997
|
-
case "polygon":
|
|
29998
|
-
return {
|
|
29999
|
-
...shared,
|
|
30000
|
-
type: "polygon",
|
|
30001
|
-
showAngles: Boolean(graph.showAngles),
|
|
30002
|
-
showSides: Boolean(graph.showSides),
|
|
30003
|
-
coords: getPolygonCoords({
|
|
30004
|
-
graph,
|
|
30005
|
-
range,
|
|
30006
|
-
step
|
|
30007
|
-
})
|
|
30008
|
-
};
|
|
30009
|
-
case "point":
|
|
30010
|
-
return {
|
|
30011
|
-
...shared,
|
|
30012
|
-
type: graph.type,
|
|
30013
|
-
coords: getDefaultPoints({
|
|
30014
|
-
graph,
|
|
30015
|
-
step,
|
|
30016
|
-
range
|
|
30017
|
-
})
|
|
30018
|
-
};
|
|
30019
|
-
case "circle":
|
|
30020
|
-
return {
|
|
30021
|
-
...shared,
|
|
30022
|
-
type: graph.type,
|
|
30023
|
-
center: [0, 0],
|
|
30024
|
-
radiusPoint: [1, 0]
|
|
30025
|
-
};
|
|
30026
|
-
case "quadratic":
|
|
30027
|
-
return {
|
|
30028
|
-
...shared,
|
|
30029
|
-
type: graph.type,
|
|
30030
|
-
coords: getQuadraticCoords(graph, range, step)
|
|
30031
|
-
};
|
|
30032
|
-
case "sinusoid":
|
|
30033
|
-
return {
|
|
30034
|
-
...shared,
|
|
30035
|
-
type: graph.type,
|
|
30036
|
-
coords: getSinusoidCoords(graph, range, step)
|
|
30037
|
-
};
|
|
30038
|
-
case "angle":
|
|
30039
|
-
throw new Error("Mafs not yet implemented for graph type: " + graph.type);
|
|
30040
|
-
default:
|
|
30041
|
-
throw new wonderStuffCore.UnreachableCaseError(graph);
|
|
30042
|
-
}
|
|
30043
|
-
}
|
|
30044
|
-
const getDefaultPoints = _ref => {
|
|
30045
|
-
let {
|
|
30046
|
-
graph,
|
|
30047
|
-
range,
|
|
30048
|
-
step
|
|
30049
|
-
} = _ref;
|
|
30050
|
-
const numPoints = graph.numPoints || 1;
|
|
30051
|
-
let coords = graph.coords?.slice();
|
|
30052
|
-
if (coords) {
|
|
30053
|
-
return coords;
|
|
30054
|
-
}
|
|
30055
|
-
switch (numPoints) {
|
|
30056
|
-
case 1:
|
|
30057
|
-
// Back in the day, one point's coords were in graph.coord
|
|
30058
|
-
coords = [graph.coord || [0, 0]];
|
|
30059
|
-
break;
|
|
30060
|
-
case 2:
|
|
30061
|
-
coords = [[-5, 0], [5, 0]];
|
|
30062
|
-
break;
|
|
30063
|
-
case 3:
|
|
30064
|
-
coords = [[-5, 0], [0, 0], [5, 0]];
|
|
30065
|
-
break;
|
|
30066
|
-
case 4:
|
|
30067
|
-
coords = [[-6, 0], [-2, 0], [2, 0], [6, 0]];
|
|
30068
|
-
break;
|
|
30069
|
-
case 5:
|
|
30070
|
-
coords = [[-6, 0], [-3, 0], [0, 0], [3, 0], [6, 0]];
|
|
30071
|
-
break;
|
|
30072
|
-
case 6:
|
|
30073
|
-
coords = [[-5, 0], [-3, 0], [-1, 0], [1, 0], [3, 0], [5, 0]];
|
|
30074
|
-
break;
|
|
30075
|
-
default:
|
|
30076
|
-
coords = [];
|
|
30077
|
-
break;
|
|
30078
|
-
}
|
|
30079
|
-
// Transform coords from their -10 to 10 space to 0 to 1
|
|
30080
|
-
// because of the old graph.coord, and also it's easier.
|
|
30081
|
-
const newCoords = normalizeCoords(coords, [[-10, 10], [-10, 10]]);
|
|
30082
|
-
return normalizePoints(range, step, newCoords);
|
|
30083
|
-
};
|
|
30084
|
-
|
|
30085
|
-
// TS v4 doesn't narrow return types, while v5 does.
|
|
30086
|
-
// Instead of updating to v5, using generic type to relate input and output types.
|
|
30087
30051
|
function getGradableGraph(state, initialGraph) {
|
|
30088
30052
|
if (!state.hasBeenInteractedWith) {
|
|
30089
30053
|
return {
|
|
@@ -30105,13 +30069,13 @@ function getGradableGraph(state, initialGraph) {
|
|
|
30105
30069
|
if (state.type === "linear" && initialGraph.type === "linear") {
|
|
30106
30070
|
return {
|
|
30107
30071
|
...initialGraph,
|
|
30108
|
-
coords: state.coords
|
|
30072
|
+
coords: state.coords
|
|
30109
30073
|
};
|
|
30110
30074
|
}
|
|
30111
30075
|
if (state.type === "ray" && initialGraph.type === "ray") {
|
|
30112
30076
|
return {
|
|
30113
30077
|
...initialGraph,
|
|
30114
|
-
coords: state.coords
|
|
30078
|
+
coords: state.coords
|
|
30115
30079
|
};
|
|
30116
30080
|
}
|
|
30117
30081
|
if (state.type === "polygon" && initialGraph.type === "polygon") {
|
|
@@ -30147,93 +30111,6 @@ function getGradableGraph(state, initialGraph) {
|
|
|
30147
30111
|
}
|
|
30148
30112
|
throw new Error("Mafs is not yet implemented for graph type: " + initialGraph.type);
|
|
30149
30113
|
}
|
|
30150
|
-
const getDefaultSegments = _ref2 => {
|
|
30151
|
-
let {
|
|
30152
|
-
graph,
|
|
30153
|
-
range,
|
|
30154
|
-
step
|
|
30155
|
-
} = _ref2;
|
|
30156
|
-
const ys = n => {
|
|
30157
|
-
switch (n) {
|
|
30158
|
-
case 2:
|
|
30159
|
-
return [5, -5];
|
|
30160
|
-
case 3:
|
|
30161
|
-
return [5, 0, -5];
|
|
30162
|
-
case 4:
|
|
30163
|
-
return [6, 2, -2, -6];
|
|
30164
|
-
case 5:
|
|
30165
|
-
return [6, 3, 0, -3, -6];
|
|
30166
|
-
case 6:
|
|
30167
|
-
return [5, 3, 1, -1, -3, -5];
|
|
30168
|
-
default:
|
|
30169
|
-
return [5];
|
|
30170
|
-
}
|
|
30171
|
-
};
|
|
30172
|
-
const defaultRange = [[-10, 10], [-10, 10]];
|
|
30173
|
-
return ys(graph.numSegments).map(y => {
|
|
30174
|
-
let endpoints = [[-5, y], [5, y]];
|
|
30175
|
-
endpoints = normalizeCoords(endpoints, defaultRange);
|
|
30176
|
-
endpoints = normalizePoints(range, step, endpoints);
|
|
30177
|
-
return endpoints;
|
|
30178
|
-
});
|
|
30179
|
-
};
|
|
30180
|
-
const defaultLinearCoords = [[[0.25, 0.75], [0.75, 0.75]], [[0.25, 0.25], [0.75, 0.25]]];
|
|
30181
|
-
const getLineCoords = _ref3 => {
|
|
30182
|
-
let {
|
|
30183
|
-
graph,
|
|
30184
|
-
range,
|
|
30185
|
-
step
|
|
30186
|
-
} = _ref3;
|
|
30187
|
-
// Return two lines for a linear system, one for a ray or linear
|
|
30188
|
-
switch (graph.type) {
|
|
30189
|
-
case "linear-system":
|
|
30190
|
-
return defaultLinearCoords.map(points => normalizePoints(range, step, points));
|
|
30191
|
-
case "linear":
|
|
30192
|
-
case "ray":
|
|
30193
|
-
return [normalizePoints(range, step, defaultLinearCoords[0])];
|
|
30194
|
-
default:
|
|
30195
|
-
throw new wonderStuffCore.UnreachableCaseError(graph);
|
|
30196
|
-
}
|
|
30197
|
-
};
|
|
30198
|
-
const getPolygonCoords = _ref4 => {
|
|
30199
|
-
let {
|
|
30200
|
-
graph,
|
|
30201
|
-
range,
|
|
30202
|
-
step
|
|
30203
|
-
} = _ref4;
|
|
30204
|
-
let coords = graph.coords?.slice();
|
|
30205
|
-
if (coords) {
|
|
30206
|
-
return coords;
|
|
30207
|
-
}
|
|
30208
|
-
const n = graph.numSides || 3;
|
|
30209
|
-
if (n === "unlimited") {
|
|
30210
|
-
coords = [];
|
|
30211
|
-
} else {
|
|
30212
|
-
const angle = 2 * Math.PI / n;
|
|
30213
|
-
const offset = (1 / n - 1 / 2) * Math.PI;
|
|
30214
|
-
|
|
30215
|
-
// TODO(alex): Generalize this to more than just triangles so that
|
|
30216
|
-
// all polygons have whole number side lengths if snapping to sides
|
|
30217
|
-
const radius = graph.snapTo === "sides" ? Math.sqrt(3) / 3 * 7 : 4;
|
|
30218
|
-
|
|
30219
|
-
// Generate coords of a regular polygon with n sides
|
|
30220
|
-
coords = [...Array(n).keys()].map(i => [radius * Math.cos(i * angle + offset), radius * Math.sin(i * angle + offset)]);
|
|
30221
|
-
}
|
|
30222
|
-
coords = normalizeCoords(coords, [[-10, 10], [-10, 10]]);
|
|
30223
|
-
const snapToGrid = !["angles", "sides"].includes(graph.snapTo || "");
|
|
30224
|
-
coords = normalizePoints(range, step, coords, /* noSnap */!snapToGrid);
|
|
30225
|
-
return coords;
|
|
30226
|
-
};
|
|
30227
|
-
const getSinusoidCoords = (graph, range, step) => {
|
|
30228
|
-
let coords = [[0.5, 0.5], [0.65, 0.6]];
|
|
30229
|
-
coords = normalizePoints(range, step, coords, true);
|
|
30230
|
-
return coords;
|
|
30231
|
-
};
|
|
30232
|
-
const getQuadraticCoords = (graph, range, step) => {
|
|
30233
|
-
let coords = [[0.25, 0.75], [0.5, 0.25], [0.75, 0.75]];
|
|
30234
|
-
coords = normalizePoints(range, step, coords, true);
|
|
30235
|
-
return coords;
|
|
30236
|
-
};
|
|
30237
30114
|
|
|
30238
30115
|
/**
|
|
30239
30116
|
* determine radius of a circle graph
|
|
@@ -30262,6 +30139,7 @@ function CircleGraph(props) {
|
|
|
30262
30139
|
onMove: newCenter => dispatch(moveCenter(newCenter))
|
|
30263
30140
|
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
30264
30141
|
point: radiusPoint,
|
|
30142
|
+
cursor: "ew-resize",
|
|
30265
30143
|
onMove: newRadiusPoint => {
|
|
30266
30144
|
dispatch(moveRadiusPoint(newRadiusPoint));
|
|
30267
30145
|
}
|
|
@@ -30366,38 +30244,16 @@ function QuadraticGraph(props) {
|
|
|
30366
30244
|
|
|
30367
30245
|
// Calculate the y value based on the current x value
|
|
30368
30246
|
const y = x => (a * x + b) * x + c;
|
|
30369
|
-
const handleOnMove = (destination, elementId) => {
|
|
30370
|
-
// If the destination is invalid, we want do not want to move the point
|
|
30371
|
-
const validDestination = isValidDestination(destination, elementId, coords);
|
|
30372
|
-
if (validDestination === false) {
|
|
30373
|
-
return;
|
|
30374
|
-
}
|
|
30375
|
-
dispatch(movePoint(elementId, destination));
|
|
30376
|
-
};
|
|
30377
30247
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Plot.OfX, {
|
|
30378
30248
|
y: y,
|
|
30379
30249
|
color: wonderBlocksTokens.color.blue
|
|
30380
30250
|
}), coords.map((coord, i) => /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
30381
30251
|
key: "point-" + i,
|
|
30382
30252
|
point: coord,
|
|
30383
|
-
onMove: destination =>
|
|
30253
|
+
onMove: destination => dispatch(movePoint(i, destination))
|
|
30384
30254
|
})));
|
|
30385
30255
|
}
|
|
30386
30256
|
|
|
30387
|
-
// Ensure that we are only snapping to coordinates that result in a valid quadratic equation
|
|
30388
|
-
const isValidDestination = (destination, elementId, coords) => {
|
|
30389
|
-
// Set up the new coords and check if the quadratic coefficients are valid
|
|
30390
|
-
const newCoords = [...coords];
|
|
30391
|
-
newCoords[elementId] = destination;
|
|
30392
|
-
const QuadraticCoefficients = getQuadraticCoefficients(newCoords);
|
|
30393
|
-
|
|
30394
|
-
// If the new destination results in an invalid quadratic equation, we don't want to move the point
|
|
30395
|
-
if (QuadraticCoefficients === undefined) {
|
|
30396
|
-
return false;
|
|
30397
|
-
}
|
|
30398
|
-
return true;
|
|
30399
|
-
};
|
|
30400
|
-
|
|
30401
30257
|
// Get the quadratic coefficients from the 3 control points
|
|
30402
30258
|
// These equations were originally set up in 2013 and may require some
|
|
30403
30259
|
// additional comments to help clarify the quadratic formula manipulations
|
|
@@ -31547,6 +31403,210 @@ const LegacyGrid = _ref => {
|
|
|
31547
31403
|
return null;
|
|
31548
31404
|
};
|
|
31549
31405
|
|
|
31406
|
+
function initializeGraphState(params) {
|
|
31407
|
+
const {
|
|
31408
|
+
graph,
|
|
31409
|
+
step,
|
|
31410
|
+
snapStep,
|
|
31411
|
+
range
|
|
31412
|
+
} = params;
|
|
31413
|
+
const shared = {
|
|
31414
|
+
hasBeenInteractedWith: false,
|
|
31415
|
+
range,
|
|
31416
|
+
snapStep
|
|
31417
|
+
};
|
|
31418
|
+
switch (graph.type) {
|
|
31419
|
+
case "segment":
|
|
31420
|
+
return {
|
|
31421
|
+
...shared,
|
|
31422
|
+
type: "segment",
|
|
31423
|
+
coords: getSegmentCoords(graph, range, step)
|
|
31424
|
+
};
|
|
31425
|
+
case "linear":
|
|
31426
|
+
return {
|
|
31427
|
+
...shared,
|
|
31428
|
+
type: graph.type,
|
|
31429
|
+
coords: getLineCoords(graph, range, step)
|
|
31430
|
+
};
|
|
31431
|
+
case "ray":
|
|
31432
|
+
return {
|
|
31433
|
+
...shared,
|
|
31434
|
+
type: graph.type,
|
|
31435
|
+
coords: getLineCoords(graph, range, step)
|
|
31436
|
+
};
|
|
31437
|
+
case "linear-system":
|
|
31438
|
+
return {
|
|
31439
|
+
...shared,
|
|
31440
|
+
type: graph.type,
|
|
31441
|
+
coords: getLinearSystemCoords(graph, range, step)
|
|
31442
|
+
};
|
|
31443
|
+
case "polygon":
|
|
31444
|
+
return {
|
|
31445
|
+
...shared,
|
|
31446
|
+
type: "polygon",
|
|
31447
|
+
showAngles: Boolean(graph.showAngles),
|
|
31448
|
+
showSides: Boolean(graph.showSides),
|
|
31449
|
+
coords: getPolygonCoords(graph, range, step),
|
|
31450
|
+
snapTo: graph.snapTo ?? "grid"
|
|
31451
|
+
};
|
|
31452
|
+
case "point":
|
|
31453
|
+
return {
|
|
31454
|
+
...shared,
|
|
31455
|
+
type: graph.type,
|
|
31456
|
+
coords: getPointCoords(graph, range, step)
|
|
31457
|
+
};
|
|
31458
|
+
case "circle":
|
|
31459
|
+
return {
|
|
31460
|
+
...shared,
|
|
31461
|
+
type: graph.type,
|
|
31462
|
+
...getCircleCoords(graph)
|
|
31463
|
+
};
|
|
31464
|
+
case "quadratic":
|
|
31465
|
+
return {
|
|
31466
|
+
...shared,
|
|
31467
|
+
type: graph.type,
|
|
31468
|
+
coords: getQuadraticCoords(graph, range, step)
|
|
31469
|
+
};
|
|
31470
|
+
case "sinusoid":
|
|
31471
|
+
return {
|
|
31472
|
+
...shared,
|
|
31473
|
+
type: graph.type,
|
|
31474
|
+
coords: getSinusoidCoords(graph, range, step)
|
|
31475
|
+
};
|
|
31476
|
+
case "angle":
|
|
31477
|
+
throw new Error("Mafs not yet implemented for graph type: " + graph.type);
|
|
31478
|
+
default:
|
|
31479
|
+
throw new wonderStuffCore.UnreachableCaseError(graph);
|
|
31480
|
+
}
|
|
31481
|
+
}
|
|
31482
|
+
function getPointCoords(graph, range, step) {
|
|
31483
|
+
const numPoints = graph.numPoints || 1;
|
|
31484
|
+
let coords = graph.coords?.slice();
|
|
31485
|
+
if (coords) {
|
|
31486
|
+
return coords;
|
|
31487
|
+
}
|
|
31488
|
+
switch (numPoints) {
|
|
31489
|
+
case 1:
|
|
31490
|
+
// Back in the day, one point's coords were in graph.coord
|
|
31491
|
+
coords = [graph.coord || [0, 0]];
|
|
31492
|
+
break;
|
|
31493
|
+
case 2:
|
|
31494
|
+
coords = [[-5, 0], [5, 0]];
|
|
31495
|
+
break;
|
|
31496
|
+
case 3:
|
|
31497
|
+
coords = [[-5, 0], [0, 0], [5, 0]];
|
|
31498
|
+
break;
|
|
31499
|
+
case 4:
|
|
31500
|
+
coords = [[-6, 0], [-2, 0], [2, 0], [6, 0]];
|
|
31501
|
+
break;
|
|
31502
|
+
case 5:
|
|
31503
|
+
coords = [[-6, 0], [-3, 0], [0, 0], [3, 0], [6, 0]];
|
|
31504
|
+
break;
|
|
31505
|
+
case 6:
|
|
31506
|
+
coords = [[-5, 0], [-3, 0], [-1, 0], [1, 0], [3, 0], [5, 0]];
|
|
31507
|
+
break;
|
|
31508
|
+
default:
|
|
31509
|
+
coords = [];
|
|
31510
|
+
break;
|
|
31511
|
+
}
|
|
31512
|
+
// Transform coords from their -10 to 10 space to 0 to 1
|
|
31513
|
+
// because of the old graph.coord, and also it's easier.
|
|
31514
|
+
const newCoords = normalizeCoords(coords, [[-10, 10], [-10, 10]]);
|
|
31515
|
+
return normalizePoints(range, step, newCoords);
|
|
31516
|
+
}
|
|
31517
|
+
function getSegmentCoords(graph, range, step) {
|
|
31518
|
+
if (graph.coords) {
|
|
31519
|
+
return graph.coords;
|
|
31520
|
+
}
|
|
31521
|
+
const ys = n => {
|
|
31522
|
+
switch (n) {
|
|
31523
|
+
case 2:
|
|
31524
|
+
return [5, -5];
|
|
31525
|
+
case 3:
|
|
31526
|
+
return [5, 0, -5];
|
|
31527
|
+
case 4:
|
|
31528
|
+
return [6, 2, -2, -6];
|
|
31529
|
+
case 5:
|
|
31530
|
+
return [6, 3, 0, -3, -6];
|
|
31531
|
+
case 6:
|
|
31532
|
+
return [5, 3, 1, -1, -3, -5];
|
|
31533
|
+
default:
|
|
31534
|
+
return [5];
|
|
31535
|
+
}
|
|
31536
|
+
};
|
|
31537
|
+
const defaultRange = [[-10, 10], [-10, 10]];
|
|
31538
|
+
return ys(graph.numSegments).map(y => {
|
|
31539
|
+
let endpoints = [[-5, y], [5, y]];
|
|
31540
|
+
endpoints = normalizeCoords(endpoints, defaultRange);
|
|
31541
|
+
endpoints = normalizePoints(range, step, endpoints);
|
|
31542
|
+
return endpoints;
|
|
31543
|
+
});
|
|
31544
|
+
}
|
|
31545
|
+
const defaultLinearCoords = [[[0.25, 0.75], [0.75, 0.75]], [[0.25, 0.25], [0.75, 0.25]]];
|
|
31546
|
+
function getLineCoords(graph, range, step) {
|
|
31547
|
+
if (graph.coords) {
|
|
31548
|
+
return graph.coords;
|
|
31549
|
+
}
|
|
31550
|
+
return normalizePoints(range, step, defaultLinearCoords[0]);
|
|
31551
|
+
}
|
|
31552
|
+
function getLinearSystemCoords(graph, range, step) {
|
|
31553
|
+
if (graph.coords) {
|
|
31554
|
+
return graph.coords;
|
|
31555
|
+
}
|
|
31556
|
+
return defaultLinearCoords.map(points => normalizePoints(range, step, points));
|
|
31557
|
+
}
|
|
31558
|
+
function getPolygonCoords(graph, range, step) {
|
|
31559
|
+
let coords = graph.coords?.slice();
|
|
31560
|
+
if (coords) {
|
|
31561
|
+
return coords;
|
|
31562
|
+
}
|
|
31563
|
+
const n = graph.numSides || 3;
|
|
31564
|
+
if (n === "unlimited") {
|
|
31565
|
+
coords = [];
|
|
31566
|
+
} else {
|
|
31567
|
+
const angle = 2 * Math.PI / n;
|
|
31568
|
+
const offset = (1 / n - 1 / 2) * Math.PI;
|
|
31569
|
+
|
|
31570
|
+
// TODO(alex): Generalize this to more than just triangles so that
|
|
31571
|
+
// all polygons have whole number side lengths if snapping to sides
|
|
31572
|
+
const radius = graph.snapTo === "sides" ? Math.sqrt(3) / 3 * 7 : 4;
|
|
31573
|
+
|
|
31574
|
+
// Generate coords of a regular polygon with n sides
|
|
31575
|
+
coords = [...Array(n).keys()].map(i => [radius * Math.cos(i * angle + offset), radius * Math.sin(i * angle + offset)]);
|
|
31576
|
+
}
|
|
31577
|
+
coords = normalizeCoords(coords, [[-10, 10], [-10, 10]]);
|
|
31578
|
+
const snapToGrid = !["angles", "sides"].includes(graph.snapTo || "");
|
|
31579
|
+
coords = normalizePoints(range, step, coords, /* noSnap */!snapToGrid);
|
|
31580
|
+
return coords;
|
|
31581
|
+
}
|
|
31582
|
+
function getSinusoidCoords(graph, range, step) {
|
|
31583
|
+
if (graph.coords) {
|
|
31584
|
+
return [graph.coords[0], graph.coords[1]];
|
|
31585
|
+
}
|
|
31586
|
+
let coords = [[0.5, 0.5], [0.65, 0.6]];
|
|
31587
|
+
coords = normalizePoints(range, step, coords, true);
|
|
31588
|
+
return coords;
|
|
31589
|
+
}
|
|
31590
|
+
function getQuadraticCoords(graph, range, step) {
|
|
31591
|
+
if (graph.coords) {
|
|
31592
|
+
return graph.coords;
|
|
31593
|
+
}
|
|
31594
|
+
const defaultCoords = [[0.25, 0.75], [0.5, 0.25], [0.75, 0.75]];
|
|
31595
|
+
return normalizePoints(range, step, defaultCoords, true);
|
|
31596
|
+
}
|
|
31597
|
+
function getCircleCoords(graph) {
|
|
31598
|
+
if (graph.center != null && graph.radius != null) {
|
|
31599
|
+
return {
|
|
31600
|
+
center: graph.center,
|
|
31601
|
+
radiusPoint: mafs.vec.add(graph.center, [graph.radius, 0])
|
|
31602
|
+
};
|
|
31603
|
+
}
|
|
31604
|
+
return {
|
|
31605
|
+
center: [0, 0],
|
|
31606
|
+
radiusPoint: [2, 0]
|
|
31607
|
+
};
|
|
31608
|
+
}
|
|
31609
|
+
|
|
31550
31610
|
function interactiveGraphReducer(state, action) {
|
|
31551
31611
|
switch (action.type) {
|
|
31552
31612
|
case MOVE_CONTROL_POINT:
|
|
@@ -31570,15 +31630,9 @@ function interactiveGraphReducer(state, action) {
|
|
|
31570
31630
|
}
|
|
31571
31631
|
}
|
|
31572
31632
|
function doMoveControlPoint(state, action) {
|
|
31573
|
-
const {
|
|
31574
|
-
snapStep,
|
|
31575
|
-
range
|
|
31576
|
-
} = state;
|
|
31577
31633
|
switch (state.type) {
|
|
31578
31634
|
case "segment":
|
|
31579
|
-
case "linear":
|
|
31580
31635
|
case "linear-system":
|
|
31581
|
-
case "ray":
|
|
31582
31636
|
{
|
|
31583
31637
|
const newCoords = updateAtIndex({
|
|
31584
31638
|
array: state.coords,
|
|
@@ -31586,11 +31640,7 @@ function doMoveControlPoint(state, action) {
|
|
|
31586
31640
|
update: tuple => setAtIndex({
|
|
31587
31641
|
array: tuple,
|
|
31588
31642
|
index: action.pointIndex,
|
|
31589
|
-
newValue:
|
|
31590
|
-
snapStep,
|
|
31591
|
-
range,
|
|
31592
|
-
point: action.destination
|
|
31593
|
-
}))
|
|
31643
|
+
newValue: boundAndSnapToGrid(action.destination, state)
|
|
31594
31644
|
})
|
|
31595
31645
|
});
|
|
31596
31646
|
const coordsToCheck = newCoords[action.itemIndex];
|
|
@@ -31603,6 +31653,20 @@ function doMoveControlPoint(state, action) {
|
|
|
31603
31653
|
coords: newCoords
|
|
31604
31654
|
};
|
|
31605
31655
|
}
|
|
31656
|
+
case "linear":
|
|
31657
|
+
case "ray":
|
|
31658
|
+
{
|
|
31659
|
+
const newCoords = setAtIndex({
|
|
31660
|
+
array: state.coords,
|
|
31661
|
+
index: action.pointIndex,
|
|
31662
|
+
newValue: boundAndSnapToGrid(action.destination, state)
|
|
31663
|
+
});
|
|
31664
|
+
return {
|
|
31665
|
+
...state,
|
|
31666
|
+
hasBeenInteractedWith: true,
|
|
31667
|
+
coords: newCoords
|
|
31668
|
+
};
|
|
31669
|
+
}
|
|
31606
31670
|
case "circle":
|
|
31607
31671
|
throw new Error("FIXME implement circle reducer");
|
|
31608
31672
|
case "point":
|
|
@@ -31614,6 +31678,9 @@ function doMoveControlPoint(state, action) {
|
|
|
31614
31678
|
throw new wonderStuffCore.UnreachableCaseError(state);
|
|
31615
31679
|
}
|
|
31616
31680
|
}
|
|
31681
|
+
|
|
31682
|
+
// (LEMS-2050): Update the reducer so that we have a separate action for moving one line
|
|
31683
|
+
// and another action for moving multiple lines
|
|
31617
31684
|
function doMoveLine(state, action) {
|
|
31618
31685
|
const {
|
|
31619
31686
|
snapStep,
|
|
@@ -31621,9 +31688,7 @@ function doMoveLine(state, action) {
|
|
|
31621
31688
|
} = state;
|
|
31622
31689
|
switch (state.type) {
|
|
31623
31690
|
case "segment":
|
|
31624
|
-
case "linear":
|
|
31625
31691
|
case "linear-system":
|
|
31626
|
-
case "ray":
|
|
31627
31692
|
{
|
|
31628
31693
|
if (action.itemIndex === undefined) {
|
|
31629
31694
|
throw new Error("Please provide index of line to move");
|
|
@@ -31649,6 +31714,22 @@ function doMoveLine(state, action) {
|
|
|
31649
31714
|
coords: newCoords
|
|
31650
31715
|
};
|
|
31651
31716
|
}
|
|
31717
|
+
case "linear":
|
|
31718
|
+
case "ray":
|
|
31719
|
+
{
|
|
31720
|
+
const currentLine = state.coords;
|
|
31721
|
+
const change = getChange(currentLine, action.delta, {
|
|
31722
|
+
snapStep,
|
|
31723
|
+
range
|
|
31724
|
+
});
|
|
31725
|
+
const newLine = [snap(snapStep, mafs.vec.add(currentLine[0], change)), snap(snapStep, mafs.vec.add(currentLine[1], change))];
|
|
31726
|
+
return {
|
|
31727
|
+
...state,
|
|
31728
|
+
type: state.type,
|
|
31729
|
+
hasBeenInteractedWith: true,
|
|
31730
|
+
coords: newLine
|
|
31731
|
+
};
|
|
31732
|
+
}
|
|
31652
31733
|
default:
|
|
31653
31734
|
// The MoveLine action doesn't make sense for other graph types;
|
|
31654
31735
|
// ignore it if it somehow happens
|
|
@@ -31663,11 +31744,20 @@ function doMoveAll(state, action) {
|
|
|
31663
31744
|
switch (state.type) {
|
|
31664
31745
|
case "polygon":
|
|
31665
31746
|
{
|
|
31666
|
-
|
|
31667
|
-
|
|
31668
|
-
|
|
31669
|
-
|
|
31670
|
-
|
|
31747
|
+
let newCoords;
|
|
31748
|
+
if (state.snapTo === "sides" || state.snapTo === "angles") {
|
|
31749
|
+
const change = getChange(state.coords, action.delta, {
|
|
31750
|
+
snapStep: [0, 0],
|
|
31751
|
+
range
|
|
31752
|
+
});
|
|
31753
|
+
newCoords = state.coords.map(point => mafs.vec.add(point, change));
|
|
31754
|
+
} else {
|
|
31755
|
+
const change = getChange(state.coords, action.delta, {
|
|
31756
|
+
snapStep,
|
|
31757
|
+
range
|
|
31758
|
+
});
|
|
31759
|
+
newCoords = state.coords.map(point => snap(snapStep, mafs.vec.add(point, change)));
|
|
31760
|
+
}
|
|
31671
31761
|
return {
|
|
31672
31762
|
...state,
|
|
31673
31763
|
hasBeenInteractedWith: true,
|
|
@@ -31682,6 +31772,29 @@ function doMoveAll(state, action) {
|
|
|
31682
31772
|
function doMovePoint(state, action) {
|
|
31683
31773
|
switch (state.type) {
|
|
31684
31774
|
case "polygon":
|
|
31775
|
+
let newValue;
|
|
31776
|
+
if (state.snapTo === "sides") {
|
|
31777
|
+
newValue = boundAndSnapToSides(action.destination, state, action.index);
|
|
31778
|
+
} else if (state.snapTo === "angles") {
|
|
31779
|
+
newValue = boundAndSnapToAngle(action.destination, state, action.index);
|
|
31780
|
+
} else {
|
|
31781
|
+
newValue = boundAndSnapToGrid(action.destination, state);
|
|
31782
|
+
}
|
|
31783
|
+
const newCoords = setAtIndex({
|
|
31784
|
+
array: state.coords,
|
|
31785
|
+
index: action.index,
|
|
31786
|
+
newValue: newValue
|
|
31787
|
+
});
|
|
31788
|
+
|
|
31789
|
+
// Reject the move if it would cause the sides of the polygon to cross
|
|
31790
|
+
if (polygonSidesIntersect(newCoords)) {
|
|
31791
|
+
return state;
|
|
31792
|
+
}
|
|
31793
|
+
return {
|
|
31794
|
+
...state,
|
|
31795
|
+
hasBeenInteractedWith: true,
|
|
31796
|
+
coords: newCoords
|
|
31797
|
+
};
|
|
31685
31798
|
case "point":
|
|
31686
31799
|
{
|
|
31687
31800
|
return {
|
|
@@ -31690,11 +31803,7 @@ function doMovePoint(state, action) {
|
|
|
31690
31803
|
coords: setAtIndex({
|
|
31691
31804
|
array: state.coords,
|
|
31692
31805
|
index: action.index,
|
|
31693
|
-
newValue:
|
|
31694
|
-
snapStep: state.snapStep,
|
|
31695
|
-
range: state.range,
|
|
31696
|
-
point: action.destination
|
|
31697
|
-
}))
|
|
31806
|
+
newValue: boundAndSnapToGrid(action.destination, state)
|
|
31698
31807
|
})
|
|
31699
31808
|
};
|
|
31700
31809
|
}
|
|
@@ -31714,27 +31823,28 @@ function doMovePoint(state, action) {
|
|
|
31714
31823
|
coords: setAtIndex({
|
|
31715
31824
|
array: state.coords,
|
|
31716
31825
|
index: action.index,
|
|
31717
|
-
newValue:
|
|
31718
|
-
snapStep: state.snapStep,
|
|
31719
|
-
range: state.range,
|
|
31720
|
-
point: destination
|
|
31721
|
-
}))
|
|
31826
|
+
newValue: boundAndSnapToGrid(destination, state)
|
|
31722
31827
|
})
|
|
31723
31828
|
};
|
|
31724
31829
|
}
|
|
31725
31830
|
case "quadratic":
|
|
31726
31831
|
{
|
|
31832
|
+
// Set up the new coords and check if the quadratic coefficients are valid
|
|
31833
|
+
const newCoords = [...state.coords];
|
|
31834
|
+
newCoords[action.index] = action.destination;
|
|
31835
|
+
const QuadraticCoefficients = getQuadraticCoefficients(newCoords);
|
|
31836
|
+
|
|
31837
|
+
// If the new destination results in an invalid quadratic equation, we don't want to move the point
|
|
31838
|
+
if (QuadraticCoefficients === undefined) {
|
|
31839
|
+
return state;
|
|
31840
|
+
}
|
|
31727
31841
|
return {
|
|
31728
31842
|
...state,
|
|
31729
31843
|
hasBeenInteractedWith: true,
|
|
31730
31844
|
coords: setAtIndex({
|
|
31731
31845
|
array: state.coords,
|
|
31732
31846
|
index: action.index,
|
|
31733
|
-
newValue:
|
|
31734
|
-
snapStep: state.snapStep,
|
|
31735
|
-
range: state.range,
|
|
31736
|
-
point: action.destination
|
|
31737
|
-
}))
|
|
31847
|
+
newValue: boundAndSnapToGrid(action.destination, state)
|
|
31738
31848
|
})
|
|
31739
31849
|
};
|
|
31740
31850
|
}
|
|
@@ -31825,8 +31935,17 @@ function doChangeRange(state, action) {
|
|
|
31825
31935
|
range: action.range
|
|
31826
31936
|
};
|
|
31827
31937
|
}
|
|
31828
|
-
const
|
|
31938
|
+
const getDeltaVertex = (maxMoves, minMoves, delta) => {
|
|
31829
31939
|
const [deltaX, deltaY] = delta;
|
|
31940
|
+
const maxXMove = Math.min(...maxMoves.map(move => move[0]));
|
|
31941
|
+
const maxYMove = Math.min(...maxMoves.map(move => move[1]));
|
|
31942
|
+
const minXMove = Math.max(...minMoves.map(move => move[0]));
|
|
31943
|
+
const minYMove = Math.max(...minMoves.map(move => move[1]));
|
|
31944
|
+
const dx = clamp(deltaX, minXMove, maxXMove);
|
|
31945
|
+
const dy = clamp(deltaY, minYMove, maxYMove);
|
|
31946
|
+
return [dx, dy];
|
|
31947
|
+
};
|
|
31948
|
+
const getChange = (coords, delta, constraintOpts) => {
|
|
31830
31949
|
const maxMoves = coords.map(point => maxMove({
|
|
31831
31950
|
...constraintOpts,
|
|
31832
31951
|
point
|
|
@@ -31835,35 +31954,175 @@ const getChange = (coords, delta, constraintOpts) => {
|
|
|
31835
31954
|
...constraintOpts,
|
|
31836
31955
|
point
|
|
31837
31956
|
}));
|
|
31838
|
-
const
|
|
31839
|
-
const maxYMove = Math.min(...maxMoves.map(move => move[1]));
|
|
31840
|
-
const minXMove = Math.max(...minMoves.map(move => move[0]));
|
|
31841
|
-
const minYMove = Math.max(...minMoves.map(move => move[1]));
|
|
31842
|
-
const dx = clamp(deltaX, minXMove, maxXMove);
|
|
31843
|
-
const dy = clamp(deltaY, minYMove, maxYMove);
|
|
31957
|
+
const [dx, dy] = getDeltaVertex(maxMoves, minMoves, delta);
|
|
31844
31958
|
return [dx, dy];
|
|
31845
31959
|
};
|
|
31960
|
+
const eq$1 = Util.eq;
|
|
31961
|
+
|
|
31962
|
+
// Less than or approximately equal
|
|
31963
|
+
function leq$1(a, b) {
|
|
31964
|
+
return a < b || eq$1(a, b);
|
|
31965
|
+
}
|
|
31966
|
+
function boundAndSnapToGrid(point, _ref) {
|
|
31967
|
+
let {
|
|
31968
|
+
snapStep,
|
|
31969
|
+
range
|
|
31970
|
+
} = _ref;
|
|
31971
|
+
return snap(snapStep, bound$1({
|
|
31972
|
+
snapStep,
|
|
31973
|
+
range,
|
|
31974
|
+
point
|
|
31975
|
+
}));
|
|
31976
|
+
}
|
|
31977
|
+
function boundAndSnapToAngle(destinationPoint, _ref2, index) {
|
|
31978
|
+
let {
|
|
31979
|
+
range,
|
|
31980
|
+
coords
|
|
31981
|
+
} = _ref2;
|
|
31982
|
+
const startingPoint = coords[index];
|
|
31983
|
+
|
|
31984
|
+
// Needed to prevent updating the original coords before the checks for
|
|
31985
|
+
// degenerate triangles and overlapping sides
|
|
31986
|
+
const coordsCopy = [...coords];
|
|
31987
|
+
|
|
31988
|
+
// Takes the destination point and makes sure it is within the bounds of the graph
|
|
31989
|
+
// SnapStep is [0, 0] because we don't want to snap to the grid
|
|
31990
|
+
coordsCopy[index] = bound$1({
|
|
31991
|
+
snapStep: [0, 0],
|
|
31992
|
+
range,
|
|
31993
|
+
point: destinationPoint
|
|
31994
|
+
});
|
|
31995
|
+
|
|
31996
|
+
// Gets the radian angles between the coords and maps them to degrees
|
|
31997
|
+
const angles = angleMeasures(coordsCopy).map(angle => angle * 180 / Math.PI);
|
|
31998
|
+
|
|
31999
|
+
// Gets the relative index of a point
|
|
32000
|
+
const rel = j => {
|
|
32001
|
+
return (index + j + coordsCopy.length) % coordsCopy.length;
|
|
32002
|
+
};
|
|
32003
|
+
|
|
32004
|
+
// Round the angles to left and right of the current point
|
|
32005
|
+
___default["default"].each([-1, 1], function (j) {
|
|
32006
|
+
angles[rel(j)] = Math.round(angles[rel(j)]);
|
|
32007
|
+
});
|
|
32008
|
+
const getAngle = function (a, vertex, b) {
|
|
32009
|
+
const angle = GraphUtils.findAngle(coordsCopy[rel(a)], coordsCopy[rel(b)], coordsCopy[rel(vertex)]);
|
|
32010
|
+
return (angle + 360) % 360;
|
|
32011
|
+
};
|
|
32012
|
+
const innerAngles = [angles[rel(-1)] - getAngle(-2, -1, 1), angles[rel(1)] - getAngle(-1, 1, 2)];
|
|
32013
|
+
innerAngles[2] = 180 - (innerAngles[0] + innerAngles[1]);
|
|
32014
|
+
|
|
32015
|
+
// Avoid degenerate triangles
|
|
32016
|
+
if (innerAngles.some(function (angle) {
|
|
32017
|
+
return leq$1(angle, 1);
|
|
32018
|
+
})) {
|
|
32019
|
+
return startingPoint;
|
|
32020
|
+
}
|
|
32021
|
+
const knownSide = magnitude(
|
|
32022
|
+
// @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'readonly Coord[]'.
|
|
32023
|
+
vector(coordsCopy[rel(-1)], coordsCopy[rel(1)]));
|
|
32024
|
+
|
|
32025
|
+
// Returns true if the points form a counter-clockwise turn;
|
|
32026
|
+
// a.k.a if the point is on the left or right of the polygon.
|
|
32027
|
+
// This is used to determine how to adjust the point: if the point is on the left,
|
|
32028
|
+
// we want to add the inner angle to the outer angle, and if it's on the right,
|
|
32029
|
+
// we want to subtract the inner angle from the outer angle. The angle solved
|
|
32030
|
+
// for is then used in the polar function to determine the new point.
|
|
32031
|
+
const onLeft = sign(ccw(coordsCopy[rel(-1)], coordsCopy[rel(1)], coordsCopy[index])) === 1;
|
|
32032
|
+
|
|
32033
|
+
// Solve for side by using the law of sines
|
|
32034
|
+
const side = Math.sin(innerAngles[1] * Math.PI / 180) / Math.sin(innerAngles[2] * Math.PI / 180) * knownSide;
|
|
32035
|
+
|
|
32036
|
+
// Angle at the second vertex of the polygon
|
|
32037
|
+
const outerAngle = GraphUtils.findAngle(coordsCopy[rel(1)], coordsCopy[rel(-1)]);
|
|
32038
|
+
|
|
32039
|
+
// Uses the length of the side of the polygon (radial coordinate)
|
|
32040
|
+
// and the angle between the first and second sides of the
|
|
32041
|
+
// polygon (angular coordinate) to determine how to adjust the point
|
|
32042
|
+
const offset = polar(side, outerAngle + (onLeft ? 1 : -1) * innerAngles[0]);
|
|
32043
|
+
return kmath.vector.add(coordsCopy[rel(-1)], offset);
|
|
32044
|
+
}
|
|
32045
|
+
function boundAndSnapToSides(destinationPoint, _ref3, index) {
|
|
32046
|
+
let {
|
|
32047
|
+
range,
|
|
32048
|
+
coords
|
|
32049
|
+
} = _ref3;
|
|
32050
|
+
const startingPoint = coords[index];
|
|
32051
|
+
|
|
32052
|
+
// Needed to prevent updating the original coords before the checks for
|
|
32053
|
+
// degenerate triangles and overlapping sides
|
|
32054
|
+
const coordsCopy = [...coords];
|
|
32055
|
+
|
|
32056
|
+
// Takes the destination point and makes sure it is within the bounds of the graph
|
|
32057
|
+
// SnapStep is [0, 0] because we don't want to snap to the grid
|
|
32058
|
+
coordsCopy[index] = bound$1({
|
|
32059
|
+
snapStep: [0, 0],
|
|
32060
|
+
range,
|
|
32061
|
+
point: destinationPoint
|
|
32062
|
+
});
|
|
32063
|
+
|
|
32064
|
+
// Gets the relative index of a point
|
|
32065
|
+
const rel = j => {
|
|
32066
|
+
return (index + j + coordsCopy.length) % coordsCopy.length;
|
|
32067
|
+
};
|
|
32068
|
+
const sides = ___default["default"].map([[coordsCopy[rel(-1)], coordsCopy[index]], [coordsCopy[index], coordsCopy[rel(1)]], [coordsCopy[rel(-1)], coordsCopy[rel(1)]]], function (coordsCopy) {
|
|
32069
|
+
// @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'readonly Coord[]'. | TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
|
|
32070
|
+
return magnitude(vector(...coordsCopy));
|
|
32071
|
+
});
|
|
32072
|
+
|
|
32073
|
+
// Round the sides to left and right of the current point
|
|
32074
|
+
___default["default"].each([0, 1], function (j) {
|
|
32075
|
+
sides[j] = Math.round(sides[j]);
|
|
32076
|
+
});
|
|
32077
|
+
|
|
32078
|
+
// Avoid degenerate triangles
|
|
32079
|
+
if (leq$1(sides[1] + sides[2], sides[0]) || leq$1(sides[0] + sides[2], sides[1]) || leq$1(sides[0] + sides[1], sides[2])) {
|
|
32080
|
+
return startingPoint;
|
|
32081
|
+
}
|
|
32082
|
+
|
|
32083
|
+
// Solve for angle by using the law of cosines
|
|
32084
|
+
// Angle at the first vertex of the polygon
|
|
32085
|
+
const innerAngle = lawOfCosines(sides[0], sides[2], sides[1]);
|
|
32086
|
+
|
|
32087
|
+
// Angle at the second vertex of the polygon
|
|
32088
|
+
const outerAngle = GraphUtils.findAngle(coordsCopy[rel(1)], coordsCopy[rel(-1)]);
|
|
32089
|
+
|
|
32090
|
+
// Returns true if the points form a counter-clockwise turn;
|
|
32091
|
+
// a.k.a if the point is on the left or right of the polygon.
|
|
32092
|
+
// This is used to determine how to adjust the point: if the point is on the left,
|
|
32093
|
+
// we want to add the inner angle to the outer angle, and if it's on the right,
|
|
32094
|
+
// we want to subtract the inner angle from the outer angle. The angle solved
|
|
32095
|
+
// for is then used in the polar function to determine the new point.
|
|
32096
|
+
const onLeft = sign(ccw(coordsCopy[rel(-1)], coordsCopy[rel(1)], coordsCopy[index])) === 1;
|
|
32097
|
+
|
|
32098
|
+
// Uses the length of the first side of the polygon (radial coordinate)
|
|
32099
|
+
// and the angle between the first and second sides of the
|
|
32100
|
+
// polygon (angular coordinate) to determine how to adjust the point
|
|
32101
|
+
const offset = polar(sides[0], outerAngle + (onLeft ? 1 : -1) * innerAngle);
|
|
32102
|
+
return kmath.vector.add(coordsCopy[rel(-1)], offset);
|
|
32103
|
+
}
|
|
32104
|
+
|
|
31846
32105
|
// Returns the closest point to the given `point` that is within the graph
|
|
31847
32106
|
// bounds given in `state`.
|
|
31848
|
-
function bound$1(
|
|
32107
|
+
function bound$1(_ref4) {
|
|
31849
32108
|
let {
|
|
31850
32109
|
snapStep,
|
|
31851
32110
|
range,
|
|
31852
32111
|
point
|
|
31853
|
-
} =
|
|
32112
|
+
} = _ref4;
|
|
31854
32113
|
const [requestedX, requestedY] = point;
|
|
31855
32114
|
const [snapX, snapY] = snapStep;
|
|
31856
32115
|
const [[minX, maxX], [minY, maxY]] = range;
|
|
31857
32116
|
return [clamp(requestedX, minX + snapX, maxX - snapX), clamp(requestedY, minY + snapY, maxY - snapY)];
|
|
31858
32117
|
}
|
|
31859
32118
|
|
|
31860
|
-
// Returns the vector from the given point to the top-right corner of the graph
|
|
31861
|
-
function maxMove(
|
|
32119
|
+
// Returns the vector from the given point to the top-right corner of the graph when snapped to the grid
|
|
32120
|
+
function maxMove(_ref5) {
|
|
31862
32121
|
let {
|
|
31863
32122
|
snapStep,
|
|
31864
32123
|
range,
|
|
31865
32124
|
point
|
|
31866
|
-
} =
|
|
32125
|
+
} = _ref5;
|
|
31867
32126
|
const topRight = bound$1({
|
|
31868
32127
|
snapStep,
|
|
31869
32128
|
range,
|
|
@@ -31872,14 +32131,13 @@ function maxMove(_ref2) {
|
|
|
31872
32131
|
return mafs.vec.sub(topRight, point);
|
|
31873
32132
|
}
|
|
31874
32133
|
|
|
31875
|
-
// Returns the vector from the given point to the bottom-left corner of the
|
|
31876
|
-
|
|
31877
|
-
function minMove(_ref3) {
|
|
32134
|
+
// Returns the vector from the given point to the bottom-left corner of the graph when snapped to the grid
|
|
32135
|
+
function minMove(_ref6) {
|
|
31878
32136
|
let {
|
|
31879
32137
|
snapStep,
|
|
31880
32138
|
range,
|
|
31881
32139
|
point
|
|
31882
|
-
} =
|
|
32140
|
+
} = _ref6;
|
|
31883
32141
|
const bottomLeft = bound$1({
|
|
31884
32142
|
snapStep,
|
|
31885
32143
|
range,
|
|
@@ -31935,8 +32193,12 @@ const renderGraph = props => {
|
|
|
31935
32193
|
graphState: state,
|
|
31936
32194
|
dispatch: dispatch
|
|
31937
32195
|
});
|
|
31938
|
-
case "linear":
|
|
31939
32196
|
case "linear-system":
|
|
32197
|
+
return /*#__PURE__*/React__namespace.createElement(LinearSystemGraph, {
|
|
32198
|
+
graphState: state,
|
|
32199
|
+
dispatch: dispatch
|
|
32200
|
+
});
|
|
32201
|
+
case "linear":
|
|
31940
32202
|
return /*#__PURE__*/React__namespace.createElement(LinearGraph, {
|
|
31941
32203
|
graphState: state,
|
|
31942
32204
|
dispatch: dispatch
|
|
@@ -44184,7 +44446,7 @@ const init = function (options) {
|
|
|
44184
44446
|
|
|
44185
44447
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44186
44448
|
const libName = "@khanacademy/perseus";
|
|
44187
|
-
const libVersion = "23.
|
|
44449
|
+
const libVersion = "23.4.0";
|
|
44188
44450
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44189
44451
|
|
|
44190
44452
|
const apiVersion = {
|
|
@@ -47284,6 +47546,7 @@ exports.itemDataVersion = itemDataVersion;
|
|
|
47284
47546
|
exports.itemToTree = itemToTree;
|
|
47285
47547
|
exports.itemVersion = ItemVersion;
|
|
47286
47548
|
exports.libVersion = libVersion;
|
|
47549
|
+
exports.lockedEllipseFillStyles = lockedEllipseFillStyles;
|
|
47287
47550
|
exports.lockedFigureColors = lockedFigureColors;
|
|
47288
47551
|
exports.mediaQueries = mediaQueries;
|
|
47289
47552
|
exports.parsePerseusItem = parsePerseusItem;
|