@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/es/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/es/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as KAS from '@khanacademy/kas';
|
|
|
2
2
|
import { MathInputI18nContext, CursorContext, getKeyTranslator, createMathField, getCursorContext, DesktopKeypad, convertDotToTimesByLocale, mathQuillInstance, KeypadInput, KeypadType, KeyArray, keypadElementPropType } from '@khanacademy/math-input';
|
|
3
3
|
import * as PerseusLinter from '@khanacademy/perseus-linter';
|
|
4
4
|
import { linterContextDefault, Rule, linterContextProps } from '@khanacademy/perseus-linter';
|
|
5
|
-
import { View, RenderStateRoot,
|
|
5
|
+
import { View, RenderStateRoot, UniqueIDProvider, useUniqueIdWithMock, Text as Text$2 } from '@khanacademy/wonder-blocks-core';
|
|
6
6
|
import Tooltip$1 from '@khanacademy/wonder-blocks-tooltip';
|
|
7
7
|
import classNames from 'classnames';
|
|
8
8
|
import * as React from 'react';
|
|
@@ -29,7 +29,7 @@ import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-block
|
|
|
29
29
|
import caretDown from '@phosphor-icons/core/regular/caret-down.svg';
|
|
30
30
|
import caretUp from '@phosphor-icons/core/regular/caret-up.svg';
|
|
31
31
|
import debounce$2 from 'lodash.debounce';
|
|
32
|
-
import { vec, Line as Line$
|
|
32
|
+
import { vec, Line as Line$4, Point as Point$2, useMovable, Text as Text$1, Polygon, Circle as Circle$1, Coordinates, Mafs } from 'mafs';
|
|
33
33
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
34
34
|
import { Body, LabelSmall, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
35
35
|
import questionIcon from '@phosphor-icons/core/regular/question.svg';
|
|
@@ -16523,7 +16523,7 @@ const Label$1 = GraphieClasses.createSimpleClass((graphie, props) => {
|
|
|
16523
16523
|
}
|
|
16524
16524
|
return elem;
|
|
16525
16525
|
});
|
|
16526
|
-
const Line$
|
|
16526
|
+
const Line$3 = GraphieClasses.createClass({
|
|
16527
16527
|
displayName: "Line",
|
|
16528
16528
|
movableProps: ["children"],
|
|
16529
16529
|
add: function (graphie) {
|
|
@@ -16642,7 +16642,7 @@ var Movables = {
|
|
|
16642
16642
|
Arc: Arc,
|
|
16643
16643
|
Circle: Circle,
|
|
16644
16644
|
Label: Label$1,
|
|
16645
|
-
Line: Line$
|
|
16645
|
+
Line: Line$3,
|
|
16646
16646
|
MovableLine: MovableLine$3,
|
|
16647
16647
|
MovablePoint: MovablePoint$3,
|
|
16648
16648
|
Parabola: Parabola,
|
|
@@ -23407,8 +23407,6 @@ const Choice = function Choice(props) {
|
|
|
23407
23407
|
const showDimmed = !reviewMode && apiOptions.readOnly || crossedOut;
|
|
23408
23408
|
const letter = getChoiceLetter(pos, strings);
|
|
23409
23409
|
const a11yText = getA11yText(letter, checked, correct, crossedOut, showCorrectness, strings);
|
|
23410
|
-
const idFactory = useUniqueIdWithMock(`choice`);
|
|
23411
|
-
const choiceId = idFactory.get(letter);
|
|
23412
23410
|
return /*#__PURE__*/React.createElement("div", {
|
|
23413
23411
|
style: {
|
|
23414
23412
|
// @ts-expect-error - TS2322 - Type '{ dispay: string; flexDirection: "column"; color: string; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
@@ -23427,9 +23425,8 @@ const Choice = function Choice(props) {
|
|
|
23427
23425
|
}
|
|
23428
23426
|
}, /*#__PURE__*/React.createElement("div", {
|
|
23429
23427
|
className: "perseus-sr-only"
|
|
23430
|
-
}, /*#__PURE__*/React.createElement("input", {
|
|
23428
|
+
}, /*#__PURE__*/React.createElement("label", null, a11yText, " \xA0 ", content, /*#__PURE__*/React.createElement("input", {
|
|
23431
23429
|
type: multipleSelect ? "checkbox" : "radio",
|
|
23432
|
-
id: choiceId,
|
|
23433
23430
|
checked: checked,
|
|
23434
23431
|
onClick: () => {
|
|
23435
23432
|
// If we're checking a crossed-out option, let's
|
|
@@ -23443,9 +23440,7 @@ const Choice = function Choice(props) {
|
|
|
23443
23440
|
disabled: disabled || apiOptions.readOnly,
|
|
23444
23441
|
tabIndex: -1,
|
|
23445
23442
|
className: ClassNames.RADIO.OPTION_CONTENT
|
|
23446
|
-
}), /*#__PURE__*/React.createElement(
|
|
23447
|
-
htmlFor: choiceId
|
|
23448
|
-
}, a11yText, " \xA0 ", content)), /*#__PURE__*/React.createElement(Clickable, {
|
|
23443
|
+
}))), /*#__PURE__*/React.createElement(Clickable, {
|
|
23449
23444
|
onClick: () => {
|
|
23450
23445
|
// If we're checking a crossed-out option, let's
|
|
23451
23446
|
// also uncross it.
|
|
@@ -27575,7 +27570,7 @@ var Image$1 = {
|
|
|
27575
27570
|
// @ts-expect-error - TS2339 - Property 'Label' does not exist on type 'typeof Graphie'.
|
|
27576
27571
|
const Label = Graphie.Label;
|
|
27577
27572
|
// @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
27578
|
-
const Line$
|
|
27573
|
+
const Line$2 = Graphie.Line;
|
|
27579
27574
|
// @ts-expect-error - TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'.
|
|
27580
27575
|
const MovablePoint$1 = Graphie.MovablePoint;
|
|
27581
27576
|
// @ts-expect-error - TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
@@ -27797,7 +27792,7 @@ class Interaction extends React.Component {
|
|
|
27797
27792
|
this._eval(element.options.endX),
|
|
27798
27793
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
27799
27794
|
this._eval(element.options.endY)];
|
|
27800
|
-
return /*#__PURE__*/React.createElement(Line$
|
|
27795
|
+
return /*#__PURE__*/React.createElement(Line$2, {
|
|
27801
27796
|
key: element.key,
|
|
27802
27797
|
start: start,
|
|
27803
27798
|
end: end,
|
|
@@ -28505,6 +28500,16 @@ function vectorsToPixels(vectors, graphState, translation = [0, 0]) {
|
|
|
28505
28500
|
const transformToPx = matrixBuilder().translate(...translation).scale(width / (xMax - xMin), -height / (yMax - yMin)).get();
|
|
28506
28501
|
return vectors.map(p => vec.transform(p, transformToPx));
|
|
28507
28502
|
}
|
|
28503
|
+
function dimensionsToPixels(dimens, graphState) {
|
|
28504
|
+
const {
|
|
28505
|
+
range,
|
|
28506
|
+
width,
|
|
28507
|
+
height
|
|
28508
|
+
} = graphState;
|
|
28509
|
+
const [[xMin, xMax], [yMin, yMax]] = range;
|
|
28510
|
+
const transformToPx = matrixBuilder().scale(width / (xMax - xMin), height / (yMax - yMin)).get();
|
|
28511
|
+
return dimens.map(d => vec.transform(d, transformToPx));
|
|
28512
|
+
}
|
|
28508
28513
|
|
|
28509
28514
|
// When converting points, we translate so the pixel point ends up in the right location.
|
|
28510
28515
|
// This is because points are specific locations on graphs, unlike vectors.
|
|
@@ -28517,6 +28522,10 @@ const useTransformVectorsToPixels = (...vectors) => {
|
|
|
28517
28522
|
const graphState = useGraphConfig();
|
|
28518
28523
|
return vectorsToPixels(vectors, graphState);
|
|
28519
28524
|
};
|
|
28525
|
+
const useTransformDimensionsToPixels = (...dimens) => {
|
|
28526
|
+
const graphState = useGraphConfig();
|
|
28527
|
+
return dimensionsToPixels(dimens, graphState);
|
|
28528
|
+
};
|
|
28520
28529
|
|
|
28521
28530
|
function AxisLabels() {
|
|
28522
28531
|
const {
|
|
@@ -28754,33 +28763,29 @@ function calculateAngleInDegrees([x, y]) {
|
|
|
28754
28763
|
*/
|
|
28755
28764
|
const getIntersectionOfRayWithBox = (initialPoint, throughPoint, box) => {
|
|
28756
28765
|
const [[xMin, xMax], [yMin, yMax]] = box;
|
|
28757
|
-
const [aX, aY] =
|
|
28758
|
-
const [bX, bY] =
|
|
28766
|
+
const [aX, aY] = initialPoint;
|
|
28767
|
+
const [bX, bY] = throughPoint;
|
|
28759
28768
|
const yDiff = bY - aY;
|
|
28760
28769
|
const xDiff = bX - aX;
|
|
28761
28770
|
const slope = yDiff / xDiff;
|
|
28762
|
-
const
|
|
28763
|
-
const
|
|
28764
|
-
const
|
|
28765
|
-
const
|
|
28766
|
-
|
|
28767
|
-
// clock analogy to describe quadrants
|
|
28771
|
+
const inverseSlope = 1 / slope;
|
|
28772
|
+
const xExtreme = xDiff < 0 ? xMin : xMax;
|
|
28773
|
+
const yExtreme = yDiff < 0 ? yMin : yMax;
|
|
28774
|
+
const yAtXExtreme = aY + (xExtreme - aX) * slope;
|
|
28775
|
+
const xAtYExtreme = aX + (yExtreme - aY) * inverseSlope;
|
|
28768
28776
|
switch (true) {
|
|
28769
|
-
//
|
|
28770
|
-
case
|
|
28771
|
-
return
|
|
28772
|
-
|
|
28773
|
-
|
|
28774
|
-
|
|
28775
|
-
return
|
|
28776
|
-
// 9 o'clock to 11:59
|
|
28777
|
-
case yDiff >= 0 && xDiff < 0:
|
|
28778
|
-
return xAtYMax < xMin ? [xMin, yAtXMin] : [xAtYMax, yMax];
|
|
28779
|
-
// 6 o'clock to 8:59
|
|
28780
|
-
case yDiff < 0 && xDiff <= 0:
|
|
28781
|
-
return xAtYMin < xMin ? [xMin, yAtXMin] : [xAtYMin, yMin];
|
|
28777
|
+
// does the ray exit the graph bounding box via the left or right edge?
|
|
28778
|
+
case isBetween(yAtXExtreme, yMin, yMax):
|
|
28779
|
+
return [xExtreme, yAtXExtreme];
|
|
28780
|
+
|
|
28781
|
+
// does the ray exit the graph bounding box via the top or bottom edge?
|
|
28782
|
+
case isBetween(xAtYExtreme, xMin, xMax):
|
|
28783
|
+
return [xAtYExtreme, yExtreme];
|
|
28782
28784
|
default:
|
|
28783
|
-
|
|
28785
|
+
// This default case is only reachable if the input is invalid
|
|
28786
|
+
// (initialPoint is outside the graph bounds, or initialPoint and
|
|
28787
|
+
// throughPoint are the same).
|
|
28788
|
+
return [0, 0];
|
|
28784
28789
|
}
|
|
28785
28790
|
};
|
|
28786
28791
|
const getLines = points => {
|
|
@@ -28789,6 +28794,9 @@ const getLines = points => {
|
|
|
28789
28794
|
return [point, next];
|
|
28790
28795
|
});
|
|
28791
28796
|
};
|
|
28797
|
+
function isBetween(x, low, high) {
|
|
28798
|
+
return x >= low && x <= high;
|
|
28799
|
+
}
|
|
28792
28800
|
|
|
28793
28801
|
function SVGLine(props) {
|
|
28794
28802
|
const {
|
|
@@ -28841,15 +28849,15 @@ const LockedLine = props => {
|
|
|
28841
28849
|
lineStyle,
|
|
28842
28850
|
kind,
|
|
28843
28851
|
points,
|
|
28844
|
-
|
|
28845
|
-
|
|
28852
|
+
showPoint1,
|
|
28853
|
+
showPoint2,
|
|
28846
28854
|
range
|
|
28847
28855
|
} = props;
|
|
28848
28856
|
const [point1, point2] = points;
|
|
28849
28857
|
let line;
|
|
28850
28858
|
if (kind === "ray") {
|
|
28851
28859
|
// Rays extend to the end of the graph in one direction.
|
|
28852
|
-
const extendedPoint = getIntersectionOfRayWithBox(
|
|
28860
|
+
const extendedPoint = getIntersectionOfRayWithBox(point1.coord, point2.coord, range);
|
|
28853
28861
|
line = /*#__PURE__*/React.createElement(Vector, {
|
|
28854
28862
|
tail: point1.coord,
|
|
28855
28863
|
tip: extendedPoint,
|
|
@@ -28859,8 +28867,8 @@ const LockedLine = props => {
|
|
|
28859
28867
|
}
|
|
28860
28868
|
});
|
|
28861
28869
|
} else {
|
|
28862
|
-
const LineType = kind === "segment" ? Line$
|
|
28863
|
-
let arrowTip = kind === "segment" ? point2.coord : getIntersectionOfRayWithBox(
|
|
28870
|
+
const LineType = kind === "segment" ? Line$4.Segment : Line$4.ThroughPoints;
|
|
28871
|
+
let arrowTip = kind === "segment" ? point2.coord : getIntersectionOfRayWithBox(point1.coord, point2.coord, range);
|
|
28864
28872
|
const direction = vec.sub(point2.coord, point1.coord);
|
|
28865
28873
|
let angle = calculateAngleInDegrees(direction);
|
|
28866
28874
|
const startArrowHead = kind !== "segment" && /*#__PURE__*/React.createElement(Arrowhead, {
|
|
@@ -28868,7 +28876,7 @@ const LockedLine = props => {
|
|
|
28868
28876
|
tip: arrowTip,
|
|
28869
28877
|
color: lockedFigureColors[color$1]
|
|
28870
28878
|
});
|
|
28871
|
-
arrowTip = kind === "segment" ? point1.coord : getIntersectionOfRayWithBox(
|
|
28879
|
+
arrowTip = kind === "segment" ? point1.coord : getIntersectionOfRayWithBox(point2.coord, point1.coord, range);
|
|
28872
28880
|
angle = angle > 180 ? angle - 180 : angle + 180;
|
|
28873
28881
|
const endArrowHead = kind !== "segment" && /*#__PURE__*/React.createElement(Arrowhead, {
|
|
28874
28882
|
angle: angle,
|
|
@@ -28884,7 +28892,7 @@ const LockedLine = props => {
|
|
|
28884
28892
|
}
|
|
28885
28893
|
return /*#__PURE__*/React.createElement("g", {
|
|
28886
28894
|
className: kind === "ray" ? "locked-ray" : "locked-line"
|
|
28887
|
-
}, line,
|
|
28895
|
+
}, line, showPoint1 && /*#__PURE__*/React.createElement(Point$2, {
|
|
28888
28896
|
x: point1.coord[0],
|
|
28889
28897
|
y: point1.coord[1],
|
|
28890
28898
|
svgCircleProps: {
|
|
@@ -28894,7 +28902,7 @@ const LockedLine = props => {
|
|
|
28894
28902
|
strokeWidth: spacing.xxxxSmall_2
|
|
28895
28903
|
}
|
|
28896
28904
|
}
|
|
28897
|
-
}),
|
|
28905
|
+
}), showPoint2 && /*#__PURE__*/React.createElement(Point$2, {
|
|
28898
28906
|
x: point2.coord[0],
|
|
28899
28907
|
y: point2.coord[1],
|
|
28900
28908
|
svgCircleProps: {
|
|
@@ -29154,9 +29162,10 @@ function tabIndex(config) {
|
|
|
29154
29162
|
return undefined;
|
|
29155
29163
|
}
|
|
29156
29164
|
|
|
29157
|
-
const
|
|
29165
|
+
const MovableLine = props => {
|
|
29158
29166
|
const {
|
|
29159
|
-
onMoveLine,
|
|
29167
|
+
onMoveLine = () => {},
|
|
29168
|
+
onMovePoint = () => {},
|
|
29160
29169
|
color,
|
|
29161
29170
|
points: [start, end],
|
|
29162
29171
|
extend
|
|
@@ -29176,18 +29185,19 @@ const Segment = props => {
|
|
|
29176
29185
|
const {
|
|
29177
29186
|
visiblePoint: visiblePoint1,
|
|
29178
29187
|
focusableHandle: focusableHandle1
|
|
29179
|
-
} = useControlPoint(start, color, p =>
|
|
29188
|
+
} = useControlPoint(start, color, p => onMovePoint(0, p));
|
|
29180
29189
|
const {
|
|
29181
29190
|
visiblePoint: visiblePoint2,
|
|
29182
29191
|
focusableHandle: focusableHandle2
|
|
29183
|
-
} = useControlPoint(end, color, p =>
|
|
29184
|
-
|
|
29192
|
+
} = useControlPoint(end, color, p => onMovePoint(1, p));
|
|
29193
|
+
const line = /*#__PURE__*/React.createElement(Line$1, {
|
|
29185
29194
|
start: start,
|
|
29186
29195
|
end: end,
|
|
29187
29196
|
stroke: color,
|
|
29188
29197
|
extend: extend,
|
|
29189
29198
|
onMove: onMoveLine
|
|
29190
|
-
})
|
|
29199
|
+
});
|
|
29200
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, focusableHandle1, line, focusableHandle2, visiblePoint1, visiblePoint2);
|
|
29191
29201
|
};
|
|
29192
29202
|
function useControlPoint(point, color, onMovePoint) {
|
|
29193
29203
|
const {
|
|
@@ -29233,7 +29243,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
29233
29243
|
};
|
|
29234
29244
|
}
|
|
29235
29245
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
29236
|
-
const
|
|
29246
|
+
const Line$1 = props => {
|
|
29237
29247
|
const {
|
|
29238
29248
|
start,
|
|
29239
29249
|
end,
|
|
@@ -29241,29 +29251,29 @@ const MovableLine = props => {
|
|
|
29241
29251
|
extend,
|
|
29242
29252
|
stroke = defaultStroke
|
|
29243
29253
|
} = props;
|
|
29244
|
-
const midpoint = vec.midpoint(start, end);
|
|
29245
29254
|
const [startPtPx, endPtPx] = useTransformVectorsToPixels(start, end);
|
|
29246
29255
|
const {
|
|
29247
29256
|
range,
|
|
29248
|
-
graphDimensionsInPixels
|
|
29257
|
+
graphDimensionsInPixels,
|
|
29258
|
+
snapStep
|
|
29249
29259
|
} = useGraphConfig();
|
|
29250
29260
|
let startExtend = undefined;
|
|
29251
29261
|
let endExtend = undefined;
|
|
29252
29262
|
if (extend) {
|
|
29253
29263
|
const trimmedRange = trimRange(range, graphDimensionsInPixels);
|
|
29254
|
-
startExtend = extend.start ? getIntersectionOfRayWithBox(
|
|
29255
|
-
endExtend = extend.end ? getIntersectionOfRayWithBox(
|
|
29264
|
+
startExtend = extend.start ? getIntersectionOfRayWithBox(end, start, trimmedRange) : undefined;
|
|
29265
|
+
endExtend = extend.end ? getIntersectionOfRayWithBox(start, end, trimmedRange) : undefined;
|
|
29256
29266
|
}
|
|
29257
29267
|
const line = useRef(null);
|
|
29258
29268
|
const {
|
|
29259
29269
|
dragging
|
|
29260
29270
|
} = useMovable({
|
|
29261
29271
|
gestureTarget: line,
|
|
29262
|
-
point:
|
|
29272
|
+
point: start,
|
|
29263
29273
|
onMove: newPoint => {
|
|
29264
|
-
onMove(vec.sub(newPoint,
|
|
29274
|
+
onMove(vec.sub(newPoint, start));
|
|
29265
29275
|
},
|
|
29266
|
-
constrain: p => p
|
|
29276
|
+
constrain: p => snap(snapStep, p)
|
|
29267
29277
|
});
|
|
29268
29278
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("g", {
|
|
29269
29279
|
ref: line,
|
|
@@ -29336,7 +29346,7 @@ const SegmentGraph = props => {
|
|
|
29336
29346
|
const {
|
|
29337
29347
|
coords: segments
|
|
29338
29348
|
} = props.graphState;
|
|
29339
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, segments == null ? void 0 : segments.map((segment, i) => /*#__PURE__*/React.createElement(
|
|
29349
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, segments == null ? void 0 : segments.map((segment, i) => /*#__PURE__*/React.createElement(MovableLine, {
|
|
29340
29350
|
key: i,
|
|
29341
29351
|
points: segment,
|
|
29342
29352
|
onMoveLine: delta => {
|
|
@@ -29356,7 +29366,7 @@ const LinearGraph = props => {
|
|
|
29356
29366
|
coords: lines
|
|
29357
29367
|
} = props.graphState;
|
|
29358
29368
|
const colors = ["var(--movable-line-stroke-color)", "var(--mafs-violet)"];
|
|
29359
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, lines == null ? void 0 : lines.map((line, i) => /*#__PURE__*/React.createElement(
|
|
29369
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, lines == null ? void 0 : lines.map((line, i) => /*#__PURE__*/React.createElement(MovableLine, {
|
|
29360
29370
|
key: i,
|
|
29361
29371
|
points: line,
|
|
29362
29372
|
onMoveLine: delta => {
|
|
@@ -29380,7 +29390,7 @@ const RayGraph = props => {
|
|
|
29380
29390
|
} = props.graphState;
|
|
29381
29391
|
const handleMoveLine = delta => dispatch(moveLine(0, delta));
|
|
29382
29392
|
const handleMovePoint = (pointIndex, newPoint) => dispatch(moveControlPoint(pointIndex, newPoint, 0));
|
|
29383
|
-
return /*#__PURE__*/React.createElement(
|
|
29393
|
+
return /*#__PURE__*/React.createElement(MovableLine
|
|
29384
29394
|
// a ray only has one line
|
|
29385
29395
|
, {
|
|
29386
29396
|
points: lines[0],
|
|
@@ -29532,7 +29542,7 @@ const isRightAngle = angle => Math.abs(angle - Math.PI / 2) < 0.01;
|
|
|
29532
29542
|
*/
|
|
29533
29543
|
const shouldDrawArcOutside = (midpoint, vertex, range, polygonLines) => {
|
|
29534
29544
|
// Create a ray from the midpoint (inside angle) to the edge of the range
|
|
29535
|
-
const rangeIntersectionPoint = getIntersectionOfRayWithBox(
|
|
29545
|
+
const rangeIntersectionPoint = getIntersectionOfRayWithBox(midpoint, vertex, range);
|
|
29536
29546
|
let lineIntersectionCount = 0;
|
|
29537
29547
|
polygonLines.forEach(line => linesIntersect([vertex, rangeIntersectionPoint], line) && lineIntersectionCount++);
|
|
29538
29548
|
|
|
@@ -29916,16 +29926,10 @@ function CircleGraph(props) {
|
|
|
29916
29926
|
center,
|
|
29917
29927
|
radiusPoint
|
|
29918
29928
|
} = graphState;
|
|
29919
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(
|
|
29929
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MovableCircle, {
|
|
29920
29930
|
center: center,
|
|
29921
29931
|
radius: getRadius(graphState),
|
|
29922
|
-
|
|
29923
|
-
color: color.blue
|
|
29924
|
-
}), /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
29925
|
-
point: center,
|
|
29926
|
-
onMove: newCenter => {
|
|
29927
|
-
dispatch(moveCenter(newCenter));
|
|
29928
|
-
}
|
|
29932
|
+
onMove: newCenter => dispatch(moveCenter(newCenter))
|
|
29929
29933
|
}), /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
29930
29934
|
point: radiusPoint,
|
|
29931
29935
|
onMove: newRadiusPoint => {
|
|
@@ -29933,6 +29937,80 @@ function CircleGraph(props) {
|
|
|
29933
29937
|
}
|
|
29934
29938
|
}));
|
|
29935
29939
|
}
|
|
29940
|
+
function MovableCircle(props) {
|
|
29941
|
+
const {
|
|
29942
|
+
center,
|
|
29943
|
+
radius,
|
|
29944
|
+
onMove
|
|
29945
|
+
} = props;
|
|
29946
|
+
const {
|
|
29947
|
+
snapStep
|
|
29948
|
+
} = useGraphConfig();
|
|
29949
|
+
const draggableRef = useRef(null);
|
|
29950
|
+
const {
|
|
29951
|
+
dragging
|
|
29952
|
+
} = useMovable({
|
|
29953
|
+
gestureTarget: draggableRef,
|
|
29954
|
+
point: center,
|
|
29955
|
+
onMove,
|
|
29956
|
+
constrain: p => snap(snapStep, p)
|
|
29957
|
+
});
|
|
29958
|
+
const [centerPx] = useTransformVectorsToPixels(center);
|
|
29959
|
+
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
29960
|
+
return /*#__PURE__*/React.createElement("g", {
|
|
29961
|
+
ref: draggableRef,
|
|
29962
|
+
tabIndex: 0,
|
|
29963
|
+
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
29964
|
+
}, /*#__PURE__*/React.createElement("ellipse", {
|
|
29965
|
+
className: "focus-ring",
|
|
29966
|
+
cx: centerPx[0],
|
|
29967
|
+
cy: centerPx[1],
|
|
29968
|
+
rx: radiiPx[0] + 3,
|
|
29969
|
+
ry: radiiPx[1] + 3
|
|
29970
|
+
}), /*#__PURE__*/React.createElement(Circle$1, {
|
|
29971
|
+
center: center,
|
|
29972
|
+
radius: radius,
|
|
29973
|
+
fillOpacity: 0,
|
|
29974
|
+
color: color.blue
|
|
29975
|
+
}), /*#__PURE__*/React.createElement(DragHandle, {
|
|
29976
|
+
center: center
|
|
29977
|
+
}));
|
|
29978
|
+
}
|
|
29979
|
+
const dragHandleDimensions = [24, 14];
|
|
29980
|
+
const dragHandleDotPositions = crossProduct([-4.4, 0, 4.4], [-2.1, 2.1]);
|
|
29981
|
+
function DragHandle(props) {
|
|
29982
|
+
const {
|
|
29983
|
+
center
|
|
29984
|
+
} = props;
|
|
29985
|
+
const cornerRadius = Math.min(...dragHandleDimensions) / 2;
|
|
29986
|
+
const [centerPx] = useTransformVectorsToPixels(center);
|
|
29987
|
+
const topLeft = vec.sub(centerPx, vec.scale(dragHandleDimensions, 0.5));
|
|
29988
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
|
|
29989
|
+
className: "movable-circle-handle",
|
|
29990
|
+
x: topLeft[0],
|
|
29991
|
+
y: topLeft[1],
|
|
29992
|
+
width: dragHandleDimensions[0],
|
|
29993
|
+
height: dragHandleDimensions[1],
|
|
29994
|
+
rx: cornerRadius,
|
|
29995
|
+
ry: cornerRadius
|
|
29996
|
+
}), dragHandleDotPositions.map(offsetPx => {
|
|
29997
|
+
const [xPx, yPx] = vec.add(offsetPx, centerPx);
|
|
29998
|
+
return /*#__PURE__*/React.createElement("circle", {
|
|
29999
|
+
className: "movable-circle-handle-dot",
|
|
30000
|
+
cx: xPx,
|
|
30001
|
+
cy: yPx
|
|
30002
|
+
});
|
|
30003
|
+
}));
|
|
30004
|
+
}
|
|
30005
|
+
function crossProduct(as, bs) {
|
|
30006
|
+
const result = [];
|
|
30007
|
+
for (const a of as) {
|
|
30008
|
+
for (const b of bs) {
|
|
30009
|
+
result.push([a, b]);
|
|
30010
|
+
}
|
|
30011
|
+
}
|
|
30012
|
+
return result;
|
|
30013
|
+
}
|
|
29936
30014
|
|
|
29937
30015
|
function PointGraph(props) {
|
|
29938
30016
|
const {
|
|
@@ -43294,7 +43372,7 @@ const init = function init(options) {
|
|
|
43294
43372
|
|
|
43295
43373
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43296
43374
|
const libName = "@khanacademy/perseus";
|
|
43297
|
-
const libVersion = "22.
|
|
43375
|
+
const libVersion = "22.5.0";
|
|
43298
43376
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43299
43377
|
|
|
43300
43378
|
const apiVersion = {
|