@khanacademy/perseus 22.7.0 → 23.0.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 +2 -14
- package/dist/es/index.js +118 -27
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +2 -14
- package/dist/index.js +120 -26
- package/dist/index.js.map +1 -1
- package/dist/perseus-api.d.ts +1 -6
- package/dist/perseus-types.d.ts +1 -2
- package/dist/server-item-renderer.d.ts +1 -2
- package/dist/types.d.ts +1 -8
- package/dist/widgets/definition.d.ts +0 -1
- package/dist/widgets/explanation.d.ts +0 -1
- package/dist/widgets/expression.d.ts +8 -26
- package/dist/widgets/interactive-graph.d.ts +2 -1
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/quadratic.d.ts +9 -0
- package/dist/widgets/interactive-graphs/mafs-supported-graph-types.d.ts +1 -1
- package/dist/widgets/interactive-graphs/types.d.ts +5 -1
- package/dist/widgets/label-image.d.ts +2 -4
- package/dist/widgets/matcher.d.ts +0 -2
- package/dist/widgets/sorter.d.ts +0 -2
- package/package.json +4 -4
package/dist/es/index.css
CHANGED
|
@@ -4177,6 +4177,7 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4177
4177
|
--mafs-origin-color: var(--mafs-fg);
|
|
4178
4178
|
--mafs-line-color: #555;
|
|
4179
4179
|
--mafs-line-stroke-dash-style: 4, 3;
|
|
4180
|
+
--mafs-axis-stroke-width: 1px;
|
|
4180
4181
|
--grid-line-subdivision-color: #222;
|
|
4181
4182
|
|
|
4182
4183
|
--mafs-red: #f11d0e;
|
|
@@ -4488,7 +4489,7 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4488
4489
|
}
|
|
4489
4490
|
|
|
4490
4491
|
.MafsView pattern g {
|
|
4491
|
-
stroke:
|
|
4492
|
+
stroke: rgba(33, 36, 44, 0.32);
|
|
4492
4493
|
}
|
|
4493
4494
|
.axis-tick-labels {
|
|
4494
4495
|
font-size: 14px;
|
|
@@ -4524,19 +4525,6 @@ html body .mq-editable-field .mq-selection .mq-nthroot-container * {
|
|
|
4524
4525
|
transform: translateY(calc(-100% + 0.25em));
|
|
4525
4526
|
}
|
|
4526
4527
|
|
|
4527
|
-
.x-axis-tick-labels span,
|
|
4528
|
-
.y-axis-tick-labels span {
|
|
4529
|
-
/* The negative sign is rendered as a pseudo-element to
|
|
4530
|
-
ensure that we are positioning all labels correctly */
|
|
4531
|
-
&::before {
|
|
4532
|
-
content: attr(data-content);
|
|
4533
|
-
position: absolute;
|
|
4534
|
-
/* We're translating the symbol up by 1px to ensure it's legible around gridlines. */
|
|
4535
|
-
transform: translate(-100%, -1px);
|
|
4536
|
-
font-weight: 600; /* This helps get the symbol to render crisply */
|
|
4537
|
-
}
|
|
4538
|
-
}
|
|
4539
|
-
|
|
4540
4528
|
.y-axis-tick-labels span {
|
|
4541
4529
|
display: inline-block;
|
|
4542
4530
|
height: var(--y-axis-label-height, 20px);
|
package/dist/es/index.js
CHANGED
|
@@ -29,7 +29,7 @@ import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-block
|
|
|
29
29
|
import caretDown from '@phosphor-icons/core/regular/caret-down.svg';
|
|
30
30
|
import caretUp from '@phosphor-icons/core/regular/caret-up.svg';
|
|
31
31
|
import debounce$2 from 'lodash.debounce';
|
|
32
|
-
import { vec, Line as Line$4, Point as Point$2, useMovable, Text as Text$1, Polygon, Coordinates, Mafs } from 'mafs';
|
|
32
|
+
import { vec, Line as Line$4, Point as Point$2, useMovable, Text as Text$1, Polygon, Plot as Plot$3, Coordinates, Mafs } from 'mafs';
|
|
33
33
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
34
34
|
import { Body, LabelSmall, LabelMedium } from '@khanacademy/wonder-blocks-typography';
|
|
35
35
|
import questionIcon from '@phosphor-icons/core/regular/question.svg';
|
|
@@ -1142,8 +1142,6 @@ const ApiOptions = {
|
|
|
1142
1142
|
// drawing area (scratchpad) should be allowed/disallowed.
|
|
1143
1143
|
// Previously handled by `Khan.scratchpad.enable/disable`
|
|
1144
1144
|
setDrawingAreaAvailable: PropTypes.func,
|
|
1145
|
-
// Whether to use the Draft.js editor or the legacy textarea
|
|
1146
|
-
useDraftEditor: PropTypes.bool,
|
|
1147
1145
|
// The color used for the hint progress indicator (eg. 1 / 3)
|
|
1148
1146
|
hintProgressColor: PropTypes.string,
|
|
1149
1147
|
// Whether this Renderer is allowed to auto-scroll the rest of the
|
|
@@ -1153,8 +1151,6 @@ const ApiOptions = {
|
|
|
1153
1151
|
//
|
|
1154
1152
|
// Defaults to `false`.
|
|
1155
1153
|
canScrollPage: PropTypes.bool,
|
|
1156
|
-
// Whether or not we are rendering content inside of a modal.
|
|
1157
|
-
inModal: PropTypes.bool,
|
|
1158
1154
|
// Whether to enable the cross-out feature on multiple-choice radio
|
|
1159
1155
|
// widgets. This allows users to note which answers they believe to
|
|
1160
1156
|
// be incorrect, to find the answer by process of elimination.
|
|
@@ -1190,9 +1186,7 @@ const ApiOptions = {
|
|
|
1190
1186
|
}
|
|
1191
1187
|
},
|
|
1192
1188
|
setDrawingAreaAvailable: function () {},
|
|
1193
|
-
useDraftEditor: false,
|
|
1194
1189
|
canScrollPage: false,
|
|
1195
|
-
inModal: false,
|
|
1196
1190
|
crossOutEnabled: false,
|
|
1197
1191
|
editorChangeDelay: 0
|
|
1198
1192
|
}
|
|
@@ -24950,8 +24944,6 @@ var CSProgram$1 = {
|
|
|
24950
24944
|
hidden: true
|
|
24951
24945
|
};
|
|
24952
24946
|
|
|
24953
|
-
// TODO(FEI-5054): Figure out how to get global .d.ts files working with monorepos
|
|
24954
|
-
|
|
24955
24947
|
class Definition extends React.Component {
|
|
24956
24948
|
constructor(...args) {
|
|
24957
24949
|
super(...args);
|
|
@@ -25166,8 +25158,6 @@ var Dropdown$1 = {
|
|
|
25166
25158
|
|
|
25167
25159
|
/* eslint-disable react/sort-comp */
|
|
25168
25160
|
|
|
25169
|
-
// TODO(FEI-5054): Figure out how to get global .d.ts files working with monorepos
|
|
25170
|
-
|
|
25171
25161
|
// transform = _.identity
|
|
25172
25162
|
|
|
25173
25163
|
function mediaQueryIsMatched(mediaQuery) {
|
|
@@ -28577,7 +28567,6 @@ function AxisLabels() {
|
|
|
28577
28567
|
|
|
28578
28568
|
// Range is replaced within this file with Interval, but it is used elsewhere
|
|
28579
28569
|
// and exported from the package, so we need to keep it around.
|
|
28580
|
-
// TODO(FEI-5054): Figure out how to get global .d.ts files working with monorepos
|
|
28581
28570
|
const ItemExtras = [
|
|
28582
28571
|
// The user might benefit from using a Scientific Calculator. Provided on Khan Academy when true
|
|
28583
28572
|
"calculator",
|
|
@@ -29742,9 +29731,13 @@ function initializeGraphState(params) {
|
|
|
29742
29731
|
center: [0, 0],
|
|
29743
29732
|
radiusPoint: [1, 0]
|
|
29744
29733
|
});
|
|
29734
|
+
case "quadratic":
|
|
29735
|
+
return _extends({}, shared, {
|
|
29736
|
+
type: graph.type,
|
|
29737
|
+
coords: getQuadraticCoords(graph, range, step)
|
|
29738
|
+
});
|
|
29745
29739
|
case "angle":
|
|
29746
29740
|
case "sinusoid":
|
|
29747
|
-
case "quadratic":
|
|
29748
29741
|
throw new Error("Mafs not yet implemented for graph type: " + graph.type);
|
|
29749
29742
|
default:
|
|
29750
29743
|
throw new UnreachableCaseError(graph);
|
|
@@ -29833,6 +29826,11 @@ function getGradableGraph(state, initialGraph) {
|
|
|
29833
29826
|
radius: getRadius(state)
|
|
29834
29827
|
});
|
|
29835
29828
|
}
|
|
29829
|
+
if (state.type === "quadratic" && initialGraph.type === "quadratic") {
|
|
29830
|
+
return _extends({}, initialGraph, {
|
|
29831
|
+
coords: state.coords
|
|
29832
|
+
});
|
|
29833
|
+
}
|
|
29836
29834
|
throw new Error("Mafs is not yet implemented for graph type: " + initialGraph.type);
|
|
29837
29835
|
}
|
|
29838
29836
|
const getDefaultSegments = ({
|
|
@@ -29910,6 +29908,11 @@ const getPolygonCoords = ({
|
|
|
29910
29908
|
coords = normalizePoints(range, step, coords, /* noSnap */!snapToGrid);
|
|
29911
29909
|
return coords;
|
|
29912
29910
|
};
|
|
29911
|
+
const getQuadraticCoords = (graph, range, step) => {
|
|
29912
|
+
let coords = [[0.25, 0.75], [0.5, 0.25], [0.75, 0.75]];
|
|
29913
|
+
coords = normalizePoints(range, step, coords, true);
|
|
29914
|
+
return coords;
|
|
29915
|
+
};
|
|
29913
29916
|
|
|
29914
29917
|
/**
|
|
29915
29918
|
* determine radius of a circle graph
|
|
@@ -30019,6 +30022,82 @@ function crossProduct(as, bs) {
|
|
|
30019
30022
|
return result;
|
|
30020
30023
|
}
|
|
30021
30024
|
|
|
30025
|
+
function QuadraticGraph(props) {
|
|
30026
|
+
const {
|
|
30027
|
+
dispatch,
|
|
30028
|
+
graphState
|
|
30029
|
+
} = props;
|
|
30030
|
+
const {
|
|
30031
|
+
coords
|
|
30032
|
+
} = graphState;
|
|
30033
|
+
|
|
30034
|
+
// The coefficients are used to calculate the quadratic equation, plot the graph, and to indicate
|
|
30035
|
+
// to content creators the currently selected "correct answer". ex: y = 0.200x^2 + 0.000x + 0.000
|
|
30036
|
+
// While we should technically never have invalid coordinates, we want to ensure that we have a fallback
|
|
30037
|
+
const coeffRef = React.useRef([0, 0, 0]);
|
|
30038
|
+
const coeffs = getQuadraticCoefficients(coords);
|
|
30039
|
+
if (coeffs !== undefined) {
|
|
30040
|
+
coeffRef.current = coeffs;
|
|
30041
|
+
}
|
|
30042
|
+
|
|
30043
|
+
// Destructure the coefficients for calculating the quadratic equation
|
|
30044
|
+
const [a, b, c] = coeffRef.current;
|
|
30045
|
+
|
|
30046
|
+
// Calculate the y value based on the current x value
|
|
30047
|
+
const y = x => (a * x + b) * x + c;
|
|
30048
|
+
const handleOnMove = (destination, elementId) => {
|
|
30049
|
+
// If the destination is invalid, we want do not want to move the point
|
|
30050
|
+
const validDestination = isValidDestination(destination, elementId, coords);
|
|
30051
|
+
if (validDestination === false) {
|
|
30052
|
+
return;
|
|
30053
|
+
}
|
|
30054
|
+
dispatch(movePoint(elementId, destination));
|
|
30055
|
+
};
|
|
30056
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Plot$3.OfX, {
|
|
30057
|
+
y: y,
|
|
30058
|
+
color: color.blue
|
|
30059
|
+
}), coords.map((coord, i) => /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
30060
|
+
key: "point-" + i,
|
|
30061
|
+
point: coord,
|
|
30062
|
+
onMove: destination => handleOnMove(destination, i)
|
|
30063
|
+
})));
|
|
30064
|
+
}
|
|
30065
|
+
|
|
30066
|
+
// Ensure that we are only snapping to coordinates that result in a valid quadratic equation
|
|
30067
|
+
const isValidDestination = (destination, elementId, coords) => {
|
|
30068
|
+
// Set up the new coords and check if the quadratic coefficients are valid
|
|
30069
|
+
const newCoords = [...coords];
|
|
30070
|
+
newCoords[elementId] = destination;
|
|
30071
|
+
const QuadraticCoefficients = getQuadraticCoefficients(newCoords);
|
|
30072
|
+
|
|
30073
|
+
// If the new destination results in an invalid quadratic equation, we don't want to move the point
|
|
30074
|
+
if (QuadraticCoefficients === undefined) {
|
|
30075
|
+
return false;
|
|
30076
|
+
}
|
|
30077
|
+
return true;
|
|
30078
|
+
};
|
|
30079
|
+
|
|
30080
|
+
// Get the quadratic coefficients from the 3 control points
|
|
30081
|
+
// These equations were originally set up in 2013 and may require some
|
|
30082
|
+
// additional comments to help clarify the quadratic formula manipulations
|
|
30083
|
+
// Origin: https://phabricator.khanacademy.org/D2413
|
|
30084
|
+
const getQuadraticCoefficients = coords => {
|
|
30085
|
+
const p1 = coords[0];
|
|
30086
|
+
const p2 = coords[1];
|
|
30087
|
+
const p3 = coords[2];
|
|
30088
|
+
|
|
30089
|
+
// If the denominator is 0, we are going to return undefined as we are
|
|
30090
|
+
// unable to calculate the quadratic coefficients when they hit infinity
|
|
30091
|
+
const denom = (p1[0] - p2[0]) * (p1[0] - p3[0]) * (p2[0] - p3[0]);
|
|
30092
|
+
if (denom === 0) {
|
|
30093
|
+
return;
|
|
30094
|
+
}
|
|
30095
|
+
const a = (p3[0] * (p2[1] - p1[1]) + p2[0] * (p1[1] - p3[1]) + p1[0] * (p3[1] - p2[1])) / denom;
|
|
30096
|
+
const b = (p3[0] * p3[0] * (p1[1] - p2[1]) + p2[0] * p2[0] * (p3[1] - p1[1]) + p1[0] * p1[0] * (p2[1] - p3[1])) / denom;
|
|
30097
|
+
const c = (p2[0] * p3[0] * (p2[0] - p3[0]) * p1[1] + p3[0] * p1[0] * (p3[0] - p1[0]) * p2[1] + p1[0] * p2[0] * (p1[0] - p2[0]) * p3[1]) / denom;
|
|
30098
|
+
return [a, b, c];
|
|
30099
|
+
};
|
|
30100
|
+
|
|
30022
30101
|
// Universal padding for the axis ticks to ensure that the labels
|
|
30023
30102
|
// have enough space to render without overlapping the tick lines
|
|
30024
30103
|
const tickPadding = 5;
|
|
@@ -30178,9 +30257,6 @@ const AxisTickLabel = ({
|
|
|
30178
30257
|
const pointOnAxis = axis === "x" ? [label, 0] : [0, label];
|
|
30179
30258
|
const pixelPoint = pointToPixel(pointOnAxis, graphConfig);
|
|
30180
30259
|
|
|
30181
|
-
// Remove the negative sign from the label string as it is handled in the data-content attribute
|
|
30182
|
-
const labelString = Math.abs(label).toString();
|
|
30183
|
-
|
|
30184
30260
|
// Determine the relevant edge of the graph based on the axis type
|
|
30185
30261
|
const graphEdge = axis === "x" ? graphConfig.width : graphConfig.height;
|
|
30186
30262
|
|
|
@@ -30196,15 +30272,9 @@ const AxisTickLabel = ({
|
|
|
30196
30272
|
gridStep: gridStep[vectorIndex],
|
|
30197
30273
|
tickStep: tickStep[vectorIndex]
|
|
30198
30274
|
});
|
|
30199
|
-
|
|
30200
|
-
// Determine whether or not to render a negative symbol for the tick label
|
|
30201
|
-
// as the negative sign is handled in the data-content attribute in order to
|
|
30202
|
-
// maintain the correct spacing between the labels
|
|
30203
|
-
const dataContent = label < 0 && shouldShowLabel ? "−" : null;
|
|
30204
30275
|
return /*#__PURE__*/React.createElement("span", {
|
|
30205
|
-
className: `${axis}-axis-tick-label
|
|
30206
|
-
|
|
30207
|
-
}, shouldShowLabel && labelString);
|
|
30276
|
+
className: `${axis}-axis-tick-label`
|
|
30277
|
+
}, shouldShowLabel && label);
|
|
30208
30278
|
};
|
|
30209
30279
|
|
|
30210
30280
|
// Determine whether or not to show the tick label text
|
|
@@ -31153,6 +31223,7 @@ function doMoveControlPoint(state, action) {
|
|
|
31153
31223
|
throw new Error("FIXME implement circle reducer");
|
|
31154
31224
|
case "point":
|
|
31155
31225
|
case "polygon":
|
|
31226
|
+
case "quadratic":
|
|
31156
31227
|
throw new Error(`Don't use moveControlPoint for ${state.type} graphs. Use movePoint instead!`);
|
|
31157
31228
|
default:
|
|
31158
31229
|
throw new UnreachableCaseError(state);
|
|
@@ -31223,8 +31294,23 @@ function doMoveAll(state, action) {
|
|
|
31223
31294
|
}
|
|
31224
31295
|
function doMovePoint(state, action) {
|
|
31225
31296
|
switch (state.type) {
|
|
31226
|
-
case "point":
|
|
31227
31297
|
case "polygon":
|
|
31298
|
+
case "point":
|
|
31299
|
+
{
|
|
31300
|
+
return _extends({}, state, {
|
|
31301
|
+
hasBeenInteractedWith: true,
|
|
31302
|
+
coords: setAtIndex({
|
|
31303
|
+
array: state.coords,
|
|
31304
|
+
index: action.index,
|
|
31305
|
+
newValue: snap(state.snapStep, bound$1({
|
|
31306
|
+
snapStep: state.snapStep,
|
|
31307
|
+
range: state.range,
|
|
31308
|
+
point: action.destination
|
|
31309
|
+
}))
|
|
31310
|
+
})
|
|
31311
|
+
});
|
|
31312
|
+
}
|
|
31313
|
+
case "quadratic":
|
|
31228
31314
|
{
|
|
31229
31315
|
return _extends({}, state, {
|
|
31230
31316
|
hasBeenInteractedWith: true,
|
|
@@ -31240,7 +31326,7 @@ function doMovePoint(state, action) {
|
|
|
31240
31326
|
});
|
|
31241
31327
|
}
|
|
31242
31328
|
default:
|
|
31243
|
-
throw new Error("The movePoint action is only for point and polygon graphs");
|
|
31329
|
+
throw new Error("The movePoint action is only for point, quadratic, and polygon graphs");
|
|
31244
31330
|
}
|
|
31245
31331
|
}
|
|
31246
31332
|
function doMoveCenter(state, action) {
|
|
@@ -31453,6 +31539,11 @@ const renderGraph = props => {
|
|
|
31453
31539
|
graphState: state,
|
|
31454
31540
|
dispatch: dispatch
|
|
31455
31541
|
});
|
|
31542
|
+
case "quadratic":
|
|
31543
|
+
return /*#__PURE__*/React.createElement(QuadraticGraph, {
|
|
31544
|
+
graphState: state,
|
|
31545
|
+
dispatch: dispatch
|
|
31546
|
+
});
|
|
31456
31547
|
default:
|
|
31457
31548
|
return new UnreachableCaseError(type);
|
|
31458
31549
|
}
|
|
@@ -43667,7 +43758,7 @@ const init = function init(options) {
|
|
|
43667
43758
|
|
|
43668
43759
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
43669
43760
|
const libName = "@khanacademy/perseus";
|
|
43670
|
-
const libVersion = "
|
|
43761
|
+
const libVersion = "23.0.0";
|
|
43671
43762
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
43672
43763
|
|
|
43673
43764
|
const apiVersion = {
|