@khanacademy/perseus 22.4.0 → 22.4.1
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 +3 -1
- package/dist/es/index.js +243 -180
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +3 -1
- package/dist/index.js +244 -180
- package/dist/index.js.map +1 -1
- package/dist/widgets/interactive-graphs/graphs/components/movable-point-view.d.ts +17 -0
- package/dist/widgets/interactive-graphs/graphs/components/segment.d.ts +27 -0
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +9 -8
- package/package.json +2 -2
- package/dist/widgets/interactive-graphs/graphs/components/movable-line.d.ts +0 -17
- package/dist/widgets/interactive-graphs/graphs/types.d.ts +0 -6
package/dist/index.css
CHANGED
|
@@ -4419,7 +4419,9 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4419
4419
|
);
|
|
4420
4420
|
}
|
|
4421
4421
|
|
|
4422
|
-
.MafsView
|
|
4422
|
+
.MafsView
|
|
4423
|
+
.movable-point:is(:focus-visible, .movable-point--focus)
|
|
4424
|
+
.movable-point-focus-outline {
|
|
4423
4425
|
visibility: visible;
|
|
4424
4426
|
}
|
|
4425
4427
|
|
package/dist/index.js
CHANGED
|
@@ -477,7 +477,7 @@ class InnerMathInput extends React__namespace.Component {
|
|
|
477
477
|
locale
|
|
478
478
|
} = this.context;
|
|
479
479
|
// Initialize MathQuill.MathField instance
|
|
480
|
-
this.__mathField = mathInput.createMathField(this.__mathFieldWrapperRef, this.props.mathInputStrings, baseConfig => ({
|
|
480
|
+
this.__mathField = mathInput.createMathField(this.__mathFieldWrapperRef, locale, this.props.mathInputStrings, baseConfig => ({
|
|
481
481
|
...baseConfig,
|
|
482
482
|
handlers: {
|
|
483
483
|
edit: debounce(mathField => {
|
|
@@ -29333,6 +29333,194 @@ function snap(snapStep, point) {
|
|
|
29333
29333
|
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
29334
29334
|
}
|
|
29335
29335
|
|
|
29336
|
+
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
29337
|
+
// graph.
|
|
29338
|
+
const hitboxSizePx = 48;
|
|
29339
|
+
|
|
29340
|
+
// MovablePointView is a purely presentational component (i.e. it is a pure
|
|
29341
|
+
// function with no state or effects) that renders the SVG for a movable point
|
|
29342
|
+
// on an interactive graph.
|
|
29343
|
+
//
|
|
29344
|
+
// It has two modes for managing tabbing / focus: "controlled" (where the caller
|
|
29345
|
+
// manages the display of the focus ring, and the point itself cannot be
|
|
29346
|
+
// focused) and "uncontrolled" (where the point is focusable, and the browser
|
|
29347
|
+
// manages the focus state and styling). For context on why we did this, see
|
|
29348
|
+
// the description of https://github.com/Khan/perseus/pull/1240
|
|
29349
|
+
const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
29350
|
+
const {
|
|
29351
|
+
range,
|
|
29352
|
+
markings,
|
|
29353
|
+
showTooltips
|
|
29354
|
+
} = useGraphConfig();
|
|
29355
|
+
const {
|
|
29356
|
+
point,
|
|
29357
|
+
color = wonderBlocksTokens.color.blue,
|
|
29358
|
+
dragging,
|
|
29359
|
+
focusBehavior
|
|
29360
|
+
} = props;
|
|
29361
|
+
|
|
29362
|
+
// WB Tooltip requires a color name for the background color.
|
|
29363
|
+
// Since the color in props is a hex value, a reverse lookup is needed.
|
|
29364
|
+
const wbColorName = Object.entries(wonderBlocksTokens.color).find(_ref => {
|
|
29365
|
+
let [_, value] = _ref;
|
|
29366
|
+
return value === color;
|
|
29367
|
+
})?.[0] ?? "blue";
|
|
29368
|
+
const pointClasses = `movable-point ${dragging ? "movable-point--dragging" : ""} ${focusClass(focusBehavior)}`;
|
|
29369
|
+
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
29370
|
+
const [xMin, xMax] = range[0];
|
|
29371
|
+
const [yMin, yMax] = range[1];
|
|
29372
|
+
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
29373
|
+
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
29374
|
+
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
29375
|
+
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
29376
|
+
const showHairlines = dragging && markings !== "none";
|
|
29377
|
+
const hairlines = /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
29378
|
+
x1: verticalStartX,
|
|
29379
|
+
y1: y,
|
|
29380
|
+
x2: verticalEndX,
|
|
29381
|
+
y2: y,
|
|
29382
|
+
stroke: color
|
|
29383
|
+
}), /*#__PURE__*/React__namespace.createElement("line", {
|
|
29384
|
+
x1: x,
|
|
29385
|
+
y1: horizontalStartY,
|
|
29386
|
+
x2: x,
|
|
29387
|
+
y2: horizontalEndY,
|
|
29388
|
+
stroke: color
|
|
29389
|
+
}));
|
|
29390
|
+
const svgForPoint = /*#__PURE__*/React__namespace.createElement("g", {
|
|
29391
|
+
ref: hitboxRef,
|
|
29392
|
+
className: pointClasses,
|
|
29393
|
+
style: {
|
|
29394
|
+
"--movable-point-color": color
|
|
29395
|
+
},
|
|
29396
|
+
"data-testid": "movable-point",
|
|
29397
|
+
tabIndex: tabIndex(focusBehavior)
|
|
29398
|
+
}, /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29399
|
+
className: "movable-point-hitbox",
|
|
29400
|
+
r: hitboxSizePx / 2,
|
|
29401
|
+
cx: x,
|
|
29402
|
+
cy: y
|
|
29403
|
+
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29404
|
+
className: "movable-point-halo",
|
|
29405
|
+
cx: x,
|
|
29406
|
+
cy: y
|
|
29407
|
+
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29408
|
+
className: "movable-point-ring",
|
|
29409
|
+
cx: x,
|
|
29410
|
+
cy: y
|
|
29411
|
+
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29412
|
+
className: "movable-point-focus-outline",
|
|
29413
|
+
cx: x,
|
|
29414
|
+
cy: y
|
|
29415
|
+
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29416
|
+
className: "movable-point-center",
|
|
29417
|
+
cx: x,
|
|
29418
|
+
cy: y,
|
|
29419
|
+
style: {
|
|
29420
|
+
fill: color
|
|
29421
|
+
},
|
|
29422
|
+
"data-testid": "movable-point__center"
|
|
29423
|
+
}));
|
|
29424
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && hairlines, showTooltips ? /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
29425
|
+
autoUpdate: true,
|
|
29426
|
+
backgroundColor: wbColorName,
|
|
29427
|
+
content: `(${point[0]}, ${point[1]})`,
|
|
29428
|
+
contentStyle: {
|
|
29429
|
+
color: "white"
|
|
29430
|
+
}
|
|
29431
|
+
}, svgForPoint) : svgForPoint);
|
|
29432
|
+
});
|
|
29433
|
+
function focusClass(config) {
|
|
29434
|
+
if (config.type === "controlled" && config.showFocusRing) {
|
|
29435
|
+
return "movable-point--focus";
|
|
29436
|
+
}
|
|
29437
|
+
return "";
|
|
29438
|
+
}
|
|
29439
|
+
function tabIndex(config) {
|
|
29440
|
+
if (config.type === "uncontrolled") {
|
|
29441
|
+
return config.tabIndex;
|
|
29442
|
+
}
|
|
29443
|
+
return undefined;
|
|
29444
|
+
}
|
|
29445
|
+
|
|
29446
|
+
const Segment = props => {
|
|
29447
|
+
const {
|
|
29448
|
+
onMoveLine,
|
|
29449
|
+
color,
|
|
29450
|
+
points: [start, end],
|
|
29451
|
+
extend
|
|
29452
|
+
} = props;
|
|
29453
|
+
|
|
29454
|
+
// We use separate focusableHandle elements, instead of letting the movable
|
|
29455
|
+
// points themselves be focusable, to allow the tab order of the points to
|
|
29456
|
+
// be different from the rendering order. We had to solve for the following
|
|
29457
|
+
// constraints:
|
|
29458
|
+
// - SVG has no equivalent of z-index, so the order of elements in the
|
|
29459
|
+
// document determines the order in which they're painted. We want the
|
|
29460
|
+
// movable line segment to render behind its endpoints (it looks weird
|
|
29461
|
+
// otherwise) so we have to render the line first.
|
|
29462
|
+
// - There isn't a browser-native way to customize tab order, other than
|
|
29463
|
+
// setting tabindex > 0. But that bumps elements to the front of the
|
|
29464
|
+
// tab order for the entire page, which is not what we want.
|
|
29465
|
+
const {
|
|
29466
|
+
visiblePoint: visiblePoint1,
|
|
29467
|
+
focusableHandle: focusableHandle1
|
|
29468
|
+
} = useControlPoint(start, color, p => props.onMovePoint(0, p));
|
|
29469
|
+
const {
|
|
29470
|
+
visiblePoint: visiblePoint2,
|
|
29471
|
+
focusableHandle: focusableHandle2
|
|
29472
|
+
} = useControlPoint(end, color, p => props.onMovePoint(1, p));
|
|
29473
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, focusableHandle1, /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29474
|
+
start: start,
|
|
29475
|
+
end: end,
|
|
29476
|
+
stroke: color,
|
|
29477
|
+
extend: extend,
|
|
29478
|
+
onMove: onMoveLine
|
|
29479
|
+
}), focusableHandle2, visiblePoint1, visiblePoint2);
|
|
29480
|
+
};
|
|
29481
|
+
function useControlPoint(point, color, onMovePoint) {
|
|
29482
|
+
const {
|
|
29483
|
+
snapStep
|
|
29484
|
+
} = useGraphConfig();
|
|
29485
|
+
const [focused, setFocused] = React.useState(false);
|
|
29486
|
+
const keyboardHandleRef = React.useRef(null);
|
|
29487
|
+
mafs.useMovable({
|
|
29488
|
+
gestureTarget: keyboardHandleRef,
|
|
29489
|
+
point,
|
|
29490
|
+
onMove: onMovePoint,
|
|
29491
|
+
constrain: p => snap(snapStep, p)
|
|
29492
|
+
});
|
|
29493
|
+
const visiblePointRef = React.useRef(null);
|
|
29494
|
+
const {
|
|
29495
|
+
dragging
|
|
29496
|
+
} = mafs.useMovable({
|
|
29497
|
+
gestureTarget: visiblePointRef,
|
|
29498
|
+
point,
|
|
29499
|
+
onMove: onMovePoint,
|
|
29500
|
+
constrain: p => snap(snapStep, p)
|
|
29501
|
+
});
|
|
29502
|
+
const focusableHandle = /*#__PURE__*/React__namespace.createElement("g", {
|
|
29503
|
+
"data-testid": "movable-point__focusable-handle",
|
|
29504
|
+
tabIndex: 0,
|
|
29505
|
+
ref: keyboardHandleRef,
|
|
29506
|
+
onFocus: () => setFocused(true),
|
|
29507
|
+
onBlur: () => setFocused(false)
|
|
29508
|
+
});
|
|
29509
|
+
const visiblePoint = /*#__PURE__*/React__namespace.createElement(MovablePointView, {
|
|
29510
|
+
point: point,
|
|
29511
|
+
dragging: dragging,
|
|
29512
|
+
color: color,
|
|
29513
|
+
ref: visiblePointRef,
|
|
29514
|
+
focusBehavior: {
|
|
29515
|
+
type: "controlled",
|
|
29516
|
+
showFocusRing: focused
|
|
29517
|
+
}
|
|
29518
|
+
});
|
|
29519
|
+
return {
|
|
29520
|
+
focusableHandle,
|
|
29521
|
+
visiblePoint
|
|
29522
|
+
};
|
|
29523
|
+
}
|
|
29336
29524
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
29337
29525
|
const MovableLine = props => {
|
|
29338
29526
|
const {
|
|
@@ -29345,12 +29533,13 @@ const MovableLine = props => {
|
|
|
29345
29533
|
const midpoint = mafs.vec.midpoint(start, end);
|
|
29346
29534
|
const [startPtPx, endPtPx] = useTransformVectorsToPixels(start, end);
|
|
29347
29535
|
const {
|
|
29536
|
+
range,
|
|
29348
29537
|
graphDimensionsInPixels
|
|
29349
29538
|
} = useGraphConfig();
|
|
29350
29539
|
let startExtend = undefined;
|
|
29351
29540
|
let endExtend = undefined;
|
|
29352
29541
|
if (extend) {
|
|
29353
|
-
const trimmedRange = trimRange(
|
|
29542
|
+
const trimmedRange = trimRange(range, graphDimensionsInPixels);
|
|
29354
29543
|
startExtend = extend.start ? getIntersectionOfRayWithBox(start, end, trimmedRange) : undefined;
|
|
29355
29544
|
endExtend = extend.end ? getIntersectionOfRayWithBox(end, start, trimmedRange) : undefined;
|
|
29356
29545
|
}
|
|
@@ -29429,103 +29618,6 @@ function size(interval) {
|
|
|
29429
29618
|
return interval[1] - interval[0];
|
|
29430
29619
|
}
|
|
29431
29620
|
|
|
29432
|
-
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
29433
|
-
// graph.
|
|
29434
|
-
const hitboxSizePx = 48;
|
|
29435
|
-
const StyledMovablePoint = props => {
|
|
29436
|
-
const {
|
|
29437
|
-
range,
|
|
29438
|
-
snapStep,
|
|
29439
|
-
markings,
|
|
29440
|
-
showTooltips
|
|
29441
|
-
} = useGraphConfig();
|
|
29442
|
-
const hitboxRef = React.useRef(null);
|
|
29443
|
-
const {
|
|
29444
|
-
point,
|
|
29445
|
-
onMove,
|
|
29446
|
-
color = wonderBlocksTokens.color.blue
|
|
29447
|
-
} = props;
|
|
29448
|
-
|
|
29449
|
-
// WB Tooltip requires a color name for the background color.
|
|
29450
|
-
// Since the color in props is a hex value, a reverse lookup is needed.
|
|
29451
|
-
const wbColorName = Object.entries(wonderBlocksTokens.color).find(_ref => {
|
|
29452
|
-
let [_, value] = _ref;
|
|
29453
|
-
return value === color;
|
|
29454
|
-
})?.[0] ?? "blue";
|
|
29455
|
-
const {
|
|
29456
|
-
dragging
|
|
29457
|
-
} = mafs.useMovable({
|
|
29458
|
-
gestureTarget: hitboxRef,
|
|
29459
|
-
point,
|
|
29460
|
-
onMove,
|
|
29461
|
-
constrain: p => snap(snapStep, p)
|
|
29462
|
-
});
|
|
29463
|
-
const pointClasses = `movable-point ${dragging ? "movable-point--dragging" : ""}`;
|
|
29464
|
-
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
29465
|
-
const [xMin, xMax] = range[0];
|
|
29466
|
-
const [yMin, yMax] = range[1];
|
|
29467
|
-
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
29468
|
-
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
29469
|
-
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
29470
|
-
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
29471
|
-
const showHairlines = dragging && markings !== "none";
|
|
29472
|
-
const hairlines = /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
29473
|
-
x1: verticalStartX,
|
|
29474
|
-
y1: y,
|
|
29475
|
-
x2: verticalEndX,
|
|
29476
|
-
y2: y,
|
|
29477
|
-
stroke: color
|
|
29478
|
-
}), /*#__PURE__*/React__namespace.createElement("line", {
|
|
29479
|
-
x1: x,
|
|
29480
|
-
y1: horizontalStartY,
|
|
29481
|
-
x2: x,
|
|
29482
|
-
y2: horizontalEndY,
|
|
29483
|
-
stroke: color
|
|
29484
|
-
}));
|
|
29485
|
-
const svgForPoint = /*#__PURE__*/React__namespace.createElement("g", {
|
|
29486
|
-
ref: hitboxRef,
|
|
29487
|
-
className: pointClasses,
|
|
29488
|
-
tabIndex: 0,
|
|
29489
|
-
style: {
|
|
29490
|
-
"--movable-point-color": color
|
|
29491
|
-
},
|
|
29492
|
-
"data-testid": "movable-point"
|
|
29493
|
-
}, /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29494
|
-
className: "movable-point-hitbox",
|
|
29495
|
-
r: hitboxSizePx / 2,
|
|
29496
|
-
cx: x,
|
|
29497
|
-
cy: y
|
|
29498
|
-
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29499
|
-
className: "movable-point-halo",
|
|
29500
|
-
cx: x,
|
|
29501
|
-
cy: y
|
|
29502
|
-
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29503
|
-
className: "movable-point-ring",
|
|
29504
|
-
cx: x,
|
|
29505
|
-
cy: y
|
|
29506
|
-
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29507
|
-
className: "movable-point-focus-outline",
|
|
29508
|
-
cx: x,
|
|
29509
|
-
cy: y
|
|
29510
|
-
}), /*#__PURE__*/React__namespace.createElement("circle", {
|
|
29511
|
-
className: "movable-point-center",
|
|
29512
|
-
cx: x,
|
|
29513
|
-
cy: y,
|
|
29514
|
-
style: {
|
|
29515
|
-
fill: color
|
|
29516
|
-
},
|
|
29517
|
-
"data-testid": "movable-point__center"
|
|
29518
|
-
}));
|
|
29519
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && hairlines, showTooltips ? /*#__PURE__*/React__namespace.createElement(Tooltip__default["default"], {
|
|
29520
|
-
autoUpdate: true,
|
|
29521
|
-
backgroundColor: wbColorName,
|
|
29522
|
-
content: `(${point[0]}, ${point[1]})`,
|
|
29523
|
-
contentStyle: {
|
|
29524
|
-
color: "white"
|
|
29525
|
-
}
|
|
29526
|
-
}, svgForPoint) : svgForPoint);
|
|
29527
|
-
};
|
|
29528
|
-
|
|
29529
29621
|
const SegmentGraph = props => {
|
|
29530
29622
|
const {
|
|
29531
29623
|
dispatch
|
|
@@ -29533,7 +29625,7 @@ const SegmentGraph = props => {
|
|
|
29533
29625
|
const {
|
|
29534
29626
|
coords: segments
|
|
29535
29627
|
} = props.graphState;
|
|
29536
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, segments?.map((segment, i) => /*#__PURE__*/React__namespace.createElement(
|
|
29628
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, segments?.map((segment, i) => /*#__PURE__*/React__namespace.createElement(Segment, {
|
|
29537
29629
|
key: i,
|
|
29538
29630
|
points: segment,
|
|
29539
29631
|
onMoveLine: delta => {
|
|
@@ -29544,27 +29636,6 @@ const SegmentGraph = props => {
|
|
|
29544
29636
|
}
|
|
29545
29637
|
})));
|
|
29546
29638
|
};
|
|
29547
|
-
const SegmentView = props => {
|
|
29548
|
-
const {
|
|
29549
|
-
onMoveLine: onMoveSegment,
|
|
29550
|
-
points: [start, end]
|
|
29551
|
-
} = props;
|
|
29552
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29553
|
-
start: start,
|
|
29554
|
-
end: end,
|
|
29555
|
-
onMove: onMoveSegment
|
|
29556
|
-
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
29557
|
-
point: start,
|
|
29558
|
-
onMove: newPoint => {
|
|
29559
|
-
props.onMovePoint(0, newPoint);
|
|
29560
|
-
}
|
|
29561
|
-
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
29562
|
-
point: end,
|
|
29563
|
-
onMove: newPoint => {
|
|
29564
|
-
props.onMovePoint(1, newPoint);
|
|
29565
|
-
}
|
|
29566
|
-
}));
|
|
29567
|
-
};
|
|
29568
29639
|
|
|
29569
29640
|
const LinearGraph = props => {
|
|
29570
29641
|
const {
|
|
@@ -29574,49 +29645,19 @@ const LinearGraph = props => {
|
|
|
29574
29645
|
coords: lines
|
|
29575
29646
|
} = props.graphState;
|
|
29576
29647
|
const colors = ["var(--movable-line-stroke-color)", "var(--mafs-violet)"];
|
|
29577
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lines?.map((line, i) => /*#__PURE__*/React__namespace.createElement(
|
|
29648
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lines?.map((line, i) => /*#__PURE__*/React__namespace.createElement(Segment, {
|
|
29578
29649
|
key: i,
|
|
29579
29650
|
points: line,
|
|
29580
29651
|
onMoveLine: delta => {
|
|
29581
29652
|
dispatch(moveLine(i, delta));
|
|
29582
29653
|
},
|
|
29583
|
-
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i)),
|
|
29584
|
-
stroke: colors[i]
|
|
29585
|
-
})));
|
|
29586
|
-
};
|
|
29587
|
-
const LineView = props => {
|
|
29588
|
-
const {
|
|
29589
|
-
onMoveLine,
|
|
29590
|
-
onMovePoint,
|
|
29591
|
-
points: [start, end],
|
|
29592
|
-
stroke
|
|
29593
|
-
} = props;
|
|
29594
|
-
const {
|
|
29595
|
-
range
|
|
29596
|
-
} = useGraphConfig();
|
|
29597
|
-
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
29598
|
-
start: start,
|
|
29599
|
-
end: end,
|
|
29600
|
-
onMove: onMoveLine,
|
|
29601
29654
|
extend: {
|
|
29602
29655
|
start: true,
|
|
29603
|
-
end: true
|
|
29604
|
-
range
|
|
29605
|
-
},
|
|
29606
|
-
stroke: stroke
|
|
29607
|
-
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
29608
|
-
point: start,
|
|
29609
|
-
onMove: newPoint => {
|
|
29610
|
-
onMovePoint(0, newPoint);
|
|
29611
|
-
},
|
|
29612
|
-
color: stroke
|
|
29613
|
-
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
29614
|
-
point: end,
|
|
29615
|
-
onMove: newPoint => {
|
|
29616
|
-
onMovePoint(1, newPoint);
|
|
29656
|
+
end: true
|
|
29617
29657
|
},
|
|
29618
|
-
|
|
29619
|
-
|
|
29658
|
+
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i)),
|
|
29659
|
+
color: colors[i]
|
|
29660
|
+
})));
|
|
29620
29661
|
};
|
|
29621
29662
|
|
|
29622
29663
|
const RayGraph = props => {
|
|
@@ -29624,30 +29665,21 @@ const RayGraph = props => {
|
|
|
29624
29665
|
dispatch
|
|
29625
29666
|
} = props;
|
|
29626
29667
|
const {
|
|
29627
|
-
coords: lines
|
|
29628
|
-
range
|
|
29668
|
+
coords: lines
|
|
29629
29669
|
} = props.graphState;
|
|
29630
|
-
|
|
29631
|
-
// a ray only has one line
|
|
29632
|
-
const [start, end] = lines[0];
|
|
29633
29670
|
const handleMoveLine = delta => dispatch(moveLine(0, delta));
|
|
29634
|
-
const handleMovePoint = (
|
|
29635
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
29636
|
-
|
|
29637
|
-
|
|
29638
|
-
|
|
29671
|
+
const handleMovePoint = (pointIndex, newPoint) => dispatch(moveControlPoint(pointIndex, newPoint, 0));
|
|
29672
|
+
return /*#__PURE__*/React__namespace.createElement(Segment
|
|
29673
|
+
// a ray only has one line
|
|
29674
|
+
, {
|
|
29675
|
+
points: lines[0],
|
|
29676
|
+
onMoveLine: handleMoveLine,
|
|
29677
|
+
onMovePoint: handleMovePoint,
|
|
29639
29678
|
extend: {
|
|
29640
|
-
end: true,
|
|
29641
29679
|
start: false,
|
|
29642
|
-
|
|
29680
|
+
end: true
|
|
29643
29681
|
}
|
|
29644
|
-
})
|
|
29645
|
-
point: start,
|
|
29646
|
-
onMove: newPoint => handleMovePoint(newPoint, 0)
|
|
29647
|
-
}), /*#__PURE__*/React__namespace.createElement(StyledMovablePoint, {
|
|
29648
|
-
point: end,
|
|
29649
|
-
onMove: newPoint => handleMovePoint(newPoint, 1)
|
|
29650
|
-
}));
|
|
29682
|
+
});
|
|
29651
29683
|
};
|
|
29652
29684
|
|
|
29653
29685
|
/**
|
|
@@ -29819,6 +29851,36 @@ const linesIntersect = (_ref3, _ref4) => {
|
|
|
29819
29851
|
};
|
|
29820
29852
|
const isEven = n => n % 2 === 0;
|
|
29821
29853
|
|
|
29854
|
+
const StyledMovablePoint = props => {
|
|
29855
|
+
const {
|
|
29856
|
+
snapStep
|
|
29857
|
+
} = useGraphConfig();
|
|
29858
|
+
const elementRef = React.useRef(null);
|
|
29859
|
+
const {
|
|
29860
|
+
point,
|
|
29861
|
+
onMove,
|
|
29862
|
+
color = wonderBlocksTokens.color.blue
|
|
29863
|
+
} = props;
|
|
29864
|
+
const {
|
|
29865
|
+
dragging
|
|
29866
|
+
} = mafs.useMovable({
|
|
29867
|
+
gestureTarget: elementRef,
|
|
29868
|
+
point,
|
|
29869
|
+
onMove,
|
|
29870
|
+
constrain: p => snap(snapStep, p)
|
|
29871
|
+
});
|
|
29872
|
+
return /*#__PURE__*/React__namespace.createElement(MovablePointView, {
|
|
29873
|
+
ref: elementRef,
|
|
29874
|
+
point: point,
|
|
29875
|
+
color: color,
|
|
29876
|
+
dragging: dragging,
|
|
29877
|
+
focusBehavior: {
|
|
29878
|
+
type: "uncontrolled",
|
|
29879
|
+
tabIndex: 0
|
|
29880
|
+
}
|
|
29881
|
+
});
|
|
29882
|
+
};
|
|
29883
|
+
|
|
29822
29884
|
const PolygonGraph = props => {
|
|
29823
29885
|
const [focused, setFocused] = React__namespace.useState(false);
|
|
29824
29886
|
const [hovered, setHovered] = React__namespace.useState(false);
|
|
@@ -29832,17 +29894,19 @@ const PolygonGraph = props => {
|
|
|
29832
29894
|
range,
|
|
29833
29895
|
snapStep
|
|
29834
29896
|
} = props.graphState;
|
|
29897
|
+
|
|
29898
|
+
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
29899
|
+
// think coords can be null.
|
|
29835
29900
|
const points = coords ?? [[0, 0]];
|
|
29836
|
-
const pointsSum = points.reduce((acc, point) => mafs.vec.add(acc, point), [0, 0]);
|
|
29837
|
-
const midpoint = pointsSum && mafs.vec.scale(pointsSum, 1 / (points.length ?? 1));
|
|
29838
29901
|
const ref = React__namespace.useRef(null);
|
|
29902
|
+
const dragReferencePoint = points[0];
|
|
29839
29903
|
const {
|
|
29840
29904
|
dragging
|
|
29841
29905
|
} = mafs.useMovable({
|
|
29842
29906
|
gestureTarget: ref,
|
|
29843
|
-
point:
|
|
29907
|
+
point: dragReferencePoint,
|
|
29844
29908
|
onMove: newPoint => {
|
|
29845
|
-
const delta = mafs.vec.sub(newPoint,
|
|
29909
|
+
const delta = mafs.vec.sub(newPoint, dragReferencePoint);
|
|
29846
29910
|
dispatch(moveAll(delta));
|
|
29847
29911
|
},
|
|
29848
29912
|
constrain: p => snap(snapStep, p)
|
|
@@ -43559,7 +43623,7 @@ const init = function (options) {
|
|
|
43559
43623
|
|
|
43560
43624
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43561
43625
|
const libName = "@khanacademy/perseus";
|
|
43562
|
-
const libVersion = "22.4.
|
|
43626
|
+
const libVersion = "22.4.1";
|
|
43563
43627
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43564
43628
|
|
|
43565
43629
|
const apiVersion = {
|