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