@khanacademy/perseus 20.5.0 → 20.7.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/components/icon.d.ts +1 -0
- package/dist/es/index.css +19 -6
- package/dist/es/index.js +750 -269
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +19 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +853 -358
- package/dist/index.js.map +1 -1
- package/dist/interactive2/movable.d.ts +1 -1
- package/dist/interactive2/objective_.d.ts +2 -2
- package/dist/styles/global-styles.d.ts +1 -0
- package/dist/styles/shared.d.ts +1 -0
- package/dist/types.d.ts +102 -0
- package/dist/util/a11y.d.ts +1 -0
- package/dist/util/extract-perseus-data.d.ts +8 -1
- package/dist/util/snowman-utils.d.ts +90 -0
- package/dist/util/widget-enum-utils.d.ts +11 -0
- package/dist/util.d.ts +1 -1
- package/dist/widgets/interactive-graph.d.ts +9 -2
- package/dist/widgets/interactive-graphs/graphs/index.d.ts +1 -0
- package/dist/widgets/interactive-graphs/graphs/polygon.d.ts +5 -0
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +1 -1
- package/dist/widgets/interactive-graphs/reducer/interactive-graph-action.d.ts +27 -0
- package/dist/widgets/interactive-graphs/reducer/interactive-graph-reducer.d.ts +3 -0
- package/dist/widgets/interactive-graphs/{interactive-graph-state.d.ts → reducer/interactive-graph-state.d.ts} +2 -2
- package/dist/widgets/interactive-graphs/types.d.ts +12 -6
- package/dist/widgets/interactive-graphs/utils.d.ts +5 -0
- package/dist/widgets/label-image/answer-pill.d.ts +1 -0
- package/dist/widgets/label-image/marker.d.ts +1 -0
- package/dist/widgets/radio/choice-icon/shared-styles.d.ts +1 -0
- package/dist/widgets/radio.d.ts +1 -1
- package/package.json +4 -6
- package/dist/widgets/interactive-graphs/interactive-graph-action.d.ts +0 -17
- package/dist/widgets/interactive-graphs/interactive-graph-reducer.d.ts +0 -3
- /package/dist/widgets/radio/{widget.d.ts → radio.d.ts} +0 -0
package/dist/es/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import { OptionItem, SingleSelect, MultiSelect } from '@khanacademy/wonder-block
|
|
|
31
31
|
import caretDown from '@phosphor-icons/core/assets/regular/caret-down.svg';
|
|
32
32
|
import caretUp from '@phosphor-icons/core/assets/regular/caret-up.svg';
|
|
33
33
|
import debounce$2 from 'lodash.debounce';
|
|
34
|
-
import { Point as Point$2, vec, useTransformContext, useMovable, Vector, Coordinates, Mafs } from 'mafs';
|
|
34
|
+
import { Point as Point$2, vec, useTransformContext, useMovable, Vector, Polygon, Coordinates, Mafs } from 'mafs';
|
|
35
35
|
import { color } from '@khanacademy/wonder-blocks-tokens';
|
|
36
36
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
37
37
|
import questionIcon from '@phosphor-icons/core/regular/question.svg';
|
|
@@ -18834,7 +18834,7 @@ const isAccessible = widgetInfo => {
|
|
|
18834
18834
|
}
|
|
18835
18835
|
return !!accessible;
|
|
18836
18836
|
};
|
|
18837
|
-
const getAllWidgetTypes = () => {
|
|
18837
|
+
const getAllWidgetTypes$1 = () => {
|
|
18838
18838
|
return _.keys(widgets);
|
|
18839
18839
|
};
|
|
18840
18840
|
const upgradeWidgetInfoToLatestVersion = oldWidgetInfo => {
|
|
@@ -19103,7 +19103,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
19103
19103
|
getVersionVector: getVersionVector,
|
|
19104
19104
|
getPublicWidgets: getPublicWidgets,
|
|
19105
19105
|
isAccessible: isAccessible,
|
|
19106
|
-
getAllWidgetTypes: getAllWidgetTypes,
|
|
19106
|
+
getAllWidgetTypes: getAllWidgetTypes$1,
|
|
19107
19107
|
upgradeWidgetInfoToLatestVersion: upgradeWidgetInfoToLatestVersion,
|
|
19108
19108
|
getRendererPropsForWidgetInfo: getRendererPropsForWidgetInfo,
|
|
19109
19109
|
traverseChildWidgets: traverseChildWidgets$3,
|
|
@@ -19337,7 +19337,6 @@ class Renderer extends React.Component {
|
|
|
19337
19337
|
};
|
|
19338
19338
|
// @ts-expect-error - TS2322 - Type '(props: Props) => Partial<Record<string, CategorizerWidget | CSProgramWidget | DefinitionWidget | DropdownWidget | ... 35 more ... | VideoWidget>>' is not assignable to type '(props: Props) => { [key: string]: PerseusWidget; }'.
|
|
19339
19339
|
this._getAllWidgetsInfo = props => {
|
|
19340
|
-
// @ts-expect-error - TS2345 - Argument of type '{ [key: string]: PerseusWidget; }' is not assignable to parameter of type 'Partial<Record<string, CategorizerWidget>>'.
|
|
19341
19340
|
return mapObject$1(props.widgets, (widgetInfo, widgetId) => {
|
|
19342
19341
|
if (!widgetInfo.type || !widgetInfo.alignment) {
|
|
19343
19342
|
const newValues = {};
|
|
@@ -28167,22 +28166,55 @@ const GraphLockedLayer = props => {
|
|
|
28167
28166
|
};
|
|
28168
28167
|
|
|
28169
28168
|
const MOVE_CONTROL_POINT = "move-control-point";
|
|
28170
|
-
function moveControlPoint(
|
|
28169
|
+
function moveControlPoint(pointIndex, destination, itemIndex) {
|
|
28171
28170
|
return {
|
|
28172
28171
|
type: MOVE_CONTROL_POINT,
|
|
28173
|
-
|
|
28172
|
+
itemIndex,
|
|
28174
28173
|
pointIndex,
|
|
28175
28174
|
destination
|
|
28176
28175
|
};
|
|
28177
28176
|
}
|
|
28177
|
+
const MOVE_ALL = "move-all";
|
|
28178
28178
|
const MOVE_LINE = "move-line";
|
|
28179
|
-
|
|
28179
|
+
/** This action assumes the state.coords holds an array of collinear tuples that define lines */
|
|
28180
|
+
function moveLine(itemIndex, delta) {
|
|
28180
28181
|
return {
|
|
28181
28182
|
type: MOVE_LINE,
|
|
28182
|
-
|
|
28183
|
+
itemIndex,
|
|
28183
28184
|
delta
|
|
28184
28185
|
};
|
|
28185
28186
|
}
|
|
28187
|
+
/** This action assumes a flat array of vectors */
|
|
28188
|
+
const moveAll = delta => ({
|
|
28189
|
+
type: MOVE_ALL,
|
|
28190
|
+
delta
|
|
28191
|
+
});
|
|
28192
|
+
|
|
28193
|
+
/**
|
|
28194
|
+
* 44 is touch best practice and AAA compliant for WCAG
|
|
28195
|
+
* https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
|
|
28196
|
+
*/
|
|
28197
|
+
const TARGET_SIZE = 44;
|
|
28198
|
+
|
|
28199
|
+
// same as pointsFromNormalized in interactive-graph.tsx
|
|
28200
|
+
const normalizePoints = (range, step, coordsList, noSnap) => coordsList.map(coords =>
|
|
28201
|
+
// maps over [x, y]
|
|
28202
|
+
coords.map((coord, i) => {
|
|
28203
|
+
const axisRange = range[i];
|
|
28204
|
+
if (noSnap) {
|
|
28205
|
+
return axisRange[0] + (axisRange[1] - axisRange[0]) * coord;
|
|
28206
|
+
}
|
|
28207
|
+
const axisStep = step[i];
|
|
28208
|
+
const nSteps = Math.floor((axisRange[1] - axisRange[0]) / axisStep);
|
|
28209
|
+
const tick = Math.round(coord * nSteps);
|
|
28210
|
+
return axisRange[0] + axisStep * tick;
|
|
28211
|
+
}));
|
|
28212
|
+
|
|
28213
|
+
// same as normalizeCoords in interactive-graph.tsx
|
|
28214
|
+
const normalizeCoords = (coordsList, ranges) => coordsList.map(coords => coords.map((coord, i) => {
|
|
28215
|
+
const extent = ranges[i][1] - ranges[i][0];
|
|
28216
|
+
return (coord + ranges[i][1]) / extent;
|
|
28217
|
+
}));
|
|
28186
28218
|
|
|
28187
28219
|
const defaultStroke = "var(--movable-line-stroke-color)";
|
|
28188
28220
|
const MovableLine = props => {
|
|
@@ -28230,7 +28262,7 @@ const MovableLine = props => {
|
|
|
28230
28262
|
end: endPtPx,
|
|
28231
28263
|
style: {
|
|
28232
28264
|
stroke: "transparent",
|
|
28233
|
-
strokeWidth:
|
|
28265
|
+
strokeWidth: TARGET_SIZE
|
|
28234
28266
|
}
|
|
28235
28267
|
}), /*#__PURE__*/React.createElement(SVGLine, {
|
|
28236
28268
|
start: startPtPx,
|
|
@@ -28263,7 +28295,7 @@ function SVGLine(props) {
|
|
|
28263
28295
|
x2: end[0],
|
|
28264
28296
|
y2: end[1],
|
|
28265
28297
|
style: style,
|
|
28266
|
-
className: dragging ? "movable-
|
|
28298
|
+
className: dragging ? "movable-dragging" : undefined
|
|
28267
28299
|
});
|
|
28268
28300
|
}
|
|
28269
28301
|
|
|
@@ -28338,7 +28370,7 @@ const StyledMovablePoint = props => {
|
|
|
28338
28370
|
}
|
|
28339
28371
|
}, /*#__PURE__*/React.createElement("circle", {
|
|
28340
28372
|
className: "movable-point-hitbox",
|
|
28341
|
-
r:
|
|
28373
|
+
r: TARGET_SIZE / 2,
|
|
28342
28374
|
cx: x,
|
|
28343
28375
|
cy: y
|
|
28344
28376
|
}), /*#__PURE__*/React.createElement("circle", {
|
|
@@ -28374,9 +28406,9 @@ const SegmentGraph = props => {
|
|
|
28374
28406
|
snaps: snapStep,
|
|
28375
28407
|
range: range,
|
|
28376
28408
|
onMoveLine: delta => {
|
|
28377
|
-
dispatch(
|
|
28409
|
+
dispatch(moveLine(i, delta));
|
|
28378
28410
|
},
|
|
28379
|
-
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(
|
|
28411
|
+
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i)),
|
|
28380
28412
|
"data-testid": "segment" + i
|
|
28381
28413
|
})));
|
|
28382
28414
|
};
|
|
@@ -28419,9 +28451,9 @@ const LinearGraph = props => {
|
|
|
28419
28451
|
snaps: snapStep,
|
|
28420
28452
|
range: range,
|
|
28421
28453
|
onMoveLine: delta => {
|
|
28422
|
-
dispatch(
|
|
28454
|
+
dispatch(moveLine(i, delta));
|
|
28423
28455
|
},
|
|
28424
|
-
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(
|
|
28456
|
+
onMovePoint: (endpointIndex, destination) => dispatch(moveControlPoint(endpointIndex, destination, i))
|
|
28425
28457
|
// "linear" or "linear-system" + index
|
|
28426
28458
|
,
|
|
28427
28459
|
"data-testid": type + i,
|
|
@@ -28472,8 +28504,8 @@ const RayGraph = props => {
|
|
|
28472
28504
|
|
|
28473
28505
|
// a ray only has one line
|
|
28474
28506
|
const [start, end] = lines[0];
|
|
28475
|
-
const handleMoveLine = delta => dispatch(
|
|
28476
|
-
const handleMovePoint = (newPoint, pointIndex) => dispatch(moveControlPoint(
|
|
28507
|
+
const handleMoveLine = delta => dispatch(moveLine(0, delta));
|
|
28508
|
+
const handleMovePoint = (newPoint, pointIndex) => dispatch(moveControlPoint(pointIndex, newPoint, 0));
|
|
28477
28509
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MovableLine, {
|
|
28478
28510
|
start: start,
|
|
28479
28511
|
end: end,
|
|
@@ -28492,6 +28524,63 @@ const RayGraph = props => {
|
|
|
28492
28524
|
}));
|
|
28493
28525
|
};
|
|
28494
28526
|
|
|
28527
|
+
const PolygonGraph = props => {
|
|
28528
|
+
var _points$length;
|
|
28529
|
+
const [focused, setFocused] = React.useState(false);
|
|
28530
|
+
const [hovered, setHovered] = React.useState(false);
|
|
28531
|
+
const {
|
|
28532
|
+
dispatch
|
|
28533
|
+
} = props;
|
|
28534
|
+
const {
|
|
28535
|
+
coords,
|
|
28536
|
+
type
|
|
28537
|
+
} = props.graphState;
|
|
28538
|
+
const points = coords != null ? coords : [[0, 0]];
|
|
28539
|
+
const pointsSum = points.reduce((acc, point) => vec.add(acc, point), [0, 0]);
|
|
28540
|
+
const midpoint = pointsSum && vec.scale(pointsSum, 1 / ((_points$length = points.length) != null ? _points$length : 1));
|
|
28541
|
+
const ref = React.useRef(null);
|
|
28542
|
+
const {
|
|
28543
|
+
dragging
|
|
28544
|
+
} = useMovable({
|
|
28545
|
+
gestureTarget: ref,
|
|
28546
|
+
point: midpoint,
|
|
28547
|
+
onMove: newPoint => {
|
|
28548
|
+
const delta = vec.sub(newPoint, midpoint);
|
|
28549
|
+
dispatch(moveAll(delta));
|
|
28550
|
+
},
|
|
28551
|
+
constrain: p => p
|
|
28552
|
+
});
|
|
28553
|
+
const active = hovered || focused || dragging;
|
|
28554
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Polygon, {
|
|
28555
|
+
points: [...points],
|
|
28556
|
+
color: "var(--movable-line-stroke-color)",
|
|
28557
|
+
svgPolygonProps: {
|
|
28558
|
+
strokeWidth: active ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)"
|
|
28559
|
+
}
|
|
28560
|
+
}), /*#__PURE__*/React.createElement(Polygon, {
|
|
28561
|
+
points: [...points],
|
|
28562
|
+
color: "transparent",
|
|
28563
|
+
svgPolygonProps: {
|
|
28564
|
+
ref,
|
|
28565
|
+
tabIndex: 0,
|
|
28566
|
+
strokeWidth: TARGET_SIZE,
|
|
28567
|
+
style: {
|
|
28568
|
+
cursor: dragging ? "grabbing" : "grab"
|
|
28569
|
+
},
|
|
28570
|
+
onFocus: () => setFocused(true),
|
|
28571
|
+
onBlur: () => setFocused(false),
|
|
28572
|
+
onMouseEnter: () => setHovered(true),
|
|
28573
|
+
onMouseLeave: () => setHovered(false),
|
|
28574
|
+
className: "movable-polygon"
|
|
28575
|
+
}
|
|
28576
|
+
}), points.map((point, i) => /*#__PURE__*/React.createElement(StyledMovablePoint, {
|
|
28577
|
+
key: i,
|
|
28578
|
+
point: point,
|
|
28579
|
+
onMove: destination => dispatch(moveControlPoint(i, destination)),
|
|
28580
|
+
"data-testid": type + i
|
|
28581
|
+
})));
|
|
28582
|
+
};
|
|
28583
|
+
|
|
28495
28584
|
const renderLineLabel = (n, [min, max]) => n !== -1 && n !== min && n !== max;
|
|
28496
28585
|
const axisOptions = (props, index) => ({
|
|
28497
28586
|
axis: props.markings === "graph",
|
|
@@ -28504,233 +28593,6 @@ const Grid = props => props.markings === "none" ? null : /*#__PURE__*/React.crea
|
|
|
28504
28593
|
yAxis: axisOptions(props, 1)
|
|
28505
28594
|
});
|
|
28506
28595
|
|
|
28507
|
-
function interactiveGraphReducer(state, action) {
|
|
28508
|
-
switch (action.type) {
|
|
28509
|
-
case MOVE_CONTROL_POINT:
|
|
28510
|
-
{
|
|
28511
|
-
const newCoords = updateAtIndex({
|
|
28512
|
-
array: state.coords,
|
|
28513
|
-
index: action.objectIndex,
|
|
28514
|
-
update: tuple => setAtIndex({
|
|
28515
|
-
array: tuple,
|
|
28516
|
-
index: action.pointIndex,
|
|
28517
|
-
newValue: snap(state, bound$1(state, action.destination))
|
|
28518
|
-
})
|
|
28519
|
-
});
|
|
28520
|
-
if (!validSegments(newCoords)) {
|
|
28521
|
-
return state;
|
|
28522
|
-
}
|
|
28523
|
-
return _extends({}, state, {
|
|
28524
|
-
hasBeenInteractedWith: true,
|
|
28525
|
-
coords: newCoords
|
|
28526
|
-
});
|
|
28527
|
-
}
|
|
28528
|
-
case MOVE_LINE:
|
|
28529
|
-
{
|
|
28530
|
-
var _state$coords;
|
|
28531
|
-
const currentLine = (_state$coords = state.coords) == null ? void 0 : _state$coords[action.lineIndex];
|
|
28532
|
-
if (!currentLine) {
|
|
28533
|
-
throw new Error("No line to move");
|
|
28534
|
-
}
|
|
28535
|
-
const maxMoves = currentLine.map(point => maxMove(state, point));
|
|
28536
|
-
const minMoves = currentLine.map(point => minMove(state, point));
|
|
28537
|
-
const maxXMove = Math.min(...maxMoves.map(move => move[0]));
|
|
28538
|
-
const maxYMove = Math.min(...maxMoves.map(move => move[1]));
|
|
28539
|
-
const minXMove = Math.max(...minMoves.map(move => move[0]));
|
|
28540
|
-
const minYMove = Math.max(...minMoves.map(move => move[1]));
|
|
28541
|
-
const dx = clamp(action.delta[0], minXMove, maxXMove);
|
|
28542
|
-
const dy = clamp(action.delta[1], minYMove, maxYMove);
|
|
28543
|
-
const newValue = [snap(state, vec.add(currentLine[0], [dx, dy])), snap(state, vec.add(currentLine[1], [dx, dy]))];
|
|
28544
|
-
const newLine = setAtIndex({
|
|
28545
|
-
array: state.coords,
|
|
28546
|
-
index: action.lineIndex,
|
|
28547
|
-
newValue
|
|
28548
|
-
});
|
|
28549
|
-
return _extends({}, state, {
|
|
28550
|
-
hasBeenInteractedWith: true,
|
|
28551
|
-
coords: newLine
|
|
28552
|
-
});
|
|
28553
|
-
}
|
|
28554
|
-
default:
|
|
28555
|
-
throw new UnreachableCaseError(action);
|
|
28556
|
-
}
|
|
28557
|
-
}
|
|
28558
|
-
function snap(state, point) {
|
|
28559
|
-
const [requestedX, requestedY] = point;
|
|
28560
|
-
const [snapX, snapY] = state.snapStep;
|
|
28561
|
-
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
28562
|
-
}
|
|
28563
|
-
|
|
28564
|
-
// Returns the closest point to the given `point` that is within the graph
|
|
28565
|
-
// bounds given in `state`.
|
|
28566
|
-
function bound$1(state, point) {
|
|
28567
|
-
const [requestedX, requestedY] = point;
|
|
28568
|
-
const [snapX, snapY] = state.snapStep;
|
|
28569
|
-
const [[minX, maxX], [minY, maxY]] = state.range;
|
|
28570
|
-
return [clamp(requestedX, minX + snapX, maxX - snapX), clamp(requestedY, minY + snapY, maxY - snapY)];
|
|
28571
|
-
}
|
|
28572
|
-
|
|
28573
|
-
// Returns the vector from the given point to the top-right corner of the graph
|
|
28574
|
-
function maxMove(state, point) {
|
|
28575
|
-
const topRight = bound$1(state, [Infinity, Infinity]);
|
|
28576
|
-
return vec.sub(topRight, point);
|
|
28577
|
-
}
|
|
28578
|
-
|
|
28579
|
-
// Returns the vector from the given point to the bottom-left corner of the
|
|
28580
|
-
// graph
|
|
28581
|
-
function minMove(state, point) {
|
|
28582
|
-
const bottomLeft = bound$1(state, [-Infinity, -Infinity]);
|
|
28583
|
-
return vec.sub(bottomLeft, point);
|
|
28584
|
-
}
|
|
28585
|
-
function clamp(value, min, max) {
|
|
28586
|
-
if (value < min) {
|
|
28587
|
-
return min;
|
|
28588
|
-
}
|
|
28589
|
-
if (value > max) {
|
|
28590
|
-
return max;
|
|
28591
|
-
}
|
|
28592
|
-
return value;
|
|
28593
|
-
}
|
|
28594
|
-
function validSegments(segments) {
|
|
28595
|
-
return segments.every(([start, end]) => !vector$1.equal(start, end));
|
|
28596
|
-
}
|
|
28597
|
-
function updateAtIndex(args) {
|
|
28598
|
-
const {
|
|
28599
|
-
array = [],
|
|
28600
|
-
index,
|
|
28601
|
-
update
|
|
28602
|
-
} = args;
|
|
28603
|
-
const newValue = update(array[index]);
|
|
28604
|
-
return setAtIndex({
|
|
28605
|
-
array,
|
|
28606
|
-
index,
|
|
28607
|
-
newValue
|
|
28608
|
-
});
|
|
28609
|
-
}
|
|
28610
|
-
function setAtIndex(args) {
|
|
28611
|
-
const {
|
|
28612
|
-
array = [],
|
|
28613
|
-
index,
|
|
28614
|
-
newValue
|
|
28615
|
-
} = args;
|
|
28616
|
-
const copy = [...array];
|
|
28617
|
-
copy[index] = newValue;
|
|
28618
|
-
// restoring readonly to array
|
|
28619
|
-
return copy;
|
|
28620
|
-
}
|
|
28621
|
-
|
|
28622
|
-
// same as pointsFromNormalized in interactive-graph.tsx
|
|
28623
|
-
const normalizePoints = (range, step, coordsList, noSnap) => coordsList.map(coords =>
|
|
28624
|
-
// maps over [x, y]
|
|
28625
|
-
coords.map((coord, i) => {
|
|
28626
|
-
const axisRange = range[i];
|
|
28627
|
-
if (noSnap) {
|
|
28628
|
-
return axisRange[0] + (axisRange[1] - axisRange[0]) * coord;
|
|
28629
|
-
}
|
|
28630
|
-
const axisStep = step[i];
|
|
28631
|
-
const nSteps = Math.floor((axisRange[1] - axisRange[0]) / axisStep);
|
|
28632
|
-
const tick = Math.round(coord * nSteps);
|
|
28633
|
-
return axisRange[0] + axisStep * tick;
|
|
28634
|
-
}));
|
|
28635
|
-
|
|
28636
|
-
// same as normalizeCoords in interactive-graph.tsx
|
|
28637
|
-
const normalizeCoords = (coordsList, ranges) => coordsList.map(coords => coords.map((coord, i) => {
|
|
28638
|
-
const extent = ranges[i][1] - ranges[i][0];
|
|
28639
|
-
return (coord + ranges[i][1]) / extent;
|
|
28640
|
-
}));
|
|
28641
|
-
|
|
28642
|
-
function initializeGraphState(params) {
|
|
28643
|
-
const {
|
|
28644
|
-
graph,
|
|
28645
|
-
step,
|
|
28646
|
-
snapStep,
|
|
28647
|
-
range
|
|
28648
|
-
} = params;
|
|
28649
|
-
switch (graph.type) {
|
|
28650
|
-
case "segment":
|
|
28651
|
-
return {
|
|
28652
|
-
type: "segment",
|
|
28653
|
-
hasBeenInteractedWith: false,
|
|
28654
|
-
range,
|
|
28655
|
-
snapStep,
|
|
28656
|
-
coords: getDefaultSegments({
|
|
28657
|
-
graph,
|
|
28658
|
-
step,
|
|
28659
|
-
range
|
|
28660
|
-
})
|
|
28661
|
-
};
|
|
28662
|
-
case "linear":
|
|
28663
|
-
case "linear-system":
|
|
28664
|
-
case "ray":
|
|
28665
|
-
return {
|
|
28666
|
-
type: graph.type,
|
|
28667
|
-
hasBeenInteractedWith: false,
|
|
28668
|
-
range,
|
|
28669
|
-
snapStep,
|
|
28670
|
-
// Linear and ray graphs have a single tuple of points, while a
|
|
28671
|
-
// linear system has two tuples of points.
|
|
28672
|
-
coords: getLineCoords(graph, range, step)
|
|
28673
|
-
};
|
|
28674
|
-
}
|
|
28675
|
-
throw new Error("Mafs not yet implemented for graph type: " + graph.type);
|
|
28676
|
-
}
|
|
28677
|
-
const getDefaultSegments = props => {
|
|
28678
|
-
const ys = n => {
|
|
28679
|
-
switch (n) {
|
|
28680
|
-
case 2:
|
|
28681
|
-
return [5, -5];
|
|
28682
|
-
case 3:
|
|
28683
|
-
return [5, 0, -5];
|
|
28684
|
-
case 4:
|
|
28685
|
-
return [6, 2, -2, -6];
|
|
28686
|
-
case 5:
|
|
28687
|
-
return [6, 3, 0, -3, -6];
|
|
28688
|
-
case 6:
|
|
28689
|
-
return [5, 3, 1, -1, -3, -5];
|
|
28690
|
-
default:
|
|
28691
|
-
return [5];
|
|
28692
|
-
}
|
|
28693
|
-
};
|
|
28694
|
-
return ys(props.graph.numSegments).map(y => {
|
|
28695
|
-
let endpoints = [[-5, y], [5, y]];
|
|
28696
|
-
endpoints = normalizeCoords(endpoints, props.range);
|
|
28697
|
-
endpoints = normalizePoints(props.range, props.step, endpoints);
|
|
28698
|
-
return endpoints;
|
|
28699
|
-
});
|
|
28700
|
-
};
|
|
28701
|
-
|
|
28702
|
-
// TS v4 doesn't narrow return types, while v5 does.
|
|
28703
|
-
// Instead of updating to v5, using generic type to relate input and output types.
|
|
28704
|
-
function getGradableGraph(state, initialGraph) {
|
|
28705
|
-
var _state$coords;
|
|
28706
|
-
if (!state.hasBeenInteractedWith) {
|
|
28707
|
-
return initialGraph;
|
|
28708
|
-
}
|
|
28709
|
-
switch (true) {
|
|
28710
|
-
// coords: Array of CollinearTuple
|
|
28711
|
-
case state.type === "linear-system" && initialGraph.type === "linear-system":
|
|
28712
|
-
case state.type === "segment" && initialGraph.type === "segment":
|
|
28713
|
-
return _extends({}, initialGraph, {
|
|
28714
|
-
coords: state.coords
|
|
28715
|
-
});
|
|
28716
|
-
// coords: CollinearTuple
|
|
28717
|
-
case state.type === "linear" && initialGraph.type === "linear":
|
|
28718
|
-
case state.type === "ray" && initialGraph.type === "ray":
|
|
28719
|
-
return _extends({}, initialGraph, {
|
|
28720
|
-
coords: (_state$coords = state.coords) == null ? void 0 : _state$coords[0]
|
|
28721
|
-
});
|
|
28722
|
-
}
|
|
28723
|
-
throw new Error("Mafs is not yet implemented for graph type: " + initialGraph.type);
|
|
28724
|
-
}
|
|
28725
|
-
const defaultLinearCoords = [[[0.25, 0.75], [0.75, 0.75]], [[0.25, 0.25], [0.75, 0.25]]];
|
|
28726
|
-
const getLineCoords = (graph, range, step) => {
|
|
28727
|
-
var _graph$coords;
|
|
28728
|
-
return (
|
|
28729
|
-
// Return two lines for a linear system, one for a ray or linear
|
|
28730
|
-
((_graph$coords = graph.coords) != null ? _graph$coords : graph.type === "linear-system") ? defaultLinearCoords.map(collinear => normalizePoints(range, step, collinear)) : [normalizePoints(range, step, defaultLinearCoords[0])]
|
|
28731
|
-
);
|
|
28732
|
-
};
|
|
28733
|
-
|
|
28734
28596
|
// Displays a stylized open eye: lint warnings are visible
|
|
28735
28597
|
const VisibleIcon = () => /*#__PURE__*/React.createElement("svg", {
|
|
28736
28598
|
width: "24",
|
|
@@ -29423,6 +29285,373 @@ const getLegacyGrid = (box, backgroundImage) => {
|
|
|
29423
29285
|
return null;
|
|
29424
29286
|
};
|
|
29425
29287
|
|
|
29288
|
+
/** Determine if coords is type CollinearTuple[] */
|
|
29289
|
+
const isCollinearTuples = coords => Array.isArray(coords[0][0]);
|
|
29290
|
+
|
|
29291
|
+
// Generic type makes returned state match input state
|
|
29292
|
+
function interactiveGraphReducer(state, action) {
|
|
29293
|
+
const {
|
|
29294
|
+
snapStep,
|
|
29295
|
+
range
|
|
29296
|
+
} = state;
|
|
29297
|
+
if (!state.coords) {
|
|
29298
|
+
throw new Error("Graph state must have been initialized with coords");
|
|
29299
|
+
}
|
|
29300
|
+
switch (action.type) {
|
|
29301
|
+
case MOVE_CONTROL_POINT:
|
|
29302
|
+
{
|
|
29303
|
+
const newCoords = action.itemIndex !== undefined && state.coords && isCollinearTuples(state.coords) ? updateAtIndex({
|
|
29304
|
+
array: state.coords,
|
|
29305
|
+
index: action.itemIndex,
|
|
29306
|
+
update: tuple => setAtIndex({
|
|
29307
|
+
array: tuple,
|
|
29308
|
+
index: action.pointIndex,
|
|
29309
|
+
newValue: snap({
|
|
29310
|
+
snapStep,
|
|
29311
|
+
point: bound$1({
|
|
29312
|
+
snapStep,
|
|
29313
|
+
range,
|
|
29314
|
+
point: action.destination
|
|
29315
|
+
})
|
|
29316
|
+
})
|
|
29317
|
+
})
|
|
29318
|
+
}) : setAtIndex({
|
|
29319
|
+
array: state.coords,
|
|
29320
|
+
index: action.pointIndex,
|
|
29321
|
+
newValue: snap({
|
|
29322
|
+
snapStep,
|
|
29323
|
+
point: bound$1({
|
|
29324
|
+
snapStep,
|
|
29325
|
+
range,
|
|
29326
|
+
point: action.destination
|
|
29327
|
+
})
|
|
29328
|
+
})
|
|
29329
|
+
});
|
|
29330
|
+
|
|
29331
|
+
// Cannot type narrow both conditions within function parameters,
|
|
29332
|
+
// so this may seem redundant, but it's necessary for type safety.
|
|
29333
|
+
const coordsToCheck = isCollinearTuples(newCoords) && action.itemIndex !== undefined ? newCoords[action.itemIndex] : newCoords;
|
|
29334
|
+
if (!isCollinearTuples(coordsToCheck) && coordsOverlap(coordsToCheck)) {
|
|
29335
|
+
return state;
|
|
29336
|
+
}
|
|
29337
|
+
return _extends({}, state, {
|
|
29338
|
+
hasBeenInteractedWith: true,
|
|
29339
|
+
coords: newCoords
|
|
29340
|
+
});
|
|
29341
|
+
}
|
|
29342
|
+
case MOVE_LINE:
|
|
29343
|
+
{
|
|
29344
|
+
var _state$coords;
|
|
29345
|
+
if (!isCollinearTuples(state.coords)) {
|
|
29346
|
+
throw new Error("Cannot call this action unless coords is array of CollinearTuple.");
|
|
29347
|
+
}
|
|
29348
|
+
if (action.itemIndex === undefined) {
|
|
29349
|
+
throw new Error("Please provide index of line to move");
|
|
29350
|
+
}
|
|
29351
|
+
const currentLine = (_state$coords = state.coords) == null ? void 0 : _state$coords[action.itemIndex];
|
|
29352
|
+
if (!currentLine) {
|
|
29353
|
+
throw new Error("No line to move");
|
|
29354
|
+
}
|
|
29355
|
+
const change = getChange(currentLine, action.delta, {
|
|
29356
|
+
snapStep,
|
|
29357
|
+
range
|
|
29358
|
+
});
|
|
29359
|
+
const newLine = [snap({
|
|
29360
|
+
snapStep,
|
|
29361
|
+
point: vec.add(currentLine[0], change)
|
|
29362
|
+
}), snap({
|
|
29363
|
+
snapStep,
|
|
29364
|
+
point: vec.add(currentLine[1], change)
|
|
29365
|
+
})];
|
|
29366
|
+
const newCoords = setAtIndex({
|
|
29367
|
+
array: state.coords,
|
|
29368
|
+
index: action.itemIndex,
|
|
29369
|
+
newValue: newLine
|
|
29370
|
+
});
|
|
29371
|
+
return _extends({}, state, {
|
|
29372
|
+
hasBeenInteractedWith: true,
|
|
29373
|
+
coords: newCoords
|
|
29374
|
+
});
|
|
29375
|
+
}
|
|
29376
|
+
case MOVE_ALL:
|
|
29377
|
+
{
|
|
29378
|
+
if (isCollinearTuples(state.coords)) {
|
|
29379
|
+
throw new Error("Cannot call this action unless coords is array of vectors.");
|
|
29380
|
+
}
|
|
29381
|
+
const change = getChange(state.coords, action.delta, {
|
|
29382
|
+
snapStep,
|
|
29383
|
+
range
|
|
29384
|
+
});
|
|
29385
|
+
const newCoords = state.coords.map(point => snap({
|
|
29386
|
+
snapStep,
|
|
29387
|
+
point: vec.add(point, change)
|
|
29388
|
+
}));
|
|
29389
|
+
return _extends({}, state, {
|
|
29390
|
+
hasBeenInteractedWith: true,
|
|
29391
|
+
coords: newCoords
|
|
29392
|
+
});
|
|
29393
|
+
}
|
|
29394
|
+
default:
|
|
29395
|
+
throw new UnreachableCaseError(action);
|
|
29396
|
+
}
|
|
29397
|
+
}
|
|
29398
|
+
const getChange = (coords, delta, constraintOpts) => {
|
|
29399
|
+
const [deltaX, deltaY] = delta;
|
|
29400
|
+
const maxMoves = coords.map(point => maxMove(_extends({}, constraintOpts, {
|
|
29401
|
+
point
|
|
29402
|
+
})));
|
|
29403
|
+
const minMoves = coords.map(point => minMove(_extends({}, constraintOpts, {
|
|
29404
|
+
point
|
|
29405
|
+
})));
|
|
29406
|
+
const maxXMove = Math.min(...maxMoves.map(move => move[0]));
|
|
29407
|
+
const maxYMove = Math.min(...maxMoves.map(move => move[1]));
|
|
29408
|
+
const minXMove = Math.max(...minMoves.map(move => move[0]));
|
|
29409
|
+
const minYMove = Math.max(...minMoves.map(move => move[1]));
|
|
29410
|
+
const dx = clamp(deltaX, minXMove, maxXMove);
|
|
29411
|
+
const dy = clamp(deltaY, minYMove, maxYMove);
|
|
29412
|
+
return [dx, dy];
|
|
29413
|
+
};
|
|
29414
|
+
function snap({
|
|
29415
|
+
snapStep,
|
|
29416
|
+
point
|
|
29417
|
+
}) {
|
|
29418
|
+
const [requestedX, requestedY] = point;
|
|
29419
|
+
const [snapX, snapY] = snapStep;
|
|
29420
|
+
return [Math.round(requestedX / snapX) * snapX, Math.round(requestedY / snapY) * snapY];
|
|
29421
|
+
}
|
|
29422
|
+
|
|
29423
|
+
// Returns the closest point to the given `point` that is within the graph
|
|
29424
|
+
// bounds given in `state`.
|
|
29425
|
+
function bound$1({
|
|
29426
|
+
snapStep,
|
|
29427
|
+
range,
|
|
29428
|
+
point
|
|
29429
|
+
}) {
|
|
29430
|
+
const [requestedX, requestedY] = point;
|
|
29431
|
+
const [snapX, snapY] = snapStep;
|
|
29432
|
+
const [[minX, maxX], [minY, maxY]] = range;
|
|
29433
|
+
return [clamp(requestedX, minX + snapX, maxX - snapX), clamp(requestedY, minY + snapY, maxY - snapY)];
|
|
29434
|
+
}
|
|
29435
|
+
|
|
29436
|
+
// Returns the vector from the given point to the top-right corner of the graph
|
|
29437
|
+
function maxMove({
|
|
29438
|
+
snapStep,
|
|
29439
|
+
range,
|
|
29440
|
+
point
|
|
29441
|
+
}) {
|
|
29442
|
+
const topRight = bound$1({
|
|
29443
|
+
snapStep,
|
|
29444
|
+
range,
|
|
29445
|
+
point: [Infinity, Infinity]
|
|
29446
|
+
});
|
|
29447
|
+
return vec.sub(topRight, point);
|
|
29448
|
+
}
|
|
29449
|
+
|
|
29450
|
+
// Returns the vector from the given point to the bottom-left corner of the
|
|
29451
|
+
// graph
|
|
29452
|
+
function minMove({
|
|
29453
|
+
snapStep,
|
|
29454
|
+
range,
|
|
29455
|
+
point
|
|
29456
|
+
}) {
|
|
29457
|
+
const bottomLeft = bound$1({
|
|
29458
|
+
snapStep,
|
|
29459
|
+
range,
|
|
29460
|
+
point: [-Infinity, -Infinity]
|
|
29461
|
+
});
|
|
29462
|
+
return vec.sub(bottomLeft, point);
|
|
29463
|
+
}
|
|
29464
|
+
function clamp(value, min, max) {
|
|
29465
|
+
if (value < min) {
|
|
29466
|
+
return min;
|
|
29467
|
+
}
|
|
29468
|
+
if (value > max) {
|
|
29469
|
+
return max;
|
|
29470
|
+
}
|
|
29471
|
+
return value;
|
|
29472
|
+
}
|
|
29473
|
+
const coordsOverlap = coords => coords.some((coord, i) => coords.some((c, j) => i !== j && vector$1.equal(coord, c)));
|
|
29474
|
+
function updateAtIndex(args) {
|
|
29475
|
+
const {
|
|
29476
|
+
array = [],
|
|
29477
|
+
index,
|
|
29478
|
+
update
|
|
29479
|
+
} = args;
|
|
29480
|
+
const newValue = update(array[index]);
|
|
29481
|
+
return setAtIndex({
|
|
29482
|
+
array,
|
|
29483
|
+
index,
|
|
29484
|
+
newValue
|
|
29485
|
+
});
|
|
29486
|
+
}
|
|
29487
|
+
function setAtIndex(args) {
|
|
29488
|
+
const {
|
|
29489
|
+
array = [],
|
|
29490
|
+
index,
|
|
29491
|
+
newValue
|
|
29492
|
+
} = args;
|
|
29493
|
+
const copy = [...array];
|
|
29494
|
+
copy[index] = newValue;
|
|
29495
|
+
// restoring readonly to array
|
|
29496
|
+
return copy;
|
|
29497
|
+
}
|
|
29498
|
+
|
|
29499
|
+
function initializeGraphState(params) {
|
|
29500
|
+
const {
|
|
29501
|
+
graph,
|
|
29502
|
+
step,
|
|
29503
|
+
snapStep,
|
|
29504
|
+
range
|
|
29505
|
+
} = params;
|
|
29506
|
+
switch (graph.type) {
|
|
29507
|
+
case "segment":
|
|
29508
|
+
return {
|
|
29509
|
+
type: "segment",
|
|
29510
|
+
hasBeenInteractedWith: false,
|
|
29511
|
+
range,
|
|
29512
|
+
snapStep,
|
|
29513
|
+
coords: getDefaultSegments({
|
|
29514
|
+
graph,
|
|
29515
|
+
step,
|
|
29516
|
+
range
|
|
29517
|
+
})
|
|
29518
|
+
};
|
|
29519
|
+
case "linear":
|
|
29520
|
+
case "linear-system":
|
|
29521
|
+
case "ray":
|
|
29522
|
+
return {
|
|
29523
|
+
type: graph.type,
|
|
29524
|
+
hasBeenInteractedWith: false,
|
|
29525
|
+
range,
|
|
29526
|
+
snapStep,
|
|
29527
|
+
// Linear and ray graphs have a single tuple of points, while a
|
|
29528
|
+
// linear system has two tuples of points.
|
|
29529
|
+
coords: getLineCoords({
|
|
29530
|
+
graph,
|
|
29531
|
+
range,
|
|
29532
|
+
step
|
|
29533
|
+
})
|
|
29534
|
+
};
|
|
29535
|
+
case "polygon":
|
|
29536
|
+
return {
|
|
29537
|
+
type: "polygon",
|
|
29538
|
+
hasBeenInteractedWith: false,
|
|
29539
|
+
range,
|
|
29540
|
+
snapStep,
|
|
29541
|
+
coords: getPolygonCoords({
|
|
29542
|
+
graph,
|
|
29543
|
+
range,
|
|
29544
|
+
step
|
|
29545
|
+
})
|
|
29546
|
+
};
|
|
29547
|
+
case "angle":
|
|
29548
|
+
case "point":
|
|
29549
|
+
case "circle":
|
|
29550
|
+
case "sinusoid":
|
|
29551
|
+
case "quadratic":
|
|
29552
|
+
throw new Error("Mafs not yet implemented for graph type: " + graph.type);
|
|
29553
|
+
default:
|
|
29554
|
+
throw new UnreachableCaseError(graph);
|
|
29555
|
+
}
|
|
29556
|
+
}
|
|
29557
|
+
|
|
29558
|
+
// TS v4 doesn't narrow return types, while v5 does.
|
|
29559
|
+
// Instead of updating to v5, using generic type to relate input and output types.
|
|
29560
|
+
function getGradableGraph(state, initialGraph) {
|
|
29561
|
+
var _state$coords;
|
|
29562
|
+
if (!state.hasBeenInteractedWith) {
|
|
29563
|
+
return initialGraph;
|
|
29564
|
+
}
|
|
29565
|
+
switch (true) {
|
|
29566
|
+
// coords: Array of CollinearTuple
|
|
29567
|
+
case state.type === "linear-system" && initialGraph.type === "linear-system":
|
|
29568
|
+
case state.type === "segment" && initialGraph.type === "segment":
|
|
29569
|
+
return _extends({}, initialGraph, {
|
|
29570
|
+
coords: state.coords
|
|
29571
|
+
});
|
|
29572
|
+
// coords: CollinearTuple
|
|
29573
|
+
case state.type === "linear" && initialGraph.type === "linear":
|
|
29574
|
+
case state.type === "ray" && initialGraph.type === "ray":
|
|
29575
|
+
return _extends({}, initialGraph, {
|
|
29576
|
+
coords: (_state$coords = state.coords) == null ? void 0 : _state$coords[0]
|
|
29577
|
+
});
|
|
29578
|
+
case state.type === "polygon" && initialGraph.type === "polygon":
|
|
29579
|
+
return _extends({}, initialGraph, {
|
|
29580
|
+
coords: state.coords
|
|
29581
|
+
});
|
|
29582
|
+
default:
|
|
29583
|
+
throw new Error("Mafs is not yet implemented for graph type: " + initialGraph.type);
|
|
29584
|
+
}
|
|
29585
|
+
}
|
|
29586
|
+
const getDefaultSegments = ({
|
|
29587
|
+
graph,
|
|
29588
|
+
range,
|
|
29589
|
+
step
|
|
29590
|
+
}) => {
|
|
29591
|
+
const ys = n => {
|
|
29592
|
+
switch (n) {
|
|
29593
|
+
case 2:
|
|
29594
|
+
return [5, -5];
|
|
29595
|
+
case 3:
|
|
29596
|
+
return [5, 0, -5];
|
|
29597
|
+
case 4:
|
|
29598
|
+
return [6, 2, -2, -6];
|
|
29599
|
+
case 5:
|
|
29600
|
+
return [6, 3, 0, -3, -6];
|
|
29601
|
+
case 6:
|
|
29602
|
+
return [5, 3, 1, -1, -3, -5];
|
|
29603
|
+
default:
|
|
29604
|
+
return [5];
|
|
29605
|
+
}
|
|
29606
|
+
};
|
|
29607
|
+
return ys(graph.numSegments).map(y => {
|
|
29608
|
+
let endpoints = [[-5, y], [5, y]];
|
|
29609
|
+
endpoints = normalizeCoords(endpoints, range);
|
|
29610
|
+
endpoints = normalizePoints(range, step, endpoints);
|
|
29611
|
+
return endpoints;
|
|
29612
|
+
});
|
|
29613
|
+
};
|
|
29614
|
+
const defaultLinearCoords = [[[0.25, 0.75], [0.75, 0.75]], [[0.25, 0.25], [0.75, 0.25]]];
|
|
29615
|
+
const getLineCoords = ({
|
|
29616
|
+
graph,
|
|
29617
|
+
range,
|
|
29618
|
+
step
|
|
29619
|
+
}) => {
|
|
29620
|
+
var _graph$coords;
|
|
29621
|
+
return (
|
|
29622
|
+
// Return two lines for a linear system, one for a ray or linear
|
|
29623
|
+
((_graph$coords = graph.coords) != null ? _graph$coords : graph.type === "linear-system") ? defaultLinearCoords.map(collinear => normalizePoints(range, step, collinear)) : [normalizePoints(range, step, defaultLinearCoords[0])]
|
|
29624
|
+
);
|
|
29625
|
+
};
|
|
29626
|
+
const getPolygonCoords = ({
|
|
29627
|
+
graph,
|
|
29628
|
+
range,
|
|
29629
|
+
step
|
|
29630
|
+
}) => {
|
|
29631
|
+
let coords = graph.coords;
|
|
29632
|
+
if (coords) {
|
|
29633
|
+
return coords;
|
|
29634
|
+
}
|
|
29635
|
+
const n = graph.numSides || 3;
|
|
29636
|
+
if (n === "unlimited") {
|
|
29637
|
+
coords = [];
|
|
29638
|
+
} else {
|
|
29639
|
+
const angle = 2 * Math.PI / n;
|
|
29640
|
+
const offset = (1 / n - 1 / 2) * Math.PI;
|
|
29641
|
+
|
|
29642
|
+
// TODO(alex): Generalize this to more than just triangles so that
|
|
29643
|
+
// all polygons have whole number side lengths if snapping to sides
|
|
29644
|
+
const radius = graph.snapTo === "sides" ? Math.sqrt(3) / 3 * 7 : 4;
|
|
29645
|
+
|
|
29646
|
+
// Generate coords of a regular polygon with n sides
|
|
29647
|
+
coords = [...Array(n).keys()].map(i => [radius * Math.cos(i * angle + offset), radius * Math.sin(i * angle + offset)]);
|
|
29648
|
+
}
|
|
29649
|
+
coords = normalizeCoords(coords, [[-10, 10], [-10, 10]]);
|
|
29650
|
+
const snapToGrid = !["angles", "sides"].includes(graph.snapTo || "");
|
|
29651
|
+
coords = normalizePoints(range, step, coords, /* noSnap */!snapToGrid);
|
|
29652
|
+
return coords;
|
|
29653
|
+
};
|
|
29654
|
+
|
|
29426
29655
|
const renderGraph = props => {
|
|
29427
29656
|
const {
|
|
29428
29657
|
state,
|
|
@@ -29448,12 +29677,16 @@ const renderGraph = props => {
|
|
|
29448
29677
|
graphState: state,
|
|
29449
29678
|
dispatch: dispatch
|
|
29450
29679
|
});
|
|
29680
|
+
case "polygon":
|
|
29681
|
+
return /*#__PURE__*/React.createElement(PolygonGraph, {
|
|
29682
|
+
graphState: state,
|
|
29683
|
+
dispatch: dispatch
|
|
29684
|
+
});
|
|
29451
29685
|
default:
|
|
29452
29686
|
return new UnreachableCaseError(type);
|
|
29453
29687
|
}
|
|
29454
29688
|
};
|
|
29455
29689
|
const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
29456
|
-
var _props$backgroundImag, _props$backgroundImag2, _props$backgroundImag3, _props$backgroundImag4;
|
|
29457
29690
|
const [width, height] = props.box;
|
|
29458
29691
|
const legacyGrid = getLegacyGrid([width, height], props.backgroundImage);
|
|
29459
29692
|
const [state, dispatch] = React.useReducer(interactiveGraphReducer, props, initializeGraphState);
|
|
@@ -29462,8 +29695,8 @@ const MafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
29462
29695
|
}));
|
|
29463
29696
|
return /*#__PURE__*/React.createElement(View, {
|
|
29464
29697
|
style: {
|
|
29465
|
-
width
|
|
29466
|
-
height
|
|
29698
|
+
width,
|
|
29699
|
+
height,
|
|
29467
29700
|
position: "relative"
|
|
29468
29701
|
}
|
|
29469
29702
|
}, legacyGrid, /*#__PURE__*/React.createElement(View, {
|
|
@@ -29546,7 +29779,7 @@ const makeInvalidTypeError = (functionName, graphType) => {
|
|
|
29546
29779
|
|
|
29547
29780
|
// There's no transform function in exports
|
|
29548
29781
|
|
|
29549
|
-
class
|
|
29782
|
+
class LegacyInteractiveGraph extends React.Component {
|
|
29550
29783
|
constructor(...args) {
|
|
29551
29784
|
super(...args);
|
|
29552
29785
|
this.angle = void 0;
|
|
@@ -29567,7 +29800,6 @@ class InteractiveGraph extends React.Component {
|
|
|
29567
29800
|
this.sinusoid = void 0;
|
|
29568
29801
|
this.trashCan = void 0;
|
|
29569
29802
|
this.vertHairline = void 0;
|
|
29570
|
-
this.mafsRef = /*#__PURE__*/React.createRef();
|
|
29571
29803
|
this.state = {
|
|
29572
29804
|
shouldShowInstructions: _getShouldShowInstructions(this.props)
|
|
29573
29805
|
};
|
|
@@ -30647,10 +30879,7 @@ class InteractiveGraph extends React.Component {
|
|
|
30647
30879
|
graph: graph
|
|
30648
30880
|
});
|
|
30649
30881
|
};
|
|
30650
|
-
this.getUserInput = () =>
|
|
30651
|
-
var _this$mafsRef$current, _this$mafsRef$current2;
|
|
30652
|
-
return (_this$mafsRef$current = (_this$mafsRef$current2 = this.mafsRef.current) == null || _this$mafsRef$current2.getUserInput == null ? void 0 : _this$mafsRef$current2.getUserInput()) != null ? _this$mafsRef$current : InteractiveGraph.getUserInputFromProps(this.props);
|
|
30653
|
-
};
|
|
30882
|
+
this.getUserInput = () => InteractiveGraph.getUserInputFromProps(this.props);
|
|
30654
30883
|
this.simpleValidate = rubric => InteractiveGraph.validate(this.getUserInput(), rubric, this);
|
|
30655
30884
|
this.focus = $.noop;
|
|
30656
30885
|
}
|
|
@@ -30703,23 +30932,10 @@ class InteractiveGraph extends React.Component {
|
|
|
30703
30932
|
areSegmentGraphsEqual(prevGraph, currentGraph) {
|
|
30704
30933
|
return prevGraph.numSegments !== currentGraph.numSegments;
|
|
30705
30934
|
}
|
|
30706
|
-
// const segment: boolean = useFeatureIsOn("mafs-segment-graph");
|
|
30707
|
-
// <Renderer apiOptions={{flags: {mafs: {segment}}}}
|
|
30708
30935
|
render() {
|
|
30709
|
-
var _this$props$apiOption;
|
|
30710
30936
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
30711
30937
|
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
30712
30938
|
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
30713
|
-
|
|
30714
|
-
// Mafs shim
|
|
30715
|
-
if ((_this$props$apiOption = this.props.apiOptions) != null && (_this$props$apiOption = _this$props$apiOption.flags) != null && (_this$props$apiOption = _this$props$apiOption["mafs"]) != null && _this$props$apiOption[this.props.graph.type]) {
|
|
30716
|
-
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, this.props, {
|
|
30717
|
-
ref: this.mafsRef,
|
|
30718
|
-
gridStep: gridStep,
|
|
30719
|
-
snapStep: snapStep,
|
|
30720
|
-
box: box
|
|
30721
|
-
}));
|
|
30722
|
-
}
|
|
30723
30939
|
let instructions;
|
|
30724
30940
|
// isClickToAddPoints() only applies to points and polygons
|
|
30725
30941
|
if (this.isClickToAddPoints() && this.state.shouldShowInstructions) {
|
|
@@ -30765,6 +30981,60 @@ class InteractiveGraph extends React.Component {
|
|
|
30765
30981
|
isMobile: isMobile
|
|
30766
30982
|
}));
|
|
30767
30983
|
}
|
|
30984
|
+
}
|
|
30985
|
+
LegacyInteractiveGraph.defaultProps = {
|
|
30986
|
+
labels: ["x", "y"],
|
|
30987
|
+
range: [[-10, 10], [-10, 10]],
|
|
30988
|
+
step: [1, 1],
|
|
30989
|
+
backgroundImage: defaultBackgroundImage,
|
|
30990
|
+
markings: "graph",
|
|
30991
|
+
showTooltips: false,
|
|
30992
|
+
showProtractor: false,
|
|
30993
|
+
showRuler: false,
|
|
30994
|
+
rulerLabel: "",
|
|
30995
|
+
rulerTicks: 10,
|
|
30996
|
+
graph: {
|
|
30997
|
+
type: "linear"
|
|
30998
|
+
}
|
|
30999
|
+
};
|
|
31000
|
+
class InteractiveGraph extends React.Component {
|
|
31001
|
+
constructor(...args) {
|
|
31002
|
+
super(...args);
|
|
31003
|
+
this.legacyGraphRef = /*#__PURE__*/React.createRef();
|
|
31004
|
+
this.mafsRef = /*#__PURE__*/React.createRef();
|
|
31005
|
+
this.getUserInput = () => {
|
|
31006
|
+
if (this.mafsRef.current) {
|
|
31007
|
+
var _this$mafsRef$current, _this$mafsRef$current2;
|
|
31008
|
+
return (_this$mafsRef$current = (_this$mafsRef$current2 = this.mafsRef.current).getUserInput) == null ? void 0 : _this$mafsRef$current.call(_this$mafsRef$current2);
|
|
31009
|
+
}
|
|
31010
|
+
if (this.legacyGraphRef.current) {
|
|
31011
|
+
return this.legacyGraphRef.current.getUserInput();
|
|
31012
|
+
}
|
|
31013
|
+
throw new PerseusError("Cannot getUserInput from a graph that has never rendered", Errors.NotAllowed);
|
|
31014
|
+
};
|
|
31015
|
+
this.simpleValidate = rubric => {
|
|
31016
|
+
var _this$getUserInput;
|
|
31017
|
+
return InteractiveGraph.validate((_this$getUserInput = this.getUserInput) == null ? void 0 : _this$getUserInput.call(this), rubric, this);
|
|
31018
|
+
};
|
|
31019
|
+
}
|
|
31020
|
+
render() {
|
|
31021
|
+
var _this$props$apiOption;
|
|
31022
|
+
// Mafs shim
|
|
31023
|
+
if ((_this$props$apiOption = this.props.apiOptions) != null && (_this$props$apiOption = _this$props$apiOption.flags) != null && (_this$props$apiOption = _this$props$apiOption["mafs"]) != null && _this$props$apiOption[this.props.graph.type]) {
|
|
31024
|
+
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
31025
|
+
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
31026
|
+
const snapStep = this.props.snapStep || Util.snapStepFromGridStep(gridStep);
|
|
31027
|
+
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, this.props, {
|
|
31028
|
+
ref: this.mafsRef,
|
|
31029
|
+
gridStep: gridStep,
|
|
31030
|
+
snapStep: snapStep,
|
|
31031
|
+
box: box
|
|
31032
|
+
}));
|
|
31033
|
+
}
|
|
31034
|
+
return /*#__PURE__*/React.createElement(LegacyInteractiveGraph, _extends({
|
|
31035
|
+
ref: this.legacyGraphRef
|
|
31036
|
+
}, this.props));
|
|
31037
|
+
}
|
|
30768
31038
|
static getQuadraticCoefficients(coords) {
|
|
30769
31039
|
const p1 = coords[0];
|
|
30770
31040
|
const p2 = coords[1];
|
|
@@ -41493,7 +41763,7 @@ const init = function init(options) {
|
|
|
41493
41763
|
|
|
41494
41764
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
41495
41765
|
const libName = "@khanacademy/perseus";
|
|
41496
|
-
const libVersion = "20.
|
|
41766
|
+
const libVersion = "20.7.0";
|
|
41497
41767
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
41498
41768
|
|
|
41499
41769
|
const apiVersion = {
|
|
@@ -42272,7 +42542,6 @@ class ServerItemRenderer extends React.Component {
|
|
|
42272
42542
|
const qScore = this.questionRenderer.scoreWidgets();
|
|
42273
42543
|
const qGuess = this.questionRenderer.getUserInputForWidgets();
|
|
42274
42544
|
const state = this.questionRenderer.getSerializedState();
|
|
42275
|
-
// @ts-expect-error - TS2322 - Type 'Partial<Record<string, KEScore>>' is not assignable to type '{ [key: string]: KEScore; }'. | TS2345 - Argument of type '{ [widgetId: string]: PerseusScore; }' is not assignable to parameter of type 'Partial<Record<string, { type: "invalid"; message?: string | null | undefined; suppressAlmostThere?: boolean | null | undefined; }>>'.
|
|
42276
42545
|
return mapObject(qScore, (score, id) => {
|
|
42277
42546
|
return Util.keScoreFromPerseusScore(score, qGuess[id], state);
|
|
42278
42547
|
});
|
|
@@ -44202,6 +44471,218 @@ function generateTestPerseusItem(customFields = {}) {
|
|
|
44202
44471
|
return _extends({}, genericPerseusItemData, customFields);
|
|
44203
44472
|
}
|
|
44204
44473
|
|
|
44474
|
+
/**
|
|
44475
|
+
* Some helpers for CEDAR logging. CEDAR convention dictates
|
|
44476
|
+
* that enum values should be upper case. Ex: for the
|
|
44477
|
+
* PerseusWidgetUsedInProblemAttempt CEDAR event, we needed
|
|
44478
|
+
* to: get the type and convert that to an enum value.
|
|
44479
|
+
*/
|
|
44480
|
+
|
|
44481
|
+
const widgetNameToEnum = {
|
|
44482
|
+
categorizer: "CATEGORIZER",
|
|
44483
|
+
"cs-program": "CS_PROGRAM",
|
|
44484
|
+
definition: "DEFINITION",
|
|
44485
|
+
"deprecated-standin": "DEPRECATED_STANDIN",
|
|
44486
|
+
dropdown: "DROPDOWN",
|
|
44487
|
+
explanation: "EXPLANATION",
|
|
44488
|
+
expression: "EXPRESSION",
|
|
44489
|
+
"graded-group-set": "GRADED_GROUP_SET",
|
|
44490
|
+
"graded-group": "GRADED_GROUP",
|
|
44491
|
+
grapher: "GRAPHER",
|
|
44492
|
+
group: "GROUP",
|
|
44493
|
+
iframe: "IFRAME",
|
|
44494
|
+
image: "IMAGE",
|
|
44495
|
+
"input-number": "INPUT_NUMBER",
|
|
44496
|
+
interaction: "INTERACTIVE",
|
|
44497
|
+
"interactive-graph": "INTERACTIVE_GRAPH",
|
|
44498
|
+
"label-image": "LABEL_IMAGE",
|
|
44499
|
+
"lights-puzzle": "LIGHTS_PUZZLE",
|
|
44500
|
+
matcher: "MATCHER",
|
|
44501
|
+
matrix: "MATRIX",
|
|
44502
|
+
measurer: "MEASURER",
|
|
44503
|
+
"molecule-renderer": "MOLECULE",
|
|
44504
|
+
"number-line": "NUMBER_LINE",
|
|
44505
|
+
"numeric-input": "NUMERIC_INPUT",
|
|
44506
|
+
orderer: "ORDERER",
|
|
44507
|
+
passage: "PASSAGE",
|
|
44508
|
+
"passage-ref": "PASSAGE_REF",
|
|
44509
|
+
"passage-ref-target": "PASSAGE_REF_TARGET",
|
|
44510
|
+
plotter: "PLOTTER",
|
|
44511
|
+
"python-program": "PYTHON_PROGRAM",
|
|
44512
|
+
"reaction-diagram": "REACTION_DIAGRAM",
|
|
44513
|
+
radio: "RADIO",
|
|
44514
|
+
sequence: "SEQUENCE",
|
|
44515
|
+
simulator: "SIMULATOR",
|
|
44516
|
+
sorter: "SORTER",
|
|
44517
|
+
table: "TABLE",
|
|
44518
|
+
"unit-input": "UNIT",
|
|
44519
|
+
video: "VIDEO"
|
|
44520
|
+
};
|
|
44521
|
+
function convertWidgetNameToEnum(name) {
|
|
44522
|
+
const widgetEnum = widgetNameToEnum[name];
|
|
44523
|
+
if (!widgetEnum) {
|
|
44524
|
+
throw new Error(`Unknown widget name: ${name}`);
|
|
44525
|
+
}
|
|
44526
|
+
return widgetEnum;
|
|
44527
|
+
}
|
|
44528
|
+
function getWidgetTypeFromWidgetId(widgetId) {
|
|
44529
|
+
const [widgetType, widgetNumber] = widgetId.split(" ");
|
|
44530
|
+
if (!widgetNumber) {
|
|
44531
|
+
throw new Error(`Incorrect format for widget ID: ${widgetId}`);
|
|
44532
|
+
}
|
|
44533
|
+
if (!widgetNameToEnum[widgetType]) {
|
|
44534
|
+
throw new Error(`Unknown widget type (${widgetType}) in widget ID: ${widgetId}`);
|
|
44535
|
+
}
|
|
44536
|
+
return widgetType;
|
|
44537
|
+
}
|
|
44538
|
+
|
|
44539
|
+
let WidgetType = /*#__PURE__*/function (WidgetType) {
|
|
44540
|
+
WidgetType["Categorizer"] = "categorizer";
|
|
44541
|
+
WidgetType["CSProgram"] = "cs-program";
|
|
44542
|
+
WidgetType["Definition"] = "definition";
|
|
44543
|
+
WidgetType["Dropdown"] = "dropdown";
|
|
44544
|
+
WidgetType["Explanation"] = "explanation";
|
|
44545
|
+
WidgetType["Expression"] = "expression";
|
|
44546
|
+
WidgetType["GradedGroup"] = "graded-group";
|
|
44547
|
+
WidgetType["GradedGroupAnswerBar"] = "graded-group-answer-bar";
|
|
44548
|
+
WidgetType["GradedGroupSet"] = "graded-group-set";
|
|
44549
|
+
WidgetType["Grapher"] = "grapher";
|
|
44550
|
+
WidgetType["Group"] = "group";
|
|
44551
|
+
WidgetType["Iframe"] = "iframe";
|
|
44552
|
+
WidgetType["Image"] = "image";
|
|
44553
|
+
WidgetType["InputNumber"] = "input-number";
|
|
44554
|
+
WidgetType["Interaction"] = "interaction";
|
|
44555
|
+
WidgetType["InteractiveGraph"] = "interactive-graph";
|
|
44556
|
+
WidgetType["InteractiveNumberLine"] = "interactive-number-line";
|
|
44557
|
+
WidgetType["LabelImage"] = "label-image";
|
|
44558
|
+
WidgetType["Matcher"] = "matcher";
|
|
44559
|
+
WidgetType["Matrix"] = "matrix";
|
|
44560
|
+
WidgetType["Measurer"] = "measurer";
|
|
44561
|
+
WidgetType["Molecule"] = "molecule";
|
|
44562
|
+
WidgetType["NumberLine"] = "number-line";
|
|
44563
|
+
WidgetType["NumericInput"] = "numeric-input";
|
|
44564
|
+
WidgetType["Orderer"] = "orderer";
|
|
44565
|
+
WidgetType["Passage"] = "passage";
|
|
44566
|
+
WidgetType["PassageRef"] = "passage-ref";
|
|
44567
|
+
WidgetType["PassageRefTarget"] = "passage-ref-target";
|
|
44568
|
+
WidgetType["Plotter"] = "plotter";
|
|
44569
|
+
WidgetType["Protractor"] = "protractor";
|
|
44570
|
+
WidgetType["PythonProgram"] = "python-program";
|
|
44571
|
+
WidgetType["Radio"] = "radio";
|
|
44572
|
+
WidgetType["Sorter"] = "sorter";
|
|
44573
|
+
WidgetType["Table"] = "table";
|
|
44574
|
+
WidgetType["Unit"] = "unit";
|
|
44575
|
+
WidgetType["Video"] = "video";
|
|
44576
|
+
WidgetType["VideoTranscriptLink"] = "video-transcript-link";
|
|
44577
|
+
return WidgetType;
|
|
44578
|
+
}({});
|
|
44579
|
+
// These are all the current widgets that require user-input and are supported for automatic scoring
|
|
44580
|
+
const QUESTION_WIDGETS = ["numeric-input", "input-number", "radio", "interactive-graph", "interactive-number-line", "categorizer", "plotter", "orderer", "protractor", "matcher", "sorter"];
|
|
44581
|
+
|
|
44582
|
+
/**
|
|
44583
|
+
* Regex for widget placeholders in a string.
|
|
44584
|
+
*
|
|
44585
|
+
* First capture group is the widget ID (ex. 'radio 1')
|
|
44586
|
+
* Second capture group is the widget type (ex. "radio)
|
|
44587
|
+
* exec return will look like: ['[[☃ radio 1]]', 'radio 1', 'radio']
|
|
44588
|
+
*/
|
|
44589
|
+
function getWidgetRegex() {
|
|
44590
|
+
return /\[\[☃ (([a-z-]+) \d+)\]\]/g;
|
|
44591
|
+
}
|
|
44592
|
+
|
|
44593
|
+
/**
|
|
44594
|
+
* Add a widget placeholder using the provided widget type and instance number.
|
|
44595
|
+
* ex. addWidget(WidgetType.Radio, 1) => "[[☃ radio 1]]"
|
|
44596
|
+
*
|
|
44597
|
+
* @param {WidgetType} widgetType
|
|
44598
|
+
* @param {number} instance
|
|
44599
|
+
* @returns {string}
|
|
44600
|
+
*/
|
|
44601
|
+
function addWidget(widgetType, instance) {
|
|
44602
|
+
return `[[☃ ${widgetType} ${String(instance)}]]`;
|
|
44603
|
+
}
|
|
44604
|
+
|
|
44605
|
+
/**
|
|
44606
|
+
* Extract all widget IDs, which includes the widget type and instance number.
|
|
44607
|
+
* example output: ['radio 1', 'categorizer 1', 'categorizor 2']
|
|
44608
|
+
*
|
|
44609
|
+
* Content should contain Perseus widget placeholders,
|
|
44610
|
+
* which look like: '[[☃ radio 1]]'.
|
|
44611
|
+
*
|
|
44612
|
+
* @param {string} content
|
|
44613
|
+
* @returns {Array<WidgetId>} widgets
|
|
44614
|
+
*/
|
|
44615
|
+
function getAllWidgetIds(content) {
|
|
44616
|
+
const widgets = [];
|
|
44617
|
+
const localWidgetRegex = getWidgetRegex();
|
|
44618
|
+
let match = localWidgetRegex.exec(content);
|
|
44619
|
+
while (match !== null) {
|
|
44620
|
+
widgets.push(match[1]);
|
|
44621
|
+
match = localWidgetRegex.exec(content);
|
|
44622
|
+
}
|
|
44623
|
+
return widgets;
|
|
44624
|
+
}
|
|
44625
|
+
|
|
44626
|
+
/**
|
|
44627
|
+
* Check if a specific widget is an actual widget type using its name.
|
|
44628
|
+
* The widget name should include a widget type, without an instance number,
|
|
44629
|
+
* as a string. ex. 'radio'
|
|
44630
|
+
*
|
|
44631
|
+
* @param {string} widgetName
|
|
44632
|
+
* @returns {boolean}
|
|
44633
|
+
*/
|
|
44634
|
+
function isWidgetType(widgetName) {
|
|
44635
|
+
return Object.values(WidgetType).includes(widgetName);
|
|
44636
|
+
}
|
|
44637
|
+
|
|
44638
|
+
/**
|
|
44639
|
+
* Extract all widget types from a Perseus JSON content string.
|
|
44640
|
+
* This does not include the instance number and prevents duplicates.
|
|
44641
|
+
* example output: ['radio', 'categorizer']
|
|
44642
|
+
*
|
|
44643
|
+
* @param {string} content
|
|
44644
|
+
* @returns {Array<WidgetId>}
|
|
44645
|
+
*/
|
|
44646
|
+
function getAllWidgetTypes(content) {
|
|
44647
|
+
const widgetTypes = [];
|
|
44648
|
+
const localWidgetRegex = getWidgetRegex();
|
|
44649
|
+
let match = localWidgetRegex.exec(content);
|
|
44650
|
+
while (match !== null) {
|
|
44651
|
+
const matchType = match[2];
|
|
44652
|
+
if (!widgetTypes.includes(matchType) && isWidgetType(matchType)) {
|
|
44653
|
+
widgetTypes.push(matchType);
|
|
44654
|
+
}
|
|
44655
|
+
match = localWidgetRegex.exec(content);
|
|
44656
|
+
}
|
|
44657
|
+
return widgetTypes;
|
|
44658
|
+
}
|
|
44659
|
+
|
|
44660
|
+
/**
|
|
44661
|
+
* Check if a specific widget is a question widget type using its ID.
|
|
44662
|
+
* The widget ID includes the widget type and the instance number.
|
|
44663
|
+
*
|
|
44664
|
+
* @param {WidgetId} widgetId
|
|
44665
|
+
* @returns {boolean}
|
|
44666
|
+
*/
|
|
44667
|
+
function isQuestionWidgetType(widgetId) {
|
|
44668
|
+
return QUESTION_WIDGETS.includes(widgetId.split(" ")[0]);
|
|
44669
|
+
}
|
|
44670
|
+
|
|
44671
|
+
/**
|
|
44672
|
+
* Extract the widget IDs of all widgets considered question widgets. Widget IDs
|
|
44673
|
+
* include widget type and instance number.
|
|
44674
|
+
* example output: ['radio 1', 'categorizer 1']
|
|
44675
|
+
*
|
|
44676
|
+
* Content should contain Perseus widget placeholders,
|
|
44677
|
+
* which look like: '[[☃ radio 1]]'.
|
|
44678
|
+
*
|
|
44679
|
+
* @param {string} content
|
|
44680
|
+
* @returns Array<WidgetId>
|
|
44681
|
+
*/
|
|
44682
|
+
function getQuestionWidgetIds(content) {
|
|
44683
|
+
return getAllWidgetIds(content).filter(isQuestionWidgetType);
|
|
44684
|
+
}
|
|
44685
|
+
|
|
44205
44686
|
const EditorJsonify = {
|
|
44206
44687
|
serialize: function () {
|
|
44207
44688
|
// Omit props that get passed to all widgets
|
|
@@ -44210,5 +44691,5 @@ const EditorJsonify = {
|
|
|
44210
44691
|
}
|
|
44211
44692
|
};
|
|
44212
44693
|
|
|
44213
|
-
export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Errors, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusError, PerseusExpressionAnswerFormConsidered, PerseusMarkdown, Plotter$1 as PlotterWidget, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, displaySigFigs, generateTestPerseusItem, genericPerseusItemData, getAnswersFromWidgets, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, traverse, violatingWidgets, allWidgets as widgets };
|
|
44694
|
+
export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Errors, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusError, PerseusExpressionAnswerFormConsidered, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, WidgetType, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, convertWidgetNameToEnum, displaySigFigs, generateTestPerseusItem, genericPerseusItemData, getAllWidgetIds, getAllWidgetTypes, getAnswersFromWidgets, getQuestionWidgetIds, getWidgetTypeFromWidgetId, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, traverse, violatingWidgets, allWidgets as widgets };
|
|
44214
44695
|
//# sourceMappingURL=index.js.map
|