@khanacademy/perseus 22.4.1 → 22.5.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 +35 -0
- package/dist/es/index.js +148 -70
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +35 -0
- package/dist/index.js +148 -67
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +3 -3
- package/dist/widgets/interactive-graphs/graphs/components/movable-line.d.ts +16 -0
- package/dist/widgets/interactive-graphs/graphs/use-transform.d.ts +2 -0
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +1 -0
- package/package.json +51 -51
- package/dist/widgets/interactive-graphs/graphs/components/segment.d.ts +0 -27
package/dist/index.css
CHANGED
|
@@ -4425,6 +4425,41 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4425
4425
|
visibility: visible;
|
|
4426
4426
|
}
|
|
4427
4427
|
|
|
4428
|
+
.MafsView .movable-circle {
|
|
4429
|
+
cursor: grab;
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
.MafsView .movable-circle.movable-circle--dragging {
|
|
4433
|
+
cursor: grabbing;
|
|
4434
|
+
outline: none;
|
|
4435
|
+
}
|
|
4436
|
+
|
|
4437
|
+
.MafsView .movable-circle .focus-ring {
|
|
4438
|
+
visibility: hidden; /* overridden when the circle is focused */
|
|
4439
|
+
stroke: var(--mafs-blue);
|
|
4440
|
+
stroke-width: 2px;
|
|
4441
|
+
fill: transparent;
|
|
4442
|
+
}
|
|
4443
|
+
|
|
4444
|
+
.MafsView .movable-circle:focus {
|
|
4445
|
+
outline: none;
|
|
4446
|
+
}
|
|
4447
|
+
|
|
4448
|
+
.MafsView .movable-circle:focus-visible .focus-ring {
|
|
4449
|
+
visibility: visible;
|
|
4450
|
+
}
|
|
4451
|
+
|
|
4452
|
+
.MafsView .movable-circle .movable-circle-handle {
|
|
4453
|
+
fill: var(--mafs-blue); /* WB fadedOffBlack64 */
|
|
4454
|
+
stroke: #fff;
|
|
4455
|
+
stroke-width: 2px;
|
|
4456
|
+
}
|
|
4457
|
+
|
|
4458
|
+
.MafsView .movable-circle .movable-circle-handle-dot {
|
|
4459
|
+
fill: #fff;
|
|
4460
|
+
r: 1.25px;
|
|
4461
|
+
}
|
|
4462
|
+
|
|
4428
4463
|
@font-face {
|
|
4429
4464
|
font-family: Mafs-MJXTEX;
|
|
4430
4465
|
src: url("https://cdn.kastatic.org/fonts/mathjax/MathJax_Main-Regular.woff")
|
package/dist/index.js
CHANGED
|
@@ -16669,7 +16669,7 @@ const Label$1 = GraphieClasses.createSimpleClass((graphie, props) => {
|
|
|
16669
16669
|
}
|
|
16670
16670
|
return elem;
|
|
16671
16671
|
});
|
|
16672
|
-
const Line$
|
|
16672
|
+
const Line$3 = GraphieClasses.createClass({
|
|
16673
16673
|
displayName: "Line",
|
|
16674
16674
|
movableProps: ["children"],
|
|
16675
16675
|
add: function (graphie) {
|
|
@@ -16788,7 +16788,7 @@ var Movables = {
|
|
|
16788
16788
|
Arc: Arc,
|
|
16789
16789
|
Circle: Circle,
|
|
16790
16790
|
Label: Label$1,
|
|
16791
|
-
Line: Line$
|
|
16791
|
+
Line: Line$3,
|
|
16792
16792
|
MovableLine: MovableLine$3,
|
|
16793
16793
|
MovablePoint: MovablePoint$3,
|
|
16794
16794
|
Parabola: Parabola,
|
|
@@ -23621,8 +23621,6 @@ const Choice = function (props) {
|
|
|
23621
23621
|
const showDimmed = !reviewMode && apiOptions.readOnly || crossedOut;
|
|
23622
23622
|
const letter = getChoiceLetter(pos, strings);
|
|
23623
23623
|
const a11yText = getA11yText(letter, checked, correct, crossedOut, showCorrectness, strings);
|
|
23624
|
-
const idFactory = wonderBlocksCore.useUniqueIdWithMock(`choice`);
|
|
23625
|
-
const choiceId = idFactory.get(letter);
|
|
23626
23624
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23627
23625
|
style: {
|
|
23628
23626
|
// @ts-expect-error - TS2322 - Type '{ dispay: string; flexDirection: "column"; color: string; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
@@ -23641,9 +23639,8 @@ const Choice = function (props) {
|
|
|
23641
23639
|
}
|
|
23642
23640
|
}, /*#__PURE__*/React__namespace.createElement("div", {
|
|
23643
23641
|
className: "perseus-sr-only"
|
|
23644
|
-
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
23642
|
+
}, /*#__PURE__*/React__namespace.createElement("label", null, a11yText, " \xA0 ", content, /*#__PURE__*/React__namespace.createElement("input", {
|
|
23645
23643
|
type: multipleSelect ? "checkbox" : "radio",
|
|
23646
|
-
id: choiceId,
|
|
23647
23644
|
checked: checked,
|
|
23648
23645
|
onClick: () => {
|
|
23649
23646
|
// If we're checking a crossed-out option, let's
|
|
@@ -23657,9 +23654,7 @@ const Choice = function (props) {
|
|
|
23657
23654
|
disabled: disabled || apiOptions.readOnly,
|
|
23658
23655
|
tabIndex: -1,
|
|
23659
23656
|
className: ClassNames.RADIO.OPTION_CONTENT
|
|
23660
|
-
}), /*#__PURE__*/React__namespace.createElement("
|
|
23661
|
-
htmlFor: choiceId
|
|
23662
|
-
}, a11yText, " \xA0 ", content)), /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
23657
|
+
}))), /*#__PURE__*/React__namespace.createElement(Clickable__default["default"], {
|
|
23663
23658
|
onClick: () => {
|
|
23664
23659
|
// If we're checking a crossed-out option, let's
|
|
23665
23660
|
// also uncross it.
|
|
@@ -27854,7 +27849,7 @@ var Image$1 = {
|
|
|
27854
27849
|
// @ts-expect-error - TS2339 - Property 'Label' does not exist on type 'typeof Graphie'.
|
|
27855
27850
|
const Label = Graphie.Label;
|
|
27856
27851
|
// @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
27857
|
-
const Line$
|
|
27852
|
+
const Line$2 = Graphie.Line;
|
|
27858
27853
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
27859
27854
|
const MovablePoint$1 = Graphie.MovablePoint;
|
|
27860
27855
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
@@ -28081,7 +28076,7 @@ class Interaction extends React__namespace.Component {
|
|
|
28081
28076
|
this._eval(element.options.endX),
|
|
28082
28077
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
28083
28078
|
this._eval(element.options.endY)];
|
|
28084
|
-
return /*#__PURE__*/React__namespace.createElement(Line$
|
|
28079
|
+
return /*#__PURE__*/React__namespace.createElement(Line$2, {
|
|
28085
28080
|
key: element.key,
|
|
28086
28081
|
start: start,
|
|
28087
28082
|
end: end,
|
|
@@ -28790,6 +28785,16 @@ function vectorsToPixels(vectors, graphState) {
|
|
|
28790
28785
|
const transformToPx = matrixBuilder().translate(...translation).scale(width / (xMax - xMin), -height / (yMax - yMin)).get();
|
|
28791
28786
|
return vectors.map(p => mafs.vec.transform(p, transformToPx));
|
|
28792
28787
|
}
|
|
28788
|
+
function dimensionsToPixels(dimens, graphState) {
|
|
28789
|
+
const {
|
|
28790
|
+
range,
|
|
28791
|
+
width,
|
|
28792
|
+
height
|
|
28793
|
+
} = graphState;
|
|
28794
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
28795
|
+
const transformToPx = matrixBuilder().scale(width / (xMax - xMin), height / (yMax - yMin)).get();
|
|
28796
|
+
return dimens.map(d => mafs.vec.transform(d, transformToPx));
|
|
28797
|
+
}
|
|
28793
28798
|
|
|
28794
28799
|
// When converting points, we translate so the pixel point ends up in the right location.
|
|
28795
28800
|
// This is because points are specific locations on graphs, unlike vectors.
|
|
@@ -28805,6 +28810,13 @@ const useTransformVectorsToPixels = function () {
|
|
|
28805
28810
|
}
|
|
28806
28811
|
return vectorsToPixels(vectors, graphState);
|
|
28807
28812
|
};
|
|
28813
|
+
const useTransformDimensionsToPixels = function () {
|
|
28814
|
+
const graphState = useGraphConfig();
|
|
28815
|
+
for (var _len2 = arguments.length, dimens = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
28816
|
+
dimens[_key2] = arguments[_key2];
|
|
28817
|
+
}
|
|
28818
|
+
return dimensionsToPixels(dimens, graphState);
|
|
28819
|
+
};
|
|
28808
28820
|
|
|
28809
28821
|
function AxisLabels() {
|
|
28810
28822
|
const {
|
|
@@ -29041,33 +29053,29 @@ function calculateAngleInDegrees(_ref) {
|
|
|
29041
29053
|
*/
|
|
29042
29054
|
const getIntersectionOfRayWithBox = (initialPoint, throughPoint, box) => {
|
|
29043
29055
|
const [[xMin, xMax], [yMin, yMax]] = box;
|
|
29044
|
-
const [aX, aY] =
|
|
29045
|
-
const [bX, bY] =
|
|
29056
|
+
const [aX, aY] = initialPoint;
|
|
29057
|
+
const [bX, bY] = throughPoint;
|
|
29046
29058
|
const yDiff = bY - aY;
|
|
29047
29059
|
const xDiff = bX - aX;
|
|
29048
29060
|
const slope = yDiff / xDiff;
|
|
29049
|
-
const
|
|
29050
|
-
const
|
|
29051
|
-
const
|
|
29052
|
-
const
|
|
29053
|
-
|
|
29054
|
-
// clock analogy to describe quadrants
|
|
29061
|
+
const inverseSlope = 1 / slope;
|
|
29062
|
+
const xExtreme = xDiff < 0 ? xMin : xMax;
|
|
29063
|
+
const yExtreme = yDiff < 0 ? yMin : yMax;
|
|
29064
|
+
const yAtXExtreme = aY + (xExtreme - aX) * slope;
|
|
29065
|
+
const xAtYExtreme = aX + (yExtreme - aY) * inverseSlope;
|
|
29055
29066
|
switch (true) {
|
|
29056
|
-
//
|
|
29057
|
-
case
|
|
29058
|
-
return
|
|
29059
|
-
|
|
29060
|
-
|
|
29061
|
-
|
|
29062
|
-
return
|
|
29063
|
-
// 9 o'clock to 11:59
|
|
29064
|
-
case yDiff >= 0 && xDiff < 0:
|
|
29065
|
-
return xAtYMax < xMin ? [xMin, yAtXMin] : [xAtYMax, yMax];
|
|
29066
|
-
// 6 o'clock to 8:59
|
|
29067
|
-
case yDiff < 0 && xDiff <= 0:
|
|
29068
|
-
return xAtYMin < xMin ? [xMin, yAtXMin] : [xAtYMin, yMin];
|
|
29067
|
+
// does the ray exit the graph bounding box via the left or right edge?
|
|
29068
|
+
case isBetween(yAtXExtreme, yMin, yMax):
|
|
29069
|
+
return [xExtreme, yAtXExtreme];
|
|
29070
|
+
|
|
29071
|
+
// does the ray exit the graph bounding box via the top or bottom edge?
|
|
29072
|
+
case isBetween(xAtYExtreme, xMin, xMax):
|
|
29073
|
+
return [xAtYExtreme, yExtreme];
|
|
29069
29074
|
default:
|
|
29070
|
-
|
|
29075
|
+
// This default case is only reachable if the input is invalid
|
|
29076
|
+
// (initialPoint is outside the graph bounds, or initialPoint and
|
|
29077
|
+
// throughPoint are the same).
|
|
29078
|
+
return [0, 0];
|
|
29071
29079
|
}
|
|
29072
29080
|
};
|
|
29073
29081
|
const getLines = points => {
|
|
@@ -29076,6 +29084,9 @@ const getLines = points => {
|
|
|
29076
29084
|
return [point, next];
|
|
29077
29085
|
});
|
|
29078
29086
|
};
|
|
29087
|
+
function isBetween(x, low, high) {
|
|
29088
|
+
return x >= low && x <= high;
|
|
29089
|
+
}
|
|
29079
29090
|
|
|
29080
29091
|
function SVGLine(props) {
|
|
29081
29092
|
const {
|
|
@@ -29128,15 +29139,15 @@ const LockedLine = props => {
|
|
|
29128
29139
|
lineStyle,
|
|
29129
29140
|
kind,
|
|
29130
29141
|
points,
|
|
29131
|
-
|
|
29132
|
-
|
|
29142
|
+
showPoint1,
|
|
29143
|
+
showPoint2,
|
|
29133
29144
|
range
|
|
29134
29145
|
} = props;
|
|
29135
29146
|
const [point1, point2] = points;
|
|
29136
29147
|
let line;
|
|
29137
29148
|
if (kind === "ray") {
|
|
29138
29149
|
// Rays extend to the end of the graph in one direction.
|
|
29139
|
-
const extendedPoint = getIntersectionOfRayWithBox(
|
|
29150
|
+
const extendedPoint = getIntersectionOfRayWithBox(point1.coord, point2.coord, range);
|
|
29140
29151
|
line = /*#__PURE__*/React__namespace.createElement(Vector, {
|
|
29141
29152
|
tail: point1.coord,
|
|
29142
29153
|
tip: extendedPoint,
|
|
@@ -29147,7 +29158,7 @@ const LockedLine = props => {
|
|
|
29147
29158
|
});
|
|
29148
29159
|
} else {
|
|
29149
29160
|
const LineType = kind === "segment" ? mafs.Line.Segment : mafs.Line.ThroughPoints;
|
|
29150
|
-
let arrowTip = kind === "segment" ? point2.coord : getIntersectionOfRayWithBox(
|
|
29161
|
+
let arrowTip = kind === "segment" ? point2.coord : getIntersectionOfRayWithBox(point1.coord, point2.coord, range);
|
|
29151
29162
|
const direction = mafs.vec.sub(point2.coord, point1.coord);
|
|
29152
29163
|
let angle = calculateAngleInDegrees(direction);
|
|
29153
29164
|
const startArrowHead = kind !== "segment" && /*#__PURE__*/React__namespace.createElement(Arrowhead, {
|
|
@@ -29155,7 +29166,7 @@ const LockedLine = props => {
|
|
|
29155
29166
|
tip: arrowTip,
|
|
29156
29167
|
color: lockedFigureColors[color]
|
|
29157
29168
|
});
|
|
29158
|
-
arrowTip = kind === "segment" ? point1.coord : getIntersectionOfRayWithBox(
|
|
29169
|
+
arrowTip = kind === "segment" ? point1.coord : getIntersectionOfRayWithBox(point2.coord, point1.coord, range);
|
|
29159
29170
|
angle = angle > 180 ? angle - 180 : angle + 180;
|
|
29160
29171
|
const endArrowHead = kind !== "segment" && /*#__PURE__*/React__namespace.createElement(Arrowhead, {
|
|
29161
29172
|
angle: angle,
|
|
@@ -29171,7 +29182,7 @@ const LockedLine = props => {
|
|
|
29171
29182
|
}
|
|
29172
29183
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
29173
29184
|
className: kind === "ray" ? "locked-ray" : "locked-line"
|
|
29174
|
-
}, line,
|
|
29185
|
+
}, line, showPoint1 && /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
29175
29186
|
x: point1.coord[0],
|
|
29176
29187
|
y: point1.coord[1],
|
|
29177
29188
|
svgCircleProps: {
|
|
@@ -29181,7 +29192,7 @@ const LockedLine = props => {
|
|
|
29181
29192
|
strokeWidth: wonderBlocksTokens.spacing.xxxxSmall_2
|
|
29182
29193
|
}
|
|
29183
29194
|
}
|
|
29184
|
-
}),
|
|
29195
|
+
}), showPoint2 && /*#__PURE__*/React__namespace.createElement(mafs.Point, {
|
|
29185
29196
|
x: point2.coord[0],
|
|
29186
29197
|
y: point2.coord[1],
|
|
29187
29198
|
svgCircleProps: {
|
|
@@ -29443,9 +29454,10 @@ function tabIndex(config) {
|
|
|
29443
29454
|
return undefined;
|
|
29444
29455
|
}
|
|
29445
29456
|
|
|
29446
|
-
const
|
|
29457
|
+
const MovableLine = props => {
|
|
29447
29458
|
const {
|
|
29448
|
-
onMoveLine,
|
|
29459
|
+
onMoveLine = () => {},
|
|
29460
|
+
onMovePoint = () => {},
|
|
29449
29461
|
color,
|
|
29450
29462
|
points: [start, end],
|
|
29451
29463
|
extend
|
|
@@ -29465,18 +29477,19 @@ const Segment = props => {
|
|
|
29465
29477
|
const {
|
|
29466
29478
|
visiblePoint: visiblePoint1,
|
|
29467
29479
|
focusableHandle: focusableHandle1
|
|
29468
|
-
} = useControlPoint(start, color, p =>
|
|
29480
|
+
} = useControlPoint(start, color, p => onMovePoint(0, p));
|
|
29469
29481
|
const {
|
|
29470
29482
|
visiblePoint: visiblePoint2,
|
|
29471
29483
|
focusableHandle: focusableHandle2
|
|
29472
|
-
} = useControlPoint(end, color, p =>
|
|
29473
|
-
|
|
29484
|
+
} = useControlPoint(end, color, p => onMovePoint(1, p));
|
|
29485
|
+
const line = /*#__PURE__*/React__namespace.createElement(Line$1, {
|
|
29474
29486
|
start: start,
|
|
29475
29487
|
end: end,
|
|
29476
29488
|
stroke: color,
|
|
29477
29489
|
extend: extend,
|
|
29478
29490
|
onMove: onMoveLine
|
|
29479
|
-
})
|
|
29491
|
+
});
|
|
29492
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, focusableHandle1, line, focusableHandle2, visiblePoint1, visiblePoint2);
|
|
29480
29493
|
};
|
|
29481
29494
|
function useControlPoint(point, color, onMovePoint) {
|
|
29482
29495
|
const {
|
|
@@ -29522,7 +29535,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
29522
29535
|
};
|
|
29523
29536
|
}
|
|
29524
29537
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
29525
|
-
const
|
|
29538
|
+
const Line$1 = props => {
|
|
29526
29539
|
const {
|
|
29527
29540
|
start,
|
|
29528
29541
|
end,
|
|
@@ -29530,29 +29543,29 @@ const MovableLine = props => {
|
|
|
29530
29543
|
extend,
|
|
29531
29544
|
stroke = defaultStroke
|
|
29532
29545
|
} = props;
|
|
29533
|
-
const midpoint = mafs.vec.midpoint(start, end);
|
|
29534
29546
|
const [startPtPx, endPtPx] = useTransformVectorsToPixels(start, end);
|
|
29535
29547
|
const {
|
|
29536
29548
|
range,
|
|
29537
|
-
graphDimensionsInPixels
|
|
29549
|
+
graphDimensionsInPixels,
|
|
29550
|
+
snapStep
|
|
29538
29551
|
} = useGraphConfig();
|
|
29539
29552
|
let startExtend = undefined;
|
|
29540
29553
|
let endExtend = undefined;
|
|
29541
29554
|
if (extend) {
|
|
29542
29555
|
const trimmedRange = trimRange(range, graphDimensionsInPixels);
|
|
29543
|
-
startExtend = extend.start ? getIntersectionOfRayWithBox(
|
|
29544
|
-
endExtend = extend.end ? getIntersectionOfRayWithBox(
|
|
29556
|
+
startExtend = extend.start ? getIntersectionOfRayWithBox(end, start, trimmedRange) : undefined;
|
|
29557
|
+
endExtend = extend.end ? getIntersectionOfRayWithBox(start, end, trimmedRange) : undefined;
|
|
29545
29558
|
}
|
|
29546
29559
|
const line = React.useRef(null);
|
|
29547
29560
|
const {
|
|
29548
29561
|
dragging
|
|
29549
29562
|
} = mafs.useMovable({
|
|
29550
29563
|
gestureTarget: line,
|
|
29551
|
-
point:
|
|
29564
|
+
point: start,
|
|
29552
29565
|
onMove: newPoint => {
|
|
29553
|
-
onMove(mafs.vec.sub(newPoint,
|
|
29566
|
+
onMove(mafs.vec.sub(newPoint, start));
|
|
29554
29567
|
},
|
|
29555
|
-
constrain: p => p
|
|
29568
|
+
constrain: p => snap(snapStep, p)
|
|
29556
29569
|
});
|
|
29557
29570
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("g", {
|
|
29558
29571
|
ref: line,
|
|
@@ -29625,7 +29638,7 @@ const SegmentGraph = props => {
|
|
|
29625
29638
|
const {
|
|
29626
29639
|
coords: segments
|
|
29627
29640
|
} = props.graphState;
|
|
29628
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, segments?.map((segment, i) => /*#__PURE__*/React__namespace.createElement(
|
|
29641
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, segments?.map((segment, i) => /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29629
29642
|
key: i,
|
|
29630
29643
|
points: segment,
|
|
29631
29644
|
onMoveLine: delta => {
|
|
@@ -29645,7 +29658,7 @@ const LinearGraph = props => {
|
|
|
29645
29658
|
coords: lines
|
|
29646
29659
|
} = props.graphState;
|
|
29647
29660
|
const colors = ["var(--movable-line-stroke-color)", "var(--mafs-violet)"];
|
|
29648
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lines?.map((line, i) => /*#__PURE__*/React__namespace.createElement(
|
|
29661
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lines?.map((line, i) => /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29649
29662
|
key: i,
|
|
29650
29663
|
points: line,
|
|
29651
29664
|
onMoveLine: delta => {
|
|
@@ -29669,7 +29682,7 @@ const RayGraph = props => {
|
|
|
29669
29682
|
} = props.graphState;
|
|
29670
29683
|
const handleMoveLine = delta => dispatch(moveLine(0, delta));
|
|
29671
29684
|
const handleMovePoint = (pointIndex, newPoint) => dispatch(moveControlPoint(pointIndex, newPoint, 0));
|
|
29672
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
29685
|
+
return /*#__PURE__*/React__namespace.createElement(MovableLine
|
|
29673
29686
|
// a ray only has one line
|
|
29674
29687
|
, {
|
|
29675
29688
|
points: lines[0],
|
|
@@ -29827,7 +29840,7 @@ const isRightAngle = angle => Math.abs(angle - Math.PI / 2) < 0.01;
|
|
|
29827
29840
|
*/
|
|
29828
29841
|
const shouldDrawArcOutside = (midpoint, vertex, range, polygonLines) => {
|
|
29829
29842
|
// Create a ray from the midpoint (inside angle) to the edge of the range
|
|
29830
|
-
const rangeIntersectionPoint = getIntersectionOfRayWithBox(
|
|
29843
|
+
const rangeIntersectionPoint = getIntersectionOfRayWithBox(midpoint, vertex, range);
|
|
29831
29844
|
let lineIntersectionCount = 0;
|
|
29832
29845
|
polygonLines.forEach(line => linesIntersect([vertex, rangeIntersectionPoint], line) && lineIntersectionCount++);
|
|
29833
29846
|
|
|
@@ -30229,16 +30242,10 @@ function CircleGraph(props) {
|
|
|
30229
30242
|
center,
|
|
30230
30243
|
radiusPoint
|
|
30231
30244
|
} = graphState;
|
|
30232
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(
|
|
30245
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(MovableCircle, {
|
|
30233
30246
|
center: center,
|
|
30234
30247
|
radius: getRadius(graphState),
|
|
30235
|
-
|
|
30236
|
-
color: wonderBlocksTokens.color.blue
|
|
30237
|
-
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
30238
|
-
point: center,
|
|
30239
|
-
onMove: newCenter => {
|
|
30240
|
-
dispatch(moveCenter(newCenter));
|
|
30241
|
-
}
|
|
30248
|
+
onMove: newCenter => dispatch(moveCenter(newCenter))
|
|
30242
30249
|
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
30243
30250
|
point: radiusPoint,
|
|
30244
30251
|
onMove: newRadiusPoint => {
|
|
@@ -30246,6 +30253,80 @@ function CircleGraph(props) {
|
|
|
30246
30253
|
}
|
|
30247
30254
|
}));
|
|
30248
30255
|
}
|
|
30256
|
+
function MovableCircle(props) {
|
|
30257
|
+
const {
|
|
30258
|
+
center,
|
|
30259
|
+
radius,
|
|
30260
|
+
onMove
|
|
30261
|
+
} = props;
|
|
30262
|
+
const {
|
|
30263
|
+
snapStep
|
|
30264
|
+
} = useGraphConfig();
|
|
30265
|
+
const draggableRef = React.useRef(null);
|
|
30266
|
+
const {
|
|
30267
|
+
dragging
|
|
30268
|
+
} = mafs.useMovable({
|
|
30269
|
+
gestureTarget: draggableRef,
|
|
30270
|
+
point: center,
|
|
30271
|
+
onMove,
|
|
30272
|
+
constrain: p => snap(snapStep, p)
|
|
30273
|
+
});
|
|
30274
|
+
const [centerPx] = useTransformVectorsToPixels(center);
|
|
30275
|
+
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
30276
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
30277
|
+
ref: draggableRef,
|
|
30278
|
+
tabIndex: 0,
|
|
30279
|
+
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
30280
|
+
}, /*#__PURE__*/React__namespace.createElement("ellipse", {
|
|
30281
|
+
className: "focus-ring",
|
|
30282
|
+
cx: centerPx[0],
|
|
30283
|
+
cy: centerPx[1],
|
|
30284
|
+
rx: radiiPx[0] + 3,
|
|
30285
|
+
ry: radiiPx[1] + 3
|
|
30286
|
+
}), /*#__PURE__*/React__namespace.createElement(mafs.Circle, {
|
|
30287
|
+
center: center,
|
|
30288
|
+
radius: radius,
|
|
30289
|
+
fillOpacity: 0,
|
|
30290
|
+
color: wonderBlocksTokens.color.blue
|
|
30291
|
+
}), /*#__PURE__*/React__namespace.createElement(DragHandle, {
|
|
30292
|
+
center: center
|
|
30293
|
+
}));
|
|
30294
|
+
}
|
|
30295
|
+
const dragHandleDimensions = [24, 14];
|
|
30296
|
+
const dragHandleDotPositions = crossProduct([-4.4, 0, 4.4], [-2.1, 2.1]);
|
|
30297
|
+
function DragHandle(props) {
|
|
30298
|
+
const {
|
|
30299
|
+
center
|
|
30300
|
+
} = props;
|
|
30301
|
+
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
30302
|
+
const [centerPx] = useTransformVectorsToPixels(center);
|
|
30303
|
+
const topLeft = mafs.vec.sub(centerPx, mafs.vec.scale(dragHandleDimensions, 0.5));
|
|
30304
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("rect", {
|
|
30305
|
+
className: "movable-circle-handle",
|
|
30306
|
+
x: topLeft[0],
|
|
30307
|
+
y: topLeft[1],
|
|
30308
|
+
width: dragHandleDimensions[0],
|
|
30309
|
+
height: dragHandleDimensions[1],
|
|
30310
|
+
rx: cornerRadius,
|
|
30311
|
+
ry: cornerRadius
|
|
30312
|
+
}), dragHandleDotPositions.map(offsetPx => {
|
|
30313
|
+
const [xPx, yPx] = mafs.vec.add(offsetPx, centerPx);
|
|
30314
|
+
return /*#__PURE__*/React__namespace.createElement("circle", {
|
|
30315
|
+
className: "movable-circle-handle-dot",
|
|
30316
|
+
cx: xPx,
|
|
30317
|
+
cy: yPx
|
|
30318
|
+
});
|
|
30319
|
+
}));
|
|
30320
|
+
}
|
|
30321
|
+
function crossProduct(as, bs) {
|
|
30322
|
+
const result = [];
|
|
30323
|
+
for (const a of as) {
|
|
30324
|
+
for (const b of bs) {
|
|
30325
|
+
result.push([a, b]);
|
|
30326
|
+
}
|
|
30327
|
+
}
|
|
30328
|
+
return result;
|
|
30329
|
+
}
|
|
30249
30330
|
|
|
30250
30331
|
function PointGraph(props) {
|
|
30251
30332
|
const {
|
|
@@ -43623,7 +43704,7 @@ const init = function (options) {
|
|
|
43623
43704
|
|
|
43624
43705
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43625
43706
|
const libName = "@khanacademy/perseus";
|
|
43626
|
-
const libVersion = "22.
|
|
43707
|
+
const libVersion = "22.5.0";
|
|
43627
43708
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43628
43709
|
|
|
43629
43710
|
const apiVersion = {
|