@khanacademy/perseus 18.0.1 → 19.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/CHANGELOG.md +6 -0
- package/dist/es/index.css +0 -24
- package/dist/es/index.js +77 -2496
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +0 -24
- package/dist/index.d.ts +0 -1
- package/dist/index.js +75 -2496
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +2 -109
- package/dist/strings.js +0 -29
- package/dist/types.d.ts +0 -4
- package/dist/widgets/expression.d.ts +2 -2
- package/dist/widgets.d.ts +1 -1
- package/package.json +1 -1
- package/src/__tests__/widgets.test.ts +0 -1
- package/src/extra-widgets.ts +0 -2
- package/src/index.ts +0 -1
- package/src/perseus-types.ts +1 -154
- package/src/styles/perseus-renderer.less +0 -1
- package/src/types.ts +0 -5
- package/src/util/register-all-widgets-for-testing.ts +1 -3
- package/src/widgets/__tests__/renderQuestion.tsx +11 -3
- package/src/widgets.ts +1 -9
- package/tsconfig-build.tsbuildinfo +1 -1
- package/dist/widgets/transformer.d.ts +0 -94
- package/src/styles/widgets/transformer.less +0 -29
- package/src/widgets/__stories__/transformer.stories.tsx +0 -14
- package/src/widgets/__testdata__/transformer.testdata.ts +0 -107
- package/src/widgets/transformer.tsx +0 -2936
package/dist/index.js
CHANGED
|
@@ -2776,7 +2776,7 @@ function gridDimensionConfig(absTickStep, extent, dimensionConstraint, gridStep)
|
|
|
2776
2776
|
*
|
|
2777
2777
|
* TODO(somewhatabstract, FEI-3464): Consolidate query string parsing functions.
|
|
2778
2778
|
*/
|
|
2779
|
-
function getGridStep
|
|
2779
|
+
function getGridStep(range, step, boxSize) {
|
|
2780
2780
|
// @ts-expect-error - TS2322 - Type '(number | null | undefined)[]' is not assignable to type 'Coordinates'.
|
|
2781
2781
|
return ___default["default"](2).times(function (i) {
|
|
2782
2782
|
const scale = scaleFromExtent(range[i], boxSize);
|
|
@@ -2958,13 +2958,13 @@ function eq$2(x, y) {
|
|
|
2958
2958
|
* Deep approximate equality on primitives, numbers, arrays, and objects.
|
|
2959
2959
|
* Recursive.
|
|
2960
2960
|
*/
|
|
2961
|
-
function deepEq$
|
|
2961
|
+
function deepEq$5(x, y) {
|
|
2962
2962
|
if (Array.isArray(x) && Array.isArray(y)) {
|
|
2963
2963
|
if (x.length !== y.length) {
|
|
2964
2964
|
return false;
|
|
2965
2965
|
}
|
|
2966
2966
|
for (let i = 0; i < x.length; i++) {
|
|
2967
|
-
if (!deepEq$
|
|
2967
|
+
if (!deepEq$5(x[i], y[i])) {
|
|
2968
2968
|
return false;
|
|
2969
2969
|
}
|
|
2970
2970
|
}
|
|
@@ -2982,10 +2982,10 @@ function deepEq$6(x, y) {
|
|
|
2982
2982
|
if (typeof x === "object" && typeof y === "object" && !!x && !!y) {
|
|
2983
2983
|
return x === y || ___default["default"].all(x, function (v, k) {
|
|
2984
2984
|
// @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
|
|
2985
|
-
return deepEq$
|
|
2985
|
+
return deepEq$5(y[k], v);
|
|
2986
2986
|
}) && ___default["default"].all(y, function (v, k) {
|
|
2987
2987
|
// @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
|
|
2988
|
-
return deepEq$
|
|
2988
|
+
return deepEq$5(x[k], v);
|
|
2989
2989
|
});
|
|
2990
2990
|
}
|
|
2991
2991
|
if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
|
|
@@ -3185,7 +3185,7 @@ const supportsPassiveEvents = () => {
|
|
|
3185
3185
|
* Pass this function as the touchstart for an element to
|
|
3186
3186
|
* avoid sending the touch to the mobile scratchpad
|
|
3187
3187
|
*/
|
|
3188
|
-
function captureScratchpadTouchStart$
|
|
3188
|
+
function captureScratchpadTouchStart$3(e) {
|
|
3189
3189
|
e.stopPropagation();
|
|
3190
3190
|
}
|
|
3191
3191
|
function getImageSize(url, callback) {
|
|
@@ -3273,7 +3273,7 @@ const Util = {
|
|
|
3273
3273
|
firstNumericalParse: firstNumericalParse$1,
|
|
3274
3274
|
stringArrayOfSize: stringArrayOfSize$1,
|
|
3275
3275
|
gridDimensionConfig,
|
|
3276
|
-
getGridStep
|
|
3276
|
+
getGridStep,
|
|
3277
3277
|
snapStepFromGridStep,
|
|
3278
3278
|
scaleFromExtent,
|
|
3279
3279
|
tickStepFromExtent,
|
|
@@ -3282,7 +3282,7 @@ const Util = {
|
|
|
3282
3282
|
constrainedTickStepsFromTickSteps,
|
|
3283
3283
|
DeprecationMixin: DeprecationMixin$1,
|
|
3284
3284
|
eq: eq$2,
|
|
3285
|
-
deepEq: deepEq$
|
|
3285
|
+
deepEq: deepEq$5,
|
|
3286
3286
|
parseQueryString,
|
|
3287
3287
|
updateQueryString: updateQueryString$2,
|
|
3288
3288
|
strongEncodeURIComponent,
|
|
@@ -3292,7 +3292,7 @@ const Util = {
|
|
|
3292
3292
|
resetTouchHandlers,
|
|
3293
3293
|
extractPointerLocation,
|
|
3294
3294
|
supportsPassiveEvents,
|
|
3295
|
-
captureScratchpadTouchStart: captureScratchpadTouchStart$
|
|
3295
|
+
captureScratchpadTouchStart: captureScratchpadTouchStart$3,
|
|
3296
3296
|
getImageSize,
|
|
3297
3297
|
getImageSizeModern: getImageSizeModern,
|
|
3298
3298
|
getRealImageUrl: getRealImageUrl,
|
|
@@ -13479,7 +13479,7 @@ ___default["default"].extend(MovableAngle.prototype, {
|
|
|
13479
13479
|
|
|
13480
13480
|
/* eslint-disable @babel/no-invalid-this */
|
|
13481
13481
|
const nestedMap$1 = Util.nestedMap;
|
|
13482
|
-
const deepEq$
|
|
13482
|
+
const deepEq$4 = Util.deepEq;
|
|
13483
13483
|
|
|
13484
13484
|
/**
|
|
13485
13485
|
* A base class for all Graphie Movables
|
|
@@ -13576,7 +13576,7 @@ const createSimpleClass = function (addFunction) {
|
|
|
13576
13576
|
this._prevProps = this.props;
|
|
13577
13577
|
},
|
|
13578
13578
|
modify: function (graphie) {
|
|
13579
|
-
if (!deepEq$
|
|
13579
|
+
if (!deepEq$4(this.props, this._prevProps)) {
|
|
13580
13580
|
this.remove();
|
|
13581
13581
|
this.add(graphie);
|
|
13582
13582
|
this._prevProps = this.props;
|
|
@@ -13621,7 +13621,7 @@ var GraphieClasses = {
|
|
|
13621
13621
|
* take appropriate action in onMoveStart, onMove, onMoveEnd
|
|
13622
13622
|
*/
|
|
13623
13623
|
const normalizeOptions$3 = InteractiveUtil.normalizeOptions;
|
|
13624
|
-
const assert$
|
|
13624
|
+
const assert$8 = InteractiveUtil.assert;
|
|
13625
13625
|
|
|
13626
13626
|
// state parameters that should be converted into an array of
|
|
13627
13627
|
// functions
|
|
@@ -13692,7 +13692,7 @@ ___default["default"].extend(Movable.prototype, {
|
|
|
13692
13692
|
* Simulates a mouse grab event on the movable object.
|
|
13693
13693
|
*/
|
|
13694
13694
|
grab: function (coord) {
|
|
13695
|
-
assert$
|
|
13695
|
+
assert$8(kmath.point.is(coord));
|
|
13696
13696
|
const self = this;
|
|
13697
13697
|
const graphie = self.graphie;
|
|
13698
13698
|
const state = self.state;
|
|
@@ -14158,7 +14158,7 @@ var MovableLineOptions = {
|
|
|
14158
14158
|
/**
|
|
14159
14159
|
* MovableLine
|
|
14160
14160
|
*/
|
|
14161
|
-
const assert$
|
|
14161
|
+
const assert$7 = InteractiveUtil.assert;
|
|
14162
14162
|
const normalizeOptions$2 = InteractiveUtil.normalizeOptions;
|
|
14163
14163
|
const FUNCTION_ARRAY_OPTIONS$2 = ["add", "draw", "remove", "onMoveStart", "constraints", "onMove", "onMoveEnd"];
|
|
14164
14164
|
|
|
@@ -14184,8 +14184,8 @@ const DEFAULT_STATE$2 = {
|
|
|
14184
14184
|
mouseTarget: null
|
|
14185
14185
|
};
|
|
14186
14186
|
const MovableLine$4 = function (graphie, movable, options) {
|
|
14187
|
-
assert$
|
|
14188
|
-
assert$
|
|
14187
|
+
assert$7(graphie != null);
|
|
14188
|
+
assert$7(options != null);
|
|
14189
14189
|
|
|
14190
14190
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
14191
14191
|
___default["default"].extend(this, {
|
|
@@ -14742,7 +14742,7 @@ var MovablePointOptions = {
|
|
|
14742
14742
|
}
|
|
14743
14743
|
};
|
|
14744
14744
|
|
|
14745
|
-
const assert$
|
|
14745
|
+
const assert$6 = InteractiveUtil.assert;
|
|
14746
14746
|
const normalizeOptions$1 = InteractiveUtil.normalizeOptions;
|
|
14747
14747
|
const {
|
|
14748
14748
|
processMath
|
|
@@ -14878,7 +14878,7 @@ ___default["default"].extend(MovablePoint$5.prototype, {
|
|
|
14878
14878
|
const self = this;
|
|
14879
14879
|
const graphie = self.graphie;
|
|
14880
14880
|
const state = ___default["default"].extend(self.state, normalizeOptions$1(FUNCTION_ARRAY_OPTIONS$1, options));
|
|
14881
|
-
assert$
|
|
14881
|
+
assert$6(kmath.point.is(state.coord));
|
|
14882
14882
|
|
|
14883
14883
|
// Default things inside the state.normalStyle object, because
|
|
14884
14884
|
// _.extend is not deep.
|
|
@@ -15080,12 +15080,12 @@ ___default["default"].extend(MovablePoint$5.prototype, {
|
|
|
15080
15080
|
return result !== false;
|
|
15081
15081
|
},
|
|
15082
15082
|
setCoord: function (coord) {
|
|
15083
|
-
assert$
|
|
15083
|
+
assert$6(kmath.point.is(coord, 2));
|
|
15084
15084
|
this.state.coord = ___default["default"].clone(coord);
|
|
15085
15085
|
this.draw();
|
|
15086
15086
|
},
|
|
15087
15087
|
setCoordConstrained: function (coord) {
|
|
15088
|
-
assert$
|
|
15088
|
+
assert$6(kmath.point.is(coord, 2));
|
|
15089
15089
|
const result = this._applyConstraints(coord, this.coord());
|
|
15090
15090
|
if (result !== false) {
|
|
15091
15091
|
this.state.coord = ___default["default"].clone(result);
|
|
@@ -15481,7 +15481,7 @@ var MovablePolygonOptions = {
|
|
|
15481
15481
|
* Creates and adds a polygon to the graph that can be dragged around.
|
|
15482
15482
|
* It allows constraints on its movement and draws when moves happen.
|
|
15483
15483
|
*/
|
|
15484
|
-
const assert$
|
|
15484
|
+
const assert$5 = InteractiveUtil.assert;
|
|
15485
15485
|
const normalizeOptions = InteractiveUtil.normalizeOptions;
|
|
15486
15486
|
|
|
15487
15487
|
// State parameters that should be converted into an array of
|
|
@@ -15520,8 +15520,8 @@ const DEFAULT_STATE = {
|
|
|
15520
15520
|
mouseTarget: null
|
|
15521
15521
|
};
|
|
15522
15522
|
const MovablePolygon = function (graphie, movable, options) {
|
|
15523
|
-
assert$
|
|
15524
|
-
assert$
|
|
15523
|
+
assert$5(graphie != null);
|
|
15524
|
+
assert$5(options != null);
|
|
15525
15525
|
|
|
15526
15526
|
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
15527
15527
|
___default["default"].extend(this, {
|
|
@@ -16039,11 +16039,11 @@ var Movables = {
|
|
|
16039
16039
|
const GraphieMovable = GraphieClasses.GraphieMovable;
|
|
16040
16040
|
const createGraphie = GraphUtils.createGraphie;
|
|
16041
16041
|
const {
|
|
16042
|
-
deepEq: deepEq$
|
|
16042
|
+
deepEq: deepEq$3,
|
|
16043
16043
|
nestedMap
|
|
16044
16044
|
} = Util;
|
|
16045
16045
|
const {
|
|
16046
|
-
assert: assert$
|
|
16046
|
+
assert: assert$4
|
|
16047
16047
|
} = InteractiveUtil;
|
|
16048
16048
|
class Graphie extends React__namespace.Component {
|
|
16049
16049
|
graphieDivRef = /*#__PURE__*/React__namespace.createRef();
|
|
@@ -16074,7 +16074,7 @@ class Graphie extends React__namespace.Component {
|
|
|
16074
16074
|
if (this.props.setup !== prevProps.setup) {
|
|
16075
16075
|
Log.error("<Graphie> was given a new setup function. " + "This is a bad idea; please refactor your code to give " + "the same setup function reference to <Graphie> on " + "every render.", Errors.Internal);
|
|
16076
16076
|
}
|
|
16077
|
-
if (!deepEq$
|
|
16077
|
+
if (!deepEq$3(this.props.options, prevProps.options) || !deepEq$3(this.props.box, prevProps.box) || !deepEq$3(this.props.range, prevProps.range)) {
|
|
16078
16078
|
this._setupGraphie();
|
|
16079
16079
|
}
|
|
16080
16080
|
this._updateMovables();
|
|
@@ -16218,7 +16218,7 @@ class Graphie extends React__namespace.Component {
|
|
|
16218
16218
|
|
|
16219
16219
|
// Instantiate the descriptor to turn it into a real Movable
|
|
16220
16220
|
const child = new childDescriptor.type(childDescriptor.props);
|
|
16221
|
-
assert$
|
|
16221
|
+
assert$4(child instanceof GraphieMovable, "All children of a Graphie component must be Graphie " + "movables");
|
|
16222
16222
|
|
|
16223
16223
|
// Give each child a key
|
|
16224
16224
|
const keyProp = childDescriptor.key;
|
|
@@ -18405,7 +18405,7 @@ const registerWidgets = widgets => {
|
|
|
18405
18405
|
* @param name - the widget that you are trying to replace
|
|
18406
18406
|
* @param replacementName - the name of the widget that takes its place
|
|
18407
18407
|
*
|
|
18408
|
-
* e.g. replaceWidget("transformer", "
|
|
18408
|
+
* e.g. replaceWidget("transformer", "deprecated-standin") will make it so the
|
|
18409
18409
|
* transformer widget is replaced by the always correct widget
|
|
18410
18410
|
*/
|
|
18411
18411
|
const replaceWidget = (name, replacementName) => {
|
|
@@ -18416,9 +18416,6 @@ const replaceWidget = (name, replacementName) => {
|
|
|
18416
18416
|
return;
|
|
18417
18417
|
}
|
|
18418
18418
|
registerWidget(name, substituteWidget);
|
|
18419
|
-
if (Log) {
|
|
18420
|
-
Log.log(`INFO: Replacing widget ${name} with ${replacementName}`);
|
|
18421
|
-
}
|
|
18422
18419
|
};
|
|
18423
18420
|
const registerEditors = editorsToRegister => {
|
|
18424
18421
|
editorsToRegister.forEach(editor => {
|
|
@@ -18445,9 +18442,6 @@ const replaceEditor = (name, replacementName) => {
|
|
|
18445
18442
|
return;
|
|
18446
18443
|
}
|
|
18447
18444
|
editors[name] = substituteEditor;
|
|
18448
|
-
if (Log) {
|
|
18449
|
-
Log.log(`INFO: Replacing editor ${name} with ${replacementName}`);
|
|
18450
|
-
}
|
|
18451
18445
|
};
|
|
18452
18446
|
const getWidget = name => {
|
|
18453
18447
|
// TODO(alex): Consider referring to these as renderers to avoid
|
|
@@ -20958,7 +20952,7 @@ class Tooltip extends React__namespace.Component {
|
|
|
20958
20952
|
|
|
20959
20953
|
/* eslint-disable react/sort-comp */
|
|
20960
20954
|
const {
|
|
20961
|
-
captureScratchpadTouchStart: captureScratchpadTouchStart$
|
|
20955
|
+
captureScratchpadTouchStart: captureScratchpadTouchStart$2
|
|
20962
20956
|
} = Util;
|
|
20963
20957
|
class InputWithExamples extends React__namespace.Component {
|
|
20964
20958
|
static defaultProps = {
|
|
@@ -21016,7 +21010,7 @@ class InputWithExamples extends React__namespace.Component {
|
|
|
21016
21010
|
// Add useful props required for MATH and TEXT modes
|
|
21017
21011
|
___default["default"].extend(inputProps, {
|
|
21018
21012
|
onChange: this.props.onChange,
|
|
21019
|
-
onTouchStart: captureScratchpadTouchStart$
|
|
21013
|
+
onTouchStart: captureScratchpadTouchStart$2
|
|
21020
21014
|
});
|
|
21021
21015
|
|
|
21022
21016
|
// And add final props that are MATH- and TEXT-specific
|
|
@@ -23044,7 +23038,7 @@ var ChoiceNoneAbove$1 = /*#__PURE__*/React__namespace.forwardRef((props, ref) =>
|
|
|
23044
23038
|
})));
|
|
23045
23039
|
|
|
23046
23040
|
const {
|
|
23047
|
-
captureScratchpadTouchStart: captureScratchpadTouchStart$
|
|
23041
|
+
captureScratchpadTouchStart: captureScratchpadTouchStart$1
|
|
23048
23042
|
} = Util;
|
|
23049
23043
|
|
|
23050
23044
|
// exported for tests
|
|
@@ -23296,7 +23290,7 @@ const BaseRadio = function (props) {
|
|
|
23296
23290
|
onClick: clickHandler
|
|
23297
23291
|
// @ts-expect-error - TS2322 - Type '((e: TouchEvent) => void) | null' is not assignable to type 'TouchEventHandler<HTMLLIElement> | undefined'.
|
|
23298
23292
|
,
|
|
23299
|
-
onTouchStart: !labelWrap ? null : captureScratchpadTouchStart$
|
|
23293
|
+
onTouchStart: !labelWrap ? null : captureScratchpadTouchStart$1
|
|
23300
23294
|
}, /*#__PURE__*/React__namespace.createElement(Element, _extends({}, elementProps, {
|
|
23301
23295
|
ref: ref
|
|
23302
23296
|
})));
|
|
@@ -26841,9 +26835,9 @@ var Iframe$1 = {
|
|
|
26841
26835
|
};
|
|
26842
26836
|
|
|
26843
26837
|
/* eslint-disable react/sort-comp */
|
|
26844
|
-
const defaultBoxSize$
|
|
26838
|
+
const defaultBoxSize$1 = 400;
|
|
26845
26839
|
const defaultRange = [0, 10];
|
|
26846
|
-
const defaultBackgroundImage$
|
|
26840
|
+
const defaultBackgroundImage$2 = {
|
|
26847
26841
|
url: null,
|
|
26848
26842
|
width: 0,
|
|
26849
26843
|
height: 0
|
|
@@ -26858,8 +26852,8 @@ class ImageWidget extends React__namespace.Component {
|
|
|
26858
26852
|
alignment: DEFAULT_ALIGNMENT,
|
|
26859
26853
|
title: "",
|
|
26860
26854
|
range: [defaultRange, defaultRange],
|
|
26861
|
-
box: [defaultBoxSize$
|
|
26862
|
-
backgroundImage: defaultBackgroundImage$
|
|
26855
|
+
box: [defaultBoxSize$1, defaultBoxSize$1],
|
|
26856
|
+
backgroundImage: defaultBackgroundImage$2,
|
|
26863
26857
|
labels: [],
|
|
26864
26858
|
alt: "",
|
|
26865
26859
|
caption: "",
|
|
@@ -27677,7 +27671,7 @@ var Interactive = {
|
|
|
27677
27671
|
};
|
|
27678
27672
|
|
|
27679
27673
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
27680
|
-
const defaultBackgroundImage$
|
|
27674
|
+
const defaultBackgroundImage$1 = {
|
|
27681
27675
|
url: null
|
|
27682
27676
|
};
|
|
27683
27677
|
|
|
@@ -27713,7 +27707,7 @@ class Graph extends React__namespace.Component {
|
|
|
27713
27707
|
gridStep: [1, 1],
|
|
27714
27708
|
snapStep: [0.5, 0.5],
|
|
27715
27709
|
markings: "graph",
|
|
27716
|
-
backgroundImage: defaultBackgroundImage$
|
|
27710
|
+
backgroundImage: defaultBackgroundImage$1,
|
|
27717
27711
|
showProtractor: false,
|
|
27718
27712
|
showRuler: false,
|
|
27719
27713
|
rulerLabel: "",
|
|
@@ -27981,7 +27975,7 @@ class Graph extends React__namespace.Component {
|
|
|
27981
27975
|
*/
|
|
27982
27976
|
const {
|
|
27983
27977
|
eq: eq$1,
|
|
27984
|
-
deepEq: deepEq$
|
|
27978
|
+
deepEq: deepEq$2
|
|
27985
27979
|
} = Util;
|
|
27986
27980
|
|
|
27987
27981
|
// This should really be a readonly tuple of [number, number]
|
|
@@ -28094,7 +28088,7 @@ function similar(coords1, coords2, tolerance) {
|
|
|
28094
28088
|
angles = rotate(angles, i);
|
|
28095
28089
|
// @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
|
|
28096
28090
|
sides = rotate(sides, i);
|
|
28097
|
-
if (deepEq$
|
|
28091
|
+
if (deepEq$2(angles1, angles)) {
|
|
28098
28092
|
const sidePairs = ___default["default"].zip(sides1, sides);
|
|
28099
28093
|
const factors = ___default["default"].map(sidePairs, function (pair) {
|
|
28100
28094
|
return pair[0] / pair[1];
|
|
@@ -28188,11 +28182,11 @@ const {
|
|
|
28188
28182
|
DeprecationMixin
|
|
28189
28183
|
} = Util;
|
|
28190
28184
|
const TRASH_ICON_URI = "https://ka-perseus-graphie.s3.amazonaws.com/b1452c0d79fd0f7ff4c3af9488474a0a0decb361.png";
|
|
28191
|
-
const defaultBackgroundImage
|
|
28185
|
+
const defaultBackgroundImage = {
|
|
28192
28186
|
url: null
|
|
28193
28187
|
};
|
|
28194
28188
|
const eq = Util.eq;
|
|
28195
|
-
const deepEq$
|
|
28189
|
+
const deepEq$1 = Util.deepEq;
|
|
28196
28190
|
const UNLIMITED = "unlimited";
|
|
28197
28191
|
|
|
28198
28192
|
// Sample background image:
|
|
@@ -28249,7 +28243,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
28249
28243
|
labels: ["x", "y"],
|
|
28250
28244
|
range: [[-10, 10], [-10, 10]],
|
|
28251
28245
|
step: [1, 1],
|
|
28252
|
-
backgroundImage: defaultBackgroundImage
|
|
28246
|
+
backgroundImage: defaultBackgroundImage,
|
|
28253
28247
|
markings: "graph",
|
|
28254
28248
|
showTooltips: false,
|
|
28255
28249
|
showProtractor: false,
|
|
@@ -29842,7 +29836,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29842
29836
|
const correctCoeffs = this.getQuadraticCoefficients(
|
|
29843
29837
|
// @ts-expect-error - TS2345 - Argument of type 'readonly Coord[] | undefined' is not assignable to parameter of type 'readonly Coord[]'.
|
|
29844
29838
|
rubric.correct.coords);
|
|
29845
|
-
if (deepEq$
|
|
29839
|
+
if (deepEq$1(guessCoeffs, correctCoeffs)) {
|
|
29846
29840
|
return {
|
|
29847
29841
|
type: "points",
|
|
29848
29842
|
earned: 1,
|
|
@@ -29858,7 +29852,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29858
29852
|
const canonicalGuessCoeffs = canonicalSineCoefficients(guessCoeffs);
|
|
29859
29853
|
const canonicalCorrectCoeffs = canonicalSineCoefficients(correctCoeffs);
|
|
29860
29854
|
// If the canonical coefficients match, it's correct.
|
|
29861
|
-
if (deepEq$
|
|
29855
|
+
if (deepEq$1(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
|
|
29862
29856
|
return {
|
|
29863
29857
|
type: "points",
|
|
29864
29858
|
earned: 1,
|
|
@@ -29867,7 +29861,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29867
29861
|
};
|
|
29868
29862
|
}
|
|
29869
29863
|
} else if (state.type === "circle" && rubric.correct.type === "circle") {
|
|
29870
|
-
if (deepEq$
|
|
29864
|
+
if (deepEq$1(state.center, rubric.correct.center) && eq(state.radius, rubric.correct.radius)) {
|
|
29871
29865
|
return {
|
|
29872
29866
|
type: "points",
|
|
29873
29867
|
earned: 1,
|
|
@@ -29886,7 +29880,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29886
29880
|
guess?.sort();
|
|
29887
29881
|
// @ts-expect-error - TS2339 - Property 'sort' does not exist on type 'readonly Coord[]'.
|
|
29888
29882
|
correct.sort();
|
|
29889
|
-
if (deepEq$
|
|
29883
|
+
if (deepEq$1(guess, correct)) {
|
|
29890
29884
|
return {
|
|
29891
29885
|
type: "points",
|
|
29892
29886
|
earned: 1,
|
|
@@ -29909,7 +29903,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29909
29903
|
/* exact */
|
|
29910
29904
|
guess.sort();
|
|
29911
29905
|
correct.sort();
|
|
29912
|
-
match = deepEq$
|
|
29906
|
+
match = deepEq$1(guess, correct);
|
|
29913
29907
|
}
|
|
29914
29908
|
if (match) {
|
|
29915
29909
|
return {
|
|
@@ -29925,7 +29919,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29925
29919
|
guess = ___default["default"].invoke(guess, "sort").sort();
|
|
29926
29920
|
// @ts-expect-error - TS2345 - Argument of type '(readonly Coord[])[] | undefined' is not assignable to parameter of type 'Collection<any>'.
|
|
29927
29921
|
correct = ___default["default"].invoke(correct, "sort").sort();
|
|
29928
|
-
if (deepEq$
|
|
29922
|
+
if (deepEq$1(guess, correct)) {
|
|
29929
29923
|
return {
|
|
29930
29924
|
type: "points",
|
|
29931
29925
|
earned: 1,
|
|
@@ -29938,7 +29932,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29938
29932
|
const correct = rubric.correct.coords;
|
|
29939
29933
|
if (
|
|
29940
29934
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'.
|
|
29941
|
-
deepEq$
|
|
29935
|
+
deepEq$1(guess[0], correct[0]) &&
|
|
29942
29936
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
29943
29937
|
collinear(correct[0], correct[1], guess[1])) {
|
|
29944
29938
|
return {
|
|
@@ -29969,7 +29963,7 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
29969
29963
|
/* exact */
|
|
29970
29964
|
match =
|
|
29971
29965
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
29972
|
-
deepEq$
|
|
29966
|
+
deepEq$1(guess[1], correct[1]) &&
|
|
29973
29967
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
29974
29968
|
collinear(correct[1], correct[0], guess[0]) &&
|
|
29975
29969
|
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
|
|
@@ -33132,7 +33126,7 @@ var Matcher$1 = {
|
|
|
33132
33126
|
|
|
33133
33127
|
const {
|
|
33134
33128
|
firstNumericalParse,
|
|
33135
|
-
captureScratchpadTouchStart
|
|
33129
|
+
captureScratchpadTouchStart
|
|
33136
33130
|
} = Util;
|
|
33137
33131
|
const toNumericString = KhanMath.toNumericString;
|
|
33138
33132
|
const getNumericFormat = KhanMath.getNumericFormat;
|
|
@@ -33205,7 +33199,7 @@ class NumberInput extends React__namespace.Component {
|
|
|
33205
33199
|
onKeyDown: this._onKeyDown
|
|
33206
33200
|
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLInputElement>'.
|
|
33207
33201
|
,
|
|
33208
|
-
onTouchStart: captureScratchpadTouchStart
|
|
33202
|
+
onTouchStart: captureScratchpadTouchStart,
|
|
33209
33203
|
defaultValue: toNumericString(this.props.value, this.state.format),
|
|
33210
33204
|
value: undefined
|
|
33211
33205
|
}));
|
|
@@ -33331,7 +33325,7 @@ class NumberInput extends React__namespace.Component {
|
|
|
33331
33325
|
// Type imports
|
|
33332
33326
|
|
|
33333
33327
|
const {
|
|
33334
|
-
assert: assert$
|
|
33328
|
+
assert: assert$3
|
|
33335
33329
|
} = InteractiveUtil;
|
|
33336
33330
|
const {
|
|
33337
33331
|
stringArrayOfSize
|
|
@@ -33365,12 +33359,12 @@ const getDefaultPath$1 = function () {
|
|
|
33365
33359
|
};
|
|
33366
33360
|
const getRowFromPath$1 = function (path) {
|
|
33367
33361
|
// 'path' should be a (row, column) pair
|
|
33368
|
-
assert$
|
|
33362
|
+
assert$3(___default["default"].isArray(path) && path.length === 2);
|
|
33369
33363
|
return +path[0];
|
|
33370
33364
|
};
|
|
33371
33365
|
const getColumnFromPath$1 = function (path) {
|
|
33372
33366
|
// 'path' should be a (row, column) pair
|
|
33373
|
-
assert$
|
|
33367
|
+
assert$3(___default["default"].isArray(path) && path.length === 2);
|
|
33374
33368
|
return +path[1];
|
|
33375
33369
|
};
|
|
33376
33370
|
const getRefForPath$1 = function (path) {
|
|
@@ -34871,7 +34865,7 @@ const MovablePoint$1 = Graphie.MovablePoint;
|
|
|
34871
34865
|
// @ts-expect-error - TS2339 - Property 'Line' does not exist on type 'typeof Graphie'.
|
|
34872
34866
|
const Line$1 = Graphie.Line;
|
|
34873
34867
|
const {
|
|
34874
|
-
assert: assert$
|
|
34868
|
+
assert: assert$2
|
|
34875
34869
|
} = InteractiveUtil;
|
|
34876
34870
|
const bound = (x, gt, lt) => Math.min(Math.max(x, gt), lt);
|
|
34877
34871
|
const EN_DASH = "\u2013";
|
|
@@ -35147,7 +35141,7 @@ class NumberLine extends React__namespace.Component {
|
|
|
35147
35141
|
const snapX = props.tickStep / props.snapDivisions;
|
|
35148
35142
|
let x = bound(numLinePosition, left, right);
|
|
35149
35143
|
x = left + kmath.number.roundTo(x - left, snapX);
|
|
35150
|
-
assert$
|
|
35144
|
+
assert$2(___default["default"].isFinite(x));
|
|
35151
35145
|
return x;
|
|
35152
35146
|
};
|
|
35153
35147
|
|
|
@@ -38254,7 +38248,7 @@ var PassageRefTarget$1 = {
|
|
|
38254
38248
|
|
|
38255
38249
|
/* eslint-disable react/no-unsafe */
|
|
38256
38250
|
const {
|
|
38257
|
-
deepEq
|
|
38251
|
+
deepEq
|
|
38258
38252
|
} = Util;
|
|
38259
38253
|
class Plotter extends React__namespace.Component {
|
|
38260
38254
|
// @ts-expect-error - TS2564 - Property 'shouldSetupGraphie' has no initializer and is not definitely assigned in the constructor.
|
|
@@ -39047,7 +39041,7 @@ class Plotter extends React__namespace.Component {
|
|
|
39047
39041
|
}
|
|
39048
39042
|
___default["default"].extend(Plotter, {
|
|
39049
39043
|
validate: function (guess, rubric) {
|
|
39050
|
-
if (deepEq
|
|
39044
|
+
if (deepEq(guess, rubric.starting)) {
|
|
39051
39045
|
return {
|
|
39052
39046
|
type: "invalid",
|
|
39053
39047
|
message: null
|
|
@@ -39055,7 +39049,7 @@ ___default["default"].extend(Plotter, {
|
|
|
39055
39049
|
}
|
|
39056
39050
|
return {
|
|
39057
39051
|
type: "points",
|
|
39058
|
-
earned: deepEq
|
|
39052
|
+
earned: deepEq(guess, rubric.correct) ? 1 : 0,
|
|
39059
39053
|
total: 1,
|
|
39060
39054
|
message: null
|
|
39061
39055
|
};
|
|
@@ -39417,7 +39411,7 @@ class InfoTip extends React__namespace.Component {
|
|
|
39417
39411
|
|
|
39418
39412
|
/* eslint-disable @typescript-eslint/no-unused-vars, react/no-unsafe, react/sort-comp */
|
|
39419
39413
|
const {
|
|
39420
|
-
assert: assert$
|
|
39414
|
+
assert: assert$1
|
|
39421
39415
|
} = InteractiveUtil;
|
|
39422
39416
|
// @ts-expect-error - TS2339 - Property 'Path' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Arc' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Circle' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Label' does not exist on type 'typeof Graphie'. | TS2339 - Property 'Line' does not exist on type 'typeof Graphie'. | TS2339 - Property 'MovablePoint' does not exist on type 'typeof Graphie'. | TS2339 - Property 'MovableLine' does not exist on type 'typeof Graphie'.
|
|
39423
39417
|
const {
|
|
@@ -39429,7 +39423,7 @@ const {
|
|
|
39429
39423
|
MovablePoint,
|
|
39430
39424
|
MovableLine
|
|
39431
39425
|
} = Graphie;
|
|
39432
|
-
const defaultBoxSize
|
|
39426
|
+
const defaultBoxSize = 400;
|
|
39433
39427
|
const maxSampleSize = 1000;
|
|
39434
39428
|
class Histogram extends React__namespace.Component {
|
|
39435
39429
|
static propTypes = {
|
|
@@ -39442,7 +39436,7 @@ class Histogram extends React__namespace.Component {
|
|
|
39442
39436
|
data: null,
|
|
39443
39437
|
xAxisLabel: "Proportion (%)",
|
|
39444
39438
|
yAxisLabel: "Number of times seen",
|
|
39445
|
-
box: [defaultBoxSize
|
|
39439
|
+
box: [defaultBoxSize, defaultBoxSize]
|
|
39446
39440
|
};
|
|
39447
39441
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
39448
39442
|
// Reset the threshold if the range has changed
|
|
@@ -39945,7 +39939,7 @@ class Simulator extends React__namespace.Component {
|
|
|
39945
39939
|
return true;
|
|
39946
39940
|
};
|
|
39947
39941
|
focusInputPath = path => {
|
|
39948
|
-
assert$
|
|
39942
|
+
assert$1(path.length > 0);
|
|
39949
39943
|
const inputID = ___default["default"].head(path);
|
|
39950
39944
|
// eslint-disable-next-line react/no-string-refs
|
|
39951
39945
|
const inputComponent = this.refs[inputID];
|
|
@@ -39953,7 +39947,7 @@ class Simulator extends React__namespace.Component {
|
|
|
39953
39947
|
inputComponent.focus();
|
|
39954
39948
|
};
|
|
39955
39949
|
blurInputPath = path => {
|
|
39956
|
-
assert$
|
|
39950
|
+
assert$1(path.length > 0);
|
|
39957
39951
|
const inputID = ___default["default"].head(path);
|
|
39958
39952
|
// eslint-disable-next-line react/no-string-refs
|
|
39959
39953
|
const inputComponent = this.refs[inputID];
|
|
@@ -39961,17 +39955,17 @@ class Simulator extends React__namespace.Component {
|
|
|
39961
39955
|
inputComponent.blur();
|
|
39962
39956
|
};
|
|
39963
39957
|
getDOMNodeForPath = path => {
|
|
39964
|
-
assert$
|
|
39958
|
+
assert$1(path.length > 0);
|
|
39965
39959
|
const inputID = ___default["default"].head(path);
|
|
39966
39960
|
// eslint-disable-next-line react/no-string-refs
|
|
39967
39961
|
return ReactDOM__default["default"].findDOMNode(this.refs[inputID]);
|
|
39968
39962
|
};
|
|
39969
39963
|
getGrammarTypeForPath = path => {
|
|
39970
|
-
assert$
|
|
39964
|
+
assert$1(path.length > 0);
|
|
39971
39965
|
return "number";
|
|
39972
39966
|
};
|
|
39973
39967
|
setInputValue = (path, newValue, cb) => {
|
|
39974
|
-
assert$
|
|
39968
|
+
assert$1(path.length > 0);
|
|
39975
39969
|
const inputID = ___default["default"].head(path);
|
|
39976
39970
|
const capitalizedID = inputID.charAt(0).toUpperCase() + inputID.slice(1);
|
|
39977
39971
|
const functionName = "handle" + capitalizedID + "Change";
|
|
@@ -40131,7 +40125,7 @@ var Sorter$1 = {
|
|
|
40131
40125
|
};
|
|
40132
40126
|
|
|
40133
40127
|
const {
|
|
40134
|
-
assert
|
|
40128
|
+
assert
|
|
40135
40129
|
} = InteractiveUtil;
|
|
40136
40130
|
|
|
40137
40131
|
/* Input handling: Maps a (row, column) pair to a unique ref used by React,
|
|
@@ -40145,12 +40139,12 @@ const getDefaultPath = function () {
|
|
|
40145
40139
|
};
|
|
40146
40140
|
const getRowFromPath = function (path) {
|
|
40147
40141
|
// 'path' should be a (row, column) pair
|
|
40148
|
-
assert
|
|
40142
|
+
assert(___default["default"].isArray(path) && path.length === 2);
|
|
40149
40143
|
return +path[0];
|
|
40150
40144
|
};
|
|
40151
40145
|
const getColumnFromPath = function (path) {
|
|
40152
40146
|
// 'path' should be a (row, column) pair
|
|
40153
|
-
assert
|
|
40147
|
+
assert(___default["default"].isArray(path) && path.length === 2);
|
|
40154
40148
|
return +path[1];
|
|
40155
40149
|
};
|
|
40156
40150
|
const getRefForPath = function (path) {
|
|
@@ -40424,2415 +40418,6 @@ var Table$1 = {
|
|
|
40424
40418
|
isLintable: true
|
|
40425
40419
|
};
|
|
40426
40420
|
|
|
40427
|
-
const {
|
|
40428
|
-
deepEq,
|
|
40429
|
-
getGridStep,
|
|
40430
|
-
captureScratchpadTouchStart
|
|
40431
|
-
} = Util;
|
|
40432
|
-
const {
|
|
40433
|
-
assert
|
|
40434
|
-
} = InteractiveUtil;
|
|
40435
|
-
const ROTATE_SNAP_DEGREES = 15;
|
|
40436
|
-
const DEGREE_SIGN = "\u00B0";
|
|
40437
|
-
const RENDER_TRANSFORM_DELAY_IN_MS = 300;
|
|
40438
|
-
const ROTATE_HANDLE_DIST = 1.5;
|
|
40439
|
-
const REFLECT_ROTATE_HANDLE_DIST = 2;
|
|
40440
|
-
const REFLECT_BUTTON_SIZE = 1;
|
|
40441
|
-
const defaultBoxSize = 400;
|
|
40442
|
-
const defaultBackgroundImage = {
|
|
40443
|
-
url: null
|
|
40444
|
-
};
|
|
40445
|
-
|
|
40446
|
-
/* Does a pluck on keys inside objects in an object
|
|
40447
|
-
*
|
|
40448
|
-
* Ex:
|
|
40449
|
-
* tools = {
|
|
40450
|
-
* translation: {
|
|
40451
|
-
* enabled: true
|
|
40452
|
-
* },
|
|
40453
|
-
* rotation: {
|
|
40454
|
-
* enabled: false
|
|
40455
|
-
* }
|
|
40456
|
-
* };
|
|
40457
|
-
* pluckObject(tools, "enabled") returns {
|
|
40458
|
-
* translation: true
|
|
40459
|
-
* rotation: false
|
|
40460
|
-
* }
|
|
40461
|
-
*/
|
|
40462
|
-
function pluckObject(object, subKey) {
|
|
40463
|
-
return ___default["default"].object(___default["default"].map(object, function (value, key) {
|
|
40464
|
-
return [key, value[subKey]];
|
|
40465
|
-
}));
|
|
40466
|
-
}
|
|
40467
|
-
const defaultGraphProps = function (setProps, boxSize) {
|
|
40468
|
-
setProps = setProps || {};
|
|
40469
|
-
const labels = setProps.labels || ["x", "y"];
|
|
40470
|
-
const range = setProps.range || [[-10, 10], [-10, 10]];
|
|
40471
|
-
const step = setProps.step || [1, 1];
|
|
40472
|
-
const gridStep = setProps.gridStep || getGridStep(range, step, boxSize);
|
|
40473
|
-
return {
|
|
40474
|
-
box: [boxSize, boxSize],
|
|
40475
|
-
labels: labels,
|
|
40476
|
-
range: range,
|
|
40477
|
-
step: step,
|
|
40478
|
-
gridStep: gridStep,
|
|
40479
|
-
valid: true,
|
|
40480
|
-
backgroundImage: defaultBackgroundImage,
|
|
40481
|
-
markings: "grid",
|
|
40482
|
-
showProtractor: false
|
|
40483
|
-
};
|
|
40484
|
-
};
|
|
40485
|
-
const defaultTransformerProps = {
|
|
40486
|
-
apiOptions: ApiOptions.defaults,
|
|
40487
|
-
gradeEmpty: false,
|
|
40488
|
-
graphMode: "interactive",
|
|
40489
|
-
listMode: "dynamic",
|
|
40490
|
-
graph: {},
|
|
40491
|
-
tools: {
|
|
40492
|
-
translation: {
|
|
40493
|
-
enabled: true,
|
|
40494
|
-
required: false,
|
|
40495
|
-
constraints: {}
|
|
40496
|
-
},
|
|
40497
|
-
rotation: {
|
|
40498
|
-
enabled: true,
|
|
40499
|
-
required: false,
|
|
40500
|
-
constraints: {
|
|
40501
|
-
fixed: false
|
|
40502
|
-
},
|
|
40503
|
-
coord: [1, 6]
|
|
40504
|
-
},
|
|
40505
|
-
reflection: {
|
|
40506
|
-
enabled: true,
|
|
40507
|
-
required: false,
|
|
40508
|
-
constraints: {
|
|
40509
|
-
fixed: false
|
|
40510
|
-
},
|
|
40511
|
-
coords: [[2, -4], [2, 2]]
|
|
40512
|
-
},
|
|
40513
|
-
dilation: {
|
|
40514
|
-
enabled: true,
|
|
40515
|
-
required: false,
|
|
40516
|
-
constraints: {
|
|
40517
|
-
fixed: false
|
|
40518
|
-
},
|
|
40519
|
-
coord: [6, 6]
|
|
40520
|
-
}
|
|
40521
|
-
},
|
|
40522
|
-
drawSolutionShape: true,
|
|
40523
|
-
starting: {
|
|
40524
|
-
shape: {
|
|
40525
|
-
type: "polygon-3",
|
|
40526
|
-
coords: [[2, 2], [2, 6], [7, 2]]
|
|
40527
|
-
},
|
|
40528
|
-
transformations: []
|
|
40529
|
-
},
|
|
40530
|
-
correct: {
|
|
40531
|
-
shape: {
|
|
40532
|
-
type: "polygon-3",
|
|
40533
|
-
coords: [[2, 2], [2, 6], [7, 2]]
|
|
40534
|
-
},
|
|
40535
|
-
transformations: []
|
|
40536
|
-
}
|
|
40537
|
-
};
|
|
40538
|
-
function colorForTool(tool) {
|
|
40539
|
-
return tool.constraints.fixed ? KhanColors.DYNAMIC : KhanColors.INTERACTIVE;
|
|
40540
|
-
}
|
|
40541
|
-
|
|
40542
|
-
/* Scales a distance from the default range of
|
|
40543
|
-
* [-10, 10] to a given props.range pair
|
|
40544
|
-
*
|
|
40545
|
-
* Used for sizing various transformation tools
|
|
40546
|
-
* (rotation handle, dilation circle)
|
|
40547
|
-
*/
|
|
40548
|
-
function scaleToRange(dist, range) {
|
|
40549
|
-
const spreadX = range[0][1] - range[0][0];
|
|
40550
|
-
const spreadY = range[1][1] - range[1][0];
|
|
40551
|
-
return dist * Math.max(spreadX, spreadY) / 20;
|
|
40552
|
-
}
|
|
40553
|
-
function dilatePointFromCenter(point, dilationCenter, scale) {
|
|
40554
|
-
const pv = kmath.vector.subtract(point, dilationCenter);
|
|
40555
|
-
const pvScaled = kmath.vector.scale(pv, scale);
|
|
40556
|
-
const transformedPoint = kmath.vector.add(dilationCenter, pvScaled);
|
|
40557
|
-
return transformedPoint;
|
|
40558
|
-
}
|
|
40559
|
-
|
|
40560
|
-
// TODO(jack): i18nize this
|
|
40561
|
-
function stringFromDecimal(number) {
|
|
40562
|
-
return String(KhanMath.roundTo(9, number));
|
|
40563
|
-
}
|
|
40564
|
-
function stringFromFraction(number) {
|
|
40565
|
-
const frac = KhanMath.toFraction(number, kmath.number.DEFAULT_TOLERANCE);
|
|
40566
|
-
if (frac[1] === 1) {
|
|
40567
|
-
return stringFromDecimal(number);
|
|
40568
|
-
}
|
|
40569
|
-
return stringFromDecimal(frac[0]) + "/" + stringFromDecimal(frac[1]);
|
|
40570
|
-
}
|
|
40571
|
-
function texFromPoint(point) {
|
|
40572
|
-
const {
|
|
40573
|
-
TeX
|
|
40574
|
-
} = getDependencies();
|
|
40575
|
-
return [/*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40576
|
-
key: "("
|
|
40577
|
-
}, "("), stringFromDecimal(point[0]), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40578
|
-
key: ","
|
|
40579
|
-
}, ", {}"), stringFromDecimal(point[1]), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40580
|
-
key: ")"
|
|
40581
|
-
}, ")")];
|
|
40582
|
-
}
|
|
40583
|
-
function texFromVector(vector) {
|
|
40584
|
-
const {
|
|
40585
|
-
TeX
|
|
40586
|
-
} = getDependencies();
|
|
40587
|
-
return [/*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40588
|
-
key: "<"
|
|
40589
|
-
}, i18n__namespace.doNotTranslate("\\langle")), stringFromDecimal(vector[0]), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40590
|
-
key: ","
|
|
40591
|
-
}, ", {}"), stringFromDecimal(vector[1]), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40592
|
-
key: ">"
|
|
40593
|
-
}, i18n__namespace.doNotTranslate("\\rangle"))];
|
|
40594
|
-
}
|
|
40595
|
-
function texFromAngleDeg(angleDeg) {
|
|
40596
|
-
return stringFromDecimal(angleDeg) + DEGREE_SIGN;
|
|
40597
|
-
}
|
|
40598
|
-
function orderInsensitiveCoordsEqual(coords1, coords2) {
|
|
40599
|
-
coords1 = ___default["default"].clone(coords1).sort(kmath.point.compare);
|
|
40600
|
-
coords2 = ___default["default"].clone(coords2).sort(kmath.point.compare);
|
|
40601
|
-
return ___default["default"].all(___default["default"].map(coords1, function (coord1, i) {
|
|
40602
|
-
const coord2 = coords2[i];
|
|
40603
|
-
return kmath.point.equal(coord1, coord2);
|
|
40604
|
-
}));
|
|
40605
|
-
}
|
|
40606
|
-
const inputComponentForApiOptions = apiOptions => {
|
|
40607
|
-
if (apiOptions.customKeypad) {
|
|
40608
|
-
return SimpleKeypadInput;
|
|
40609
|
-
}
|
|
40610
|
-
return NumberInput;
|
|
40611
|
-
};
|
|
40612
|
-
|
|
40613
|
-
/* Perform operations on raw transform objects */
|
|
40614
|
-
const TransformOps = {
|
|
40615
|
-
apply: function (transform) {
|
|
40616
|
-
// Any transformation with empty text boxes is a no-op until
|
|
40617
|
-
// filled out (these show up as nulls in transform.vector/line/etc).
|
|
40618
|
-
// TODO (jack): Merge this just into reflections now that other
|
|
40619
|
-
// transforms are always valid (after merging transformation
|
|
40620
|
-
// collapsing, which may use isValid)
|
|
40621
|
-
// @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
|
|
40622
|
-
if (!Transformations[transform.type].isValid(transform)) {
|
|
40623
|
-
return ___default["default"].identity; // do not transform the coord
|
|
40624
|
-
}
|
|
40625
|
-
// @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
|
|
40626
|
-
return Transformations[transform.type].apply(transform);
|
|
40627
|
-
},
|
|
40628
|
-
append: function (transformList, newTransform) {
|
|
40629
|
-
// Append newTransform to transformList, and collapse the last
|
|
40630
|
-
// two transforms if they are collapsable
|
|
40631
|
-
const results = TransformOps._appendAndCollapseLastTwo(transformList, newTransform);
|
|
40632
|
-
// Collapse any no-ops at the end of the transformation list
|
|
40633
|
-
return TransformOps._collapseFinalNoOps(results);
|
|
40634
|
-
},
|
|
40635
|
-
_collapseFinalNoOps: function (transforms) {
|
|
40636
|
-
// Collapse no-op transformations at the end of the list
|
|
40637
|
-
if (transforms.length && TransformOps.isNoOp(___default["default"].last(transforms))) {
|
|
40638
|
-
return ___default["default"].initial(transforms);
|
|
40639
|
-
}
|
|
40640
|
-
return transforms;
|
|
40641
|
-
},
|
|
40642
|
-
_appendAndCollapseLastTwo: function (transformList, newTransform) {
|
|
40643
|
-
if (!transformList.length) {
|
|
40644
|
-
return [newTransform];
|
|
40645
|
-
}
|
|
40646
|
-
const collapsed = TransformOps.collapse(___default["default"].last(transformList), newTransform);
|
|
40647
|
-
return ___default["default"].initial(transformList).concat(collapsed);
|
|
40648
|
-
},
|
|
40649
|
-
isNoOp: function (transform) {
|
|
40650
|
-
return Transformations[transform.type].isNoOp(transform);
|
|
40651
|
-
},
|
|
40652
|
-
collapse: function (transform1, transform2) {
|
|
40653
|
-
// We can only collapse transforms that have the same type
|
|
40654
|
-
if (transform1.type !== transform2.type) {
|
|
40655
|
-
return [transform1, transform2];
|
|
40656
|
-
}
|
|
40657
|
-
|
|
40658
|
-
// Clicking the button again removes empty transformations
|
|
40659
|
-
if (TransformOps.isEmpty(transform1) && TransformOps.isEmpty(transform2)) {
|
|
40660
|
-
return [];
|
|
40661
|
-
}
|
|
40662
|
-
|
|
40663
|
-
// Don't collapse invalid transformations otherwise
|
|
40664
|
-
if (!TransformOps.isValid(transform1) || !TransformOps.isValid(transform2)) {
|
|
40665
|
-
return [transform1, transform2];
|
|
40666
|
-
}
|
|
40667
|
-
return TransformOps._collapseValidMonotypedTransforms(transform1, transform2);
|
|
40668
|
-
},
|
|
40669
|
-
isValid: function (transform) {
|
|
40670
|
-
// @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
|
|
40671
|
-
return Transformations[transform.type].isValid(transform);
|
|
40672
|
-
},
|
|
40673
|
-
isEmpty: function (transform) {
|
|
40674
|
-
// @ts-expect-error - TS2345 - Argument of type 'PerseusTransformerTransformation' is not assignable to parameter of type 'never'.
|
|
40675
|
-
return Transformations[transform.type].isEmpty(transform);
|
|
40676
|
-
},
|
|
40677
|
-
_collapseValidMonotypedTransforms: function (transform1, transform2) {
|
|
40678
|
-
let collapsed = Transformations[transform1.type].collapse(transform1, transform2);
|
|
40679
|
-
if (collapsed) {
|
|
40680
|
-
// Force all answers into an array
|
|
40681
|
-
if (!___default["default"].isArray(collapsed)) {
|
|
40682
|
-
collapsed = [collapsed];
|
|
40683
|
-
}
|
|
40684
|
-
// Add types to all transforms in the answer
|
|
40685
|
-
___default["default"].each(collapsed, function (transform) {
|
|
40686
|
-
transform.type = transform1.type;
|
|
40687
|
-
});
|
|
40688
|
-
return collapsed;
|
|
40689
|
-
}
|
|
40690
|
-
// These transforms can't be collapsed together
|
|
40691
|
-
return [transform1, transform2];
|
|
40692
|
-
},
|
|
40693
|
-
toTeX: function (transform) {
|
|
40694
|
-
return Transformations[transform.type].toTeX(transform);
|
|
40695
|
-
},
|
|
40696
|
-
/* A react representation of this transform object */
|
|
40697
|
-
ListItem: createReactClass__default["default"]({
|
|
40698
|
-
displayName: "ListItem",
|
|
40699
|
-
render: function () {
|
|
40700
|
-
if (this.props.mode === "dynamic") {
|
|
40701
|
-
return /*#__PURE__*/React__namespace.createElement("div", null, TransformOps.toTeX(this.props.transform));
|
|
40702
|
-
}
|
|
40703
|
-
if (this.props.mode === "interactive") {
|
|
40704
|
-
const TransformClass = Transformations[this.props.transform.type].Input;
|
|
40705
|
-
return /*#__PURE__*/React__namespace.createElement(TransformClass
|
|
40706
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40707
|
-
, _extends({
|
|
40708
|
-
ref: "transform",
|
|
40709
|
-
onChange: this.handleChange,
|
|
40710
|
-
onFocus: this.props.onFocus,
|
|
40711
|
-
onBlur: this.props.onBlur,
|
|
40712
|
-
keypadElement: this.props.keypadElement,
|
|
40713
|
-
apiOptions: this.props.apiOptions
|
|
40714
|
-
}, this.props.transform));
|
|
40715
|
-
}
|
|
40716
|
-
throw new PerseusError("Invalid mode: " + this.props.mode, Errors.InvalidInput);
|
|
40717
|
-
},
|
|
40718
|
-
value: function () {
|
|
40719
|
-
if (this.props.mode === "interactive") {
|
|
40720
|
-
return ___default["default"].extend({
|
|
40721
|
-
type: this.props.transform.type
|
|
40722
|
-
},
|
|
40723
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40724
|
-
this.refs.transform.value());
|
|
40725
|
-
}
|
|
40726
|
-
return this.props.transform;
|
|
40727
|
-
},
|
|
40728
|
-
handleChange: ___default["default"].debounce(function (callback) {
|
|
40729
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
40730
|
-
this.props.onChange(this.value(), callback);
|
|
40731
|
-
}, RENDER_TRANSFORM_DELAY_IN_MS),
|
|
40732
|
-
/* InputPath API: depending on the API call, this could involve simply
|
|
40733
|
-
* navigating to the right ref and calling the function on that
|
|
40734
|
-
* component, or threading the call down and returning the result. */
|
|
40735
|
-
_getComponentAtPath: function (path) {
|
|
40736
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40737
|
-
const transform = this.refs.transform;
|
|
40738
|
-
const ref = ___default["default"].head(path);
|
|
40739
|
-
return transform.refs[ref];
|
|
40740
|
-
},
|
|
40741
|
-
focus: function () {
|
|
40742
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40743
|
-
const transform = this.refs.transform;
|
|
40744
|
-
const path = ___default["default"].head(transform.getInputPaths());
|
|
40745
|
-
if (path) {
|
|
40746
|
-
this.focusInputPath(path);
|
|
40747
|
-
}
|
|
40748
|
-
},
|
|
40749
|
-
focusInputPath: function (path) {
|
|
40750
|
-
this._getComponentAtPath(path).focus();
|
|
40751
|
-
},
|
|
40752
|
-
blurInputPath: function (path) {
|
|
40753
|
-
this._getComponentAtPath(path).blur();
|
|
40754
|
-
},
|
|
40755
|
-
getDOMNodeForPath: function (path) {
|
|
40756
|
-
return ReactDOM__default["default"].findDOMNode(this._getComponentAtPath(path));
|
|
40757
|
-
},
|
|
40758
|
-
getGrammarTypeForPath: function (path) {
|
|
40759
|
-
return "number";
|
|
40760
|
-
},
|
|
40761
|
-
setInputValue: function (path, value, cb) {
|
|
40762
|
-
// `value` comes in as a string on mobile, but we need a number
|
|
40763
|
-
// We let through the empty string so that "Clear" works -- in
|
|
40764
|
-
// that case, the transformer widget will just act as if there is
|
|
40765
|
-
// no input, which is what we want.
|
|
40766
|
-
// @ts-expect-error - TS2339 - Property 'length' does not exist on type 'string | number'.
|
|
40767
|
-
if (value.length) {
|
|
40768
|
-
// @ts-expect-error - TS2345 - Argument of type 'string | number' is not assignable to parameter of type 'string'.
|
|
40769
|
-
value = parseFloat(value);
|
|
40770
|
-
if (isNaN(value)) {
|
|
40771
|
-
return;
|
|
40772
|
-
}
|
|
40773
|
-
}
|
|
40774
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40775
|
-
this.refs.transform.setInputValue(path, value, cb);
|
|
40776
|
-
},
|
|
40777
|
-
getInputPaths: function () {
|
|
40778
|
-
// If we're in dynamic mode, then the list items are made up of
|
|
40779
|
-
// static text.
|
|
40780
|
-
if (this.props.mode === "dynamic") {
|
|
40781
|
-
return [];
|
|
40782
|
-
}
|
|
40783
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40784
|
-
return this.refs.transform.getInputPaths();
|
|
40785
|
-
}
|
|
40786
|
-
})
|
|
40787
|
-
};
|
|
40788
|
-
const Transformations = {
|
|
40789
|
-
translation: {
|
|
40790
|
-
// I18N: As in the command, "Translate the polygon"
|
|
40791
|
-
verbName: i18n__namespace._("Translate"),
|
|
40792
|
-
nounName: i18n__namespace._("Translation"),
|
|
40793
|
-
lowerNounName: i18n__namespace._("translation"),
|
|
40794
|
-
apply: function (transform) {
|
|
40795
|
-
return function (coord) {
|
|
40796
|
-
return kmath.vector.add(coord, transform.vector);
|
|
40797
|
-
};
|
|
40798
|
-
},
|
|
40799
|
-
isValid: function (transform) {
|
|
40800
|
-
return ___default["default"].isFinite(transform.vector[0]) && ___default["default"].isFinite(transform.vector[1]);
|
|
40801
|
-
},
|
|
40802
|
-
isEmpty: function (transform) {
|
|
40803
|
-
return transform.vector[0] === null && transform.vector[1] === null;
|
|
40804
|
-
},
|
|
40805
|
-
isNoOp: function (transform) {
|
|
40806
|
-
return kmath.vector.equal(transform.vector, [0, 0]);
|
|
40807
|
-
},
|
|
40808
|
-
collapse: function (transform1, transform2) {
|
|
40809
|
-
return {
|
|
40810
|
-
vector: kmath.vector.add(transform1.vector, transform2.vector)
|
|
40811
|
-
};
|
|
40812
|
-
},
|
|
40813
|
-
toTeX: function (transform) {
|
|
40814
|
-
// I18N: As in the command, "Translation by <3, 1>"
|
|
40815
|
-
return i18n__namespace.$_("Translation by %(vector)s", {
|
|
40816
|
-
vector: texFromVector(transform.vector)
|
|
40817
|
-
});
|
|
40818
|
-
},
|
|
40819
|
-
Input: class extends React__namespace.Component {
|
|
40820
|
-
state = {
|
|
40821
|
-
vector: this.props.vector || [null, null]
|
|
40822
|
-
};
|
|
40823
|
-
componentDidUpdate(prevProps) {
|
|
40824
|
-
if (!deepEq(this.props, prevProps)) {
|
|
40825
|
-
this.setState({
|
|
40826
|
-
vector: this.props.vector
|
|
40827
|
-
});
|
|
40828
|
-
}
|
|
40829
|
-
}
|
|
40830
|
-
render() {
|
|
40831
|
-
const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
|
|
40832
|
-
const {
|
|
40833
|
-
TeX
|
|
40834
|
-
} = getDependencies();
|
|
40835
|
-
const vector = [/*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40836
|
-
key: "<"
|
|
40837
|
-
}, i18n__namespace.doNotTranslate("\\langle")), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
40838
|
-
key: "vec_x"
|
|
40839
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40840
|
-
,
|
|
40841
|
-
ref: "x",
|
|
40842
|
-
placeholder: 0,
|
|
40843
|
-
value: this.state.vector[0],
|
|
40844
|
-
useArrowKeys: true,
|
|
40845
|
-
onChange: val0 => {
|
|
40846
|
-
const val1 = this.state.vector[1];
|
|
40847
|
-
this.setState({
|
|
40848
|
-
vector: [val0, val1]
|
|
40849
|
-
}, () => {
|
|
40850
|
-
this.props.onChange();
|
|
40851
|
-
});
|
|
40852
|
-
},
|
|
40853
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "x"),
|
|
40854
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "x"),
|
|
40855
|
-
keypadElement: this.props.keypadElement
|
|
40856
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40857
|
-
key: ","
|
|
40858
|
-
}, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
40859
|
-
key: "vec_y"
|
|
40860
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40861
|
-
,
|
|
40862
|
-
ref: "y",
|
|
40863
|
-
placeholder: 0,
|
|
40864
|
-
value: this.state.vector[1],
|
|
40865
|
-
useArrowKeys: true,
|
|
40866
|
-
onChange: val1 => {
|
|
40867
|
-
const val0 = this.state.vector[0];
|
|
40868
|
-
this.setState({
|
|
40869
|
-
vector: [val0, val1]
|
|
40870
|
-
}, () => {
|
|
40871
|
-
this.props.onChange();
|
|
40872
|
-
});
|
|
40873
|
-
},
|
|
40874
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "y"),
|
|
40875
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "y"),
|
|
40876
|
-
keypadElement: this.props.keypadElement
|
|
40877
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40878
|
-
key: ">"
|
|
40879
|
-
}, i18n__namespace.doNotTranslate("\\rangle"))];
|
|
40880
|
-
return /*#__PURE__*/React__namespace.createElement("div", null, i18n__namespace.$_("Translation by %(vector)s", {
|
|
40881
|
-
vector: vector
|
|
40882
|
-
}));
|
|
40883
|
-
}
|
|
40884
|
-
value = () => {
|
|
40885
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40886
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
40887
|
-
const x = this.refs.x.getValue();
|
|
40888
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40889
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
40890
|
-
const y = this.refs.y.getValue();
|
|
40891
|
-
return {
|
|
40892
|
-
vector: [x, y]
|
|
40893
|
-
};
|
|
40894
|
-
};
|
|
40895
|
-
|
|
40896
|
-
/* InputPath API */
|
|
40897
|
-
setInputValue = (path, value, cb) => {
|
|
40898
|
-
const id = ___default["default"].first(path);
|
|
40899
|
-
const vector = ___default["default"].clone(this.state.vector);
|
|
40900
|
-
if (id === "x") {
|
|
40901
|
-
vector[0] = value;
|
|
40902
|
-
} else if (id === "y") {
|
|
40903
|
-
vector[1] = value;
|
|
40904
|
-
}
|
|
40905
|
-
this.setState({
|
|
40906
|
-
vector: vector
|
|
40907
|
-
}, () => {
|
|
40908
|
-
this.props.onChange(cb);
|
|
40909
|
-
});
|
|
40910
|
-
};
|
|
40911
|
-
getInputPaths = () => {
|
|
40912
|
-
return [["x"], ["y"]];
|
|
40913
|
-
};
|
|
40914
|
-
}
|
|
40915
|
-
},
|
|
40916
|
-
rotation: {
|
|
40917
|
-
// I18N: As in the command, "Rotate the polygon"
|
|
40918
|
-
verbName: i18n__namespace._("Rotate"),
|
|
40919
|
-
nounName: i18n__namespace._("Rotation"),
|
|
40920
|
-
lowerNounName: i18n__namespace._("rotation"),
|
|
40921
|
-
apply: function (transform) {
|
|
40922
|
-
return function (coord) {
|
|
40923
|
-
return kmath.point.rotateDeg(coord, transform.angleDeg, transform.center);
|
|
40924
|
-
};
|
|
40925
|
-
},
|
|
40926
|
-
isValid: function (transform) {
|
|
40927
|
-
return ___default["default"].isFinite(transform.angleDeg) && ___default["default"].isFinite(transform.center[0]) && ___default["default"].isFinite(transform.center[1]);
|
|
40928
|
-
},
|
|
40929
|
-
isEmpty: function (transform) {
|
|
40930
|
-
return transform.angleDeg === null && transform.center[0] === null && transform.center[1] === null;
|
|
40931
|
-
},
|
|
40932
|
-
isNoOp: function (transform) {
|
|
40933
|
-
return kmath.number.equal(transform.angleDeg, 0);
|
|
40934
|
-
},
|
|
40935
|
-
collapse: function (transform1, transform2) {
|
|
40936
|
-
if (!kmath.point.equal(transform1.center, transform2.center)) {
|
|
40937
|
-
return false;
|
|
40938
|
-
}
|
|
40939
|
-
return {
|
|
40940
|
-
center: transform1.center,
|
|
40941
|
-
angleDeg: transform1.angleDeg + transform2.angleDeg
|
|
40942
|
-
};
|
|
40943
|
-
},
|
|
40944
|
-
toTeX: function (transform) {
|
|
40945
|
-
return i18n__namespace.$_("Rotation by %(degrees)s about %(point)s", {
|
|
40946
|
-
degrees: texFromAngleDeg(transform.angleDeg),
|
|
40947
|
-
point: texFromPoint(transform.center)
|
|
40948
|
-
});
|
|
40949
|
-
},
|
|
40950
|
-
Input: class extends React__namespace.Component {
|
|
40951
|
-
state = {
|
|
40952
|
-
center: this.props.center || [null, null],
|
|
40953
|
-
angleDeg: this.props.angleDeg || null
|
|
40954
|
-
};
|
|
40955
|
-
componentDidUpdate(prevProps) {
|
|
40956
|
-
if (!deepEq(this.props, prevProps)) {
|
|
40957
|
-
this.setState({
|
|
40958
|
-
center: this.props.center,
|
|
40959
|
-
angleDeg: this.props.angleDeg
|
|
40960
|
-
});
|
|
40961
|
-
}
|
|
40962
|
-
}
|
|
40963
|
-
render() {
|
|
40964
|
-
const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
|
|
40965
|
-
const {
|
|
40966
|
-
TeX
|
|
40967
|
-
} = getDependencies();
|
|
40968
|
-
const point = [/*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40969
|
-
key: "("
|
|
40970
|
-
}, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
40971
|
-
key: "X"
|
|
40972
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40973
|
-
,
|
|
40974
|
-
ref: "centerX",
|
|
40975
|
-
placeholder: 0,
|
|
40976
|
-
value: this.state.center[0],
|
|
40977
|
-
useArrowKeys: true,
|
|
40978
|
-
onChange: val0 => {
|
|
40979
|
-
const val1 = this.state.center[1];
|
|
40980
|
-
this.setState({
|
|
40981
|
-
center: [val0, val1]
|
|
40982
|
-
}, () => {
|
|
40983
|
-
this.props.onChange();
|
|
40984
|
-
});
|
|
40985
|
-
},
|
|
40986
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "centerX"),
|
|
40987
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "centerX"),
|
|
40988
|
-
keypadElement: this.props.keypadElement
|
|
40989
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
40990
|
-
key: ","
|
|
40991
|
-
}, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
40992
|
-
key: "Y"
|
|
40993
|
-
// eslint-disable-next-line react/no-string-refs
|
|
40994
|
-
,
|
|
40995
|
-
ref: "centerY",
|
|
40996
|
-
placeholder: 0,
|
|
40997
|
-
value: this.state.center[1],
|
|
40998
|
-
useArrowKeys: true,
|
|
40999
|
-
onChange: val1 => {
|
|
41000
|
-
const val0 = this.state.center[0];
|
|
41001
|
-
this.setState({
|
|
41002
|
-
center: [val0, val1]
|
|
41003
|
-
}, () => {
|
|
41004
|
-
this.props.onChange();
|
|
41005
|
-
});
|
|
41006
|
-
},
|
|
41007
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "centerY"),
|
|
41008
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "centerY"),
|
|
41009
|
-
keypadElement: this.props.keypadElement
|
|
41010
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41011
|
-
key: ")"
|
|
41012
|
-
}, ")")];
|
|
41013
|
-
const degrees = [/*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
41014
|
-
key: "deg"
|
|
41015
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41016
|
-
,
|
|
41017
|
-
ref: "angleDeg",
|
|
41018
|
-
placeholder: 0,
|
|
41019
|
-
value: this.state.angleDeg,
|
|
41020
|
-
useArrowKeys: true,
|
|
41021
|
-
onChange: val => {
|
|
41022
|
-
this.setState({
|
|
41023
|
-
angleDeg: val
|
|
41024
|
-
}, () => {
|
|
41025
|
-
this.props.onChange();
|
|
41026
|
-
});
|
|
41027
|
-
},
|
|
41028
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "angleDeg"),
|
|
41029
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "angleDeg"),
|
|
41030
|
-
keypadElement: this.props.keypadElement
|
|
41031
|
-
}), DEGREE_SIGN];
|
|
41032
|
-
// I18N: %(point)s must come before %(degrees)s in this phrase
|
|
41033
|
-
const text = i18n__namespace.$_("Rotation about %(point)s by %(degrees)s", {
|
|
41034
|
-
point,
|
|
41035
|
-
degrees
|
|
41036
|
-
});
|
|
41037
|
-
return /*#__PURE__*/React__namespace.createElement("div", null, text);
|
|
41038
|
-
}
|
|
41039
|
-
value = () => {
|
|
41040
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41041
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41042
|
-
const angleDeg = this.refs.angleDeg.getValue();
|
|
41043
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41044
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41045
|
-
const centerX = this.refs.centerX.getValue();
|
|
41046
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41047
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41048
|
-
const centerY = this.refs.centerY.getValue();
|
|
41049
|
-
return {
|
|
41050
|
-
angleDeg: angleDeg,
|
|
41051
|
-
center: [centerX, centerY]
|
|
41052
|
-
};
|
|
41053
|
-
};
|
|
41054
|
-
|
|
41055
|
-
/* InputPath API */
|
|
41056
|
-
setInputValue = (path, value, cb) => {
|
|
41057
|
-
const id = ___default["default"].first(path);
|
|
41058
|
-
let angleDeg = ___default["default"].clone(this.state.angleDeg);
|
|
41059
|
-
const center = ___default["default"].clone(this.state.center);
|
|
41060
|
-
if (id === "angleDeg") {
|
|
41061
|
-
angleDeg = value;
|
|
41062
|
-
} else if (id === "centerX") {
|
|
41063
|
-
center[0] = value;
|
|
41064
|
-
} else if (id === "centerY") {
|
|
41065
|
-
center[1] = value;
|
|
41066
|
-
}
|
|
41067
|
-
this.setState({
|
|
41068
|
-
angleDeg: angleDeg,
|
|
41069
|
-
center: center
|
|
41070
|
-
}, () => {
|
|
41071
|
-
this.props.onChange(cb);
|
|
41072
|
-
});
|
|
41073
|
-
};
|
|
41074
|
-
getInputPaths = () => {
|
|
41075
|
-
return [["centerX"], ["centerY"], ["angleDeg"]];
|
|
41076
|
-
};
|
|
41077
|
-
}
|
|
41078
|
-
},
|
|
41079
|
-
reflection: {
|
|
41080
|
-
// I18N: As in the command, "Reflect the polygon"
|
|
41081
|
-
verbName: i18n__namespace._("Reflect"),
|
|
41082
|
-
nounName: i18n__namespace._("Reflection"),
|
|
41083
|
-
lowerNounName: i18n__namespace._("reflection"),
|
|
41084
|
-
apply: function (transform) {
|
|
41085
|
-
return function (coord) {
|
|
41086
|
-
return kmath.point.reflectOverLine(coord, transform.line);
|
|
41087
|
-
};
|
|
41088
|
-
},
|
|
41089
|
-
isValid: function (transform) {
|
|
41090
|
-
// A bit hacky, but we'll also define reflecting over a
|
|
41091
|
-
// single point as a no-op, to avoid NaN fun.
|
|
41092
|
-
return ___default["default"].all(___default["default"].flatten(transform.line), ___default["default"].isFinite) && !kmath.point.equal(transform.line[0], transform.line[1]);
|
|
41093
|
-
},
|
|
41094
|
-
isEmpty: function (transform) {
|
|
41095
|
-
return ___default["default"].all(___default["default"].flatten(transform.line), ___default["default"].isNull);
|
|
41096
|
-
},
|
|
41097
|
-
isNoOp: function (transform) {
|
|
41098
|
-
// Invalid transforms are implicitly no-ops, so we don't
|
|
41099
|
-
// have to catch that case here.
|
|
41100
|
-
return false;
|
|
41101
|
-
},
|
|
41102
|
-
collapse: function (transform1, transform2) {
|
|
41103
|
-
if (!kmath.line.equal(transform1.line, transform2.line)) {
|
|
41104
|
-
return false;
|
|
41105
|
-
}
|
|
41106
|
-
return [];
|
|
41107
|
-
},
|
|
41108
|
-
toTeX: function (transform) {
|
|
41109
|
-
const point1 = transform.line[0];
|
|
41110
|
-
const point2 = transform.line[1];
|
|
41111
|
-
return i18n__namespace.$_("Reflection over the line from %(point1)s to %(point2)s", {
|
|
41112
|
-
point1: texFromPoint(point1),
|
|
41113
|
-
point2: texFromPoint(point2)
|
|
41114
|
-
});
|
|
41115
|
-
},
|
|
41116
|
-
Input: class extends React__namespace.Component {
|
|
41117
|
-
state = {
|
|
41118
|
-
line: this.props.line || [[null, null], [null, null]]
|
|
41119
|
-
};
|
|
41120
|
-
componentDidUpdate(prevProps) {
|
|
41121
|
-
if (!deepEq(this.props, prevProps)) {
|
|
41122
|
-
this.setState({
|
|
41123
|
-
line: this.props.line
|
|
41124
|
-
});
|
|
41125
|
-
}
|
|
41126
|
-
}
|
|
41127
|
-
render() {
|
|
41128
|
-
const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
|
|
41129
|
-
const {
|
|
41130
|
-
TeX
|
|
41131
|
-
} = getDependencies();
|
|
41132
|
-
const point1 = [/*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41133
|
-
key: "("
|
|
41134
|
-
}, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
41135
|
-
key: "x1"
|
|
41136
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41137
|
-
,
|
|
41138
|
-
ref: "x1",
|
|
41139
|
-
value: this.state.line[0][0],
|
|
41140
|
-
useArrowKeys: true
|
|
41141
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
41142
|
-
,
|
|
41143
|
-
onChange: this.changePoint.bind(this, 0, 0),
|
|
41144
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "x1"),
|
|
41145
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "x1"),
|
|
41146
|
-
keypadElement: this.props.keypadElement
|
|
41147
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41148
|
-
key: ","
|
|
41149
|
-
}, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
41150
|
-
key: "y1"
|
|
41151
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41152
|
-
,
|
|
41153
|
-
ref: "y1",
|
|
41154
|
-
value: this.state.line[0][1],
|
|
41155
|
-
useArrowKeys: true
|
|
41156
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
41157
|
-
,
|
|
41158
|
-
onChange: this.changePoint.bind(this, 0, 1),
|
|
41159
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "y1"),
|
|
41160
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "y1"),
|
|
41161
|
-
keypadElement: this.props.keypadElement
|
|
41162
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41163
|
-
key: ")"
|
|
41164
|
-
}, ")")];
|
|
41165
|
-
const point2 = [/*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41166
|
-
key: "("
|
|
41167
|
-
}, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
41168
|
-
key: "x2"
|
|
41169
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41170
|
-
,
|
|
41171
|
-
ref: "x2",
|
|
41172
|
-
value: this.state.line[1][0],
|
|
41173
|
-
useArrowKeys: true
|
|
41174
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
41175
|
-
,
|
|
41176
|
-
onChange: this.changePoint.bind(this, 1, 0),
|
|
41177
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "x2"),
|
|
41178
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "x2"),
|
|
41179
|
-
keypadElement: this.props.keypadElement
|
|
41180
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41181
|
-
key: ","
|
|
41182
|
-
}, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
41183
|
-
key: "y2"
|
|
41184
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41185
|
-
,
|
|
41186
|
-
ref: "y2",
|
|
41187
|
-
value: this.state.line[1][1],
|
|
41188
|
-
useArrowKeys: true
|
|
41189
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
41190
|
-
,
|
|
41191
|
-
onChange: this.changePoint.bind(this, 1, 1),
|
|
41192
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "y2"),
|
|
41193
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "y2"),
|
|
41194
|
-
keypadElement: this.props.keypadElement
|
|
41195
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41196
|
-
key: ")"
|
|
41197
|
-
}, ")")];
|
|
41198
|
-
return /*#__PURE__*/React__namespace.createElement("div", null, i18n__namespace.$_("Reflection over the line from " + "%(point1)s to %(point2)s", {
|
|
41199
|
-
point1,
|
|
41200
|
-
point2
|
|
41201
|
-
}));
|
|
41202
|
-
}
|
|
41203
|
-
changePoint = (i, j, val, cb) => {
|
|
41204
|
-
const line = ___default["default"].map(this.state.line, ___default["default"].clone);
|
|
41205
|
-
// @ts-expect-error - TS2538 - Type 'undefined' cannot be used as an index type.
|
|
41206
|
-
line[i][j] = val;
|
|
41207
|
-
this.setState({
|
|
41208
|
-
line: line
|
|
41209
|
-
}, () => {
|
|
41210
|
-
this.props.onChange(cb);
|
|
41211
|
-
});
|
|
41212
|
-
};
|
|
41213
|
-
value = () => {
|
|
41214
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41215
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41216
|
-
const x1 = this.refs.x1.getValue();
|
|
41217
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41218
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41219
|
-
const y1 = this.refs.y1.getValue();
|
|
41220
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41221
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41222
|
-
const x2 = this.refs.x2.getValue();
|
|
41223
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41224
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41225
|
-
const y2 = this.refs.y2.getValue();
|
|
41226
|
-
return {
|
|
41227
|
-
line: [[x1, y1], [x2, y2]]
|
|
41228
|
-
};
|
|
41229
|
-
};
|
|
41230
|
-
|
|
41231
|
-
/* InputPath API */
|
|
41232
|
-
setInputValue = (path, value, cb) => {
|
|
41233
|
-
const id = ___default["default"].first(path);
|
|
41234
|
-
let j;
|
|
41235
|
-
if (id[0] === "x") {
|
|
41236
|
-
j = 0;
|
|
41237
|
-
} else if (id[0] === "y") {
|
|
41238
|
-
j = 1;
|
|
41239
|
-
}
|
|
41240
|
-
let i;
|
|
41241
|
-
if (id[1] === "1") {
|
|
41242
|
-
i = 0;
|
|
41243
|
-
} else if (id[1] === "2") {
|
|
41244
|
-
i = 1;
|
|
41245
|
-
}
|
|
41246
|
-
this.changePoint(i, j, value, cb);
|
|
41247
|
-
};
|
|
41248
|
-
getInputPaths = () => {
|
|
41249
|
-
return [["x1"], ["y1"], ["x2"], ["y2"]];
|
|
41250
|
-
};
|
|
41251
|
-
}
|
|
41252
|
-
},
|
|
41253
|
-
dilation: {
|
|
41254
|
-
// I18N: As in the command, "Dilate the polygon"
|
|
41255
|
-
verbName: i18n__namespace._("Dilate"),
|
|
41256
|
-
nounName: i18n__namespace._("Dilation"),
|
|
41257
|
-
lowerNounName: i18n__namespace._("dilation"),
|
|
41258
|
-
apply: function (transform) {
|
|
41259
|
-
return function (coord) {
|
|
41260
|
-
return dilatePointFromCenter(coord, transform.center, transform.scale);
|
|
41261
|
-
};
|
|
41262
|
-
},
|
|
41263
|
-
isValid: function (transform) {
|
|
41264
|
-
return ___default["default"].isFinite(transform.scale) && ___default["default"].isFinite(transform.center[0]) && ___default["default"].isFinite(transform.center[1]);
|
|
41265
|
-
},
|
|
41266
|
-
isEmpty: function (transform) {
|
|
41267
|
-
return transform.scale === null && transform.center[0] === null && transform.center[1] === null;
|
|
41268
|
-
},
|
|
41269
|
-
isNoOp: function (transform) {
|
|
41270
|
-
return kmath.number.equal(transform.scale, 1);
|
|
41271
|
-
},
|
|
41272
|
-
collapse: function (transform1, transform2) {
|
|
41273
|
-
if (!kmath.point.equal(transform1.center, transform2.center)) {
|
|
41274
|
-
return false;
|
|
41275
|
-
}
|
|
41276
|
-
return {
|
|
41277
|
-
center: transform1.center,
|
|
41278
|
-
scale: transform1.scale * transform2.scale
|
|
41279
|
-
};
|
|
41280
|
-
},
|
|
41281
|
-
toTeX: function (transform) {
|
|
41282
|
-
const scaleString = stringFromFraction(transform.scale);
|
|
41283
|
-
return i18n__namespace.$_("Dilation of scale %(scale)s about %(point)s", {
|
|
41284
|
-
scale: scaleString,
|
|
41285
|
-
point: texFromPoint(transform.center)
|
|
41286
|
-
});
|
|
41287
|
-
},
|
|
41288
|
-
Input: class extends React__namespace.Component {
|
|
41289
|
-
state = {
|
|
41290
|
-
center: this.props.center || [null, null],
|
|
41291
|
-
scale: this.props.scale || null
|
|
41292
|
-
};
|
|
41293
|
-
componentDidUpdate(prevProps) {
|
|
41294
|
-
if (!deepEq(this.props, prevProps)) {
|
|
41295
|
-
this.setState({
|
|
41296
|
-
center: this.props.center,
|
|
41297
|
-
scale: this.props.scale
|
|
41298
|
-
});
|
|
41299
|
-
}
|
|
41300
|
-
}
|
|
41301
|
-
render() {
|
|
41302
|
-
const InputComponent = inputComponentForApiOptions(this.props.apiOptions);
|
|
41303
|
-
const {
|
|
41304
|
-
TeX
|
|
41305
|
-
} = getDependencies();
|
|
41306
|
-
const point = [/*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41307
|
-
key: "("
|
|
41308
|
-
}, "("), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
41309
|
-
key: "point_x"
|
|
41310
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41311
|
-
,
|
|
41312
|
-
ref: "x",
|
|
41313
|
-
placeholder: 0,
|
|
41314
|
-
value: this.state.center[0],
|
|
41315
|
-
useArrowKeys: true,
|
|
41316
|
-
onChange: val0 => {
|
|
41317
|
-
const val1 = this.state.center[1];
|
|
41318
|
-
this.setState({
|
|
41319
|
-
center: [val0, val1]
|
|
41320
|
-
}, () => {
|
|
41321
|
-
this.props.onChange();
|
|
41322
|
-
});
|
|
41323
|
-
},
|
|
41324
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "x"),
|
|
41325
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "x"),
|
|
41326
|
-
keypadElement: this.props.keypadElement
|
|
41327
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41328
|
-
key: ","
|
|
41329
|
-
}, ", {}"), /*#__PURE__*/React__namespace.createElement(InputComponent, {
|
|
41330
|
-
key: "point_y"
|
|
41331
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41332
|
-
,
|
|
41333
|
-
ref: "y",
|
|
41334
|
-
placeholder: 0,
|
|
41335
|
-
value: this.state.center[1],
|
|
41336
|
-
useArrowKeys: true,
|
|
41337
|
-
onChange: val1 => {
|
|
41338
|
-
const val0 = this.state.center[0];
|
|
41339
|
-
this.setState({
|
|
41340
|
-
center: [val0, val1]
|
|
41341
|
-
}, () => {
|
|
41342
|
-
this.props.onChange();
|
|
41343
|
-
});
|
|
41344
|
-
},
|
|
41345
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "y"),
|
|
41346
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "y"),
|
|
41347
|
-
keypadElement: this.props.keypadElement
|
|
41348
|
-
}), /*#__PURE__*/React__namespace.createElement(TeX, {
|
|
41349
|
-
key: ")"
|
|
41350
|
-
}, ")")];
|
|
41351
|
-
const scale = /*#__PURE__*/React__namespace.createElement(InputComponent
|
|
41352
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41353
|
-
, {
|
|
41354
|
-
ref: "scale",
|
|
41355
|
-
placeholder: 1,
|
|
41356
|
-
value: this.state.scale,
|
|
41357
|
-
useArrowKeys: true,
|
|
41358
|
-
onChange: val => {
|
|
41359
|
-
this.setState({
|
|
41360
|
-
scale: val
|
|
41361
|
-
}, () => {
|
|
41362
|
-
this.props.onChange();
|
|
41363
|
-
});
|
|
41364
|
-
},
|
|
41365
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "scale"),
|
|
41366
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "scale"),
|
|
41367
|
-
keypadElement: this.props.keypadElement
|
|
41368
|
-
});
|
|
41369
|
-
return /*#__PURE__*/React__namespace.createElement("div", null, i18n__namespace.$_("Dilation about %(point)s by %(scale)s", {
|
|
41370
|
-
point,
|
|
41371
|
-
scale
|
|
41372
|
-
}));
|
|
41373
|
-
}
|
|
41374
|
-
value = () => {
|
|
41375
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41376
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41377
|
-
const scale = this.refs.scale.getValue();
|
|
41378
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41379
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41380
|
-
const x = this.refs.x.getValue();
|
|
41381
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41382
|
-
// @ts-expect-error - TS2339 - Property 'getValue' does not exist on type 'ReactInstance'.
|
|
41383
|
-
const y = this.refs.y.getValue();
|
|
41384
|
-
return {
|
|
41385
|
-
scale: scale,
|
|
41386
|
-
center: [x, y]
|
|
41387
|
-
};
|
|
41388
|
-
};
|
|
41389
|
-
|
|
41390
|
-
/* InputPath API */
|
|
41391
|
-
setInputValue = (path, value, cb) => {
|
|
41392
|
-
const id = ___default["default"].first(path);
|
|
41393
|
-
let scale = this.state.scale;
|
|
41394
|
-
const center = ___default["default"].clone(this.state.center);
|
|
41395
|
-
if (id === "x") {
|
|
41396
|
-
center[0] = value;
|
|
41397
|
-
} else if (id === "y") {
|
|
41398
|
-
center[1] = value;
|
|
41399
|
-
} else if (id === "scale") {
|
|
41400
|
-
scale = value;
|
|
41401
|
-
}
|
|
41402
|
-
this.setState({
|
|
41403
|
-
scale: scale,
|
|
41404
|
-
center: center
|
|
41405
|
-
}, () => {
|
|
41406
|
-
this.props.onChange(cb);
|
|
41407
|
-
});
|
|
41408
|
-
};
|
|
41409
|
-
getInputPaths = () => {
|
|
41410
|
-
return [["x"], ["y"], ["scale"]];
|
|
41411
|
-
};
|
|
41412
|
-
}
|
|
41413
|
-
}
|
|
41414
|
-
};
|
|
41415
|
-
|
|
41416
|
-
/* Various functions to deal with different shape types */
|
|
41417
|
-
const ShapeTypes = {
|
|
41418
|
-
getPointCountForType: function (type) {
|
|
41419
|
-
const splitType = type.split("-");
|
|
41420
|
-
if (splitType[0] === "polygon") {
|
|
41421
|
-
return splitType[1] || 3;
|
|
41422
|
-
}
|
|
41423
|
-
if (splitType[0] === "line" || splitType[0] === "lineSegment") {
|
|
41424
|
-
return 2;
|
|
41425
|
-
}
|
|
41426
|
-
if (splitType[0] === "angle") {
|
|
41427
|
-
return 3;
|
|
41428
|
-
}
|
|
41429
|
-
if (splitType[0] === "circle") {
|
|
41430
|
-
return 2;
|
|
41431
|
-
}
|
|
41432
|
-
if (splitType[0] === "point") {
|
|
41433
|
-
return 1;
|
|
41434
|
-
}
|
|
41435
|
-
},
|
|
41436
|
-
addMovableShape: function (graphie, options) {
|
|
41437
|
-
if (options.editable && options.translatable) {
|
|
41438
|
-
throw new PerseusError("It doesn't make sense to have a movable shape " + "where you can stretch the points and translate them " + "simultaneously. options: " + JSON.stringify(options), Errors.InvalidInput);
|
|
41439
|
-
}
|
|
41440
|
-
const points = ___default["default"].map(options.shape.coords, function (coord) {
|
|
41441
|
-
let isMoving = false;
|
|
41442
|
-
let previousCoord = coord;
|
|
41443
|
-
const onMove = function (x, y) {
|
|
41444
|
-
if (!isMoving) {
|
|
41445
|
-
previousCoord = currentPoint.coord;
|
|
41446
|
-
isMoving = true;
|
|
41447
|
-
}
|
|
41448
|
-
let moveVector = kmath.vector.subtract([x, y], currentPoint.coord);
|
|
41449
|
-
|
|
41450
|
-
// Translate from (x, y) semantics to (dX, dY) semantics
|
|
41451
|
-
// This is more useful for translations on multiple points,
|
|
41452
|
-
// where we care about how the points moved, not where any
|
|
41453
|
-
// individual point ended up
|
|
41454
|
-
if (options.onMove) {
|
|
41455
|
-
moveVector = options.onMove(moveVector[0], moveVector[1]);
|
|
41456
|
-
}
|
|
41457
|
-
|
|
41458
|
-
// Perform a translation on all points in this shape when
|
|
41459
|
-
// any point moves
|
|
41460
|
-
if (options.translatable) {
|
|
41461
|
-
___default["default"].each(points, function (point) {
|
|
41462
|
-
// The point itself will be updated by the
|
|
41463
|
-
// movablePoint class, so only translate the other
|
|
41464
|
-
// points
|
|
41465
|
-
if (point !== currentPoint) {
|
|
41466
|
-
point.setCoord(kmath.vector.add(point.coord, moveVector));
|
|
41467
|
-
}
|
|
41468
|
-
});
|
|
41469
|
-
}
|
|
41470
|
-
|
|
41471
|
-
// Update our shape and our currentPoint
|
|
41472
|
-
// Without this, some shapes (circles, angles) appear
|
|
41473
|
-
// "bouncy" as they are updated with currentPoint at the
|
|
41474
|
-
// current mouse coordinate (oldCoord), rather than newCoord
|
|
41475
|
-
const oldCoord = currentPoint.coord;
|
|
41476
|
-
const newCoord = kmath.vector.add(currentPoint.coord, moveVector);
|
|
41477
|
-
// Temporarily change our coordinate so that
|
|
41478
|
-
// shape.update() sees the new coordinate
|
|
41479
|
-
currentPoint.coord = newCoord;
|
|
41480
|
-
shape.update();
|
|
41481
|
-
// ...But don't break onMove, which assumes it
|
|
41482
|
-
// is the only thing changing our coord
|
|
41483
|
-
currentPoint.coord = oldCoord;
|
|
41484
|
-
return newCoord;
|
|
41485
|
-
};
|
|
41486
|
-
const onMoveEnd = function () {
|
|
41487
|
-
// onMove isn't guaranteed to be called before onMoveEnd, so
|
|
41488
|
-
// we have to take into account that we may not have moved and
|
|
41489
|
-
// set previousCoord.
|
|
41490
|
-
if (options.onMoveEnd && isMoving) {
|
|
41491
|
-
isMoving = false;
|
|
41492
|
-
// We don't use the supplied x and y parameters here
|
|
41493
|
-
// because MovablePoint's onMoveEnd semantics suck.
|
|
41494
|
-
// It returns the mouseX, mouseY without processing them
|
|
41495
|
-
// through onMove, leaving us with weird fractional moves
|
|
41496
|
-
const change = kmath.vector.subtract(currentPoint.coord, previousCoord);
|
|
41497
|
-
options.onMoveEnd(change[0], change[1]);
|
|
41498
|
-
}
|
|
41499
|
-
shape.update();
|
|
41500
|
-
};
|
|
41501
|
-
const currentPoint = graphie.addMovablePoint({
|
|
41502
|
-
coord: coord,
|
|
41503
|
-
normalStyle: options.normalPointStyle,
|
|
41504
|
-
highlightStyle: options.highlightPointStyle,
|
|
41505
|
-
constraints: {
|
|
41506
|
-
fixed: !options.translatable && !options.editable
|
|
41507
|
-
},
|
|
41508
|
-
visible: options.showPoints,
|
|
41509
|
-
snapX: options.snap && options.snap[0] || 0,
|
|
41510
|
-
snapY: options.snap && options.snap[1] || 0,
|
|
41511
|
-
bounded: false,
|
|
41512
|
-
// Don't bound it when placing it on the graph
|
|
41513
|
-
onMove: onMove,
|
|
41514
|
-
onMoveEnd: onMoveEnd
|
|
41515
|
-
});
|
|
41516
|
-
|
|
41517
|
-
// Bound it when moving
|
|
41518
|
-
// We can't set this earlier, because doing so would mean any
|
|
41519
|
-
// points outside of the graph would be moved into a moved into
|
|
41520
|
-
// a position that doesn't preserve the shape
|
|
41521
|
-
currentPoint.bounded = true;
|
|
41522
|
-
return currentPoint;
|
|
41523
|
-
});
|
|
41524
|
-
const shape = ShapeTypes.addShape(graphie, options, points);
|
|
41525
|
-
const removeShapeWithoutPoints = shape.remove;
|
|
41526
|
-
shape.remove = function () {
|
|
41527
|
-
removeShapeWithoutPoints.apply(shape);
|
|
41528
|
-
___default["default"].invoke(points, "remove");
|
|
41529
|
-
};
|
|
41530
|
-
return shape;
|
|
41531
|
-
},
|
|
41532
|
-
addShape: function (graphie, options, points) {
|
|
41533
|
-
points = points || options.shape.coords;
|
|
41534
|
-
const types = ShapeTypes._typesOf(options.shape);
|
|
41535
|
-
const typeOptions = options.shape.options || ShapeTypes.defaultOptions(types);
|
|
41536
|
-
|
|
41537
|
-
// @ts-expect-error - TS2554 - Expected 4 arguments, but got 3.
|
|
41538
|
-
const shapes = ShapeTypes._mapTypes(types, points, function (type, points, i) {
|
|
41539
|
-
const shapeOptions = ___default["default"].extend({}, options, typeOptions[i]);
|
|
41540
|
-
return ShapeTypes._addType(graphie, type, points, shapeOptions);
|
|
41541
|
-
});
|
|
41542
|
-
const updateFuncs = ___default["default"].filter(___default["default"].pluck(shapes, "update"), ___default["default"].identity);
|
|
41543
|
-
const update = function () {
|
|
41544
|
-
___default["default"].invoke(updateFuncs, "call");
|
|
41545
|
-
};
|
|
41546
|
-
const removeFuncs = ___default["default"].filter(___default["default"].pluck(shapes, "remove"), ___default["default"].identity);
|
|
41547
|
-
const remove = function () {
|
|
41548
|
-
___default["default"].invoke(removeFuncs, "call");
|
|
41549
|
-
};
|
|
41550
|
-
const getOptions = function () {
|
|
41551
|
-
return ___default["default"].map(shapes, function (shape) {
|
|
41552
|
-
if (shape.getOptions) {
|
|
41553
|
-
return shape.getOptions();
|
|
41554
|
-
}
|
|
41555
|
-
return {};
|
|
41556
|
-
});
|
|
41557
|
-
};
|
|
41558
|
-
const toJSON = function () {
|
|
41559
|
-
const coords = ___default["default"].map(points, function (pt) {
|
|
41560
|
-
if (___default["default"].isArray(pt)) {
|
|
41561
|
-
return pt;
|
|
41562
|
-
}
|
|
41563
|
-
return pt.coord;
|
|
41564
|
-
});
|
|
41565
|
-
return {
|
|
41566
|
-
type: types,
|
|
41567
|
-
coords: coords,
|
|
41568
|
-
options: getOptions()
|
|
41569
|
-
};
|
|
41570
|
-
};
|
|
41571
|
-
return {
|
|
41572
|
-
type: types,
|
|
41573
|
-
points: points,
|
|
41574
|
-
update: update,
|
|
41575
|
-
remove: remove,
|
|
41576
|
-
toJSON: toJSON,
|
|
41577
|
-
getOptions: getOptions
|
|
41578
|
-
};
|
|
41579
|
-
},
|
|
41580
|
-
equal: function (shape1, shape2) {
|
|
41581
|
-
const types1 = ShapeTypes._typesOf(shape1);
|
|
41582
|
-
const types2 = ShapeTypes._typesOf(shape2);
|
|
41583
|
-
if (types1.length !== types2.length) {
|
|
41584
|
-
return false;
|
|
41585
|
-
}
|
|
41586
|
-
// @ts-expect-error - TS2554 - Expected 4 arguments, but got 3.
|
|
41587
|
-
const shapes1 = ShapeTypes._mapTypes(types1, shape1.coords, ShapeTypes._combine);
|
|
41588
|
-
// @ts-expect-error - TS2554 - Expected 4 arguments, but got 3.
|
|
41589
|
-
const shapes2 = ShapeTypes._mapTypes(types2, shape2.coords, ShapeTypes._combine);
|
|
41590
|
-
return ___default["default"].all(___default["default"].map(shapes1, function (partialShape1, i) {
|
|
41591
|
-
const partialShape2 = shapes2[i];
|
|
41592
|
-
if (partialShape1.type !== partialShape2.type) {
|
|
41593
|
-
return false;
|
|
41594
|
-
}
|
|
41595
|
-
return ShapeTypes._forType(partialShape1.type).equal(partialShape1.coords, partialShape2.coords);
|
|
41596
|
-
}));
|
|
41597
|
-
},
|
|
41598
|
-
_typesOf: function (shape) {
|
|
41599
|
-
let types = shape.type;
|
|
41600
|
-
if (!___default["default"].isArray(types)) {
|
|
41601
|
-
types = [types];
|
|
41602
|
-
}
|
|
41603
|
-
return ___default["default"].map(types, function (type) {
|
|
41604
|
-
if (type === "polygon") {
|
|
41605
|
-
return "polygon-3";
|
|
41606
|
-
}
|
|
41607
|
-
return type;
|
|
41608
|
-
});
|
|
41609
|
-
},
|
|
41610
|
-
defaultOptions: function (types) {
|
|
41611
|
-
return ___default["default"].map(types, function (type) {
|
|
41612
|
-
const typeDefaultOptions = ShapeTypes._forType(type).defaultOptions;
|
|
41613
|
-
return ___default["default"].extend({}, typeDefaultOptions);
|
|
41614
|
-
});
|
|
41615
|
-
},
|
|
41616
|
-
_forType: function (type) {
|
|
41617
|
-
const baseType = type.split("-")[0];
|
|
41618
|
-
return ShapeTypes[baseType];
|
|
41619
|
-
},
|
|
41620
|
-
_mapTypes: function (types, points, func, context) {
|
|
41621
|
-
return ___default["default"].map(types, function (type, i) {
|
|
41622
|
-
const pointCount = ShapeTypes.getPointCountForType(type);
|
|
41623
|
-
const currentPoints = ___default["default"].first(points, pointCount);
|
|
41624
|
-
points = ___default["default"].rest(points, pointCount);
|
|
41625
|
-
return func.call(context, type, currentPoints, i);
|
|
41626
|
-
});
|
|
41627
|
-
},
|
|
41628
|
-
_addType: function (graphie, type, points, options) {
|
|
41629
|
-
const lineCoords = ___default["default"].isArray(points[0]) ? {
|
|
41630
|
-
coordA: points[0],
|
|
41631
|
-
coordZ: points[1]
|
|
41632
|
-
} : {
|
|
41633
|
-
pointA: points[0],
|
|
41634
|
-
pointZ: points[1]
|
|
41635
|
-
};
|
|
41636
|
-
type = type.split("-")[0];
|
|
41637
|
-
if (type === "polygon") {
|
|
41638
|
-
const polygon = graphie.addMovablePolygon(___default["default"].extend({}, options, {
|
|
41639
|
-
fixed: !options.editable,
|
|
41640
|
-
snapX: options.snap && options.snap[0] || 0,
|
|
41641
|
-
snapY: options.snap && options.snap[1] || 0,
|
|
41642
|
-
points: points,
|
|
41643
|
-
constrainToGraph: false
|
|
41644
|
-
}));
|
|
41645
|
-
return {
|
|
41646
|
-
update: polygon.transform.bind(polygon),
|
|
41647
|
-
remove: polygon.remove.bind(polygon)
|
|
41648
|
-
};
|
|
41649
|
-
}
|
|
41650
|
-
if (type === "line" || type === "lineSegment") {
|
|
41651
|
-
const line = graphie.addMovableLineSegment(___default["default"].extend({}, options, lineCoords, {
|
|
41652
|
-
movePointsWithLine: true,
|
|
41653
|
-
fixed: true,
|
|
41654
|
-
constraints: {
|
|
41655
|
-
fixed: true
|
|
41656
|
-
},
|
|
41657
|
-
extendLine: type === "line"
|
|
41658
|
-
}));
|
|
41659
|
-
|
|
41660
|
-
// TODO(jack): Hide points on uneditable lines when translation
|
|
41661
|
-
// is a vector.
|
|
41662
|
-
// We can't just remove the points yet, because they are the
|
|
41663
|
-
// translation handle for the line.
|
|
41664
|
-
return {
|
|
41665
|
-
update: line.transform.bind(line, true),
|
|
41666
|
-
remove: line.remove.bind(line)
|
|
41667
|
-
};
|
|
41668
|
-
}
|
|
41669
|
-
if (type === "angle") {
|
|
41670
|
-
// If this angle is editable, we want to be able to make angles
|
|
41671
|
-
// both larger and smaller than 180 degrees.
|
|
41672
|
-
// If this angle is not editable, it should always maintain
|
|
41673
|
-
// it's angle measure, even if it is reflected (causing the
|
|
41674
|
-
// clockwise-ness of the points to change)
|
|
41675
|
-
const shouldChangeReflexivity = options.editable ? null : false;
|
|
41676
|
-
const angle = graphie.addMovableAngle({
|
|
41677
|
-
angleLabel: "$deg0",
|
|
41678
|
-
fixed: true,
|
|
41679
|
-
points: points,
|
|
41680
|
-
normalStyle: options.normalStyle,
|
|
41681
|
-
reflex: options.reflex
|
|
41682
|
-
});
|
|
41683
|
-
|
|
41684
|
-
// Hide non-vertex points on uneditable angles
|
|
41685
|
-
if (!___default["default"].isArray(points[0]) && !options.editable) {
|
|
41686
|
-
points[0].remove();
|
|
41687
|
-
points[2].remove();
|
|
41688
|
-
}
|
|
41689
|
-
return {
|
|
41690
|
-
update: angle.update.bind(angle, shouldChangeReflexivity),
|
|
41691
|
-
remove: angle.remove.bind(angle),
|
|
41692
|
-
getOptions: function () {
|
|
41693
|
-
return {
|
|
41694
|
-
reflex: angle.isReflex()
|
|
41695
|
-
};
|
|
41696
|
-
}
|
|
41697
|
-
};
|
|
41698
|
-
}
|
|
41699
|
-
if (type === "circle") {
|
|
41700
|
-
let perimeter = {
|
|
41701
|
-
// temporary object for the first removal
|
|
41702
|
-
remove: ___default["default"].identity
|
|
41703
|
-
};
|
|
41704
|
-
const redrawPerim = function () {
|
|
41705
|
-
const coord0 = points[0].coord || points[0];
|
|
41706
|
-
const coord1 = points[1].coord || points[1];
|
|
41707
|
-
const radius = kmath.point.distanceToPoint(coord0, coord1);
|
|
41708
|
-
// @ts-expect-error - TS2554 - Expected 1 arguments, but got 0.
|
|
41709
|
-
perimeter.remove();
|
|
41710
|
-
perimeter = graphie.circle(coord0, radius, ___default["default"].extend({
|
|
41711
|
-
stroke: KhanColors.DYNAMIC,
|
|
41712
|
-
"stroke-width": 2
|
|
41713
|
-
}, options.normalStyle));
|
|
41714
|
-
};
|
|
41715
|
-
redrawPerim();
|
|
41716
|
-
if (points[1].remove && !options.editable) {
|
|
41717
|
-
points[1].remove();
|
|
41718
|
-
}
|
|
41719
|
-
return {
|
|
41720
|
-
update: redrawPerim,
|
|
41721
|
-
remove: function () {
|
|
41722
|
-
// Not _.bind because the remove function changes
|
|
41723
|
-
// when the perimeter is redrawn
|
|
41724
|
-
// @ts-expect-error - TS2554 - Expected 1 arguments, but got 0.
|
|
41725
|
-
perimeter.remove();
|
|
41726
|
-
}
|
|
41727
|
-
};
|
|
41728
|
-
}
|
|
41729
|
-
if (type === "point") {
|
|
41730
|
-
// do nothing
|
|
41731
|
-
return {
|
|
41732
|
-
update: null,
|
|
41733
|
-
remove: null
|
|
41734
|
-
};
|
|
41735
|
-
}
|
|
41736
|
-
throw new PerseusError("Invalid shape type " + type, Errors.InvalidInput);
|
|
41737
|
-
},
|
|
41738
|
-
_combine: function (type, coords) {
|
|
41739
|
-
return {
|
|
41740
|
-
type: type,
|
|
41741
|
-
coords: coords
|
|
41742
|
-
};
|
|
41743
|
-
},
|
|
41744
|
-
polygon: {
|
|
41745
|
-
equal: orderInsensitiveCoordsEqual
|
|
41746
|
-
},
|
|
41747
|
-
line: {
|
|
41748
|
-
equal: kmath.line.equal
|
|
41749
|
-
},
|
|
41750
|
-
lineSegment: {
|
|
41751
|
-
equal: orderInsensitiveCoordsEqual
|
|
41752
|
-
},
|
|
41753
|
-
angle: {
|
|
41754
|
-
equal: function (points1, points2) {
|
|
41755
|
-
if (!kmath.point.equal(points1[1], points2[1])) {
|
|
41756
|
-
return false;
|
|
41757
|
-
}
|
|
41758
|
-
const line1_0 = [points1[1], points1[0]];
|
|
41759
|
-
const line1_2 = [points1[1], points1[2]];
|
|
41760
|
-
const line2_0 = [points2[1], points2[0]];
|
|
41761
|
-
const line2_2 = [points2[1], points2[2]];
|
|
41762
|
-
const equalUnflipped =
|
|
41763
|
-
// @ts-expect-error - TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'. | TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'.
|
|
41764
|
-
kmath.ray.equal(line1_0, line2_0) && kmath.ray.equal(line1_2, line2_2);
|
|
41765
|
-
const equalFlipped =
|
|
41766
|
-
// @ts-expect-error - TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'. | TS2345 - Argument of type 'any[]' is not assignable to parameter of type 'Ray'.
|
|
41767
|
-
kmath.ray.equal(line1_0, line2_2) && kmath.ray.equal(line1_2, line2_0);
|
|
41768
|
-
return equalUnflipped || equalFlipped;
|
|
41769
|
-
},
|
|
41770
|
-
defaultOptions: {
|
|
41771
|
-
reflex: false
|
|
41772
|
-
}
|
|
41773
|
-
},
|
|
41774
|
-
circle: {
|
|
41775
|
-
equal: function (points1, points2) {
|
|
41776
|
-
const radius1 = kmath.point.distanceToPoint(points1[0], points1[1]);
|
|
41777
|
-
const radius2 = kmath.point.distanceToPoint(points2[0], points2[1]);
|
|
41778
|
-
return kmath.point.equal(points1[0], points2[0]) && kmath.number.equal(radius1, radius2);
|
|
41779
|
-
}
|
|
41780
|
-
},
|
|
41781
|
-
point: {
|
|
41782
|
-
equal: kmath.point.equal
|
|
41783
|
-
}
|
|
41784
|
-
};
|
|
41785
|
-
const TransformationListItem = TransformOps.ListItem;
|
|
41786
|
-
class TransformationList extends React__namespace.Component {
|
|
41787
|
-
render() {
|
|
41788
|
-
if (this.props.mode === "static") {
|
|
41789
|
-
return /*#__PURE__*/React__namespace.createElement("span", null); // don't render anything
|
|
41790
|
-
}
|
|
41791
|
-
|
|
41792
|
-
const transformationList = ___default["default"].map(this.props.transformations, function (transform, i) {
|
|
41793
|
-
return /*#__PURE__*/React__namespace.createElement(TransformationListItem, {
|
|
41794
|
-
ref: "transformation" + i,
|
|
41795
|
-
key: "transformation" + i,
|
|
41796
|
-
transform: transform
|
|
41797
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41798
|
-
,
|
|
41799
|
-
mode: this.props.mode
|
|
41800
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41801
|
-
,
|
|
41802
|
-
onChange: this.handleChange
|
|
41803
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41804
|
-
,
|
|
41805
|
-
onFocus: ___default["default"].partial(this.props.onFocus, "" + i)
|
|
41806
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41807
|
-
,
|
|
41808
|
-
onBlur: ___default["default"].partial(this.props.onBlur, "" + i)
|
|
41809
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41810
|
-
,
|
|
41811
|
-
keypadElement: this.props.keypadElement
|
|
41812
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41813
|
-
,
|
|
41814
|
-
apiOptions: this.props.apiOptions
|
|
41815
|
-
});
|
|
41816
|
-
}, this);
|
|
41817
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41818
|
-
className: "perseus-transformation-list"
|
|
41819
|
-
}, transformationList);
|
|
41820
|
-
}
|
|
41821
|
-
_transformationRefs = () => {
|
|
41822
|
-
return ___default["default"].times(this.props.transformations.length, i => {
|
|
41823
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41824
|
-
return this.refs["transformation" + i];
|
|
41825
|
-
});
|
|
41826
|
-
};
|
|
41827
|
-
value = () => {
|
|
41828
|
-
return ___default["default"].invoke(this._transformationRefs(), "value");
|
|
41829
|
-
};
|
|
41830
|
-
handleChange = (changed, callback) => {
|
|
41831
|
-
this.props.onChange(this.value(), callback);
|
|
41832
|
-
};
|
|
41833
|
-
focusLast = () => {
|
|
41834
|
-
const transformationRefs = this._transformationRefs();
|
|
41835
|
-
if (transformationRefs.length !== 0) {
|
|
41836
|
-
// @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2339 - Property 'focus' does not exist on type 'ReactInstance'.
|
|
41837
|
-
___default["default"].last(transformationRefs).focus();
|
|
41838
|
-
}
|
|
41839
|
-
};
|
|
41840
|
-
}
|
|
41841
|
-
class ToolButton extends React__namespace.Component {
|
|
41842
|
-
render() {
|
|
41843
|
-
const classes = this.props.toggled ? "simple-button exercise-orange toggled highlighted-tool-button" : "simple-button";
|
|
41844
|
-
return /*#__PURE__*/React__namespace.createElement("button", {
|
|
41845
|
-
type: "button",
|
|
41846
|
-
className: classes,
|
|
41847
|
-
disabled: this.props.disabled,
|
|
41848
|
-
onClick: this.props.onClick
|
|
41849
|
-
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLButtonElement>'.
|
|
41850
|
-
,
|
|
41851
|
-
onTouchStart: captureScratchpadTouchStart
|
|
41852
|
-
}, this.props.children);
|
|
41853
|
-
}
|
|
41854
|
-
}
|
|
41855
|
-
class ToolsBar extends React__namespace.Component {
|
|
41856
|
-
state = {
|
|
41857
|
-
selected: null
|
|
41858
|
-
};
|
|
41859
|
-
render() {
|
|
41860
|
-
const tools = ___default["default"].map(Transformations, function (tool, type) {
|
|
41861
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41862
|
-
if (this.props.enabled[type]) {
|
|
41863
|
-
return /*#__PURE__*/React__namespace.createElement(ToolButton, {
|
|
41864
|
-
key: type
|
|
41865
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41866
|
-
,
|
|
41867
|
-
disabled: this.props.apiOptions.readOnly
|
|
41868
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41869
|
-
,
|
|
41870
|
-
toggled: this.state.selected === type
|
|
41871
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
41872
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41873
|
-
,
|
|
41874
|
-
onClick: this.changeSelected.bind(this, type)
|
|
41875
|
-
}, tool.verbName);
|
|
41876
|
-
}
|
|
41877
|
-
}, this);
|
|
41878
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41879
|
-
className: "transformer-tools-bar"
|
|
41880
|
-
}, /*#__PURE__*/React__namespace.createElement("span", {
|
|
41881
|
-
className: "simple-button-group"
|
|
41882
|
-
}, tools), /*#__PURE__*/React__namespace.createElement("button", {
|
|
41883
|
-
className: "transformer-undo-button simple-button",
|
|
41884
|
-
type: "button",
|
|
41885
|
-
disabled: this.props.apiOptions.readOnly,
|
|
41886
|
-
onClick: this.props.onUndoClick
|
|
41887
|
-
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLButtonElement>'.
|
|
41888
|
-
,
|
|
41889
|
-
onTouchStart: captureScratchpadTouchStart
|
|
41890
|
-
}, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconUndo), " " + i18n__namespace._("Undo")), /*#__PURE__*/React__namespace.createElement("div", {
|
|
41891
|
-
className: "clear"
|
|
41892
|
-
}));
|
|
41893
|
-
}
|
|
41894
|
-
changeSelected = tool => {
|
|
41895
|
-
this.props.removeTool(this.state.selected);
|
|
41896
|
-
if (!tool || tool === this.state.selected) {
|
|
41897
|
-
this.setState({
|
|
41898
|
-
selected: null
|
|
41899
|
-
});
|
|
41900
|
-
} else {
|
|
41901
|
-
this.props.addTool(tool);
|
|
41902
|
-
this.setState({
|
|
41903
|
-
selected: tool
|
|
41904
|
-
});
|
|
41905
|
-
}
|
|
41906
|
-
};
|
|
41907
|
-
}
|
|
41908
|
-
class AddTransformBar extends React__namespace.Component {
|
|
41909
|
-
render() {
|
|
41910
|
-
const tools = ___default["default"].map(Transformations, function (tool, type) {
|
|
41911
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41912
|
-
if (this.props.enabled[type]) {
|
|
41913
|
-
return /*#__PURE__*/React__namespace.createElement(ToolButton, {
|
|
41914
|
-
key: type,
|
|
41915
|
-
toggled: false
|
|
41916
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41917
|
-
,
|
|
41918
|
-
disabled: this.props.apiOptions.readOnly
|
|
41919
|
-
// eslint-disable-next-line react/jsx-no-bind
|
|
41920
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation. | TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
41921
|
-
,
|
|
41922
|
-
onClick: this.changeSelected.bind(this, type)
|
|
41923
|
-
}, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconPlus), " ", tool.nounName);
|
|
41924
|
-
}
|
|
41925
|
-
}, this);
|
|
41926
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41927
|
-
className: "transformer-tools-bar"
|
|
41928
|
-
}, tools, /*#__PURE__*/React__namespace.createElement("button", {
|
|
41929
|
-
className: "transformer-undo-button simple-button",
|
|
41930
|
-
type: "button",
|
|
41931
|
-
onClick: this.props.onUndoClick,
|
|
41932
|
-
disabled: this.props.apiOptions.readOnly
|
|
41933
|
-
// @ts-expect-error - TS2322 - Type '(e: TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLButtonElement>'.
|
|
41934
|
-
,
|
|
41935
|
-
onTouchStart: captureScratchpadTouchStart
|
|
41936
|
-
}, /*#__PURE__*/React__namespace.createElement(InlineIcon, iconUndo), " " + i18n__namespace._("Undo")), /*#__PURE__*/React__namespace.createElement("div", {
|
|
41937
|
-
className: "clear"
|
|
41938
|
-
}));
|
|
41939
|
-
}
|
|
41940
|
-
changeSelected = tool => {
|
|
41941
|
-
if (tool) {
|
|
41942
|
-
this.props.addTool(tool);
|
|
41943
|
-
}
|
|
41944
|
-
};
|
|
41945
|
-
}
|
|
41946
|
-
|
|
41947
|
-
// there's no transform in the exports
|
|
41948
|
-
|
|
41949
|
-
class Transformer extends React__namespace.Component {
|
|
41950
|
-
// @ts-expect-error - TS2564 - Property 'tools' has no initializer and is not definitely assigned in the constructor.
|
|
41951
|
-
|
|
41952
|
-
// @ts-expect-error - TS2564 - Property 'transformations' has no initializer and is not definitely assigned in the constructor.
|
|
41953
|
-
|
|
41954
|
-
// This is not the same as TransformerShape
|
|
41955
|
-
|
|
41956
|
-
static defaultProps = ___default["default"].defaults({
|
|
41957
|
-
transformations: []
|
|
41958
|
-
}, defaultTransformerProps);
|
|
41959
|
-
render() {
|
|
41960
|
-
// Fill in any missing value in this.props.graph
|
|
41961
|
-
// this can happen because the graph json doesn't include
|
|
41962
|
-
// box, for example
|
|
41963
|
-
const graph = ___default["default"].extend(defaultGraphProps(this.props.graph, defaultBoxSize), this.props.graph);
|
|
41964
|
-
const interactiveToolsMode = this.props.graphMode === "interactive";
|
|
41965
|
-
const ToolsBarClass = interactiveToolsMode ? ToolsBar : AddTransformBar;
|
|
41966
|
-
|
|
41967
|
-
// This style is applied inline because it is dependent on the
|
|
41968
|
-
// size of the graph as set by the graph.box prop, and this also
|
|
41969
|
-
// lets us specify it in the same place the graph's width is
|
|
41970
|
-
// specified.
|
|
41971
|
-
const toolsBar = /*#__PURE__*/React__namespace.createElement("div", {
|
|
41972
|
-
style: {
|
|
41973
|
-
width: graph.box[0]
|
|
41974
|
-
}
|
|
41975
|
-
}, /*#__PURE__*/React__namespace.createElement(ToolsBarClass
|
|
41976
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41977
|
-
, {
|
|
41978
|
-
ref: "toolsBar",
|
|
41979
|
-
enabled: pluckObject(this.props.tools, "enabled"),
|
|
41980
|
-
apiOptions: this.props.apiOptions,
|
|
41981
|
-
addTool: this.addTool,
|
|
41982
|
-
removeTool: this.removeTool,
|
|
41983
|
-
onUndoClick: this.handleUndoClick
|
|
41984
|
-
}));
|
|
41985
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
41986
|
-
className: "perseus-widget " + "perseus-widget-transformer"
|
|
41987
|
-
}, /*#__PURE__*/React__namespace.createElement(Graph
|
|
41988
|
-
// eslint-disable-next-line react/no-string-refs
|
|
41989
|
-
, {
|
|
41990
|
-
ref: "graph",
|
|
41991
|
-
box: graph.box,
|
|
41992
|
-
range: graph.range,
|
|
41993
|
-
labels: graph.labels,
|
|
41994
|
-
step: graph.step,
|
|
41995
|
-
gridStep: graph.gridStep,
|
|
41996
|
-
markings: graph.markings,
|
|
41997
|
-
backgroundImage: graph.backgroundImage,
|
|
41998
|
-
showProtractor: graph.showProtractor,
|
|
41999
|
-
onGraphieUpdated: this.setupGraphie,
|
|
42000
|
-
setDrawingAreaAvailable: this.props.apiOptions.setDrawingAreaAvailable
|
|
42001
|
-
}), !interactiveToolsMode && i18n__namespace._("Add transformations below:"), this.props.graphMode === "static" && [/*#__PURE__*/React__namespace.createElement("br", {
|
|
42002
|
-
key: "static-br"
|
|
42003
|
-
}), /*#__PURE__*/React__namespace.createElement("em", {
|
|
42004
|
-
key: "static-nomove"
|
|
42005
|
-
}, " ", i18n__namespace._("Note: For this question, the shape will not move."), " ")], interactiveToolsMode && toolsBar, /*#__PURE__*/React__namespace.createElement(TransformationList
|
|
42006
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42007
|
-
, {
|
|
42008
|
-
ref: "transformationList",
|
|
42009
|
-
mode: this.props.listMode,
|
|
42010
|
-
transformations: this.props.transformations,
|
|
42011
|
-
onChange: this.setTransformationProps,
|
|
42012
|
-
onFocus: this._handleFocus,
|
|
42013
|
-
onBlur: this._handleBlur,
|
|
42014
|
-
keypadElement: this.props.keypadElement,
|
|
42015
|
-
apiOptions: this.props.apiOptions
|
|
42016
|
-
}), !interactiveToolsMode && toolsBar);
|
|
42017
|
-
}
|
|
42018
|
-
componentDidMount() {
|
|
42019
|
-
this.setupGraphie(this.graphie());
|
|
42020
|
-
}
|
|
42021
|
-
componentDidUpdate(prevProps) {
|
|
42022
|
-
if (this.shouldSetupGraphie(this.props, prevProps)) {
|
|
42023
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42024
|
-
// @ts-expect-error - TS2339 - Property 'reset' does not exist on type 'ReactInstance'.
|
|
42025
|
-
this.refs.graph.reset();
|
|
42026
|
-
} else if (!deepEq(this.props.transformations, this.transformations)) {
|
|
42027
|
-
this.setTransformations(this.props.transformations);
|
|
42028
|
-
}
|
|
42029
|
-
}
|
|
42030
|
-
shouldSetupGraphie = (nextProps, prevProps) => {
|
|
42031
|
-
if (!deepEq(prevProps.starting, nextProps.starting)) {
|
|
42032
|
-
return true;
|
|
42033
|
-
}
|
|
42034
|
-
if (prevProps.graphMode !== nextProps.graphMode) {
|
|
42035
|
-
return true;
|
|
42036
|
-
}
|
|
42037
|
-
if (prevProps.listMode !== nextProps.listMode) {
|
|
42038
|
-
return true;
|
|
42039
|
-
}
|
|
42040
|
-
if (prevProps.drawSolutionShape !== nextProps.drawSolutionShape) {
|
|
42041
|
-
return true;
|
|
42042
|
-
}
|
|
42043
|
-
if (nextProps.drawSolutionShape && !deepEq(prevProps.correct.shape, nextProps.correct.shape)) {
|
|
42044
|
-
return true;
|
|
42045
|
-
}
|
|
42046
|
-
if (!deepEq(this.tools, nextProps.tools)) {
|
|
42047
|
-
return true;
|
|
42048
|
-
}
|
|
42049
|
-
return false;
|
|
42050
|
-
};
|
|
42051
|
-
graphie = () => {
|
|
42052
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42053
|
-
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
|
|
42054
|
-
return this.refs.graph.graphie();
|
|
42055
|
-
};
|
|
42056
|
-
setupGraphie = graphie => {
|
|
42057
|
-
// A background image of our solution:
|
|
42058
|
-
if (this.props.drawSolutionShape && this.props.correct.shape && this.props.correct.shape.coords) {
|
|
42059
|
-
// @ts-expect-error - TS2554 - Expected 3 arguments, but got 2.
|
|
42060
|
-
ShapeTypes.addShape(graphie, {
|
|
42061
|
-
fixed: true,
|
|
42062
|
-
shape: this.props.correct.shape,
|
|
42063
|
-
normalStyle: {
|
|
42064
|
-
stroke: KhanColors.GRAY,
|
|
42065
|
-
"stroke-dasharray": "",
|
|
42066
|
-
"stroke-width": 2
|
|
42067
|
-
}
|
|
42068
|
-
});
|
|
42069
|
-
}
|
|
42070
|
-
this.currentTool = null;
|
|
42071
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42072
|
-
// @ts-expect-error - TS2339 - Property 'changeSelected' does not exist on type 'ReactInstance'.
|
|
42073
|
-
this.refs.toolsBar.changeSelected(null);
|
|
42074
|
-
this.addTransformerShape(this.props.starting.shape, /* translatable */false);
|
|
42075
|
-
this.setTransformations(this.props.transformations);
|
|
42076
|
-
|
|
42077
|
-
// Save a copy of our tools so that we can check future
|
|
42078
|
-
// this.props.tools changes against them
|
|
42079
|
-
// This seems weird, but gives us an easy way to tell whether
|
|
42080
|
-
// props changes were self-inflicted (for which a graphie reset
|
|
42081
|
-
// is not required, and is in fact a bad idea right now because
|
|
42082
|
-
// of resetting the size of the dilation tool).
|
|
42083
|
-
// TODO (jack): A deepClone method would be nice here
|
|
42084
|
-
this.tools = {
|
|
42085
|
-
translation: ___default["default"].clone(this.props.tools.translation),
|
|
42086
|
-
rotation: ___default["default"].clone(this.props.tools.rotation),
|
|
42087
|
-
reflection: ___default["default"].clone(this.props.tools.reflection),
|
|
42088
|
-
dilation: ___default["default"].clone(this.props.tools.dilation)
|
|
42089
|
-
};
|
|
42090
|
-
};
|
|
42091
|
-
|
|
42092
|
-
/* Applies all transformations in `transformations`
|
|
42093
|
-
* to the starting shape, and updates this.transformations
|
|
42094
|
-
* to reflect this
|
|
42095
|
-
*
|
|
42096
|
-
* Usually called with this.props.transformations
|
|
42097
|
-
*/
|
|
42098
|
-
setTransformations = transformations => {
|
|
42099
|
-
this.resetCoords();
|
|
42100
|
-
this.transformations = ___default["default"].clone(transformations);
|
|
42101
|
-
___default["default"].each(this.transformations, this.applyTransform);
|
|
42102
|
-
};
|
|
42103
|
-
|
|
42104
|
-
// the polygon that we transform
|
|
42105
|
-
addTransformerShape = (shape, translatable) => {
|
|
42106
|
-
const self = this;
|
|
42107
|
-
const graphie = this.graphie();
|
|
42108
|
-
this.shape = ShapeTypes.addMovableShape(graphie, {
|
|
42109
|
-
shape: shape,
|
|
42110
|
-
editable: false,
|
|
42111
|
-
showPoints: this.props.graphMode !== "static",
|
|
42112
|
-
translatable: translatable,
|
|
42113
|
-
onMove: function (dX, dY) {
|
|
42114
|
-
dX = KhanMath.roundToNearest(graphie.snap[0], dX);
|
|
42115
|
-
dY = KhanMath.roundToNearest(graphie.snap[1], dY);
|
|
42116
|
-
// NOTE(kevinb): object is missing .constraints property
|
|
42117
|
-
// @ts-expect-error - TS2345 - Argument of type '{ type: "translation"; vector: [any, any]; }' is not assignable to parameter of type 'PerseusTransformerTransformation'.
|
|
42118
|
-
self.addTransform({
|
|
42119
|
-
type: "translation",
|
|
42120
|
-
vector: [dX, dY]
|
|
42121
|
-
});
|
|
42122
|
-
return [dX, dY];
|
|
42123
|
-
},
|
|
42124
|
-
normalPointStyle: {
|
|
42125
|
-
fill: translatable ? KhanColors.INTERACTIVE : KhanColors.DYNAMIC,
|
|
42126
|
-
stroke: translatable ? KhanColors.INTERACTIVE : KhanColors.DYNAMIC
|
|
42127
|
-
},
|
|
42128
|
-
highlightPointStyle: {
|
|
42129
|
-
fill: KhanColors.INTERACTING,
|
|
42130
|
-
stroke: KhanColors.INTERACTING
|
|
42131
|
-
}
|
|
42132
|
-
});
|
|
42133
|
-
};
|
|
42134
|
-
addTool = toolId => {
|
|
42135
|
-
const self = this;
|
|
42136
|
-
if (this.props.graphMode === "interactive") {
|
|
42137
|
-
if (toolId === "translation") {
|
|
42138
|
-
this.currentTool = this.addTranslationTool();
|
|
42139
|
-
} else if (toolId === "rotation") {
|
|
42140
|
-
this.currentTool = this.addRotationTool();
|
|
42141
|
-
} else if (toolId === "reflection") {
|
|
42142
|
-
this.currentTool = this.addReflectionTool();
|
|
42143
|
-
} else if (toolId === "dilation") {
|
|
42144
|
-
this.currentTool = this.addDilationTool();
|
|
42145
|
-
} else {
|
|
42146
|
-
throw new PerseusError("Invalid tool id: " + toolId, Errors.InvalidInput);
|
|
42147
|
-
}
|
|
42148
|
-
} else {
|
|
42149
|
-
let transform;
|
|
42150
|
-
if (toolId === "translation") {
|
|
42151
|
-
// NOTE(kevinb): object is missing .constraints property
|
|
42152
|
-
transform = {
|
|
42153
|
-
type: "translation",
|
|
42154
|
-
// NOTE(kevib): these should be numbers
|
|
42155
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
|
|
42156
|
-
vector: [null, null]
|
|
42157
|
-
};
|
|
42158
|
-
} else if (toolId === "rotation") {
|
|
42159
|
-
// NOTE(kevinb): object is missing .constraints property
|
|
42160
|
-
transform = {
|
|
42161
|
-
type: "rotation",
|
|
42162
|
-
// NOTE(kevib): these should be numbers
|
|
42163
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
|
|
42164
|
-
center: [null, null],
|
|
42165
|
-
// NOTE(kevib): this should be a number
|
|
42166
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'.
|
|
42167
|
-
angleDeg: null
|
|
42168
|
-
};
|
|
42169
|
-
} else if (toolId === "reflection") {
|
|
42170
|
-
// Reflections with nulls in them won't be applied until
|
|
42171
|
-
// fills in the blanks
|
|
42172
|
-
transform = {
|
|
42173
|
-
type: "reflection",
|
|
42174
|
-
line: [
|
|
42175
|
-
// NOTE(kevib): these should be numbers
|
|
42176
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
|
|
42177
|
-
[null, null],
|
|
42178
|
-
// NOTE(kevib): these should be numbers
|
|
42179
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
|
|
42180
|
-
[null, null]]
|
|
42181
|
-
};
|
|
42182
|
-
} else if (toolId === "dilation") {
|
|
42183
|
-
// NOTE(kevinb): object is missing .constraints property
|
|
42184
|
-
transform = {
|
|
42185
|
-
type: "dilation",
|
|
42186
|
-
// NOTE(kevib): these should be numbers
|
|
42187
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'. | TS2322 - Type 'null' is not assignable to type 'number'.
|
|
42188
|
-
center: [null, null],
|
|
42189
|
-
// NOTE(kevib): this should be a number
|
|
42190
|
-
// @ts-expect-error - TS2322 - Type 'null' is not assignable to type 'number'.
|
|
42191
|
-
scale: null
|
|
42192
|
-
};
|
|
42193
|
-
} else {
|
|
42194
|
-
throw new PerseusError("Invalid tool id: " + toolId, Errors.InvalidInput);
|
|
42195
|
-
}
|
|
42196
|
-
this.doTransform(transform, function () {
|
|
42197
|
-
// @ts-expect-error - TS2339 - Property 'focusLast' does not exist on type 'ReactInstance'.
|
|
42198
|
-
self.refs.transformationList.focusLast();
|
|
42199
|
-
});
|
|
42200
|
-
}
|
|
42201
|
-
};
|
|
42202
|
-
removeTool = toolId => {
|
|
42203
|
-
if (this.currentTool) {
|
|
42204
|
-
this.currentTool.remove();
|
|
42205
|
-
}
|
|
42206
|
-
this.currentTool = null;
|
|
42207
|
-
};
|
|
42208
|
-
addTranslationTool = () => {
|
|
42209
|
-
const self = this;
|
|
42210
|
-
this.shape?.remove();
|
|
42211
|
-
this.addTransformerShape(this.shape?.toJSON(), /* translatable */true);
|
|
42212
|
-
return {
|
|
42213
|
-
remove: function () {
|
|
42214
|
-
self.shape?.remove();
|
|
42215
|
-
self.addTransformerShape(self.shape?.toJSON(), /* translatable */false);
|
|
42216
|
-
}
|
|
42217
|
-
};
|
|
42218
|
-
};
|
|
42219
|
-
|
|
42220
|
-
// Snaps a coord to this.graphie()'s snap
|
|
42221
|
-
// @ts-expect-error - TS2322 - Type '(coord: Coord) => number[]' is not assignable to type '(arg1: Coord) => Coord'.
|
|
42222
|
-
snapCoord = coord => {
|
|
42223
|
-
const graphie = this.graphie();
|
|
42224
|
-
return ___default["default"].map(coord, function (val, dim) {
|
|
42225
|
-
return KhanMath.roundToNearest(graphie.snap[dim], val);
|
|
42226
|
-
});
|
|
42227
|
-
};
|
|
42228
|
-
|
|
42229
|
-
// Normalize the coords into something that fits the new 45 degree
|
|
42230
|
-
// reflection line.
|
|
42231
|
-
// @ts-expect-error - TS2322 - Type '(messyCoords: [Coord, Coord]) => any[]' is not assignable to type '(arg1: [Coord, Coord]) => [Coord, Coord]'.
|
|
42232
|
-
normalizeReflectionCoords = messyCoords => {
|
|
42233
|
-
// @ts-expect-error - TS2345 - Argument of type 'Point' is not assignable to parameter of type 'Coord'.
|
|
42234
|
-
const midpoint = this.snapCoord(kmath.line.midpoint(messyCoords));
|
|
42235
|
-
const origDirectionPolar = kmath.vector.polarDegFromCart(kmath.vector.subtract(messyCoords[0], messyCoords[1]));
|
|
42236
|
-
const direction = kmath.vector.cartFromPolarDeg(1, KhanMath.roundToNearest(45, origDirectionPolar[1]));
|
|
42237
|
-
const coords = ___default["default"].map([-1, 1], function (directionCoefficient) {
|
|
42238
|
-
const coord = kmath.vector.add(midpoint, kmath.vector.scale(direction, directionCoefficient *
|
|
42239
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
42240
|
-
this.scaleToCurrentRange(REFLECT_ROTATE_HANDLE_DIST)));
|
|
42241
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
42242
|
-
return this.snapCoord(coord);
|
|
42243
|
-
}, this);
|
|
42244
|
-
return coords;
|
|
42245
|
-
};
|
|
42246
|
-
addReflectionTool = () => {
|
|
42247
|
-
const options = this.props.tools.reflection;
|
|
42248
|
-
if (!options.enabled) {
|
|
42249
|
-
return;
|
|
42250
|
-
}
|
|
42251
|
-
const self = this;
|
|
42252
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42253
|
-
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
|
|
42254
|
-
const graphie = this.refs.graph.graphie();
|
|
42255
|
-
const updateReflectionTool = function () {
|
|
42256
|
-
self.changeTool("reflection", {
|
|
42257
|
-
coords: ___default["default"].pluck(reflectPoints, "coord")
|
|
42258
|
-
});
|
|
42259
|
-
};
|
|
42260
|
-
const coords = this.normalizeReflectionCoords(options.coords);
|
|
42261
|
-
|
|
42262
|
-
// The points defining the line of reflection; hidden from the
|
|
42263
|
-
// user.
|
|
42264
|
-
const reflectPoints = ___default["default"].map(coords, function (coord) {
|
|
42265
|
-
return graphie.addMovablePoint({
|
|
42266
|
-
coord: coord,
|
|
42267
|
-
visible: false
|
|
42268
|
-
});
|
|
42269
|
-
}, this);
|
|
42270
|
-
|
|
42271
|
-
// the line of reflection
|
|
42272
|
-
// TODO(jack): graphie.style here is a hack to prevent the dashed
|
|
42273
|
-
// style from leaking into the rest of the shapes. Remove when
|
|
42274
|
-
// graphie.addMovableLineSegment doesn't leak styles anymore.
|
|
42275
|
-
let reflectLine;
|
|
42276
|
-
const normalColor = colorForTool(options);
|
|
42277
|
-
graphie.style({}, function () {
|
|
42278
|
-
reflectLine = graphie.addMovableLineSegment({
|
|
42279
|
-
fixed: options.constraints.fixed,
|
|
42280
|
-
constraints: options.constraints,
|
|
42281
|
-
pointA: reflectPoints[0],
|
|
42282
|
-
pointZ: reflectPoints[1],
|
|
42283
|
-
snapX: graphie.snap[0],
|
|
42284
|
-
snapY: graphie.snap[1],
|
|
42285
|
-
extendLine: true,
|
|
42286
|
-
normalStyle: {
|
|
42287
|
-
stroke: normalColor,
|
|
42288
|
-
"stroke-width": 2,
|
|
42289
|
-
"stroke-dasharray": "- "
|
|
42290
|
-
},
|
|
42291
|
-
highlightStyle: {
|
|
42292
|
-
stroke: KhanColors.INTERACTING,
|
|
42293
|
-
"stroke-width": 2,
|
|
42294
|
-
"stroke-dasharray": "- " // TODO(jack) solid doesn't
|
|
42295
|
-
// work here, but would be
|
|
42296
|
-
// nicer
|
|
42297
|
-
},
|
|
42298
|
-
|
|
42299
|
-
movePointsWithLine: true,
|
|
42300
|
-
onMoveEnd: updateReflectionTool
|
|
42301
|
-
});
|
|
42302
|
-
});
|
|
42303
|
-
|
|
42304
|
-
// the "button" point in the center of the line of reflection
|
|
42305
|
-
const reflectButton = graphie.addReflectButton({
|
|
42306
|
-
fixed: options.constraints.fixed,
|
|
42307
|
-
line: reflectLine,
|
|
42308
|
-
size: this.scaleToCurrentRange(REFLECT_BUTTON_SIZE),
|
|
42309
|
-
onClick: function () {
|
|
42310
|
-
self.doTransform({
|
|
42311
|
-
type: "reflection",
|
|
42312
|
-
// @ts-expect-error - TS2322 - Type 'any[]' is not assignable to type '[Coord, Coord]'.
|
|
42313
|
-
line: ___default["default"].pluck(reflectPoints, "coord")
|
|
42314
|
-
});
|
|
42315
|
-
if (reflectRotateHandle) {
|
|
42316
|
-
// flip the rotation handle
|
|
42317
|
-
// @ts-expect-error - TS2339 - Property 'setCoord' does not exist on type 'never'.
|
|
42318
|
-
reflectRotateHandle.setCoord(kmath.vector.add(reflectButton.coord, kmath.vector.subtract(reflectButton.coord,
|
|
42319
|
-
// @ts-expect-error - TS2339 - Property 'coord' does not exist on type 'never'.
|
|
42320
|
-
reflectRotateHandle.coord)));
|
|
42321
|
-
// @ts-expect-error - TS2339 - Property 'update' does not exist on type 'never'.
|
|
42322
|
-
reflectRotateHandle.update();
|
|
42323
|
-
}
|
|
42324
|
-
},
|
|
42325
|
-
normalStyle: {
|
|
42326
|
-
stroke: normalColor,
|
|
42327
|
-
"stroke-width": 2,
|
|
42328
|
-
fill: normalColor
|
|
42329
|
-
},
|
|
42330
|
-
highlightStyle: {
|
|
42331
|
-
stroke: KhanColors.INTERACTING,
|
|
42332
|
-
"stroke-width": 3,
|
|
42333
|
-
fill: KhanColors.INTERACTING
|
|
42334
|
-
},
|
|
42335
|
-
onMoveEnd: updateReflectionTool
|
|
42336
|
-
});
|
|
42337
|
-
let reflectRotateHandle = null;
|
|
42338
|
-
if (!options.constraints.fixed) {
|
|
42339
|
-
// The rotation handle for rotating the line of reflection
|
|
42340
|
-
const initRotateHandleAngle = kmath.vector.polarDegFromCart(kmath.vector.subtract(reflectPoints[1].coord, reflectPoints[0].coord))[1] + 90; // 90 degrees off of the line
|
|
42341
|
-
reflectRotateHandle = graphie.addRotateHandle({
|
|
42342
|
-
center: reflectButton,
|
|
42343
|
-
radius: this.scaleToCurrentRange(REFLECT_ROTATE_HANDLE_DIST),
|
|
42344
|
-
angleDeg: initRotateHandleAngle,
|
|
42345
|
-
width: this.scaleToCurrentRange(0.24),
|
|
42346
|
-
hoverWidth: this.scaleToCurrentRange(0.4),
|
|
42347
|
-
lengthAngle: 17,
|
|
42348
|
-
onMove: function (newAngle) {
|
|
42349
|
-
return KhanMath.roundToNearest(45, newAngle);
|
|
42350
|
-
},
|
|
42351
|
-
onMoveEnd: updateReflectionTool
|
|
42352
|
-
});
|
|
42353
|
-
}
|
|
42354
|
-
|
|
42355
|
-
// Move the reflectButton and reflectRotateHandle with the line
|
|
42356
|
-
$__default["default"](reflectLine).on("move", function () {
|
|
42357
|
-
reflectButton.update();
|
|
42358
|
-
$__default["default"](reflectButton).trigger("move"); // update the rotation handle,
|
|
42359
|
-
// which watches for this in util/interactive.js.
|
|
42360
|
-
});
|
|
42361
|
-
|
|
42362
|
-
// Update the line and reflect button when the reflectRotateHandle is
|
|
42363
|
-
// rotated
|
|
42364
|
-
if (reflectRotateHandle) {
|
|
42365
|
-
$__default["default"](reflectRotateHandle).on("move", function () {
|
|
42366
|
-
const rotateHandleApprox = self.snapCoord(
|
|
42367
|
-
// @ts-expect-error - TS2531 - Object is possibly 'null'.
|
|
42368
|
-
reflectRotateHandle.coord);
|
|
42369
|
-
const rotateVector = kmath.vector.subtract(rotateHandleApprox, reflectButton.coord);
|
|
42370
|
-
const flipped = reflectButton.isFlipped() ? 1 : 0;
|
|
42371
|
-
reflectPoints[flipped].setCoord(kmath.vector.add(reflectButton.coord, kmath.vector.rotateDeg(rotateVector, 90)));
|
|
42372
|
-
reflectPoints[1 - flipped].setCoord(kmath.vector.add(reflectButton.coord, kmath.vector.rotateDeg(rotateVector, -90)));
|
|
42373
|
-
reflectLine.transform(true);
|
|
42374
|
-
reflectButton.update();
|
|
42375
|
-
});
|
|
42376
|
-
}
|
|
42377
|
-
return {
|
|
42378
|
-
remove: function () {
|
|
42379
|
-
reflectButton.remove();
|
|
42380
|
-
if (reflectRotateHandle) {
|
|
42381
|
-
// @ts-expect-error - TS2339 - Property 'remove' does not exist on type 'never'.
|
|
42382
|
-
reflectRotateHandle.remove();
|
|
42383
|
-
}
|
|
42384
|
-
reflectLine.remove();
|
|
42385
|
-
reflectPoints[0].remove();
|
|
42386
|
-
reflectPoints[1].remove();
|
|
42387
|
-
}
|
|
42388
|
-
};
|
|
42389
|
-
};
|
|
42390
|
-
|
|
42391
|
-
/* Scales a distance from the default range of
|
|
42392
|
-
* [-10, 10] to the current this.props.graph.range
|
|
42393
|
-
*
|
|
42394
|
-
* Used for sizing various transformation tools
|
|
42395
|
-
* (rotation handle, dilation circle)
|
|
42396
|
-
*/
|
|
42397
|
-
scaleToCurrentRange = dist => {
|
|
42398
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42399
|
-
// @ts-expect-error - TS2339 - Property 'props' does not exist on type 'ReactInstance'.
|
|
42400
|
-
return scaleToRange(dist, this.refs.graph.props.range);
|
|
42401
|
-
};
|
|
42402
|
-
addRotationTool = () => {
|
|
42403
|
-
const options = this.props.tools.rotation;
|
|
42404
|
-
if (!options.enabled) {
|
|
42405
|
-
return;
|
|
42406
|
-
}
|
|
42407
|
-
const self = this;
|
|
42408
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42409
|
-
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
|
|
42410
|
-
const graphie = this.refs.graph.graphie();
|
|
42411
|
-
const pointColor = colorForTool(options);
|
|
42412
|
-
// The center of our rotation, which can be moved to change the
|
|
42413
|
-
// center of rotation
|
|
42414
|
-
this.rotatePoint = graphie.addMovablePoint({
|
|
42415
|
-
constraints: options.constraints,
|
|
42416
|
-
coord: options.coord,
|
|
42417
|
-
snapX: graphie.snap[0],
|
|
42418
|
-
snapY: graphie.snap[1],
|
|
42419
|
-
normalStyle: {
|
|
42420
|
-
// ugh, this seems to be a global and
|
|
42421
|
-
"stroke-dasharray": "",
|
|
42422
|
-
// is set to dash above
|
|
42423
|
-
stroke: pointColor,
|
|
42424
|
-
fill: pointColor
|
|
42425
|
-
},
|
|
42426
|
-
highlightStyle: {
|
|
42427
|
-
"stroke-dasharray": "",
|
|
42428
|
-
stroke: KhanColors.INTERACTING,
|
|
42429
|
-
fill: KhanColors.INTERACTING
|
|
42430
|
-
}
|
|
42431
|
-
});
|
|
42432
|
-
|
|
42433
|
-
// The point that we move around the center of rotation to actually
|
|
42434
|
-
// cause rotations
|
|
42435
|
-
this.rotateHandle = graphie.addRotateHandle({
|
|
42436
|
-
center: this.rotatePoint,
|
|
42437
|
-
radius: this.scaleToCurrentRange(ROTATE_HANDLE_DIST),
|
|
42438
|
-
width: this.scaleToCurrentRange(0.24),
|
|
42439
|
-
hoverWidth: this.scaleToCurrentRange(0.4),
|
|
42440
|
-
onMove: function (newAngle, oldAngle) {
|
|
42441
|
-
const transform = self.getRotationTransformFromAngle(self.rotatePoint.coord, newAngle - oldAngle);
|
|
42442
|
-
|
|
42443
|
-
// Rotate polygon with rotateHandle
|
|
42444
|
-
self.doTransform(transform);
|
|
42445
|
-
|
|
42446
|
-
// @ts-expect-error - TS2339 - Property 'angleDeg' does not exist on type 'PerseusTransformerTransformation'.
|
|
42447
|
-
return oldAngle + transform.angleDeg;
|
|
42448
|
-
}
|
|
42449
|
-
});
|
|
42450
|
-
|
|
42451
|
-
// Update tools.rotation.coord
|
|
42452
|
-
this.rotatePoint.onMoveEnd = (x, y) => {
|
|
42453
|
-
self.changeTool("rotation", {
|
|
42454
|
-
coord: [x, y]
|
|
42455
|
-
});
|
|
42456
|
-
};
|
|
42457
|
-
return {
|
|
42458
|
-
remove: function () {
|
|
42459
|
-
self.rotateHandle?.remove();
|
|
42460
|
-
self.rotatePoint?.remove();
|
|
42461
|
-
}
|
|
42462
|
-
};
|
|
42463
|
-
};
|
|
42464
|
-
addDilationTool = () => {
|
|
42465
|
-
const options = this.props.tools.dilation;
|
|
42466
|
-
if (!options.enabled) {
|
|
42467
|
-
return;
|
|
42468
|
-
}
|
|
42469
|
-
const self = this;
|
|
42470
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42471
|
-
// @ts-expect-error - TS2339 - Property 'graphie' does not exist on type 'ReactInstance'.
|
|
42472
|
-
const graphie = this.refs.graph.graphie();
|
|
42473
|
-
const pointColor = colorForTool(options);
|
|
42474
|
-
// the circle for causing dilation transforms
|
|
42475
|
-
self.dilationCircle = graphie.addCircleGraph({
|
|
42476
|
-
centerConstraints: options.constraints,
|
|
42477
|
-
center: options.coord,
|
|
42478
|
-
radius: self.scaleToCurrentRange(2),
|
|
42479
|
-
snapX: graphie.snap[0],
|
|
42480
|
-
snapY: graphie.snap[1],
|
|
42481
|
-
minRadius: self.scaleToCurrentRange(1),
|
|
42482
|
-
snapRadius: self.scaleToCurrentRange(0.5),
|
|
42483
|
-
onResize: function (newRadius, oldRadius) {
|
|
42484
|
-
// NOTE(kevinb): object is missing .constraints property
|
|
42485
|
-
// @ts-expect-error - TS2345 - Argument of type '{ type: "dilation"; center: any; scale: number; }' is not assignable to parameter of type 'PerseusTransformerTransformation'.
|
|
42486
|
-
self.doTransform({
|
|
42487
|
-
type: "dilation",
|
|
42488
|
-
center: self.dilationCircle.centerPoint.coord,
|
|
42489
|
-
scale: newRadius / oldRadius
|
|
42490
|
-
});
|
|
42491
|
-
},
|
|
42492
|
-
circleNormalStyle: {
|
|
42493
|
-
stroke: pointColor,
|
|
42494
|
-
"stroke-width": 2,
|
|
42495
|
-
"stroke-dasharray": "- ",
|
|
42496
|
-
"fill-opacity": 0
|
|
42497
|
-
},
|
|
42498
|
-
circleHighlightStyle: {
|
|
42499
|
-
stroke: KhanColors.INTERACTING,
|
|
42500
|
-
"stroke-width": 2,
|
|
42501
|
-
"stroke-dasharray": "",
|
|
42502
|
-
fill: KhanColors.INTERACTING,
|
|
42503
|
-
"fill-opacity": 0.05
|
|
42504
|
-
},
|
|
42505
|
-
centerNormalStyle: {
|
|
42506
|
-
stroke: pointColor,
|
|
42507
|
-
fill: pointColor,
|
|
42508
|
-
"stroke-width": 2,
|
|
42509
|
-
"stroke-dasharray": ""
|
|
42510
|
-
},
|
|
42511
|
-
centerHighlightStyle: {
|
|
42512
|
-
stroke: pointColor,
|
|
42513
|
-
fill: pointColor,
|
|
42514
|
-
"stroke-width": 2,
|
|
42515
|
-
"stroke-dasharray": ""
|
|
42516
|
-
}
|
|
42517
|
-
});
|
|
42518
|
-
const origOnMoveEnd = this.dilationCircle.centerPoint.onMoveEnd;
|
|
42519
|
-
this.dilationCircle.centerPoint.onMoveEnd = function () {
|
|
42520
|
-
if (origOnMoveEnd) {
|
|
42521
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
42522
|
-
args[_key] = arguments[_key];
|
|
42523
|
-
}
|
|
42524
|
-
origOnMoveEnd(args);
|
|
42525
|
-
}
|
|
42526
|
-
self.changeTool("dilation", {
|
|
42527
|
-
coord: self.dilationCircle.centerPoint.coord
|
|
42528
|
-
});
|
|
42529
|
-
};
|
|
42530
|
-
return {
|
|
42531
|
-
remove: function () {
|
|
42532
|
-
self.dilationCircle?.remove();
|
|
42533
|
-
}
|
|
42534
|
-
};
|
|
42535
|
-
};
|
|
42536
|
-
|
|
42537
|
-
// returns a transformation object representing a rotation
|
|
42538
|
-
// rounds the angle to the nearest 15 degrees
|
|
42539
|
-
// @ts-expect-error - TS2322 - Type '(center: Coord, angleChanged: number) => { type: "rotation"; center: Coord; angleDeg: number; }' is not assignable to type '(arg1: Coord, arg2: number) => PerseusTransformerTransformation'.
|
|
42540
|
-
getRotationTransformFromAngle = (center, angleChanged) => {
|
|
42541
|
-
angleChanged = (angleChanged + 360) % 360;
|
|
42542
|
-
if (angleChanged > 180) {
|
|
42543
|
-
angleChanged -= 360;
|
|
42544
|
-
}
|
|
42545
|
-
const roundedAngle = Math.round(angleChanged / ROTATE_SNAP_DEGREES) * ROTATE_SNAP_DEGREES;
|
|
42546
|
-
|
|
42547
|
-
// NOTE(kevinb): return object is missing .constraints property
|
|
42548
|
-
return {
|
|
42549
|
-
type: "rotation",
|
|
42550
|
-
center: center,
|
|
42551
|
-
angleDeg: roundedAngle
|
|
42552
|
-
};
|
|
42553
|
-
};
|
|
42554
|
-
|
|
42555
|
-
// apply and save a transform
|
|
42556
|
-
doTransform = (transform, callback) => {
|
|
42557
|
-
this.applyTransform(transform);
|
|
42558
|
-
this.addTransform(transform, callback);
|
|
42559
|
-
};
|
|
42560
|
-
|
|
42561
|
-
// apply a transform to our polygon (without modifying our transformation
|
|
42562
|
-
// list)
|
|
42563
|
-
applyTransform = transform => {
|
|
42564
|
-
if (this.props.graphMode !== "static") {
|
|
42565
|
-
const transformFunc = TransformOps.apply(transform);
|
|
42566
|
-
// @ts-expect-error - TS2345 - Argument of type '(coord: any) => any' is not assignable to parameter of type 'PerseusTransformerTransformation'.
|
|
42567
|
-
this.applyCoordTransformation(transformFunc);
|
|
42568
|
-
}
|
|
42569
|
-
};
|
|
42570
|
-
|
|
42571
|
-
// transform our polygon by transforming each point using a given function
|
|
42572
|
-
applyCoordTransformation = pointTransform => {
|
|
42573
|
-
___default["default"].each(this.shape.points, function (point) {
|
|
42574
|
-
// @ts-expect-error - TS2349 - This expression is not callable.
|
|
42575
|
-
const newCoord = pointTransform(point.coord);
|
|
42576
|
-
point.setCoord(newCoord);
|
|
42577
|
-
});
|
|
42578
|
-
this.shape?.update();
|
|
42579
|
-
};
|
|
42580
|
-
resetCoords = () => {
|
|
42581
|
-
const startCoords = this.props.starting.shape.coords;
|
|
42582
|
-
___default["default"].each(this.shape.points, function (point, i) {
|
|
42583
|
-
point.setCoord(startCoords[i]);
|
|
42584
|
-
});
|
|
42585
|
-
this.shape?.update();
|
|
42586
|
-
};
|
|
42587
|
-
|
|
42588
|
-
// Remove the last transformation
|
|
42589
|
-
handleUndoClick = () => {
|
|
42590
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42591
|
-
// @ts-expect-error - TS2339 - Property 'changeSelected' does not exist on type 'ReactInstance'.
|
|
42592
|
-
this.refs.toolsBar.changeSelected(null);
|
|
42593
|
-
if (this.props.transformations.length) {
|
|
42594
|
-
this.props.onChange({
|
|
42595
|
-
transformations: ___default["default"].initial(this.props.transformations)
|
|
42596
|
-
});
|
|
42597
|
-
}
|
|
42598
|
-
};
|
|
42599
|
-
setTransformationProps = (newTransfomationList, callback) => {
|
|
42600
|
-
this.props.onChange({
|
|
42601
|
-
transformations: newTransfomationList
|
|
42602
|
-
},
|
|
42603
|
-
// @ts-expect-error - TS2345 - Argument of type '(arg1: any) => unknown' is not assignable to parameter of type '() => unknown'.
|
|
42604
|
-
callback);
|
|
42605
|
-
};
|
|
42606
|
-
|
|
42607
|
-
// add a transformation to our props list of transformation
|
|
42608
|
-
addTransform = (transform, callback) => {
|
|
42609
|
-
this.transformations = TransformOps.append(this.transformations, transform);
|
|
42610
|
-
this.props.onChange({
|
|
42611
|
-
transformations: ___default["default"].clone(this.transformations)
|
|
42612
|
-
},
|
|
42613
|
-
// @ts-expect-error - TS2345 - Argument of type '((arg1: any) => unknown) | undefined' is not assignable to parameter of type '(() => unknown) | undefined'.
|
|
42614
|
-
callback);
|
|
42615
|
-
};
|
|
42616
|
-
changeTool = (tool, changes) => {
|
|
42617
|
-
const newTools = ___default["default"].clone(this.props.tools);
|
|
42618
|
-
newTools[tool] = ___default["default"].extend({}, this.props.tools[tool], changes);
|
|
42619
|
-
this.tools[tool] = ___default["default"].clone(newTools[tool]);
|
|
42620
|
-
this.props.onChange({
|
|
42621
|
-
// @ts-expect-error - TS2740 - Type '{ dilation: DilationTool; reflection: ReflectionTool; rotation: RotationTool; translation: TranslationTool; }' is missing the following properties from type 'readonly any[]': length, concat, join, slice, and 18 more.
|
|
42622
|
-
tools: newTools
|
|
42623
|
-
});
|
|
42624
|
-
this.props.trackInteraction();
|
|
42625
|
-
};
|
|
42626
|
-
simpleValidate = rubric => {
|
|
42627
|
-
return Transformer.validate(this.getUserInput(), rubric);
|
|
42628
|
-
};
|
|
42629
|
-
|
|
42630
|
-
/**
|
|
42631
|
-
* Calculate where the coordinates would be if they were
|
|
42632
|
-
* moved, even if we're in formal mode with no movement
|
|
42633
|
-
* (and thus the actual movablepoints may not have moved
|
|
42634
|
-
*/
|
|
42635
|
-
// @ts-expect-error - TS2322 - Type '() => [Coord, Coord] | readonly Coord[] | [Coord, Coord, Coord]' is not assignable to type '() => Coord'.
|
|
42636
|
-
getCoords = () => {
|
|
42637
|
-
const startCoords = this.props.starting.shape.coords;
|
|
42638
|
-
const transforms = this.props.transformations;
|
|
42639
|
-
return ___default["default"].reduce(transforms, function (coords, transform) {
|
|
42640
|
-
return ___default["default"].map(coords, TransformOps.apply(transform));
|
|
42641
|
-
}, startCoords);
|
|
42642
|
-
};
|
|
42643
|
-
getEditorJSON = () => {
|
|
42644
|
-
const json = ___default["default"].pick(this.props, "grading", "starting", "graphMode", "listMode", "tools", "drawSolutionShape", "gradeEmpty");
|
|
42645
|
-
// eslint-disable-next-line react/no-string-refs
|
|
42646
|
-
// @ts-expect-error - TS2339 - Property 'graph' does not exist on type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "tools" | "starting" | "drawSolutionShape" | "gradeEmpty" | "graphMode" | "listMode">'. | TS2339 - Property 'toJSON' does not exist on type 'ReactInstance'.
|
|
42647
|
-
json.graph = this.refs.graph.toJSON();
|
|
42648
|
-
// @ts-expect-error - TS2339 - Property 'version' does not exist on type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "tools" | "starting" | "drawSolutionShape" | "gradeEmpty" | "graphMode" | "listMode">'.
|
|
42649
|
-
json.version = 1.2; // Give us some safety to change the format
|
|
42650
|
-
// when we realize that I wrote
|
|
42651
|
-
// a horrible json spec for this widget
|
|
42652
|
-
|
|
42653
|
-
// @ts-expect-error - TS2339 - Property 'answer' does not exist on type 'Pick<Readonly<Props> & Readonly<{ children?: ReactNode; }>, "tools" | "starting" | "drawSolutionShape" | "gradeEmpty" | "graphMode" | "listMode">'.
|
|
42654
|
-
json.answer = this.getUserInput();
|
|
42655
|
-
return json;
|
|
42656
|
-
};
|
|
42657
|
-
getUserInput = () => {
|
|
42658
|
-
return {
|
|
42659
|
-
transformations: this.props.transformations,
|
|
42660
|
-
// This doesn't call this.shape.toJSON() because that doesn't
|
|
42661
|
-
// handle coordinates in formal mode without movement, since
|
|
42662
|
-
// the movablepoints never move
|
|
42663
|
-
shape: {
|
|
42664
|
-
type: this.shape.type,
|
|
42665
|
-
coords: this.getCoords(),
|
|
42666
|
-
options: this.shape?.getOptions()
|
|
42667
|
-
}
|
|
42668
|
-
};
|
|
42669
|
-
};
|
|
42670
|
-
|
|
42671
|
-
/* InputPath API */
|
|
42672
|
-
|
|
42673
|
-
_handleFocus = (() => {
|
|
42674
|
-
var _this = this;
|
|
42675
|
-
return function () {
|
|
42676
|
-
for (var _len2 = arguments.length, path = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
42677
|
-
path[_key2] = arguments[_key2];
|
|
42678
|
-
}
|
|
42679
|
-
_this.props.onFocus(path);
|
|
42680
|
-
};
|
|
42681
|
-
})();
|
|
42682
|
-
_handleBlur = (() => {
|
|
42683
|
-
var _this2 = this;
|
|
42684
|
-
return function () {
|
|
42685
|
-
for (var _len3 = arguments.length, path = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
|
|
42686
|
-
path[_key3] = arguments[_key3];
|
|
42687
|
-
}
|
|
42688
|
-
_this2.props.onBlur(path);
|
|
42689
|
-
};
|
|
42690
|
-
})();
|
|
42691
|
-
_getTransformationForID = transformationID => {
|
|
42692
|
-
// Returns the 'transformation' component corresponding to a given ID
|
|
42693
|
-
const refPath = ["transformationList", "transformation" + transformationID];
|
|
42694
|
-
|
|
42695
|
-
// Follow the path of references
|
|
42696
|
-
let component = this;
|
|
42697
|
-
___default["default"].each(refPath, ref => {
|
|
42698
|
-
// @ts-expect-error - TS2322 - Type 'ReactInstance' is not assignable to type 'this'.
|
|
42699
|
-
component = component.refs[ref];
|
|
42700
|
-
});
|
|
42701
|
-
return component;
|
|
42702
|
-
};
|
|
42703
|
-
getInputPaths = () => {
|
|
42704
|
-
// If we're in static mode, then there is no transformation list, and,
|
|
42705
|
-
// as a result, no input paths.
|
|
42706
|
-
if (this.props.listMode === "static") {
|
|
42707
|
-
return [];
|
|
42708
|
-
}
|
|
42709
|
-
let inputPaths = [];
|
|
42710
|
-
___default["default"].each(this.props.transformations, (transformation, i) => {
|
|
42711
|
-
// @ts-expect-error - TS2345 - Argument of type 'number' is not assignable to parameter of type 'string'.
|
|
42712
|
-
transformation = this._getTransformationForID(i);
|
|
42713
|
-
// @ts-expect-error - TS2339 - Property 'getInputPaths' does not exist on type 'PerseusTransformerTransformation'.
|
|
42714
|
-
const innerPaths = transformation.getInputPaths();
|
|
42715
|
-
const fullPaths = ___default["default"].map(innerPaths, innerPath => {
|
|
42716
|
-
return ["" + i].concat(innerPath);
|
|
42717
|
-
});
|
|
42718
|
-
// @ts-expect-error - TS2345 - Argument of type 'string[][]' is not assignable to parameter of type 'ConcatArray<never>'.
|
|
42719
|
-
inputPaths = inputPaths.concat(fullPaths);
|
|
42720
|
-
});
|
|
42721
|
-
return inputPaths;
|
|
42722
|
-
};
|
|
42723
|
-
_passToInner = function (functionName, path) {
|
|
42724
|
-
if (!path || !path.length) {
|
|
42725
|
-
return;
|
|
42726
|
-
}
|
|
42727
|
-
|
|
42728
|
-
// First argument tells us which transformation will receive the call;
|
|
42729
|
-
// remaining arguments are used within that transformation to identify
|
|
42730
|
-
// a specific input.
|
|
42731
|
-
const innerPath = ___default["default"].rest(path);
|
|
42732
|
-
|
|
42733
|
-
// Pass arguments down to appropriate 'transformation' component
|
|
42734
|
-
const transformationID = ___default["default"].head(path);
|
|
42735
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
42736
|
-
const caller = this._getTransformationForID(transformationID);
|
|
42737
|
-
for (var _len4 = arguments.length, args = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) {
|
|
42738
|
-
args[_key4 - 2] = arguments[_key4];
|
|
42739
|
-
}
|
|
42740
|
-
return caller[functionName](innerPath, ...args);
|
|
42741
|
-
};
|
|
42742
|
-
focus = () => {
|
|
42743
|
-
// Just focus the first showing input
|
|
42744
|
-
const inputs = this.getInputPaths();
|
|
42745
|
-
if (inputs.length > 0) {
|
|
42746
|
-
this.focusInputPath(inputs[0]);
|
|
42747
|
-
return true;
|
|
42748
|
-
}
|
|
42749
|
-
return false;
|
|
42750
|
-
};
|
|
42751
|
-
focusInputPath = path => {
|
|
42752
|
-
// Since the transformer exposes the input API, it needs to be robust
|
|
42753
|
-
// to empty paths. We don't expect this to happen, as entire-widget
|
|
42754
|
-
// focusing is typically done through the focus() method, which already
|
|
42755
|
-
// handles the empty path case properly, but it's better to be safe
|
|
42756
|
-
// here.
|
|
42757
|
-
if (path.length === 0) {
|
|
42758
|
-
return false;
|
|
42759
|
-
}
|
|
42760
|
-
assert(path.length >= 2);
|
|
42761
|
-
return this._passToInner("focusInputPath", path);
|
|
42762
|
-
};
|
|
42763
|
-
blurInputPath = path => {
|
|
42764
|
-
// Since the transformer exposes the input API, it needs to be robust
|
|
42765
|
-
// to empty paths (which indicate a blurring of the entire widget,
|
|
42766
|
-
// e.g., when switching from interacting with the transformer to
|
|
42767
|
-
// interacting with some other widget).
|
|
42768
|
-
if (path.length === 0) {
|
|
42769
|
-
return false;
|
|
42770
|
-
}
|
|
42771
|
-
assert(path.length >= 2);
|
|
42772
|
-
return this._passToInner("blurInputPath", path);
|
|
42773
|
-
};
|
|
42774
|
-
setInputValue = (path, value, cb) => {
|
|
42775
|
-
assert(path.length >= 2);
|
|
42776
|
-
return this._passToInner("setInputValue", path, value, cb);
|
|
42777
|
-
};
|
|
42778
|
-
getDOMNodeForPath = path => {
|
|
42779
|
-
assert(path.length >= 2);
|
|
42780
|
-
return this._passToInner("getDOMNodeForPath", path);
|
|
42781
|
-
};
|
|
42782
|
-
getGrammarTypeForPath = path => {
|
|
42783
|
-
assert(path.length >= 2);
|
|
42784
|
-
return this._passToInner("getGrammarTypeForPath", path);
|
|
42785
|
-
};
|
|
42786
|
-
static validate(guess, rubric) {
|
|
42787
|
-
// Check for any required transformations
|
|
42788
|
-
for (const type in Transformations) {
|
|
42789
|
-
if (rubric.tools[type].required) {
|
|
42790
|
-
const isUsed = ___default["default"].any(___default["default"].map(guess.transformations, function (transform) {
|
|
42791
|
-
// Required transformations must appear in the
|
|
42792
|
-
// transformation list, and must not be no-ops
|
|
42793
|
-
return transform.type === type && !TransformOps.isEmpty(transform) && !TransformOps.isNoOp(transform);
|
|
42794
|
-
}));
|
|
42795
|
-
if (!isUsed) {
|
|
42796
|
-
return {
|
|
42797
|
-
type: "invalid",
|
|
42798
|
-
message: i18n__namespace._("Your transformation must use a " + "%(type)s.", {
|
|
42799
|
-
type: Transformations[type].lowerNounName
|
|
42800
|
-
})
|
|
42801
|
-
};
|
|
42802
|
-
}
|
|
42803
|
-
}
|
|
42804
|
-
}
|
|
42805
|
-
|
|
42806
|
-
// Compare shapes
|
|
42807
|
-
if (ShapeTypes.equal(guess.shape, rubric.correct.shape)) {
|
|
42808
|
-
return {
|
|
42809
|
-
type: "points",
|
|
42810
|
-
earned: 1,
|
|
42811
|
-
total: 1,
|
|
42812
|
-
message: null
|
|
42813
|
-
};
|
|
42814
|
-
}
|
|
42815
|
-
if (!rubric.gradeEmpty && deepEq(guess.shape.coords, rubric.starting.shape.coords)) {
|
|
42816
|
-
return {
|
|
42817
|
-
type: "invalid",
|
|
42818
|
-
message: i18n__namespace._("Use the interactive graph to define a " + "correct transformation.")
|
|
42819
|
-
};
|
|
42820
|
-
}
|
|
42821
|
-
return {
|
|
42822
|
-
type: "points",
|
|
42823
|
-
earned: 0,
|
|
42824
|
-
total: 1,
|
|
42825
|
-
message: null
|
|
42826
|
-
};
|
|
42827
|
-
}
|
|
42828
|
-
}
|
|
42829
|
-
var Transformer$1 = {
|
|
42830
|
-
name: "transformer",
|
|
42831
|
-
displayName: "Transformer (deprecated)",
|
|
42832
|
-
hidden: true,
|
|
42833
|
-
widget: Transformer
|
|
42834
|
-
};
|
|
42835
|
-
|
|
42836
40421
|
var hubble = {exports: {}};
|
|
42837
40422
|
|
|
42838
40423
|
(function (module, exports) {
|
|
@@ -44058,7 +41643,7 @@ var Video$1 = {
|
|
|
44058
41643
|
};
|
|
44059
41644
|
|
|
44060
41645
|
/* eslint-disable import/no-named-as-default */
|
|
44061
|
-
var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1,
|
|
41646
|
+
var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, LightsPuzzle$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, ReactionDiagram, Sequence$1, Simulator$1, Sorter$1, Table$1, Unit, Video$1, DeprecatedStandin$1];
|
|
44062
41647
|
|
|
44063
41648
|
/**
|
|
44064
41649
|
* This should be called by all clients, specifying whether extra widgets are
|
|
@@ -44102,7 +41687,7 @@ const init = function (options) {
|
|
|
44102
41687
|
|
|
44103
41688
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44104
41689
|
const libName = "@khanacademy/perseus";
|
|
44105
|
-
const libVersion = "
|
|
41690
|
+
const libVersion = "19.0.0";
|
|
44106
41691
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44107
41692
|
|
|
44108
41693
|
const apiVersion = {
|
|
@@ -45547,8 +43132,6 @@ const ItemExtras = [
|
|
|
45547
43132
|
|
|
45548
43133
|
// prettier-ignore
|
|
45549
43134
|
|
|
45550
|
-
// prettier-ignore
|
|
45551
|
-
|
|
45552
43135
|
//prettier-ignore
|
|
45553
43136
|
|
|
45554
43137
|
// A background image applied to various widgets.
|
|
@@ -46673,10 +44256,7 @@ function violatingWidgets(itemData) {
|
|
|
46673
44256
|
*/
|
|
46674
44257
|
const registerAllWidgetsForTesting = () => {
|
|
46675
44258
|
registerWidgets(allWidgets);
|
|
46676
|
-
|
|
46677
|
-
// When it's time to replace the transformer widget
|
|
46678
|
-
// uncomment this line
|
|
46679
|
-
// Widgets.replaceWidget("transformer", "deprecated-standin");
|
|
44259
|
+
replaceWidget("transformer", "deprecated-standin");
|
|
46680
44260
|
};
|
|
46681
44261
|
|
|
46682
44262
|
/**
|
|
@@ -47136,7 +44716,6 @@ exports.Renderer = Renderer;
|
|
|
47136
44716
|
exports.ServerItemRenderer = ref;
|
|
47137
44717
|
exports.SizingUtils = sizingUtils;
|
|
47138
44718
|
exports.TableWidget = Table$1;
|
|
47139
|
-
exports.TransformerWidget = Transformer$1;
|
|
47140
44719
|
exports.Util = Util;
|
|
47141
44720
|
exports.WIDGET_PROP_DENYLIST = denylist;
|
|
47142
44721
|
exports.WidgetJsonifyDeprecated = WidgetJsonifyDeprecated;
|