@khanacademy/perseus 21.3.0 → 21.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +17 -1
- package/dist/es/index.js +258 -139
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +17 -1
- package/dist/index.js +254 -128
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +9 -1
- package/dist/perseus-types.d.ts +1 -21
- package/dist/renderer.d.ts +19 -16
- package/dist/server-item-renderer.d.ts +9 -1
- package/dist/strings.js +0 -4
- package/dist/types.d.ts +11 -1
- package/dist/util/svg.d.ts +9 -0
- package/dist/widgets/expression.d.ts +54 -6
- package/dist/widgets/interactive-graphs/axis-ticks.d.ts +2 -0
- package/dist/widgets/interactive-graphs/graphs/components/arrowhead.d.ts +8 -0
- package/dist/widgets/interactive-graphs/graphs/components/svg-line.d.ts +10 -0
- package/dist/widgets/interactive-graphs/graphs/components/vector.d.ts +9 -0
- package/dist/widgets/interactive-graphs/graphs/types.d.ts +2 -5
- package/dist/widgets/interactive-graphs/reducer/interactive-graph-state.d.ts +9 -8
- package/dist/widgets/interactive-graphs/reducer/use-graph-config.d.ts +10 -0
- package/dist/widgets/interactive-graphs/types.d.ts +1 -0
- package/dist/widgets/label-image.d.ts +18 -2
- package/dist/widgets/radio/radio.d.ts +5 -8
- package/package.json +1 -1
- package/dist/widgets/interactive-graphs/reducer/use-graph-state.d.ts +0 -11
- package/dist/widgets/lights-puzzle.d.ts +0 -53
- package/dist/widgets/reaction-diagram.d.ts +0 -42
package/dist/index.js
CHANGED
|
@@ -10366,7 +10366,7 @@ class WrappedPath extends WrappedDrawing {
|
|
|
10366
10366
|
}
|
|
10367
10367
|
}
|
|
10368
10368
|
|
|
10369
|
-
class Arrowhead extends WrappedPath {
|
|
10369
|
+
class Arrowhead$1 extends WrappedPath {
|
|
10370
10370
|
static scale = 1.4;
|
|
10371
10371
|
constructor(graphie, style) {
|
|
10372
10372
|
// Points that define the arrowhead
|
|
@@ -10374,7 +10374,7 @@ class Arrowhead extends WrappedPath {
|
|
|
10374
10374
|
const points = [[-3, 4], [-2.75, 2.5], [0, 0.25], center, [0, -0.25], [-2.75, -2.5], [-3, -4]].map(point => {
|
|
10375
10375
|
// Scale points by `Arrowhead.scale` around `center`
|
|
10376
10376
|
const pv = kmath.vector.subtract(point, center);
|
|
10377
|
-
const pvScaled = kmath.vector.scale(pv, Arrowhead.scale);
|
|
10377
|
+
const pvScaled = kmath.vector.scale(pv, Arrowhead$1.scale);
|
|
10378
10378
|
return kmath.vector.add(center, pvScaled);
|
|
10379
10379
|
});
|
|
10380
10380
|
const unscaledPoints = points.map(graphie.unscalePoint);
|
|
@@ -10391,7 +10391,7 @@ class Arrowhead extends WrappedPath {
|
|
|
10391
10391
|
}
|
|
10392
10392
|
toCoordAtAngle(coord, angle) {
|
|
10393
10393
|
const clipPoint = this.graphie.scalePoint(getClipPoint(this.graphie, coord, angle));
|
|
10394
|
-
this.transform("translateX(" + (clipPoint[0] + Arrowhead.scale * this.center[0]) + "px) " + "translateY(" + (clipPoint[1] + Arrowhead.scale * this.center[1]) + "px) " + "translateZ(0) " + "rotate(" + (360 - KhanMath.bound(angle)) + "deg)");
|
|
10394
|
+
this.transform("translateX(" + (clipPoint[0] + Arrowhead$1.scale * this.center[0]) + "px) " + "translateY(" + (clipPoint[1] + Arrowhead$1.scale * this.center[1]) + "px) " + "translateZ(0) " + "rotate(" + (360 - KhanMath.bound(angle)) + "deg)");
|
|
10395
10395
|
}
|
|
10396
10396
|
}
|
|
10397
10397
|
|
|
@@ -11632,10 +11632,10 @@ ___default["default"].extend(GraphUtils.Graphie.prototype, {
|
|
|
11632
11632
|
if (this._arrows == null) {
|
|
11633
11633
|
this._arrows = [];
|
|
11634
11634
|
if (this.extendLine) {
|
|
11635
|
-
this._arrows.push(new Arrowhead(graph, this.normalStyle));
|
|
11636
|
-
this._arrows.push(new Arrowhead(graph, this.normalStyle));
|
|
11635
|
+
this._arrows.push(new Arrowhead$1(graph, this.normalStyle));
|
|
11636
|
+
this._arrows.push(new Arrowhead$1(graph, this.normalStyle));
|
|
11637
11637
|
} else if (this.extendRay) {
|
|
11638
|
-
this._arrows.push(new Arrowhead(graph, this.normalStyle));
|
|
11638
|
+
this._arrows.push(new Arrowhead$1(graph, this.normalStyle));
|
|
11639
11639
|
}
|
|
11640
11640
|
}
|
|
11641
11641
|
const coordForArrow = [this.coordA, this.coordZ];
|
|
@@ -14162,16 +14162,16 @@ const draw$3 = {
|
|
|
14162
14162
|
// @ts-expect-error - TS2551 - Property '_arrows' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. Did you mean 'arrows'?
|
|
14163
14163
|
this._arrows.push(
|
|
14164
14164
|
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. | TS2339 - Property 'normalStyle' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'.
|
|
14165
|
-
new Arrowhead(this.graphie, this.normalStyle()));
|
|
14165
|
+
new Arrowhead$1(this.graphie, this.normalStyle()));
|
|
14166
14166
|
// @ts-expect-error - TS2551 - Property '_arrows' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. Did you mean 'arrows'?
|
|
14167
14167
|
this._arrows.push(
|
|
14168
14168
|
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. | TS2339 - Property 'normalStyle' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'.
|
|
14169
|
-
new Arrowhead(this.graphie, this.normalStyle()));
|
|
14169
|
+
new Arrowhead$1(this.graphie, this.normalStyle()));
|
|
14170
14170
|
} else if (state.extendRay) {
|
|
14171
14171
|
// @ts-expect-error - TS2551 - Property '_arrows' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. Did you mean 'arrows'?
|
|
14172
14172
|
this._arrows.push(
|
|
14173
14173
|
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'. | TS2339 - Property 'normalStyle' does not exist on type '{ readonly basic: (state: any) => void; readonly arrows: (state: any) => void; readonly highlight: (state: any, prevState: any) => void; }'.
|
|
14174
|
-
new Arrowhead(this.graphie, this.normalStyle()));
|
|
14174
|
+
new Arrowhead$1(this.graphie, this.normalStyle()));
|
|
14175
14175
|
}
|
|
14176
14176
|
}
|
|
14177
14177
|
|
|
@@ -19398,6 +19398,7 @@ class Renderer extends React__namespace.Component {
|
|
|
19398
19398
|
images: {},
|
|
19399
19399
|
highlightedWidgets: [],
|
|
19400
19400
|
questionCompleted: false,
|
|
19401
|
+
showSolutions: "none",
|
|
19401
19402
|
// onRender may be called multiple times per render, for example
|
|
19402
19403
|
// if there are multiple images or TeX pieces within `content`.
|
|
19403
19404
|
// It is a good idea to debounce any functions passed here.
|
|
@@ -19688,6 +19689,7 @@ class Renderer extends React__namespace.Component {
|
|
|
19688
19689
|
apiOptions: this.getApiOptions(),
|
|
19689
19690
|
keypadElement: this.props.keypadElement,
|
|
19690
19691
|
questionCompleted: this.props.questionCompleted,
|
|
19692
|
+
showSolutions: this.props.showSolutions,
|
|
19691
19693
|
onFocus: ___default["default"].partial(this._onWidgetFocus, id),
|
|
19692
19694
|
onBlur: ___default["default"].partial(this._onWidgetBlur, id),
|
|
19693
19695
|
findWidgets: this.findWidgets,
|
|
@@ -23171,14 +23173,6 @@ const ellipsisHorizontalIcon = {
|
|
|
23171
23173
|
width: 100,
|
|
23172
23174
|
height: 27.284
|
|
23173
23175
|
};
|
|
23174
|
-
// Note(TB): Received errors when using useUniqueIdWithMock
|
|
23175
|
-
// so created this workaround function. Will update when
|
|
23176
|
-
// useUniqueIdWithMock is available.
|
|
23177
|
-
// https://khanacademy.atlassian.net/browse/FEI-4861?atlOrigin=eyJpIjoiNDJlZWMwNjM1NWJhNDBkMWFjY2FmN2I0ZjcxZmQxOGUiLCJwIjoiaiJ9
|
|
23178
|
-
let id = 0;
|
|
23179
|
-
function uniqueId() {
|
|
23180
|
-
return `choice-${id++}`;
|
|
23181
|
-
}
|
|
23182
23176
|
const Choice = function (props) {
|
|
23183
23177
|
const {
|
|
23184
23178
|
disabled = false,
|
|
@@ -23228,7 +23222,8 @@ const Choice = function (props) {
|
|
|
23228
23222
|
const showDimmed = !reviewMode && apiOptions.readOnly || crossedOut;
|
|
23229
23223
|
const letter = getChoiceLetter(pos);
|
|
23230
23224
|
const a11yText = getA11yText(letter, checked, correct, crossedOut, showCorrectness);
|
|
23231
|
-
const
|
|
23225
|
+
const idFactory = wonderBlocksCore.useUniqueIdWithMock(`choice`);
|
|
23226
|
+
const choiceId = idFactory.get(letter);
|
|
23232
23227
|
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
23233
23228
|
style: {
|
|
23234
23229
|
// @ts-expect-error - TS2322 - Type '{ dispay: string; flexDirection: "column"; color: string; }' is not assignable to type 'Properties<string | number, string & {}>'.
|
|
@@ -23815,7 +23810,8 @@ class Radio$1 extends React__namespace.Component {
|
|
|
23815
23810
|
multipleSelect: false,
|
|
23816
23811
|
countChoices: false,
|
|
23817
23812
|
deselectEnabled: false,
|
|
23818
|
-
linterContext: PerseusLinter.linterContextDefault
|
|
23813
|
+
linterContext: PerseusLinter.linterContextDefault,
|
|
23814
|
+
showSolutions: "none"
|
|
23819
23815
|
};
|
|
23820
23816
|
static validate(userInput, rubric) {
|
|
23821
23817
|
const numSelected = userInput.choicesSelected.reduce((sum, selected) => {
|
|
@@ -23925,6 +23921,11 @@ class Radio$1 extends React__namespace.Component {
|
|
|
23925
23921
|
choicesSelected: props.choices.map(() => false)
|
|
23926
23922
|
};
|
|
23927
23923
|
}
|
|
23924
|
+
componentDidUpdate(prevProps) {
|
|
23925
|
+
if (this.props.showSolutions === "selected" && prevProps.showSolutions !== "selected") {
|
|
23926
|
+
this.showRationalesForCurrentlySelectedChoices(this.props);
|
|
23927
|
+
}
|
|
23928
|
+
}
|
|
23928
23929
|
_renderRenderer = (() => {
|
|
23929
23930
|
var _this = this;
|
|
23930
23931
|
return function () {
|
|
@@ -24047,6 +24048,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24047
24048
|
* Turn on rationale display for the currently selected choices. Note that
|
|
24048
24049
|
* this leaves rationales on for choices that are already showing
|
|
24049
24050
|
* rationales.
|
|
24051
|
+
* @deprecated Internal only. Use `showSolutions` prop instead.
|
|
24050
24052
|
*/
|
|
24051
24053
|
showRationalesForCurrentlySelectedChoices = rubric => {
|
|
24052
24054
|
const {
|
|
@@ -24068,7 +24070,7 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24068
24070
|
// We use the same behavior for the readOnly flag as for
|
|
24069
24071
|
// rationaleShown, but we keep it separate in case other
|
|
24070
24072
|
// behaviors want to disable choices without showing rationales.
|
|
24071
|
-
readOnly: state.selected || state.readOnly || widgetCorrect,
|
|
24073
|
+
readOnly: state.selected || state.readOnly || widgetCorrect || this.props.showSolutions !== "none",
|
|
24072
24074
|
correctnessShown: state.selected || state.correctnessShown,
|
|
24073
24075
|
previouslyAnswered: state.previouslyAnswered || state.selected
|
|
24074
24076
|
}));
|
|
@@ -24119,6 +24121,23 @@ class Radio$1 extends React__namespace.Component {
|
|
|
24119
24121
|
correctnessShown: true,
|
|
24120
24122
|
previouslyAnswered: false
|
|
24121
24123
|
}));
|
|
24124
|
+
} else if (this.props.showSolutions === "all") {
|
|
24125
|
+
choiceStates = choices.map(_ref => {
|
|
24126
|
+
let {
|
|
24127
|
+
correct
|
|
24128
|
+
} = _ref;
|
|
24129
|
+
return {
|
|
24130
|
+
selected: correct,
|
|
24131
|
+
// to draw the eye to the correct answer
|
|
24132
|
+
crossedOut: false,
|
|
24133
|
+
readOnly: true,
|
|
24134
|
+
highlighted: false,
|
|
24135
|
+
// has no effect in this mode
|
|
24136
|
+
rationaleShown: true,
|
|
24137
|
+
correctnessShown: true,
|
|
24138
|
+
previouslyAnswered: false
|
|
24139
|
+
};
|
|
24140
|
+
});
|
|
24122
24141
|
} else if (this.props.choiceStates) {
|
|
24123
24142
|
choiceStates = this.props.choiceStates;
|
|
24124
24143
|
} else if (this.props.values) {
|
|
@@ -28477,6 +28496,118 @@ const getLines = points => points.map((point, i) => {
|
|
|
28477
28496
|
return [point, next];
|
|
28478
28497
|
});
|
|
28479
28498
|
|
|
28499
|
+
function SVGLine(props) {
|
|
28500
|
+
const {
|
|
28501
|
+
start,
|
|
28502
|
+
end,
|
|
28503
|
+
style,
|
|
28504
|
+
className,
|
|
28505
|
+
testId
|
|
28506
|
+
} = props;
|
|
28507
|
+
return /*#__PURE__*/React__namespace.createElement("line", {
|
|
28508
|
+
x1: start[0],
|
|
28509
|
+
y1: start[1],
|
|
28510
|
+
x2: end[0],
|
|
28511
|
+
y2: end[1],
|
|
28512
|
+
style: style,
|
|
28513
|
+
className: `${className}`,
|
|
28514
|
+
"data-test-id": testId
|
|
28515
|
+
});
|
|
28516
|
+
}
|
|
28517
|
+
|
|
28518
|
+
function pathBuilder() {
|
|
28519
|
+
return new PathBuilder();
|
|
28520
|
+
}
|
|
28521
|
+
class PathBuilder {
|
|
28522
|
+
path = [];
|
|
28523
|
+
scaleFactor = 1;
|
|
28524
|
+
build() {
|
|
28525
|
+
return this.path.map(scaleCommandBy(this.scaleFactor)).map(commandToString).join("");
|
|
28526
|
+
}
|
|
28527
|
+
|
|
28528
|
+
// add a move (M) command to the path
|
|
28529
|
+
move(x, y) {
|
|
28530
|
+
this.path.push({
|
|
28531
|
+
action: "M",
|
|
28532
|
+
coords: [x, y]
|
|
28533
|
+
});
|
|
28534
|
+
return this;
|
|
28535
|
+
}
|
|
28536
|
+
|
|
28537
|
+
// add a curve (C) command to the path
|
|
28538
|
+
curve(control1X, control1Y, control2X, control2Y, endX, endY) {
|
|
28539
|
+
this.path.push({
|
|
28540
|
+
action: "C",
|
|
28541
|
+
coords: [control1X, control1Y, control2X, control2Y, endX, endY]
|
|
28542
|
+
});
|
|
28543
|
+
return this;
|
|
28544
|
+
}
|
|
28545
|
+
|
|
28546
|
+
// Scale all coordinates of the path by a factor
|
|
28547
|
+
scale(factor) {
|
|
28548
|
+
this.scaleFactor *= factor;
|
|
28549
|
+
return this;
|
|
28550
|
+
}
|
|
28551
|
+
}
|
|
28552
|
+
function commandToString(command) {
|
|
28553
|
+
return `${command.action}${command.coords.join(" ")}`;
|
|
28554
|
+
}
|
|
28555
|
+
function scaleCommandBy(scaleFactor) {
|
|
28556
|
+
return command => ({
|
|
28557
|
+
...command,
|
|
28558
|
+
coords: command.coords.map(c => c * scaleFactor)
|
|
28559
|
+
});
|
|
28560
|
+
}
|
|
28561
|
+
|
|
28562
|
+
// We use the pathBuilder here to scale up the SVG path coordinates used
|
|
28563
|
+
// elsewhere for arrowheads. We scale in the path itself instead of using a CSS
|
|
28564
|
+
// transform because a transform would also scale up the stroke weight, and we
|
|
28565
|
+
// don't want that.
|
|
28566
|
+
const arrowPath = pathBuilder().move(-3, 4).curve(-2.75, 2.5, 0, 0.25, 0.75, 0).curve(0, -0.25, -2.75, -2.5, -3, -4).scale(1.4).build();
|
|
28567
|
+
function Arrowhead(props) {
|
|
28568
|
+
const [point] = useTransform([props.x, props.y]);
|
|
28569
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
28570
|
+
transform: `translate(${point[0]} ${point[1]}) rotate(${-props.angle})`
|
|
28571
|
+
}, /*#__PURE__*/React__namespace.createElement("g", {
|
|
28572
|
+
transform: "translate(-1.5)"
|
|
28573
|
+
}, /*#__PURE__*/React__namespace.createElement("path", {
|
|
28574
|
+
d: arrowPath,
|
|
28575
|
+
fill: "none",
|
|
28576
|
+
style: {
|
|
28577
|
+
stroke: "inherit"
|
|
28578
|
+
},
|
|
28579
|
+
strokeLinejoin: "round",
|
|
28580
|
+
strokeLinecap: "round"
|
|
28581
|
+
})));
|
|
28582
|
+
}
|
|
28583
|
+
|
|
28584
|
+
function Vector(props) {
|
|
28585
|
+
const {
|
|
28586
|
+
tail,
|
|
28587
|
+
tip,
|
|
28588
|
+
color
|
|
28589
|
+
} = props;
|
|
28590
|
+
const [tailPx, tipPx] = useTransform(tail, tip);
|
|
28591
|
+
const direction = mafs.vec.sub(tip, tail);
|
|
28592
|
+
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
28593
|
+
style: {
|
|
28594
|
+
stroke: color,
|
|
28595
|
+
strokeWidth: 2
|
|
28596
|
+
}
|
|
28597
|
+
}, /*#__PURE__*/React__namespace.createElement(SVGLine, {
|
|
28598
|
+
start: tailPx,
|
|
28599
|
+
end: tipPx
|
|
28600
|
+
}), /*#__PURE__*/React__namespace.createElement(Arrowhead, {
|
|
28601
|
+
x: tip[0],
|
|
28602
|
+
y: tip[1],
|
|
28603
|
+
angle: angleDegrees(direction)
|
|
28604
|
+
}));
|
|
28605
|
+
}
|
|
28606
|
+
function angleDegrees(_ref) {
|
|
28607
|
+
let [x, y] = _ref;
|
|
28608
|
+
return Math.atan2(y, x) * 180 / Math.PI;
|
|
28609
|
+
}
|
|
28610
|
+
|
|
28480
28611
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
28481
28612
|
const MovableLine = props => {
|
|
28482
28613
|
const {
|
|
@@ -28537,45 +28668,27 @@ const MovableLine = props => {
|
|
|
28537
28668
|
stroke,
|
|
28538
28669
|
strokeWidth: "var(--movable-line-stroke-weight)"
|
|
28539
28670
|
},
|
|
28540
|
-
dragging:
|
|
28671
|
+
className: dragging ? "movable-dragging" : "",
|
|
28541
28672
|
testId: "movable-line__line"
|
|
28542
|
-
})), startExtend && /*#__PURE__*/React__namespace.createElement(
|
|
28673
|
+
})), startExtend && /*#__PURE__*/React__namespace.createElement(Vector, {
|
|
28543
28674
|
tail: start,
|
|
28544
28675
|
tip: startExtend,
|
|
28545
28676
|
color: stroke
|
|
28546
|
-
}), endExtend && /*#__PURE__*/React__namespace.createElement(
|
|
28677
|
+
}), endExtend && /*#__PURE__*/React__namespace.createElement(Vector, {
|
|
28547
28678
|
tail: end,
|
|
28548
28679
|
tip: endExtend,
|
|
28549
28680
|
color: stroke
|
|
28550
28681
|
}));
|
|
28551
28682
|
};
|
|
28552
|
-
function SVGLine(props) {
|
|
28553
|
-
const {
|
|
28554
|
-
start,
|
|
28555
|
-
end,
|
|
28556
|
-
style,
|
|
28557
|
-
dragging,
|
|
28558
|
-
className,
|
|
28559
|
-
testId
|
|
28560
|
-
} = props;
|
|
28561
|
-
const draggingClass = dragging ? "movable-dragging" : "";
|
|
28562
|
-
return /*#__PURE__*/React__namespace.createElement("line", {
|
|
28563
|
-
x1: start[0],
|
|
28564
|
-
y1: start[1],
|
|
28565
|
-
x2: end[0],
|
|
28566
|
-
y2: end[1],
|
|
28567
|
-
style: style,
|
|
28568
|
-
className: `${className} ${draggingClass}`,
|
|
28569
|
-
"data-test-id": testId
|
|
28570
|
-
});
|
|
28571
|
-
}
|
|
28572
28683
|
|
|
28573
|
-
const
|
|
28574
|
-
|
|
28575
|
-
|
|
28576
|
-
|
|
28577
|
-
|
|
28578
|
-
|
|
28684
|
+
const defaultGraphConfig = {
|
|
28685
|
+
range: [[0, 1], [0, 1]],
|
|
28686
|
+
snapStep: [1, 1],
|
|
28687
|
+
markings: "none"
|
|
28688
|
+
};
|
|
28689
|
+
const GraphConfigContext = /*#__PURE__*/React.createContext(defaultGraphConfig);
|
|
28690
|
+
function useGraphConfig() {
|
|
28691
|
+
return React__default["default"].useContext(GraphConfigContext);
|
|
28579
28692
|
}
|
|
28580
28693
|
|
|
28581
28694
|
// The hitbox size of 48px by 48px is preserved from the legacy interactive
|
|
@@ -28583,8 +28696,10 @@ function useGraphState() {
|
|
|
28583
28696
|
const hitboxSizePx = 48;
|
|
28584
28697
|
const StyledMovablePoint = props => {
|
|
28585
28698
|
const {
|
|
28586
|
-
|
|
28587
|
-
|
|
28699
|
+
range,
|
|
28700
|
+
snapStep,
|
|
28701
|
+
markings
|
|
28702
|
+
} = useGraphConfig();
|
|
28588
28703
|
const hitboxRef = React.useRef(null);
|
|
28589
28704
|
const {
|
|
28590
28705
|
point,
|
|
@@ -28597,17 +28712,34 @@ const StyledMovablePoint = props => {
|
|
|
28597
28712
|
gestureTarget: hitboxRef,
|
|
28598
28713
|
point,
|
|
28599
28714
|
onMove,
|
|
28600
|
-
constrain: p => snap(
|
|
28715
|
+
constrain: p => snap(snapStep, p)
|
|
28601
28716
|
});
|
|
28717
|
+
const pointClasses = `movable-point ${dragging ? "movable-point--dragging" : ""}`;
|
|
28602
28718
|
const [[x, y]] = useTransform(point);
|
|
28603
|
-
|
|
28719
|
+
const [xMin, xMax] = range[0];
|
|
28720
|
+
const [yMin, yMax] = range[1];
|
|
28721
|
+
const [[verticalStartX]] = useTransform([xMin, 0]);
|
|
28722
|
+
const [[verticalEndX]] = useTransform([xMax, 0]);
|
|
28723
|
+
const [[_, horizontalStartY]] = useTransform([0, yMin]);
|
|
28724
|
+
const [[__, horizontalEndY]] = useTransform([0, yMax]);
|
|
28725
|
+
const showHairlines = dragging && markings !== "none";
|
|
28726
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, showHairlines && /*#__PURE__*/React__namespace.createElement("g", null, /*#__PURE__*/React__namespace.createElement("line", {
|
|
28727
|
+
x1: verticalStartX,
|
|
28728
|
+
y1: y,
|
|
28729
|
+
x2: verticalEndX,
|
|
28730
|
+
y2: y,
|
|
28731
|
+
stroke: wonderBlocksTokens.color.green
|
|
28732
|
+
}), /*#__PURE__*/React__namespace.createElement("line", {
|
|
28733
|
+
x1: x,
|
|
28734
|
+
y1: horizontalStartY,
|
|
28735
|
+
x2: x,
|
|
28736
|
+
y2: horizontalEndY,
|
|
28737
|
+
stroke: wonderBlocksTokens.color.green
|
|
28738
|
+
})), /*#__PURE__*/React__namespace.createElement("g", {
|
|
28604
28739
|
ref: hitboxRef,
|
|
28605
|
-
className:
|
|
28740
|
+
className: pointClasses,
|
|
28606
28741
|
tabIndex: 0,
|
|
28607
28742
|
style: {
|
|
28608
|
-
cursor: dragging ? "grabbing" : "grab",
|
|
28609
|
-
touchAction: "none",
|
|
28610
|
-
outline: "none",
|
|
28611
28743
|
"--movable-point-color": color
|
|
28612
28744
|
},
|
|
28613
28745
|
"data-test-id": "movable-point"
|
|
@@ -28636,7 +28768,7 @@ const StyledMovablePoint = props => {
|
|
|
28636
28768
|
fill: color
|
|
28637
28769
|
},
|
|
28638
28770
|
"data-test-id": "movable-point__center"
|
|
28639
|
-
}));
|
|
28771
|
+
})));
|
|
28640
28772
|
};
|
|
28641
28773
|
|
|
28642
28774
|
const SegmentGraph = props => {
|
|
@@ -28644,15 +28776,11 @@ const SegmentGraph = props => {
|
|
|
28644
28776
|
dispatch
|
|
28645
28777
|
} = props;
|
|
28646
28778
|
const {
|
|
28647
|
-
coords: segments
|
|
28648
|
-
snapStep,
|
|
28649
|
-
range
|
|
28779
|
+
coords: segments
|
|
28650
28780
|
} = props.graphState;
|
|
28651
28781
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, segments?.map((segment, i) => /*#__PURE__*/React__namespace.createElement(SegmentView, {
|
|
28652
28782
|
key: i,
|
|
28653
|
-
|
|
28654
|
-
snaps: snapStep,
|
|
28655
|
-
range: range,
|
|
28783
|
+
points: segment,
|
|
28656
28784
|
onMoveLine: delta => {
|
|
28657
28785
|
dispatch(moveLine(i, delta));
|
|
28658
28786
|
},
|
|
@@ -28665,7 +28793,7 @@ const SegmentGraph = props => {
|
|
|
28665
28793
|
const SegmentView = props => {
|
|
28666
28794
|
const {
|
|
28667
28795
|
onMoveLine: onMoveSegment,
|
|
28668
|
-
|
|
28796
|
+
points: [start, end]
|
|
28669
28797
|
} = props;
|
|
28670
28798
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
28671
28799
|
start: start,
|
|
@@ -28690,16 +28818,12 @@ const LinearGraph = props => {
|
|
|
28690
28818
|
} = props;
|
|
28691
28819
|
const {
|
|
28692
28820
|
coords: lines,
|
|
28693
|
-
snapStep,
|
|
28694
|
-
range,
|
|
28695
28821
|
type
|
|
28696
28822
|
} = props.graphState;
|
|
28697
28823
|
const colors = ["var(--movable-line-stroke-color)", "var(--mafs-violet)"];
|
|
28698
28824
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, lines?.map((line, i) => /*#__PURE__*/React__namespace.createElement(LineView, {
|
|
28699
28825
|
key: i,
|
|
28700
|
-
|
|
28701
|
-
snaps: snapStep,
|
|
28702
|
-
range: range,
|
|
28826
|
+
points: line,
|
|
28703
28827
|
onMoveLine: delta => {
|
|
28704
28828
|
dispatch(moveLine(i, delta));
|
|
28705
28829
|
},
|
|
@@ -28714,10 +28838,12 @@ const LineView = props => {
|
|
|
28714
28838
|
const {
|
|
28715
28839
|
onMoveLine,
|
|
28716
28840
|
onMovePoint,
|
|
28717
|
-
|
|
28718
|
-
range,
|
|
28841
|
+
points: [start, end],
|
|
28719
28842
|
stroke
|
|
28720
28843
|
} = props;
|
|
28844
|
+
const {
|
|
28845
|
+
range
|
|
28846
|
+
} = useGraphConfig();
|
|
28721
28847
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(MovableLine, {
|
|
28722
28848
|
start: start,
|
|
28723
28849
|
end: end,
|
|
@@ -29039,46 +29165,26 @@ function PointGraph(props) {
|
|
|
29039
29165
|
})));
|
|
29040
29166
|
}
|
|
29041
29167
|
|
|
29042
|
-
function Arrow(props) {
|
|
29043
|
-
const {
|
|
29044
|
-
userTransform,
|
|
29045
|
-
viewTransform
|
|
29046
|
-
} = mafs.useTransformContext();
|
|
29047
|
-
const point = [props.x, props.y];
|
|
29048
|
-
const userTransformedPoint = mafs.vec.transform(point, userTransform);
|
|
29049
|
-
const viewTransformedPoint = mafs.vec.transform(userTransformedPoint, viewTransform);
|
|
29050
|
-
return /*#__PURE__*/React__default["default"].createElement("g", {
|
|
29051
|
-
transform: `translate(${viewTransformedPoint[0]} ${viewTransformedPoint[1]}) rotate(${props.rotate}) scale(1.25)`
|
|
29052
|
-
}, /*#__PURE__*/React__default["default"].createElement("g", {
|
|
29053
|
-
transform: "translate(-1)"
|
|
29054
|
-
}, /*#__PURE__*/React__default["default"].createElement("path", {
|
|
29055
|
-
d: "M-3 4 C-2.75 2.5 0 0.25 0.75 0C0 -0.25 -2.75 -2.5 -3 -4",
|
|
29056
|
-
fill: "none"
|
|
29057
|
-
})));
|
|
29058
|
-
}
|
|
29059
29168
|
function AxisArrows() {
|
|
29060
29169
|
const {
|
|
29061
|
-
|
|
29062
|
-
} =
|
|
29063
|
-
|
|
29064
|
-
const [xMin, xMax] = range[0];
|
|
29065
|
-
const [yMin, yMax] = range[1];
|
|
29066
|
-
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Arrow, {
|
|
29170
|
+
range: [[xMin, xMax], [yMin, yMax]]
|
|
29171
|
+
} = useGraphConfig();
|
|
29172
|
+
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29067
29173
|
x: xMax,
|
|
29068
29174
|
y: 0,
|
|
29069
|
-
|
|
29070
|
-
}), /*#__PURE__*/React__default["default"].createElement(
|
|
29175
|
+
angle: 0
|
|
29176
|
+
}), /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29071
29177
|
x: 0,
|
|
29072
29178
|
y: yMin,
|
|
29073
|
-
|
|
29074
|
-
}), /*#__PURE__*/React__default["default"].createElement(
|
|
29179
|
+
angle: 90
|
|
29180
|
+
}), /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29075
29181
|
x: xMin,
|
|
29076
29182
|
y: 0,
|
|
29077
|
-
|
|
29078
|
-
}), /*#__PURE__*/React__default["default"].createElement(
|
|
29183
|
+
angle: 180
|
|
29184
|
+
}), /*#__PURE__*/React__default["default"].createElement(Arrowhead, {
|
|
29079
29185
|
x: 0,
|
|
29080
29186
|
y: yMax,
|
|
29081
|
-
|
|
29187
|
+
angle: 270
|
|
29082
29188
|
}));
|
|
29083
29189
|
}
|
|
29084
29190
|
|
|
@@ -29087,9 +29193,20 @@ const tickStyle = {
|
|
|
29087
29193
|
stroke: "black",
|
|
29088
29194
|
strokeWidth: 1
|
|
29089
29195
|
};
|
|
29196
|
+
|
|
29197
|
+
// We only want to show the initial negative tick labels (e.g. -1) on each
|
|
29198
|
+
// axis if the tickStep > gridStep, to ensure that these labels do not overlap.
|
|
29199
|
+
// e.g. If gridStep = 1 and tickStep = 2, there are 2 grid lines for every 1 tick,
|
|
29200
|
+
// which allows enough room for both these tick labels to render.
|
|
29201
|
+
const showTickLabel = (gridStep, tickStep, label) => {
|
|
29202
|
+
const showLabel = tickStep > gridStep ? true : label !== -tickStep;
|
|
29203
|
+
return showLabel;
|
|
29204
|
+
};
|
|
29090
29205
|
const YGridTick = _ref => {
|
|
29091
29206
|
let {
|
|
29092
|
-
y
|
|
29207
|
+
y,
|
|
29208
|
+
gridStep,
|
|
29209
|
+
tickStep
|
|
29093
29210
|
} = _ref;
|
|
29094
29211
|
const pointOnAxis = [0, y];
|
|
29095
29212
|
const [[xPosition, yPosition]] = useTransform(pointOnAxis);
|
|
@@ -29101,7 +29218,7 @@ const YGridTick = _ref => {
|
|
|
29101
29218
|
x2: xPosition + tickSize / 2,
|
|
29102
29219
|
y2: yPosition,
|
|
29103
29220
|
style: tickStyle
|
|
29104
|
-
}),
|
|
29221
|
+
}), showTickLabel(gridStep, tickStep, y) && /*#__PURE__*/React__namespace.createElement("text", {
|
|
29105
29222
|
height: 20,
|
|
29106
29223
|
width: 50,
|
|
29107
29224
|
textAnchor: "end",
|
|
@@ -29111,7 +29228,9 @@ const YGridTick = _ref => {
|
|
|
29111
29228
|
};
|
|
29112
29229
|
const XGridTick = _ref2 => {
|
|
29113
29230
|
let {
|
|
29114
|
-
x
|
|
29231
|
+
x,
|
|
29232
|
+
gridStep,
|
|
29233
|
+
tickStep
|
|
29115
29234
|
} = _ref2;
|
|
29116
29235
|
const pointOnAxis = [x, 0];
|
|
29117
29236
|
const [[xPosition, yPosition]] = useTransform(pointOnAxis);
|
|
@@ -29123,7 +29242,7 @@ const XGridTick = _ref2 => {
|
|
|
29123
29242
|
x2: xPosition,
|
|
29124
29243
|
y2: yPosition - tickSize / 2,
|
|
29125
29244
|
style: tickStyle
|
|
29126
|
-
}),
|
|
29245
|
+
}), showTickLabel(gridStep, tickStep, x) && /*#__PURE__*/React__namespace.createElement("text", {
|
|
29127
29246
|
height: 20,
|
|
29128
29247
|
width: 50,
|
|
29129
29248
|
textAnchor: "middle",
|
|
@@ -29158,12 +29277,16 @@ const AxisTicks = props => {
|
|
|
29158
29277
|
}, yGridTicks.map(y => {
|
|
29159
29278
|
return /*#__PURE__*/React__namespace.createElement(YGridTick, {
|
|
29160
29279
|
y: y,
|
|
29161
|
-
key: `y-grid-tick-${y}
|
|
29280
|
+
key: `y-grid-tick-${y}`,
|
|
29281
|
+
gridStep: props.gridStep[0],
|
|
29282
|
+
tickStep: yTickStep
|
|
29162
29283
|
});
|
|
29163
29284
|
}), xGridTicks.map(x => {
|
|
29164
29285
|
return /*#__PURE__*/React__namespace.createElement(XGridTick, {
|
|
29165
29286
|
x: x,
|
|
29166
|
-
key: `x-grid-tick-${x}
|
|
29287
|
+
key: `x-grid-tick-${x}`,
|
|
29288
|
+
gridStep: props.gridStep[1],
|
|
29289
|
+
tickStep: xTickStep
|
|
29167
29290
|
});
|
|
29168
29291
|
}));
|
|
29169
29292
|
};
|
|
@@ -29189,10 +29312,13 @@ const Grid = props => {
|
|
|
29189
29312
|
return props.markings === "none" ? null : /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Coordinates.Cartesian, {
|
|
29190
29313
|
xAxis: axisOptions(props, 0),
|
|
29191
29314
|
yAxis: axisOptions(props, 1)
|
|
29192
|
-
}), /*#__PURE__*/React__namespace.createElement(
|
|
29315
|
+
}), props.markings === "graph" && /*#__PURE__*/React__namespace.createElement(AxisArrows, null),
|
|
29316
|
+
// Only render the axis ticks and arrows if the markings are set to a full "graph"
|
|
29317
|
+
props.markings === "graph" && /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(AxisTicks, {
|
|
29193
29318
|
range: props.range,
|
|
29194
|
-
tickStep: props.tickStep
|
|
29195
|
-
|
|
29319
|
+
tickStep: props.tickStep,
|
|
29320
|
+
gridStep: props.gridStep
|
|
29321
|
+
}), /*#__PURE__*/React__namespace.createElement(AxisArrows, null)));
|
|
29196
29322
|
};
|
|
29197
29323
|
|
|
29198
29324
|
// Displays a stylized open eye: lint warnings are visible
|
|
@@ -30163,15 +30289,20 @@ function initializeGraphState(params) {
|
|
|
30163
30289
|
graph,
|
|
30164
30290
|
step,
|
|
30165
30291
|
snapStep,
|
|
30166
|
-
range
|
|
30292
|
+
range,
|
|
30293
|
+
markings
|
|
30167
30294
|
} = params;
|
|
30295
|
+
const shared = {
|
|
30296
|
+
hasBeenInteractedWith: false,
|
|
30297
|
+
range,
|
|
30298
|
+
snapStep,
|
|
30299
|
+
markings
|
|
30300
|
+
};
|
|
30168
30301
|
switch (graph.type) {
|
|
30169
30302
|
case "segment":
|
|
30170
30303
|
return {
|
|
30304
|
+
...shared,
|
|
30171
30305
|
type: "segment",
|
|
30172
|
-
hasBeenInteractedWith: false,
|
|
30173
|
-
range,
|
|
30174
|
-
snapStep,
|
|
30175
30306
|
coords: getDefaultSegments({
|
|
30176
30307
|
graph,
|
|
30177
30308
|
step,
|
|
@@ -30182,10 +30313,8 @@ function initializeGraphState(params) {
|
|
|
30182
30313
|
case "linear-system":
|
|
30183
30314
|
case "ray":
|
|
30184
30315
|
return {
|
|
30316
|
+
...shared,
|
|
30185
30317
|
type: graph.type,
|
|
30186
|
-
hasBeenInteractedWith: false,
|
|
30187
|
-
range,
|
|
30188
|
-
snapStep,
|
|
30189
30318
|
// Linear and ray graphs have a single tuple of points, while a
|
|
30190
30319
|
// linear system has two tuples of points.
|
|
30191
30320
|
coords: getLineCoords({
|
|
@@ -30196,10 +30325,8 @@ function initializeGraphState(params) {
|
|
|
30196
30325
|
};
|
|
30197
30326
|
case "polygon":
|
|
30198
30327
|
return {
|
|
30328
|
+
...shared,
|
|
30199
30329
|
type: "polygon",
|
|
30200
|
-
hasBeenInteractedWith: false,
|
|
30201
|
-
range,
|
|
30202
|
-
snapStep,
|
|
30203
30330
|
showAngles: Boolean(graph.showAngles),
|
|
30204
30331
|
showSides: Boolean(graph.showSides),
|
|
30205
30332
|
coords: getPolygonCoords({
|
|
@@ -30210,10 +30337,8 @@ function initializeGraphState(params) {
|
|
|
30210
30337
|
};
|
|
30211
30338
|
case "point":
|
|
30212
30339
|
return {
|
|
30340
|
+
...shared,
|
|
30213
30341
|
type: graph.type,
|
|
30214
|
-
hasBeenInteractedWith: false,
|
|
30215
|
-
range,
|
|
30216
|
-
snapStep,
|
|
30217
30342
|
coords: getDefaultPoints({
|
|
30218
30343
|
graph,
|
|
30219
30344
|
step,
|
|
@@ -30466,10 +30591,11 @@ const MafsGraph = props => {
|
|
|
30466
30591
|
React.useEffect(() => {
|
|
30467
30592
|
dispatch(changeRange([[xMinRange, xMaxRange], [yMinRange, yMaxRange]]));
|
|
30468
30593
|
}, [dispatch, xMinRange, xMaxRange, yMinRange, yMaxRange]);
|
|
30469
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
30594
|
+
return /*#__PURE__*/React__namespace.createElement(GraphConfigContext.Provider, {
|
|
30470
30595
|
value: {
|
|
30471
|
-
state,
|
|
30472
|
-
|
|
30596
|
+
range: state.range,
|
|
30597
|
+
snapStep: state.snapStep,
|
|
30598
|
+
markings: props.markings
|
|
30473
30599
|
}
|
|
30474
30600
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
30475
30601
|
style: {
|
|
@@ -42518,7 +42644,7 @@ const init = function (options) {
|
|
|
42518
42644
|
|
|
42519
42645
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
42520
42646
|
const libName = "@khanacademy/perseus";
|
|
42521
|
-
const libVersion = "21.
|
|
42647
|
+
const libVersion = "21.4.0";
|
|
42522
42648
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
42523
42649
|
|
|
42524
42650
|
const apiVersion = {
|