@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/es/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/es/index.js
CHANGED
|
@@ -2,11 +2,11 @@ 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';
|
|
9
|
-
import React__default, { useContext, useState, useEffect, useRef, createContext, useImperativeHandle } from 'react';
|
|
9
|
+
import React__default, { useContext, useState, useEffect, useRef, createContext, forwardRef, useImperativeHandle } from 'react';
|
|
10
10
|
import _, { debounce as debounce$1 } from 'underscore';
|
|
11
11
|
import Clickable from '@khanacademy/wonder-blocks-clickable';
|
|
12
12
|
import { Popover, PopoverContentCore, PopoverContent } from '@khanacademy/wonder-blocks-popover';
|
|
@@ -341,7 +341,7 @@ class InnerMathInput extends React.Component {
|
|
|
341
341
|
locale
|
|
342
342
|
} = this.context;
|
|
343
343
|
// Initialize MathQuill.MathField instance
|
|
344
|
-
this.__mathField = createMathField(this.__mathFieldWrapperRef, this.props.mathInputStrings, baseConfig => _extends({}, baseConfig, {
|
|
344
|
+
this.__mathField = createMathField(this.__mathFieldWrapperRef, locale, this.props.mathInputStrings, baseConfig => _extends({}, baseConfig, {
|
|
345
345
|
handlers: {
|
|
346
346
|
edit: debounce(mathField => {
|
|
347
347
|
// This handler is guaranteed to be called on change, but
|
|
@@ -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.
|
|
@@ -29046,6 +29041,192 @@ function snap(snapStep, point) {
|
|
|
29046
29041
|
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
29047
29042
|
}
|
|
29048
29043
|
|
|
29044
|
+
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
29045
|
+
// graph.
|
|
29046
|
+
const hitboxSizePx = 48;
|
|
29047
|
+
|
|
29048
|
+
// MovablePointView is a purely presentational component (i.e. it is a pure
|
|
29049
|
+
// function with no state or effects) that renders the SVG for a movable point
|
|
29050
|
+
// on an interactive graph.
|
|
29051
|
+
//
|
|
29052
|
+
// It has two modes for managing tabbing / focus: "controlled" (where the caller
|
|
29053
|
+
// manages the display of the focus ring, and the point itself cannot be
|
|
29054
|
+
// focused) and "uncontrolled" (where the point is focusable, and the browser
|
|
29055
|
+
// manages the focus state and styling). For context on why we did this, see
|
|
29056
|
+
// the description of https://github.com/Khan/perseus/pull/1240
|
|
29057
|
+
const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
29058
|
+
var _Object$entries$find$, _Object$entries$find;
|
|
29059
|
+
const {
|
|
29060
|
+
range,
|
|
29061
|
+
markings,
|
|
29062
|
+
showTooltips
|
|
29063
|
+
} = useGraphConfig();
|
|
29064
|
+
const {
|
|
29065
|
+
point,
|
|
29066
|
+
color: color$1 = color.blue,
|
|
29067
|
+
dragging,
|
|
29068
|
+
focusBehavior
|
|
29069
|
+
} = props;
|
|
29070
|
+
|
|
29071
|
+
// WB Tooltip requires a color name for the background color.
|
|
29072
|
+
// Since the color in props is a hex value, a reverse lookup is needed.
|
|
29073
|
+
const wbColorName = (_Object$entries$find$ = (_Object$entries$find = Object.entries(color).find(([_, value]) => value === color$1)) == null ? void 0 : _Object$entries$find[0]) != null ? _Object$entries$find$ : "blue";
|
|
29074
|
+
const pointClasses = `movable-point ${dragging ? "movable-point--dragging" : ""} ${focusClass(focusBehavior)}`;
|
|
29075
|
+
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
29076
|
+
const [xMin, xMax] = range[0];
|
|
29077
|
+
const [yMin, yMax] = range[1];
|
|
29078
|
+
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
29079
|
+
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
29080
|
+
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
29081
|
+
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
29082
|
+
const showHairlines = dragging && markings !== "none";
|
|
29083
|
+
const hairlines = /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("line", {
|
|
29084
|
+
x1: verticalStartX,
|
|
29085
|
+
y1: y,
|
|
29086
|
+
x2: verticalEndX,
|
|
29087
|
+
y2: y,
|
|
29088
|
+
stroke: color$1
|
|
29089
|
+
}), /*#__PURE__*/React.createElement("line", {
|
|
29090
|
+
x1: x,
|
|
29091
|
+
y1: horizontalStartY,
|
|
29092
|
+
x2: x,
|
|
29093
|
+
y2: horizontalEndY,
|
|
29094
|
+
stroke: color$1
|
|
29095
|
+
}));
|
|
29096
|
+
const svgForPoint = /*#__PURE__*/React.createElement("g", {
|
|
29097
|
+
ref: hitboxRef,
|
|
29098
|
+
className: pointClasses,
|
|
29099
|
+
style: {
|
|
29100
|
+
"--movable-point-color": color$1
|
|
29101
|
+
},
|
|
29102
|
+
"data-testid": "movable-point",
|
|
29103
|
+
tabIndex: tabIndex(focusBehavior)
|
|
29104
|
+
}, /*#__PURE__*/React.createElement("circle", {
|
|
29105
|
+
className: "movable-point-hitbox",
|
|
29106
|
+
r: hitboxSizePx / 2,
|
|
29107
|
+
cx: x,
|
|
29108
|
+
cy: y
|
|
29109
|
+
}), /*#__PURE__*/React.createElement("circle", {
|
|
29110
|
+
className: "movable-point-halo",
|
|
29111
|
+
cx: x,
|
|
29112
|
+
cy: y
|
|
29113
|
+
}), /*#__PURE__*/React.createElement("circle", {
|
|
29114
|
+
className: "movable-point-ring",
|
|
29115
|
+
cx: x,
|
|
29116
|
+
cy: y
|
|
29117
|
+
}), /*#__PURE__*/React.createElement("circle", {
|
|
29118
|
+
className: "movable-point-focus-outline",
|
|
29119
|
+
cx: x,
|
|
29120
|
+
cy: y
|
|
29121
|
+
}), /*#__PURE__*/React.createElement("circle", {
|
|
29122
|
+
className: "movable-point-center",
|
|
29123
|
+
cx: x,
|
|
29124
|
+
cy: y,
|
|
29125
|
+
style: {
|
|
29126
|
+
fill: color$1
|
|
29127
|
+
},
|
|
29128
|
+
"data-testid": "movable-point__center"
|
|
29129
|
+
}));
|
|
29130
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, showHairlines && hairlines, showTooltips ? /*#__PURE__*/React.createElement(Tooltip$1, {
|
|
29131
|
+
autoUpdate: true,
|
|
29132
|
+
backgroundColor: wbColorName,
|
|
29133
|
+
content: `(${point[0]}, ${point[1]})`,
|
|
29134
|
+
contentStyle: {
|
|
29135
|
+
color: "white"
|
|
29136
|
+
}
|
|
29137
|
+
}, svgForPoint) : svgForPoint);
|
|
29138
|
+
});
|
|
29139
|
+
function focusClass(config) {
|
|
29140
|
+
if (config.type === "controlled" && config.showFocusRing) {
|
|
29141
|
+
return "movable-point--focus";
|
|
29142
|
+
}
|
|
29143
|
+
return "";
|
|
29144
|
+
}
|
|
29145
|
+
function tabIndex(config) {
|
|
29146
|
+
if (config.type === "uncontrolled") {
|
|
29147
|
+
return config.tabIndex;
|
|
29148
|
+
}
|
|
29149
|
+
return undefined;
|
|
29150
|
+
}
|
|
29151
|
+
|
|
29152
|
+
const Segment = props => {
|
|
29153
|
+
const {
|
|
29154
|
+
onMoveLine,
|
|
29155
|
+
color,
|
|
29156
|
+
points: [start, end],
|
|
29157
|
+
extend
|
|
29158
|
+
} = props;
|
|
29159
|
+
|
|
29160
|
+
// We use separate focusableHandle elements, instead of letting the movable
|
|
29161
|
+
// points themselves be focusable, to allow the tab order of the points to
|
|
29162
|
+
// be different from the rendering order. We had to solve for the following
|
|
29163
|
+
// constraints:
|
|
29164
|
+
// - SVG has no equivalent of z-index, so the order of elements in the
|
|
29165
|
+
// document determines the order in which they're painted. We want the
|
|
29166
|
+
// movable line segment to render behind its endpoints (it looks weird
|
|
29167
|
+
// otherwise) so we have to render the line first.
|
|
29168
|
+
// - There isn't a browser-native way to customize tab order, other than
|
|
29169
|
+
// setting tabindex > 0. But that bumps elements to the front of the
|
|
29170
|
+
// tab order for the entire page, which is not what we want.
|
|
29171
|
+
const {
|
|
29172
|
+
visiblePoint: visiblePoint1,
|
|
29173
|
+
focusableHandle: focusableHandle1
|
|
29174
|
+
} = useControlPoint(start, color, p => props.onMovePoint(0, p));
|
|
29175
|
+
const {
|
|
29176
|
+
visiblePoint: visiblePoint2,
|
|
29177
|
+
focusableHandle: focusableHandle2
|
|
29178
|
+
} = useControlPoint(end, color, p => props.onMovePoint(1, p));
|
|
29179
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, focusableHandle1, /*#__PURE__*/React.createElement(MovableLine, {
|
|
29180
|
+
start: start,
|
|
29181
|
+
end: end,
|
|
29182
|
+
stroke: color,
|
|
29183
|
+
extend: extend,
|
|
29184
|
+
onMove: onMoveLine
|
|
29185
|
+
}), focusableHandle2, visiblePoint1, visiblePoint2);
|
|
29186
|
+
};
|
|
29187
|
+
function useControlPoint(point, color, onMovePoint) {
|
|
29188
|
+
const {
|
|
29189
|
+
snapStep
|
|
29190
|
+
} = useGraphConfig();
|
|
29191
|
+
const [focused, setFocused] = useState(false);
|
|
29192
|
+
const keyboardHandleRef = useRef(null);
|
|
29193
|
+
useMovable({
|
|
29194
|
+
gestureTarget: keyboardHandleRef,
|
|
29195
|
+
point,
|
|
29196
|
+
onMove: onMovePoint,
|
|
29197
|
+
constrain: p => snap(snapStep, p)
|
|
29198
|
+
});
|
|
29199
|
+
const visiblePointRef = useRef(null);
|
|
29200
|
+
const {
|
|
29201
|
+
dragging
|
|
29202
|
+
} = useMovable({
|
|
29203
|
+
gestureTarget: visiblePointRef,
|
|
29204
|
+
point,
|
|
29205
|
+
onMove: onMovePoint,
|
|
29206
|
+
constrain: p => snap(snapStep, p)
|
|
29207
|
+
});
|
|
29208
|
+
const focusableHandle = /*#__PURE__*/React.createElement("g", {
|
|
29209
|
+
"data-testid": "movable-point__focusable-handle",
|
|
29210
|
+
tabIndex: 0,
|
|
29211
|
+
ref: keyboardHandleRef,
|
|
29212
|
+
onFocus: () => setFocused(true),
|
|
29213
|
+
onBlur: () => setFocused(false)
|
|
29214
|
+
});
|
|
29215
|
+
const visiblePoint = /*#__PURE__*/React.createElement(MovablePointView, {
|
|
29216
|
+
point: point,
|
|
29217
|
+
dragging: dragging,
|
|
29218
|
+
color: color,
|
|
29219
|
+
ref: visiblePointRef,
|
|
29220
|
+
focusBehavior: {
|
|
29221
|
+
type: "controlled",
|
|
29222
|
+
showFocusRing: focused
|
|
29223
|
+
}
|
|
29224
|
+
});
|
|
29225
|
+
return {
|
|
29226
|
+
focusableHandle,
|
|
29227
|
+
visiblePoint
|
|
29228
|
+
};
|
|
29229
|
+
}
|
|
29049
29230
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
29050
29231
|
const MovableLine = props => {
|
|
29051
29232
|
const {
|
|
@@ -29058,12 +29239,13 @@ const MovableLine = props => {
|
|
|
29058
29239
|
const midpoint = vec.midpoint(start, end);
|
|
29059
29240
|
const [startPtPx, endPtPx] = useTransformVectorsToPixels(start, end);
|
|
29060
29241
|
const {
|
|
29242
|
+
range,
|
|
29061
29243
|
graphDimensionsInPixels
|
|
29062
29244
|
} = useGraphConfig();
|
|
29063
29245
|
let startExtend = undefined;
|
|
29064
29246
|
let endExtend = undefined;
|
|
29065
29247
|
if (extend) {
|
|
29066
|
-
const trimmedRange = trimRange(
|
|
29248
|
+
const trimmedRange = trimRange(range, graphDimensionsInPixels);
|
|
29067
29249
|
startExtend = extend.start ? getIntersectionOfRayWithBox(start, end, trimmedRange) : undefined;
|
|
29068
29250
|
endExtend = extend.end ? getIntersectionOfRayWithBox(end, start, trimmedRange) : undefined;
|
|
29069
29251
|
}
|
|
@@ -29142,101 +29324,6 @@ function size(interval) {
|
|
|
29142
29324
|
return interval[1] - interval[0];
|
|
29143
29325
|
}
|
|
29144
29326
|
|
|
29145
|
-
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
29146
|
-
// graph.
|
|
29147
|
-
const hitboxSizePx = 48;
|
|
29148
|
-
const StyledMovablePoint = props => {
|
|
29149
|
-
var _Object$entries$find$, _Object$entries$find;
|
|
29150
|
-
const {
|
|
29151
|
-
range,
|
|
29152
|
-
snapStep,
|
|
29153
|
-
markings,
|
|
29154
|
-
showTooltips
|
|
29155
|
-
} = useGraphConfig();
|
|
29156
|
-
const hitboxRef = useRef(null);
|
|
29157
|
-
const {
|
|
29158
|
-
point,
|
|
29159
|
-
onMove,
|
|
29160
|
-
color: color$1 = color.blue
|
|
29161
|
-
} = props;
|
|
29162
|
-
|
|
29163
|
-
// WB Tooltip requires a color name for the background color.
|
|
29164
|
-
// Since the color in props is a hex value, a reverse lookup is needed.
|
|
29165
|
-
const wbColorName = (_Object$entries$find$ = (_Object$entries$find = Object.entries(color).find(([_, value]) => value === color$1)) == null ? void 0 : _Object$entries$find[0]) != null ? _Object$entries$find$ : "blue";
|
|
29166
|
-
const {
|
|
29167
|
-
dragging
|
|
29168
|
-
} = useMovable({
|
|
29169
|
-
gestureTarget: hitboxRef,
|
|
29170
|
-
point,
|
|
29171
|
-
onMove,
|
|
29172
|
-
constrain: p => snap(snapStep, p)
|
|
29173
|
-
});
|
|
29174
|
-
const pointClasses = `movable-point ${dragging ? "movable-point--dragging" : ""}`;
|
|
29175
|
-
const [[x, y]] = useTransformVectorsToPixels(point);
|
|
29176
|
-
const [xMin, xMax] = range[0];
|
|
29177
|
-
const [yMin, yMax] = range[1];
|
|
29178
|
-
const [[verticalStartX]] = useTransformVectorsToPixels([xMin, 0]);
|
|
29179
|
-
const [[verticalEndX]] = useTransformVectorsToPixels([xMax, 0]);
|
|
29180
|
-
const [[_, horizontalStartY]] = useTransformVectorsToPixels([0, yMin]);
|
|
29181
|
-
const [[__, horizontalEndY]] = useTransformVectorsToPixels([0, yMax]);
|
|
29182
|
-
const showHairlines = dragging && markings !== "none";
|
|
29183
|
-
const hairlines = /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("line", {
|
|
29184
|
-
x1: verticalStartX,
|
|
29185
|
-
y1: y,
|
|
29186
|
-
x2: verticalEndX,
|
|
29187
|
-
y2: y,
|
|
29188
|
-
stroke: color$1
|
|
29189
|
-
}), /*#__PURE__*/React.createElement("line", {
|
|
29190
|
-
x1: x,
|
|
29191
|
-
y1: horizontalStartY,
|
|
29192
|
-
x2: x,
|
|
29193
|
-
y2: horizontalEndY,
|
|
29194
|
-
stroke: color$1
|
|
29195
|
-
}));
|
|
29196
|
-
const svgForPoint = /*#__PURE__*/React.createElement("g", {
|
|
29197
|
-
ref: hitboxRef,
|
|
29198
|
-
className: pointClasses,
|
|
29199
|
-
tabIndex: 0,
|
|
29200
|
-
style: {
|
|
29201
|
-
"--movable-point-color": color$1
|
|
29202
|
-
},
|
|
29203
|
-
"data-testid": "movable-point"
|
|
29204
|
-
}, /*#__PURE__*/React.createElement("circle", {
|
|
29205
|
-
className: "movable-point-hitbox",
|
|
29206
|
-
r: hitboxSizePx / 2,
|
|
29207
|
-
cx: x,
|
|
29208
|
-
cy: y
|
|
29209
|
-
}), /*#__PURE__*/React.createElement("circle", {
|
|
29210
|
-
className: "movable-point-halo",
|
|
29211
|
-
cx: x,
|
|
29212
|
-
cy: y
|
|
29213
|
-
}), /*#__PURE__*/React.createElement("circle", {
|
|
29214
|
-
className: "movable-point-ring",
|
|
29215
|
-
cx: x,
|
|
29216
|
-
cy: y
|
|
29217
|
-
}), /*#__PURE__*/React.createElement("circle", {
|
|
29218
|
-
className: "movable-point-focus-outline",
|
|
29219
|
-
cx: x,
|
|
29220
|
-
cy: y
|
|
29221
|
-
}), /*#__PURE__*/React.createElement("circle", {
|
|
29222
|
-
className: "movable-point-center",
|
|
29223
|
-
cx: x,
|
|
29224
|
-
cy: y,
|
|
29225
|
-
style: {
|
|
29226
|
-
fill: color$1
|
|
29227
|
-
},
|
|
29228
|
-
"data-testid": "movable-point__center"
|
|
29229
|
-
}));
|
|
29230
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, showHairlines && hairlines, showTooltips ? /*#__PURE__*/React.createElement(Tooltip$1, {
|
|
29231
|
-
autoUpdate: true,
|
|
29232
|
-
backgroundColor: wbColorName,
|
|
29233
|
-
content: `(${point[0]}, ${point[1]})`,
|
|
29234
|
-
contentStyle: {
|
|
29235
|
-
color: "white"
|
|
29236
|
-
}
|
|
29237
|
-
}, svgForPoint) : svgForPoint);
|
|
29238
|
-
};
|
|
29239
|
-
|
|
29240
29327
|
const SegmentGraph = props => {
|
|
29241
29328
|
const {
|
|
29242
29329
|
dispatch
|
|
@@ -29244,7 +29331,7 @@ const SegmentGraph = props => {
|
|
|
29244
29331
|
const {
|
|
29245
29332
|
coords: segments
|
|
29246
29333
|
} = props.graphState;
|
|
29247
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, segments == null ? void 0 : segments.map((segment, i) => /*#__PURE__*/React.createElement(
|
|
29334
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, segments == null ? void 0 : segments.map((segment, i) => /*#__PURE__*/React.createElement(Segment, {
|
|
29248
29335
|
key: i,
|
|
29249
29336
|
points: segment,
|
|
29250
29337
|
onMoveLine: delta => {
|
|
@@ -29255,27 +29342,6 @@ const SegmentGraph = props => {
|
|
|
29255
29342
|
}
|
|
29256
29343
|
})));
|
|
29257
29344
|
};
|
|
29258
|
-
const SegmentView = props => {
|
|
29259
|
-
const {
|
|
29260
|
-
onMoveLine: onMoveSegment,
|
|
29261
|
-
points: [start, end]
|
|
29262
|
-
} = props;
|
|
29263
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MovableLine, {
|
|
29264
|
-
start: start,
|
|
29265
|
-
end: end,
|
|
29266
|
-
onMove: onMoveSegment
|
|
29267
|
-
}), /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
29268
|
-
point: start,
|
|
29269
|
-
onMove: newPoint => {
|
|
29270
|
-
props.onMovePoint(0, newPoint);
|
|
29271
|
-
}
|
|
29272
|
-
}), /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
29273
|
-
point: end,
|
|
29274
|
-
onMove: newPoint => {
|
|
29275
|
-
props.onMovePoint(1, newPoint);
|
|
29276
|
-
}
|
|
29277
|
-
}));
|
|
29278
|
-
};
|
|
29279
29345
|
|
|
29280
29346
|
const LinearGraph = props => {
|
|
29281
29347
|
const {
|
|
@@ -29285,49 +29351,19 @@ const LinearGraph = props => {
|
|
|
29285
29351
|
coords: lines
|
|
29286
29352
|
} = props.graphState;
|
|
29287
29353
|
const colors = ["var(--movable-line-stroke-color)", "var(--mafs-violet)"];
|
|
29288
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, lines == null ? void 0 : lines.map((line, i) => /*#__PURE__*/React.createElement(
|
|
29354
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, lines == null ? void 0 : lines.map((line, i) => /*#__PURE__*/React.createElement(Segment, {
|
|
29289
29355
|
key: i,
|
|
29290
29356
|
points: line,
|
|
29291
29357
|
onMoveLine: delta => {
|
|
29292
29358
|
dispatch(moveLine(i, delta));
|
|
29293
29359
|
},
|
|
29294
|
-
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i)),
|
|
29295
|
-
stroke: colors[i]
|
|
29296
|
-
})));
|
|
29297
|
-
};
|
|
29298
|
-
const LineView = props => {
|
|
29299
|
-
const {
|
|
29300
|
-
onMoveLine,
|
|
29301
|
-
onMovePoint,
|
|
29302
|
-
points: [start, end],
|
|
29303
|
-
stroke
|
|
29304
|
-
} = props;
|
|
29305
|
-
const {
|
|
29306
|
-
range
|
|
29307
|
-
} = useGraphConfig();
|
|
29308
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MovableLine, {
|
|
29309
|
-
start: start,
|
|
29310
|
-
end: end,
|
|
29311
|
-
onMove: onMoveLine,
|
|
29312
29360
|
extend: {
|
|
29313
29361
|
start: true,
|
|
29314
|
-
end: true
|
|
29315
|
-
range
|
|
29362
|
+
end: true
|
|
29316
29363
|
},
|
|
29317
|
-
|
|
29318
|
-
|
|
29319
|
-
|
|
29320
|
-
onMove: newPoint => {
|
|
29321
|
-
onMovePoint(0, newPoint);
|
|
29322
|
-
},
|
|
29323
|
-
color: stroke
|
|
29324
|
-
}), /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
29325
|
-
point: end,
|
|
29326
|
-
onMove: newPoint => {
|
|
29327
|
-
onMovePoint(1, newPoint);
|
|
29328
|
-
},
|
|
29329
|
-
color: stroke
|
|
29330
|
-
}));
|
|
29364
|
+
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i)),
|
|
29365
|
+
color: colors[i]
|
|
29366
|
+
})));
|
|
29331
29367
|
};
|
|
29332
29368
|
|
|
29333
29369
|
const RayGraph = props => {
|
|
@@ -29335,30 +29371,21 @@ const RayGraph = props => {
|
|
|
29335
29371
|
dispatch
|
|
29336
29372
|
} = props;
|
|
29337
29373
|
const {
|
|
29338
|
-
coords: lines
|
|
29339
|
-
range
|
|
29374
|
+
coords: lines
|
|
29340
29375
|
} = props.graphState;
|
|
29341
|
-
|
|
29342
|
-
// a ray only has one line
|
|
29343
|
-
const [start, end] = lines[0];
|
|
29344
29376
|
const handleMoveLine = delta => dispatch(moveLine(0, delta));
|
|
29345
|
-
const handleMovePoint = (
|
|
29346
|
-
return /*#__PURE__*/React.createElement(
|
|
29347
|
-
|
|
29348
|
-
|
|
29349
|
-
|
|
29377
|
+
const handleMovePoint = (pointIndex, newPoint) => dispatch(moveControlPoint(pointIndex, newPoint, 0));
|
|
29378
|
+
return /*#__PURE__*/React.createElement(Segment
|
|
29379
|
+
// a ray only has one line
|
|
29380
|
+
, {
|
|
29381
|
+
points: lines[0],
|
|
29382
|
+
onMoveLine: handleMoveLine,
|
|
29383
|
+
onMovePoint: handleMovePoint,
|
|
29350
29384
|
extend: {
|
|
29351
|
-
end: true,
|
|
29352
29385
|
start: false,
|
|
29353
|
-
|
|
29386
|
+
end: true
|
|
29354
29387
|
}
|
|
29355
|
-
})
|
|
29356
|
-
point: start,
|
|
29357
|
-
onMove: newPoint => handleMovePoint(newPoint, 0)
|
|
29358
|
-
}), /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
29359
|
-
point: end,
|
|
29360
|
-
onMove: newPoint => handleMovePoint(newPoint, 1)
|
|
29361
|
-
}));
|
|
29388
|
+
});
|
|
29362
29389
|
};
|
|
29363
29390
|
|
|
29364
29391
|
/**
|
|
@@ -29522,8 +29549,37 @@ const linesIntersect = ([[a, b], [c, d]], [[p, q], [r, s]]) => {
|
|
|
29522
29549
|
};
|
|
29523
29550
|
const isEven = n => n % 2 === 0;
|
|
29524
29551
|
|
|
29552
|
+
const StyledMovablePoint = props => {
|
|
29553
|
+
const {
|
|
29554
|
+
snapStep
|
|
29555
|
+
} = useGraphConfig();
|
|
29556
|
+
const elementRef = useRef(null);
|
|
29557
|
+
const {
|
|
29558
|
+
point,
|
|
29559
|
+
onMove,
|
|
29560
|
+
color: color$1 = color.blue
|
|
29561
|
+
} = props;
|
|
29562
|
+
const {
|
|
29563
|
+
dragging
|
|
29564
|
+
} = useMovable({
|
|
29565
|
+
gestureTarget: elementRef,
|
|
29566
|
+
point,
|
|
29567
|
+
onMove,
|
|
29568
|
+
constrain: p => snap(snapStep, p)
|
|
29569
|
+
});
|
|
29570
|
+
return /*#__PURE__*/React.createElement(MovablePointView, {
|
|
29571
|
+
ref: elementRef,
|
|
29572
|
+
point: point,
|
|
29573
|
+
color: color$1,
|
|
29574
|
+
dragging: dragging,
|
|
29575
|
+
focusBehavior: {
|
|
29576
|
+
type: "uncontrolled",
|
|
29577
|
+
tabIndex: 0
|
|
29578
|
+
}
|
|
29579
|
+
});
|
|
29580
|
+
};
|
|
29581
|
+
|
|
29525
29582
|
const PolygonGraph = props => {
|
|
29526
|
-
var _points$length;
|
|
29527
29583
|
const [focused, setFocused] = React.useState(false);
|
|
29528
29584
|
const [hovered, setHovered] = React.useState(false);
|
|
29529
29585
|
const {
|
|
@@ -29536,17 +29592,19 @@ const PolygonGraph = props => {
|
|
|
29536
29592
|
range,
|
|
29537
29593
|
snapStep
|
|
29538
29594
|
} = props.graphState;
|
|
29595
|
+
|
|
29596
|
+
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
29597
|
+
// think coords can be null.
|
|
29539
29598
|
const points = coords != null ? coords : [[0, 0]];
|
|
29540
|
-
const pointsSum = points.reduce((acc, point) => vec.add(acc, point), [0, 0]);
|
|
29541
|
-
const midpoint = pointsSum && vec.scale(pointsSum, 1 / ((_points$length = points.length) != null ? _points$length : 1));
|
|
29542
29599
|
const ref = React.useRef(null);
|
|
29600
|
+
const dragReferencePoint = points[0];
|
|
29543
29601
|
const {
|
|
29544
29602
|
dragging
|
|
29545
29603
|
} = useMovable({
|
|
29546
29604
|
gestureTarget: ref,
|
|
29547
|
-
point:
|
|
29605
|
+
point: dragReferencePoint,
|
|
29548
29606
|
onMove: newPoint => {
|
|
29549
|
-
const delta = vec.sub(newPoint,
|
|
29607
|
+
const delta = vec.sub(newPoint, dragReferencePoint);
|
|
29550
29608
|
dispatch(moveAll(delta));
|
|
29551
29609
|
},
|
|
29552
29610
|
constrain: p => snap(snapStep, p)
|
|
@@ -43231,7 +43289,7 @@ const init = function init(options) {
|
|
|
43231
43289
|
|
|
43232
43290
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43233
43291
|
const libName = "@khanacademy/perseus";
|
|
43234
|
-
const libVersion = "22.4.
|
|
43292
|
+
const libVersion = "22.4.2";
|
|
43235
43293
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43236
43294
|
|
|
43237
43295
|
const apiVersion = {
|