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